Branch data Line data Source code
1 : : !!****m* ABINIT/m_htetra
2 : : !! NAME
3 : : !! m_htetra
4 : : !!
5 : : !! FUNCTION
6 : : !! Module for tetrahedron integration of DOS and similar quantities
7 : : !! Uses some functions from a previous implementation by MJV
8 : : !!
9 : : !! COPYRIGHT
10 : : !! Copyright (C) 2010-2026 ABINIT group (HM,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 more carefully the case of degenerate tethraedron
17 : : !! 2) Add options to get only delta and/or theta ?
18 : : !!
19 : : !! SOURCE
20 : :
21 : : #if defined HAVE_CONFIG_H
22 : : #include "config.h"
23 : : #endif
24 : :
25 : : #include "abi_common.h"
26 : :
27 : : module m_htetra
28 : :
29 : : use defs_basis
30 : : use m_abicore
31 : : use m_krank
32 : : use m_xmpi
33 : : use m_errors
34 : :
35 : : use m_fstrings, only : sjoin, itoa, ftoa
36 : : use m_numeric_tools, only : linspace
37 : : use m_simtet, only : sim0onei, SIM0TWOI
38 : :
39 : : implicit none
40 : :
41 : : private
42 : : !!***
43 : :
44 : : integer, parameter :: TETRA_SIZE = 6
45 : : integer, parameter :: TETRA_STEP = 6
46 : :
47 : : !!****t* m_htetra/t_htetra_bucket
48 : : !! NAME
49 : : !! t_htetra_bucket
50 : : !!
51 : : !! FUNCTION
52 : : !! Store a bunch of tetrahedra
53 : : !!
54 : : !! SOURCE
55 : :
56 : : type :: htetra_bucket
57 : :
58 : : integer,allocatable :: indexes(:,:)
59 : :
60 : : end type htetra_bucket
61 : : !!***
62 : :
63 : : !!****t* m_htetra/htetra_t
64 : : !! NAME
65 : : !! htetra_t
66 : : !!
67 : : !! FUNCTION
68 : : !! tetrahedron geometry object
69 : : !!
70 : : !! SOURCE
71 : :
72 : : type, public :: htetra_t
73 : :
74 : : integer :: opt
75 : : ! Option for the generation of tetrahedra
76 : :
77 : : integer :: nkibz
78 : : ! Number of points in the irreducible Brillouin zone
79 : :
80 : : integer :: nkbz
81 : : ! Number of points in the full Brillouin zone
82 : :
83 : : integer :: nbuckets
84 : : ! Number of buckets for the hash table
85 : :
86 : : integer :: nunique_tetra
87 : : ! Number of unique tetrahedron
88 : :
89 : : integer :: nibz_tetra
90 : : ! Number of ibz tetrahedron
91 : :
92 : : integer,allocatable :: tetra_total(:)
93 : : ! (%nbkibz)
94 : : ! Equivalent tetrahedra per kpoint (number of irred tetra times multiplicity)
95 : :
96 : : integer,allocatable :: tetra_count(:)
97 : : ! (%nbkibz)
98 : : ! Inequivalent tetrahedra per kpoint (number of irred tetra)
99 : :
100 : : integer,allocatable :: ibz_multiplicity(:)
101 : : ! (%nbkibz)
102 : : ! Multiplicity of each k-point
103 : :
104 : : real(dp) :: vv
105 : : ! volume of the tetrahedra
106 : :
107 : : real(dp) :: klatt(3, 3)
108 : : ! reciprocal of equivalent supercell lattice vectors for full kpoint grid
109 : :
110 : : type(htetra_bucket),allocatable :: ibz(:)
111 : : ! indexes of the tetrahedra for each k-point
112 : :
113 : : type(htetra_bucket),allocatable :: unique_tetra(:)
114 : : ! indexes of the unique tetrahedra
115 : :
116 : : contains
117 : :
118 : : procedure :: init => htetra_init ! Initialize the object
119 : :
120 : : procedure :: free => htetra_free
121 : : ! Free memory
122 : :
123 : : procedure :: print => htetra_print
124 : : ! Print information about tetrahedron object
125 : :
126 : : procedure :: get_onewk => htetra_get_onewk
127 : : ! Calculate integration weights and their derivatives for a single k-point in the IBZ.
128 : :
129 : : procedure :: get_onewk_wvals => htetra_get_onewk_wvals
130 : : ! Similar to tetra_get_onewk but receives arbitrary list of frequency points.
131 : :
132 : : procedure :: get_onewk_wvals_zinv => htetra_get_onewk_wvals_zinv
133 : : ! Calculate integration weights for 1/(z-E(k)) for a single k-point in the IBZ.
134 : :
135 : : procedure :: weights_wvals_zinv => htetra_weights_wvals_zinv
136 : : ! Same as above but return the weight on all the kpoints by looping over tetrahedra
137 : :
138 : : procedure :: wvals_weights => htetra_wvals_weights
139 : : ! Compute delta and theta on a list of energies for all kpoints
140 : :
141 : : procedure :: wvals_weights_delta => htetra_wvals_weights_delta
142 : : ! Compute delta on a list of energies for all kpoints
143 : :
144 : : procedure :: blochl_weights => htetra_blochl_weights
145 : : ! And interface to help to facilitate the transition to the new tetrahedron implementation
146 : :
147 : : end type htetra_t
148 : : !!***
149 : :
150 : : !!***
151 : :
152 : : contains
153 : : !!***
154 : :
155 : : !----------------------------------------------------------------------
156 : :
157 : : !!****f* m_htetra/htetra_init
158 : : !! NAME
159 : : !! htetra_init
160 : : !!
161 : : !! FUNCTION
162 : : !! get tetrahedra characterized by apexes
163 : : !!
164 : : !! INPUTS
165 : : !! bz2ibz(nkpt_fullbz)=indexes of irred kpoints equivalent to kpt_fullbz
166 : : !! gprimd(3,3) = reciprocal space vectors
167 : : !! klatt(3,3)=reciprocal of lattice vectors for full kpoint grid
168 : : !! kpt_fullbz(3,nkpt_fullbz)=kpoints in full brillouin zone
169 : : !! nkpt_fullbz=number of kpoints in full brillouin zone
170 : : !! options=1.generate 24 tetrahedra per k-point
171 : : !! faster but gives different results depending on the IBZ, small error for large grids
172 : : !! 2.generate tetrahedra on the FBZ and map to IBZ
173 : : !! slower but same results for IBZ and FBZ.
174 : : !! comm= MPI communicator
175 : : !! [opt]= 1 for Togo's version, 2 for Blochl's version (default)
176 : : !!
177 : : !! OUTPUT
178 : : !! tetra%ibz(4,24,nkibz)=for each k-point, the indexes in the IBZ
179 : : !! tetra%vv = tetrahedron volume divided by full BZ volume
180 : : !!
181 : : !! SOURCE
182 : :
183 : 486 : subroutine htetra_init(tetra, bz2ibz, gprimd, klatt, kpt_fullbz, nkpt_fullbz, kpt_ibz, nkpt_ibz, &
184 : : ierr, errorstring, comm, &
185 : : opt) ! optional
186 : :
187 : : !Arguments ------------------------------------
188 : : !scalars
189 : : class(htetra_t),intent(out),target :: tetra
190 : : integer,intent(in) :: nkpt_fullbz, nkpt_ibz, comm
191 : : integer,optional,intent(in) :: opt
192 : : integer,intent(out) :: ierr
193 : : character(len=80),intent(out) :: errorstring
194 : : !arrays
195 : : integer,intent(in) :: bz2ibz(nkpt_fullbz)
196 : : real(dp),intent(in) :: gprimd(3,3),klatt(3,3),kpt_fullbz(3,nkpt_fullbz),kpt_ibz(3,nkpt_ibz)
197 : :
198 : : !Local variables-------------------------------
199 : : !scalars
200 : : !type(octree_t) :: oct
201 : 243 : type(krank_t) :: krank
202 : : integer :: ikpt2,isummit,itetra,jtetra
203 : : integer :: ikibz,ikbz,idiag,ihash,min_idiag,my_rank,nprocs
204 : : integer :: max_ntetra, ntetra
205 : : real(dp) :: rcvol,length,min_length
206 : : !arrays
207 [ + - ]: 243 : integer,allocatable,target :: indexes(:,:), tetra_hash_count(:)
208 : : integer :: tetra_ibz(4)
209 : : integer :: tetra_shifts(3,4,24,4) ! 3 dimensions, 4 summits, 24 tetrahedra, 4 main diagonals
210 : : integer :: tetra_shifts_6(3,4,6,1) ! 3 dimensions, 4 summits, 6 tetrahedra, 4 main diagonals
211 : : integer :: main_diagonals(3,4), tetra_mibz(0:4)
212 : : real(dp) :: k1(3),k2(3),k3(3),diag(3)
213 : : ! *********************************************************************
214 : :
215 : : ! Use the shifts from kpclib developed by Atsushi Togo
216 : : ! This part is produced by a python script
217 : : ! This implementation is based on spglib and kpclib by Atsushi Togo
218 : : ! after a discussion with hin on the APS 2019 where he provided
219 : : ! details of his implementation.
220 : : ! Note that we don't use it in production as we found that is approach, although faster than the original
221 : : ! one proposed by Blochl (and implemented by MJV) does not preserve symmetries that is calculations done on the full BZ
222 : : ! and the IBZ do not produce the same result. The diff, however, decreases if the sampling is densified.
223 : :
224 [ + + ]: 972 : tetra_shifts(:, 1, 1,1) = [ 0, 0, 0]
225 [ + + ]: 972 : tetra_shifts(:, 2, 1,1) = [ 1, 0, 0]
226 [ + + ]: 972 : tetra_shifts(:, 3, 1,1) = [ 1, 1, 0]
227 [ + + ]: 972 : tetra_shifts(:, 4, 1,1) = [ 1, 1, 1]
228 [ + + ]: 972 : tetra_shifts(:, 1, 2,1) = [ 0, 0, 0]
229 [ + + ]: 972 : tetra_shifts(:, 2, 2,1) = [ 1, 0, 0]
230 [ + + ]: 972 : tetra_shifts(:, 3, 2,1) = [ 1, 0, 1]
231 [ + + ]: 972 : tetra_shifts(:, 4, 2,1) = [ 1, 1, 1]
232 [ + + ]: 972 : tetra_shifts(:, 1, 3,1) = [ 0, 0, 0]
233 [ + + ]: 972 : tetra_shifts(:, 2, 3,1) = [ 0, 1, 0]
234 [ + + ]: 972 : tetra_shifts(:, 3, 3,1) = [ 1, 1, 0]
235 [ + + ]: 972 : tetra_shifts(:, 4, 3,1) = [ 1, 1, 1]
236 [ + + ]: 972 : tetra_shifts(:, 1, 4,1) = [ 0, 0, 0]
237 [ + + ]: 972 : tetra_shifts(:, 2, 4,1) = [ 0, 1, 0]
238 [ + + ]: 972 : tetra_shifts(:, 3, 4,1) = [ 0, 1, 1]
239 [ + + ]: 972 : tetra_shifts(:, 4, 4,1) = [ 1, 1, 1]
240 [ + + ]: 972 : tetra_shifts(:, 1, 5,1) = [ 0, 0, 0]
241 [ + + ]: 972 : tetra_shifts(:, 2, 5,1) = [ 0, 0, 1]
242 [ + + ]: 972 : tetra_shifts(:, 3, 5,1) = [ 1, 0, 1]
243 [ + + ]: 972 : tetra_shifts(:, 4, 5,1) = [ 1, 1, 1]
244 [ + + ]: 972 : tetra_shifts(:, 1, 6,1) = [ 0, 0, 0]
245 [ + + ]: 972 : tetra_shifts(:, 2, 6,1) = [ 0, 0, 1]
246 [ + + ]: 972 : tetra_shifts(:, 3, 6,1) = [ 0, 1, 1]
247 [ + + ]: 972 : tetra_shifts(:, 4, 6,1) = [ 1, 1, 1]
248 [ + + ]: 972 : tetra_shifts(:, 1, 7,1) = [ 0, 0, 0]
249 [ + + ]: 972 : tetra_shifts(:, 2, 7,1) = [ 0, 1, 0]
250 [ + + ]: 972 : tetra_shifts(:, 3, 7,1) = [ 0, 1, 1]
251 [ + + ]: 972 : tetra_shifts(:, 4, 7,1) = [ -1, 0, 0]
252 [ + + ]: 972 : tetra_shifts(:, 1, 8,1) = [ 0, 0, 0]
253 [ + + ]: 972 : tetra_shifts(:, 2, 8,1) = [ 0, 0, 1]
254 [ + + ]: 972 : tetra_shifts(:, 3, 8,1) = [ 0, 1, 1]
255 [ + + ]: 972 : tetra_shifts(:, 4, 8,1) = [ -1, 0, 0]
256 [ + + ]: 972 : tetra_shifts(:, 1, 9,1) = [ 0, 0, 0]
257 [ + + ]: 972 : tetra_shifts(:, 2, 9,1) = [ 1, 0, 0]
258 [ + + ]: 972 : tetra_shifts(:, 3, 9,1) = [ 1, 0, 1]
259 [ + + ]: 972 : tetra_shifts(:, 4, 9,1) = [ 0, -1, 0]
260 [ + + ]: 972 : tetra_shifts(:, 1,10,1) = [ 0, 0, 0]
261 [ + + ]: 972 : tetra_shifts(:, 2,10,1) = [ 0, 0, 1]
262 [ + + ]: 972 : tetra_shifts(:, 3,10,1) = [ 1, 0, 1]
263 [ + + ]: 972 : tetra_shifts(:, 4,10,1) = [ 0, -1, 0]
264 [ + + ]: 972 : tetra_shifts(:, 1,11,1) = [ 0, 0, 0]
265 [ + + ]: 972 : tetra_shifts(:, 2,11,1) = [ 0, 0, 1]
266 [ + + ]: 972 : tetra_shifts(:, 3,11,1) = [ -1, -1, 0]
267 [ + + ]: 972 : tetra_shifts(:, 4,11,1) = [ 0, -1, 0]
268 [ + + ]: 972 : tetra_shifts(:, 1,12,1) = [ 0, 0, 0]
269 [ + + ]: 972 : tetra_shifts(:, 2,12,1) = [ 0, 0, 1]
270 [ + + ]: 972 : tetra_shifts(:, 3,12,1) = [ -1, -1, 0]
271 [ + + ]: 972 : tetra_shifts(:, 4,12,1) = [ -1, 0, 0]
272 [ + + ]: 972 : tetra_shifts(:, 1,13,1) = [ 0, 0, 0]
273 [ + + ]: 972 : tetra_shifts(:, 2,13,1) = [ 1, 0, 0]
274 [ + + ]: 972 : tetra_shifts(:, 3,13,1) = [ 1, 1, 0]
275 [ + + ]: 972 : tetra_shifts(:, 4,13,1) = [ 0, 0, -1]
276 [ + + ]: 972 : tetra_shifts(:, 1,14,1) = [ 0, 0, 0]
277 [ + + ]: 972 : tetra_shifts(:, 2,14,1) = [ 0, 1, 0]
278 [ + + ]: 972 : tetra_shifts(:, 3,14,1) = [ 1, 1, 0]
279 [ + + ]: 972 : tetra_shifts(:, 4,14,1) = [ 0, 0, -1]
280 [ + + ]: 972 : tetra_shifts(:, 1,15,1) = [ 0, 0, 0]
281 [ + + ]: 972 : tetra_shifts(:, 2,15,1) = [ 0, 1, 0]
282 [ + + ]: 972 : tetra_shifts(:, 3,15,1) = [ -1, 0, -1]
283 [ + + ]: 972 : tetra_shifts(:, 4,15,1) = [ 0, 0, -1]
284 [ + + ]: 972 : tetra_shifts(:, 1,16,1) = [ 0, 0, 0]
285 [ + + ]: 972 : tetra_shifts(:, 2,16,1) = [ 0, 1, 0]
286 [ + + ]: 972 : tetra_shifts(:, 3,16,1) = [ -1, 0, -1]
287 [ + + ]: 972 : tetra_shifts(:, 4,16,1) = [ -1, 0, 0]
288 [ + + ]: 972 : tetra_shifts(:, 1,17,1) = [ 0, 0, 0]
289 [ + + ]: 972 : tetra_shifts(:, 2,17,1) = [ 1, 0, 0]
290 [ + + ]: 972 : tetra_shifts(:, 3,17,1) = [ 0, -1, -1]
291 [ + + ]: 972 : tetra_shifts(:, 4,17,1) = [ 0, 0, -1]
292 [ + + ]: 972 : tetra_shifts(:, 1,18,1) = [ 0, 0, 0]
293 [ + + ]: 972 : tetra_shifts(:, 2,18,1) = [ 1, 0, 0]
294 [ + + ]: 972 : tetra_shifts(:, 3,18,1) = [ 0, -1, -1]
295 [ + + ]: 972 : tetra_shifts(:, 4,18,1) = [ 0, -1, 0]
296 [ + + ]: 972 : tetra_shifts(:, 1,19,1) = [ 0, 0, 0]
297 [ + + ]: 972 : tetra_shifts(:, 2,19,1) = [ -1, -1, -1]
298 [ + + ]: 972 : tetra_shifts(:, 3,19,1) = [ 0, -1, -1]
299 [ + + ]: 972 : tetra_shifts(:, 4,19,1) = [ 0, 0, -1]
300 [ + + ]: 972 : tetra_shifts(:, 1,20,1) = [ 0, 0, 0]
301 [ + + ]: 972 : tetra_shifts(:, 2,20,1) = [ -1, -1, -1]
302 [ + + ]: 972 : tetra_shifts(:, 3,20,1) = [ 0, -1, -1]
303 [ + + ]: 972 : tetra_shifts(:, 4,20,1) = [ 0, -1, 0]
304 [ + + ]: 972 : tetra_shifts(:, 1,21,1) = [ 0, 0, 0]
305 [ + + ]: 972 : tetra_shifts(:, 2,21,1) = [ -1, -1, -1]
306 [ + + ]: 972 : tetra_shifts(:, 3,21,1) = [ -1, 0, -1]
307 [ + + ]: 972 : tetra_shifts(:, 4,21,1) = [ 0, 0, -1]
308 [ + + ]: 972 : tetra_shifts(:, 1,22,1) = [ 0, 0, 0]
309 [ + + ]: 972 : tetra_shifts(:, 2,22,1) = [ -1, -1, -1]
310 [ + + ]: 972 : tetra_shifts(:, 3,22,1) = [ -1, 0, -1]
311 [ + + ]: 972 : tetra_shifts(:, 4,22,1) = [ -1, 0, 0]
312 [ + + ]: 972 : tetra_shifts(:, 1,23,1) = [ 0, 0, 0]
313 [ + + ]: 972 : tetra_shifts(:, 2,23,1) = [ -1, -1, -1]
314 [ + + ]: 972 : tetra_shifts(:, 3,23,1) = [ -1, -1, 0]
315 [ + + ]: 972 : tetra_shifts(:, 4,23,1) = [ 0, -1, 0]
316 [ + + ]: 972 : tetra_shifts(:, 1,24,1) = [ 0, 0, 0]
317 [ + + ]: 972 : tetra_shifts(:, 2,24,1) = [ -1, -1, -1]
318 [ + + ]: 972 : tetra_shifts(:, 3,24,1) = [ -1, -1, 0]
319 [ + + ]: 972 : tetra_shifts(:, 4,24,1) = [ -1, 0, 0]
320 [ + + ]: 972 : tetra_shifts(:, 1, 1,2) = [ 0, 0, 0]
321 [ + + ]: 972 : tetra_shifts(:, 2, 1,2) = [ 1, 0, 0]
322 [ + + ]: 972 : tetra_shifts(:, 3, 1,2) = [ 0, 1, 0]
323 [ + + ]: 972 : tetra_shifts(:, 4, 1,2) = [ 0, 1, 1]
324 [ + + ]: 972 : tetra_shifts(:, 1, 2,2) = [ 0, 0, 0]
325 [ + + ]: 972 : tetra_shifts(:, 2, 2,2) = [ 1, 0, 0]
326 [ + + ]: 972 : tetra_shifts(:, 3, 2,2) = [ 0, 0, 1]
327 [ + + ]: 972 : tetra_shifts(:, 4, 2,2) = [ 0, 1, 1]
328 [ + + ]: 972 : tetra_shifts(:, 1, 3,2) = [ 0, 0, 0]
329 [ + + ]: 972 : tetra_shifts(:, 2, 3,2) = [ -1, 1, 0]
330 [ + + ]: 972 : tetra_shifts(:, 3, 3,2) = [ -1, 1, 1]
331 [ + + ]: 972 : tetra_shifts(:, 4, 3,2) = [ -1, 0, 0]
332 [ + + ]: 972 : tetra_shifts(:, 1, 4,2) = [ 0, 0, 0]
333 [ + + ]: 972 : tetra_shifts(:, 2, 4,2) = [ -1, 0, 1]
334 [ + + ]: 972 : tetra_shifts(:, 3, 4,2) = [ -1, 1, 1]
335 [ + + ]: 972 : tetra_shifts(:, 4, 4,2) = [ -1, 0, 0]
336 [ + + ]: 972 : tetra_shifts(:, 1, 5,2) = [ 0, 0, 0]
337 [ + + ]: 972 : tetra_shifts(:, 2, 5,2) = [ -1, 1, 0]
338 [ + + ]: 972 : tetra_shifts(:, 3, 5,2) = [ 0, 1, 0]
339 [ + + ]: 972 : tetra_shifts(:, 4, 5,2) = [ -1, 1, 1]
340 [ + + ]: 972 : tetra_shifts(:, 1, 6,2) = [ 0, 0, 0]
341 [ + + ]: 972 : tetra_shifts(:, 2, 6,2) = [ 0, 1, 0]
342 [ + + ]: 972 : tetra_shifts(:, 3, 6,2) = [ -1, 1, 1]
343 [ + + ]: 972 : tetra_shifts(:, 4, 6,2) = [ 0, 1, 1]
344 [ + + ]: 972 : tetra_shifts(:, 1, 7,2) = [ 0, 0, 0]
345 [ + + ]: 972 : tetra_shifts(:, 2, 7,2) = [ -1, 0, 1]
346 [ + + ]: 972 : tetra_shifts(:, 3, 7,2) = [ 0, 0, 1]
347 [ + + ]: 972 : tetra_shifts(:, 4, 7,2) = [ -1, 1, 1]
348 [ + + ]: 972 : tetra_shifts(:, 1, 8,2) = [ 0, 0, 0]
349 [ + + ]: 972 : tetra_shifts(:, 2, 8,2) = [ 0, 0, 1]
350 [ + + ]: 972 : tetra_shifts(:, 3, 8,2) = [ -1, 1, 1]
351 [ + + ]: 972 : tetra_shifts(:, 4, 8,2) = [ 0, 1, 1]
352 [ + + ]: 972 : tetra_shifts(:, 1, 9,2) = [ 0, 0, 0]
353 [ + + ]: 972 : tetra_shifts(:, 2, 9,2) = [ 0, 0, 1]
354 [ + + ]: 972 : tetra_shifts(:, 3, 9,2) = [ 0, -1, 0]
355 [ + + ]: 972 : tetra_shifts(:, 4, 9,2) = [ 1, -1, 0]
356 [ + + ]: 972 : tetra_shifts(:, 1,10,2) = [ 0, 0, 0]
357 [ + + ]: 972 : tetra_shifts(:, 2,10,2) = [ 1, 0, 0]
358 [ + + ]: 972 : tetra_shifts(:, 3,10,2) = [ 0, 0, 1]
359 [ + + ]: 972 : tetra_shifts(:, 4,10,2) = [ 1, -1, 0]
360 [ + + ]: 972 : tetra_shifts(:, 1,11,2) = [ 0, 0, 0]
361 [ + + ]: 972 : tetra_shifts(:, 2,11,2) = [ -1, 0, 1]
362 [ + + ]: 972 : tetra_shifts(:, 3,11,2) = [ 0, -1, 0]
363 [ + + ]: 972 : tetra_shifts(:, 4,11,2) = [ -1, 0, 0]
364 [ + + ]: 972 : tetra_shifts(:, 1,12,2) = [ 0, 0, 0]
365 [ + + ]: 972 : tetra_shifts(:, 2,12,2) = [ -1, 0, 1]
366 [ + + ]: 972 : tetra_shifts(:, 3,12,2) = [ 0, 0, 1]
367 [ + + ]: 972 : tetra_shifts(:, 4,12,2) = [ 0, -1, 0]
368 [ + + ]: 972 : tetra_shifts(:, 1,13,2) = [ 0, 0, 0]
369 [ + + ]: 972 : tetra_shifts(:, 2,13,2) = [ 0, 1, 0]
370 [ + + ]: 972 : tetra_shifts(:, 3,13,2) = [ 0, 0, -1]
371 [ + + ]: 972 : tetra_shifts(:, 4,13,2) = [ 1, 0, -1]
372 [ + + ]: 972 : tetra_shifts(:, 1,14,2) = [ 0, 0, 0]
373 [ + + ]: 972 : tetra_shifts(:, 2,14,2) = [ 1, 0, 0]
374 [ + + ]: 972 : tetra_shifts(:, 3,14,2) = [ 0, 1, 0]
375 [ + + ]: 972 : tetra_shifts(:, 4,14,2) = [ 1, 0, -1]
376 [ + + ]: 972 : tetra_shifts(:, 1,15,2) = [ 0, 0, 0]
377 [ + + ]: 972 : tetra_shifts(:, 2,15,2) = [ -1, 1, 0]
378 [ + + ]: 972 : tetra_shifts(:, 3,15,2) = [ 0, 0, -1]
379 [ + + ]: 972 : tetra_shifts(:, 4,15,2) = [ -1, 0, 0]
380 [ + + ]: 972 : tetra_shifts(:, 1,16,2) = [ 0, 0, 0]
381 [ + + ]: 972 : tetra_shifts(:, 2,16,2) = [ -1, 1, 0]
382 [ + + ]: 972 : tetra_shifts(:, 3,16,2) = [ 0, 1, 0]
383 [ + + ]: 972 : tetra_shifts(:, 4,16,2) = [ 0, 0, -1]
384 [ + + ]: 972 : tetra_shifts(:, 1,17,2) = [ 0, 0, 0]
385 [ + + ]: 972 : tetra_shifts(:, 2,17,2) = [ 0, -1, -1]
386 [ + + ]: 972 : tetra_shifts(:, 3,17,2) = [ 1, -1, -1]
387 [ + + ]: 972 : tetra_shifts(:, 4,17,2) = [ 0, 0, -1]
388 [ + + ]: 972 : tetra_shifts(:, 1,18,2) = [ 0, 0, 0]
389 [ + + ]: 972 : tetra_shifts(:, 2,18,2) = [ 0, -1, -1]
390 [ + + ]: 972 : tetra_shifts(:, 3,18,2) = [ 1, -1, -1]
391 [ + + ]: 972 : tetra_shifts(:, 4,18,2) = [ 0, -1, 0]
392 [ + + ]: 972 : tetra_shifts(:, 1,19,2) = [ 0, 0, 0]
393 [ + + ]: 972 : tetra_shifts(:, 2,19,2) = [ 1, -1, -1]
394 [ + + ]: 972 : tetra_shifts(:, 3,19,2) = [ 0, 0, -1]
395 [ + + ]: 972 : tetra_shifts(:, 4,19,2) = [ 1, 0, -1]
396 [ + + ]: 972 : tetra_shifts(:, 1,20,2) = [ 0, 0, 0]
397 [ + + ]: 972 : tetra_shifts(:, 2,20,2) = [ 1, 0, 0]
398 [ + + ]: 972 : tetra_shifts(:, 3,20,2) = [ 1, -1, -1]
399 [ + + ]: 972 : tetra_shifts(:, 4,20,2) = [ 1, 0, -1]
400 [ + + ]: 972 : tetra_shifts(:, 1,21,2) = [ 0, 0, 0]
401 [ + + ]: 972 : tetra_shifts(:, 2,21,2) = [ 1, -1, -1]
402 [ + + ]: 972 : tetra_shifts(:, 3,21,2) = [ 0, -1, 0]
403 [ + + ]: 972 : tetra_shifts(:, 4,21,2) = [ 1, -1, 0]
404 [ + + ]: 972 : tetra_shifts(:, 1,22,2) = [ 0, 0, 0]
405 [ + + ]: 972 : tetra_shifts(:, 2,22,2) = [ 1, 0, 0]
406 [ + + ]: 972 : tetra_shifts(:, 3,22,2) = [ 1, -1, -1]
407 [ + + ]: 972 : tetra_shifts(:, 4,22,2) = [ 1, -1, 0]
408 [ + + ]: 972 : tetra_shifts(:, 1,23,2) = [ 0, 0, 0]
409 [ + + ]: 972 : tetra_shifts(:, 2,23,2) = [ 0, -1, -1]
410 [ + + ]: 972 : tetra_shifts(:, 3,23,2) = [ 0, 0, -1]
411 [ + + ]: 972 : tetra_shifts(:, 4,23,2) = [ -1, 0, 0]
412 [ + + ]: 972 : tetra_shifts(:, 1,24,2) = [ 0, 0, 0]
413 [ + + ]: 972 : tetra_shifts(:, 2,24,2) = [ 0, -1, -1]
414 [ + + ]: 972 : tetra_shifts(:, 3,24,2) = [ 0, -1, 0]
415 [ + + ]: 972 : tetra_shifts(:, 4,24,2) = [ -1, 0, 0]
416 [ + + ]: 972 : tetra_shifts(:, 1, 1,3) = [ 0, 0, 0]
417 [ + + ]: 972 : tetra_shifts(:, 2, 1,3) = [ 1, 0, 0]
418 [ + + ]: 972 : tetra_shifts(:, 3, 1,3) = [ 0, 1, 0]
419 [ + + ]: 972 : tetra_shifts(:, 4, 1,3) = [ 1, 0, 1]
420 [ + + ]: 972 : tetra_shifts(:, 1, 2,3) = [ 0, 0, 0]
421 [ + + ]: 972 : tetra_shifts(:, 2, 2,3) = [ 0, 1, 0]
422 [ + + ]: 972 : tetra_shifts(:, 3, 2,3) = [ 0, 0, 1]
423 [ + + ]: 972 : tetra_shifts(:, 4, 2,3) = [ 1, 0, 1]
424 [ + + ]: 972 : tetra_shifts(:, 1, 3,3) = [ 0, 0, 0]
425 [ + + ]: 972 : tetra_shifts(:, 2, 3,3) = [ -1, 1, 0]
426 [ + + ]: 972 : tetra_shifts(:, 3, 3,3) = [ 0, 0, 1]
427 [ + + ]: 972 : tetra_shifts(:, 4, 3,3) = [ -1, 0, 0]
428 [ + + ]: 972 : tetra_shifts(:, 1, 4,3) = [ 0, 0, 0]
429 [ + + ]: 972 : tetra_shifts(:, 2, 4,3) = [ -1, 1, 0]
430 [ + + ]: 972 : tetra_shifts(:, 3, 4,3) = [ 0, 1, 0]
431 [ + + ]: 972 : tetra_shifts(:, 4, 4,3) = [ 0, 0, 1]
432 [ + + ]: 972 : tetra_shifts(:, 1, 5,3) = [ 0, 0, 0]
433 [ + + ]: 972 : tetra_shifts(:, 2, 5,3) = [ 1, -1, 1]
434 [ + + ]: 972 : tetra_shifts(:, 3, 5,3) = [ 0, -1, 0]
435 [ + + ]: 972 : tetra_shifts(:, 4, 5,3) = [ 1, -1, 0]
436 [ + + ]: 972 : tetra_shifts(:, 1, 6,3) = [ 0, 0, 0]
437 [ + + ]: 972 : tetra_shifts(:, 2, 6,3) = [ 0, -1, 1]
438 [ + + ]: 972 : tetra_shifts(:, 3, 6,3) = [ 1, -1, 1]
439 [ + + ]: 972 : tetra_shifts(:, 4, 6,3) = [ 0, -1, 0]
440 [ + + ]: 972 : tetra_shifts(:, 1, 7,3) = [ 0, 0, 0]
441 [ + + ]: 972 : tetra_shifts(:, 2, 7,3) = [ 1, 0, 0]
442 [ + + ]: 972 : tetra_shifts(:, 3, 7,3) = [ 1, -1, 1]
443 [ + + ]: 972 : tetra_shifts(:, 4, 7,3) = [ 1, -1, 0]
444 [ + + ]: 972 : tetra_shifts(:, 1, 8,3) = [ 0, 0, 0]
445 [ + + ]: 972 : tetra_shifts(:, 2, 8,3) = [ 1, 0, 0]
446 [ + + ]: 972 : tetra_shifts(:, 3, 8,3) = [ 1, -1, 1]
447 [ + + ]: 972 : tetra_shifts(:, 4, 8,3) = [ 1, 0, 1]
448 [ + + ]: 972 : tetra_shifts(:, 1, 9,3) = [ 0, 0, 0]
449 [ + + ]: 972 : tetra_shifts(:, 2, 9,3) = [ 0, -1, 1]
450 [ + + ]: 972 : tetra_shifts(:, 3, 9,3) = [ 1, -1, 1]
451 [ + + ]: 972 : tetra_shifts(:, 4, 9,3) = [ 0, 0, 1]
452 [ + + ]: 972 : tetra_shifts(:, 1,10,3) = [ 0, 0, 0]
453 [ + + ]: 972 : tetra_shifts(:, 2,10,3) = [ 1, -1, 1]
454 [ + + ]: 972 : tetra_shifts(:, 3,10,3) = [ 0, 0, 1]
455 [ + + ]: 972 : tetra_shifts(:, 4,10,3) = [ 1, 0, 1]
456 [ + + ]: 972 : tetra_shifts(:, 1,11,3) = [ 0, 0, 0]
457 [ + + ]: 972 : tetra_shifts(:, 2,11,3) = [ 0, -1, 1]
458 [ + + ]: 972 : tetra_shifts(:, 3,11,3) = [ 0, -1, 0]
459 [ + + ]: 972 : tetra_shifts(:, 4,11,3) = [ -1, 0, 0]
460 [ + + ]: 972 : tetra_shifts(:, 1,12,3) = [ 0, 0, 0]
461 [ + + ]: 972 : tetra_shifts(:, 2,12,3) = [ 0, -1, 1]
462 [ + + ]: 972 : tetra_shifts(:, 3,12,3) = [ 0, 0, 1]
463 [ + + ]: 972 : tetra_shifts(:, 4,12,3) = [ -1, 0, 0]
464 [ + + ]: 972 : tetra_shifts(:, 1,13,3) = [ 0, 0, 0]
465 [ + + ]: 972 : tetra_shifts(:, 2,13,3) = [ 1, 0, 0]
466 [ + + ]: 972 : tetra_shifts(:, 3,13,3) = [ 0, 0, -1]
467 [ + + ]: 972 : tetra_shifts(:, 4,13,3) = [ 0, 1, -1]
468 [ + + ]: 972 : tetra_shifts(:, 1,14,3) = [ 0, 0, 0]
469 [ + + ]: 972 : tetra_shifts(:, 2,14,3) = [ 1, 0, 0]
470 [ + + ]: 972 : tetra_shifts(:, 3,14,3) = [ 0, 1, 0]
471 [ + + ]: 972 : tetra_shifts(:, 4,14,3) = [ 0, 1, -1]
472 [ + + ]: 972 : tetra_shifts(:, 1,15,3) = [ 0, 0, 0]
473 [ + + ]: 972 : tetra_shifts(:, 2,15,3) = [ -1, 0, -1]
474 [ + + ]: 972 : tetra_shifts(:, 3,15,3) = [ 0, 0, -1]
475 [ + + ]: 972 : tetra_shifts(:, 4,15,3) = [ -1, 1, -1]
476 [ + + ]: 972 : tetra_shifts(:, 1,16,3) = [ 0, 0, 0]
477 [ + + ]: 972 : tetra_shifts(:, 2,16,3) = [ -1, 0, -1]
478 [ + + ]: 972 : tetra_shifts(:, 3,16,3) = [ -1, 1, -1]
479 [ + + ]: 972 : tetra_shifts(:, 4,16,3) = [ -1, 0, 0]
480 [ + + ]: 972 : tetra_shifts(:, 1,17,3) = [ 0, 0, 0]
481 [ + + ]: 972 : tetra_shifts(:, 2,17,3) = [ 0, 0, -1]
482 [ + + ]: 972 : tetra_shifts(:, 3,17,3) = [ -1, 1, -1]
483 [ + + ]: 972 : tetra_shifts(:, 4,17,3) = [ 0, 1, -1]
484 [ + + ]: 972 : tetra_shifts(:, 1,18,3) = [ 0, 0, 0]
485 [ + + ]: 972 : tetra_shifts(:, 2,18,3) = [ 0, 1, 0]
486 [ + + ]: 972 : tetra_shifts(:, 3,18,3) = [ -1, 1, -1]
487 [ + + ]: 972 : tetra_shifts(:, 4,18,3) = [ 0, 1, -1]
488 [ + + ]: 972 : tetra_shifts(:, 1,19,3) = [ 0, 0, 0]
489 [ + + ]: 972 : tetra_shifts(:, 2,19,3) = [ -1, 1, 0]
490 [ + + ]: 972 : tetra_shifts(:, 3,19,3) = [ -1, 1, -1]
491 [ + + ]: 972 : tetra_shifts(:, 4,19,3) = [ -1, 0, 0]
492 [ + + ]: 972 : tetra_shifts(:, 1,20,3) = [ 0, 0, 0]
493 [ + + ]: 972 : tetra_shifts(:, 2,20,3) = [ -1, 1, 0]
494 [ + + ]: 972 : tetra_shifts(:, 3,20,3) = [ 0, 1, 0]
495 [ + + ]: 972 : tetra_shifts(:, 4,20,3) = [ -1, 1, -1]
496 [ + + ]: 972 : tetra_shifts(:, 1,21,3) = [ 0, 0, 0]
497 [ + + ]: 972 : tetra_shifts(:, 2,21,3) = [ 0, 0, -1]
498 [ + + ]: 972 : tetra_shifts(:, 3,21,3) = [ 0, -1, 0]
499 [ + + ]: 972 : tetra_shifts(:, 4,21,3) = [ 1, -1, 0]
500 [ + + ]: 972 : tetra_shifts(:, 1,22,3) = [ 0, 0, 0]
501 [ + + ]: 972 : tetra_shifts(:, 2,22,3) = [ 1, 0, 0]
502 [ + + ]: 972 : tetra_shifts(:, 3,22,3) = [ 0, 0, -1]
503 [ + + ]: 972 : tetra_shifts(:, 4,22,3) = [ 1, -1, 0]
504 [ + + ]: 972 : tetra_shifts(:, 1,23,3) = [ 0, 0, 0]
505 [ + + ]: 972 : tetra_shifts(:, 2,23,3) = [ -1, 0, -1]
506 [ + + ]: 972 : tetra_shifts(:, 3,23,3) = [ 0, 0, -1]
507 [ + + ]: 972 : tetra_shifts(:, 4,23,3) = [ 0, -1, 0]
508 [ + + ]: 972 : tetra_shifts(:, 1,24,3) = [ 0, 0, 0]
509 [ + + ]: 972 : tetra_shifts(:, 2,24,3) = [ -1, 0, -1]
510 [ + + ]: 972 : tetra_shifts(:, 3,24,3) = [ 0, -1, 0]
511 [ + + ]: 972 : tetra_shifts(:, 4,24,3) = [ -1, 0, 0]
512 [ + + ]: 972 : tetra_shifts(:, 1, 1,4) = [ 0, 0, 0]
513 [ + + ]: 972 : tetra_shifts(:, 2, 1,4) = [ 1, 0, 0]
514 [ + + ]: 972 : tetra_shifts(:, 3, 1,4) = [ 1, 1, 0]
515 [ + + ]: 972 : tetra_shifts(:, 4, 1,4) = [ 0, 0, 1]
516 [ + + ]: 972 : tetra_shifts(:, 1, 2,4) = [ 0, 0, 0]
517 [ + + ]: 972 : tetra_shifts(:, 2, 2,4) = [ 0, 1, 0]
518 [ + + ]: 972 : tetra_shifts(:, 3, 2,4) = [ 1, 1, 0]
519 [ + + ]: 972 : tetra_shifts(:, 4, 2,4) = [ 0, 0, 1]
520 [ + + ]: 972 : tetra_shifts(:, 1, 3,4) = [ 0, 0, 0]
521 [ + + ]: 972 : tetra_shifts(:, 2, 3,4) = [ 0, 1, 0]
522 [ + + ]: 972 : tetra_shifts(:, 3, 3,4) = [ -1, 0, 1]
523 [ + + ]: 972 : tetra_shifts(:, 4, 3,4) = [ -1, 0, 0]
524 [ + + ]: 972 : tetra_shifts(:, 1, 4,4) = [ 0, 0, 0]
525 [ + + ]: 972 : tetra_shifts(:, 2, 4,4) = [ 0, 1, 0]
526 [ + + ]: 972 : tetra_shifts(:, 3, 4,4) = [ -1, 0, 1]
527 [ + + ]: 972 : tetra_shifts(:, 4, 4,4) = [ 0, 0, 1]
528 [ + + ]: 972 : tetra_shifts(:, 1, 5,4) = [ 0, 0, 0]
529 [ + + ]: 972 : tetra_shifts(:, 2, 5,4) = [ 1, 0, 0]
530 [ + + ]: 972 : tetra_shifts(:, 3, 5,4) = [ 0, -1, 1]
531 [ + + ]: 972 : tetra_shifts(:, 4, 5,4) = [ 0, -1, 0]
532 [ + + ]: 972 : tetra_shifts(:, 1, 6,4) = [ 0, 0, 0]
533 [ + + ]: 972 : tetra_shifts(:, 2, 6,4) = [ 1, 0, 0]
534 [ + + ]: 972 : tetra_shifts(:, 3, 6,4) = [ 0, -1, 1]
535 [ + + ]: 972 : tetra_shifts(:, 4, 6,4) = [ 0, 0, 1]
536 [ + + ]: 972 : tetra_shifts(:, 1, 7,4) = [ 0, 0, 0]
537 [ + + ]: 972 : tetra_shifts(:, 2, 7,4) = [ -1, -1, 1]
538 [ + + ]: 972 : tetra_shifts(:, 3, 7,4) = [ -1, -1, 0]
539 [ + + ]: 972 : tetra_shifts(:, 4, 7,4) = [ 0, -1, 0]
540 [ + + ]: 972 : tetra_shifts(:, 1, 8,4) = [ 0, 0, 0]
541 [ + + ]: 972 : tetra_shifts(:, 2, 8,4) = [ -1, -1, 1]
542 [ + + ]: 972 : tetra_shifts(:, 3, 8,4) = [ -1, -1, 0]
543 [ + + ]: 972 : tetra_shifts(:, 4, 8,4) = [ -1, 0, 0]
544 [ + + ]: 972 : tetra_shifts(:, 1, 9,4) = [ 0, 0, 0]
545 [ + + ]: 972 : tetra_shifts(:, 2, 9,4) = [ -1, -1, 1]
546 [ + + ]: 972 : tetra_shifts(:, 3, 9,4) = [ 0, -1, 1]
547 [ + + ]: 972 : tetra_shifts(:, 4, 9,4) = [ 0, -1, 0]
548 [ + + ]: 972 : tetra_shifts(:, 1,10,4) = [ 0, 0, 0]
549 [ + + ]: 972 : tetra_shifts(:, 2,10,4) = [ -1, -1, 1]
550 [ + + ]: 972 : tetra_shifts(:, 3,10,4) = [ -1, 0, 1]
551 [ + + ]: 972 : tetra_shifts(:, 4,10,4) = [ -1, 0, 0]
552 [ + + ]: 972 : tetra_shifts(:, 1,11,4) = [ 0, 0, 0]
553 [ + + ]: 972 : tetra_shifts(:, 2,11,4) = [ -1, -1, 1]
554 [ + + ]: 972 : tetra_shifts(:, 3,11,4) = [ 0, -1, 1]
555 [ + + ]: 972 : tetra_shifts(:, 4,11,4) = [ 0, 0, 1]
556 [ + + ]: 972 : tetra_shifts(:, 1,12,4) = [ 0, 0, 0]
557 [ + + ]: 972 : tetra_shifts(:, 2,12,4) = [ -1, -1, 1]
558 [ + + ]: 972 : tetra_shifts(:, 3,12,4) = [ -1, 0, 1]
559 [ + + ]: 972 : tetra_shifts(:, 4,12,4) = [ 0, 0, 1]
560 [ + + ]: 972 : tetra_shifts(:, 1,13,4) = [ 0, 0, 0]
561 [ + + ]: 972 : tetra_shifts(:, 2,13,4) = [ 0, 0, -1]
562 [ + + ]: 972 : tetra_shifts(:, 3,13,4) = [ 1, 0, -1]
563 [ + + ]: 972 : tetra_shifts(:, 4,13,4) = [ 1, 1, -1]
564 [ + + ]: 972 : tetra_shifts(:, 1,14,4) = [ 0, 0, 0]
565 [ + + ]: 972 : tetra_shifts(:, 2,14,4) = [ 0, 0, -1]
566 [ + + ]: 972 : tetra_shifts(:, 3,14,4) = [ 0, 1, -1]
567 [ + + ]: 972 : tetra_shifts(:, 4,14,4) = [ 1, 1, -1]
568 [ + + ]: 972 : tetra_shifts(:, 1,15,4) = [ 0, 0, 0]
569 [ + + ]: 972 : tetra_shifts(:, 2,15,4) = [ 1, 0, 0]
570 [ + + ]: 972 : tetra_shifts(:, 3,15,4) = [ 1, 0, -1]
571 [ + + ]: 972 : tetra_shifts(:, 4,15,4) = [ 1, 1, -1]
572 [ + + ]: 972 : tetra_shifts(:, 1,16,4) = [ 0, 0, 0]
573 [ + + ]: 972 : tetra_shifts(:, 2,16,4) = [ 0, 1, 0]
574 [ + + ]: 972 : tetra_shifts(:, 3,16,4) = [ 0, 1, -1]
575 [ + + ]: 972 : tetra_shifts(:, 4,16,4) = [ 1, 1, -1]
576 [ + + ]: 972 : tetra_shifts(:, 1,17,4) = [ 0, 0, 0]
577 [ + + ]: 972 : tetra_shifts(:, 2,17,4) = [ 1, 0, 0]
578 [ + + ]: 972 : tetra_shifts(:, 3,17,4) = [ 1, 1, 0]
579 [ + + ]: 972 : tetra_shifts(:, 4,17,4) = [ 1, 1, -1]
580 [ + + ]: 972 : tetra_shifts(:, 1,18,4) = [ 0, 0, 0]
581 [ + + ]: 972 : tetra_shifts(:, 2,18,4) = [ 0, 1, 0]
582 [ + + ]: 972 : tetra_shifts(:, 3,18,4) = [ 1, 1, 0]
583 [ + + ]: 972 : tetra_shifts(:, 4,18,4) = [ 1, 1, -1]
584 [ + + ]: 972 : tetra_shifts(:, 1,19,4) = [ 0, 0, 0]
585 [ + + ]: 972 : tetra_shifts(:, 2,19,4) = [ 0, 0, -1]
586 [ + + ]: 972 : tetra_shifts(:, 3,19,4) = [ 0, 1, -1]
587 [ + + ]: 972 : tetra_shifts(:, 4,19,4) = [ -1, 0, 0]
588 [ + + ]: 972 : tetra_shifts(:, 1,20,4) = [ 0, 0, 0]
589 [ + + ]: 972 : tetra_shifts(:, 2,20,4) = [ 0, 1, 0]
590 [ + + ]: 972 : tetra_shifts(:, 3,20,4) = [ 0, 1, -1]
591 [ + + ]: 972 : tetra_shifts(:, 4,20,4) = [ -1, 0, 0]
592 [ + + ]: 972 : tetra_shifts(:, 1,21,4) = [ 0, 0, 0]
593 [ + + ]: 972 : tetra_shifts(:, 2,21,4) = [ 0, 0, -1]
594 [ + + ]: 972 : tetra_shifts(:, 3,21,4) = [ 1, 0, -1]
595 [ + + ]: 972 : tetra_shifts(:, 4,21,4) = [ 0, -1, 0]
596 [ + + ]: 972 : tetra_shifts(:, 1,22,4) = [ 0, 0, 0]
597 [ + + ]: 972 : tetra_shifts(:, 2,22,4) = [ 1, 0, 0]
598 [ + + ]: 972 : tetra_shifts(:, 3,22,4) = [ 1, 0, -1]
599 [ + + ]: 972 : tetra_shifts(:, 4,22,4) = [ 0, -1, 0]
600 [ + + ]: 972 : tetra_shifts(:, 1,23,4) = [ 0, 0, 0]
601 [ + + ]: 972 : tetra_shifts(:, 2,23,4) = [ 0, 0, -1]
602 [ + + ]: 972 : tetra_shifts(:, 3,23,4) = [ -1, -1, 0]
603 [ + + ]: 972 : tetra_shifts(:, 4,23,4) = [ 0, -1, 0]
604 [ + + ]: 972 : tetra_shifts(:, 1,24,4) = [ 0, 0, 0]
605 [ + + ]: 972 : tetra_shifts(:, 2,24,4) = [ 0, 0, -1]
606 [ + + ]: 972 : tetra_shifts(:, 3,24,4) = [ -1, -1, 0]
607 [ + + ]: 972 : tetra_shifts(:, 4,24,4) = [ -1, 0, 0]
608 : :
609 : : ! These shifts are taken from previous tetrahedron implementation by MJV and BXU
610 : : ! TODO: implement shifts for the other diagonals
611 [ + + ]: 972 : tetra_shifts_6(:,1,1,1) = [0,0,0]
612 [ + + ]: 972 : tetra_shifts_6(:,2,1,1) = [1,0,0]
613 [ + + ]: 972 : tetra_shifts_6(:,3,1,1) = [0,1,0]
614 [ + + ]: 972 : tetra_shifts_6(:,4,1,1) = [1,0,1]
615 [ + + ]: 972 : tetra_shifts_6(:,1,2,1) = [1,0,0]
616 [ + + ]: 972 : tetra_shifts_6(:,2,2,1) = [1,1,0]
617 [ + + ]: 972 : tetra_shifts_6(:,3,2,1) = [0,1,0]
618 [ + + ]: 972 : tetra_shifts_6(:,4,2,1) = [1,0,1]
619 [ + + ]: 972 : tetra_shifts_6(:,1,3,1) = [0,1,0]
620 [ + + ]: 972 : tetra_shifts_6(:,2,3,1) = [1,1,0]
621 [ + + ]: 972 : tetra_shifts_6(:,3,3,1) = [1,0,1]
622 [ + + ]: 972 : tetra_shifts_6(:,4,3,1) = [1,1,1]
623 [ + + ]: 972 : tetra_shifts_6(:,1,4,1) = [0,0,0]
624 [ + + ]: 972 : tetra_shifts_6(:,2,4,1) = [0,1,0]
625 [ + + ]: 972 : tetra_shifts_6(:,3,4,1) = [0,0,1]
626 [ + + ]: 972 : tetra_shifts_6(:,4,4,1) = [1,0,1]
627 [ + + ]: 972 : tetra_shifts_6(:,1,5,1) = [0,0,1]
628 [ + + ]: 972 : tetra_shifts_6(:,2,5,1) = [1,0,1]
629 [ + + ]: 972 : tetra_shifts_6(:,3,5,1) = [0,1,0]
630 [ + + ]: 972 : tetra_shifts_6(:,4,5,1) = [0,1,1]
631 [ + + ]: 972 : tetra_shifts_6(:,1,6,1) = [0,1,0]
632 [ + + ]: 972 : tetra_shifts_6(:,2,6,1) = [1,0,1]
633 [ + + ]: 972 : tetra_shifts_6(:,3,6,1) = [0,1,1]
634 [ + + ]: 972 : tetra_shifts_6(:,4,6,1) = [1,1,1]
635 : :
636 [ + + ]: 972 : main_diagonals(:,1) = [ 1, 1, 1] ! 0-7
637 [ + + ]: 972 : main_diagonals(:,2) = [-1, 1, 1] ! 1-6
638 [ + + ]: 972 : main_diagonals(:,3) = [ 1,-1, 1] ! 2-5
639 [ + + ]: 972 : main_diagonals(:,4) = [ 1, 1,-1] ! 3-4
640 : :
641 : 243 : nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
642 : 243 : tetra%nkibz = nkpt_ibz
643 : 243 : tetra%nkbz = nkpt_fullbz
644 : : ! HM: this value should be important for performance
645 : : ! more buckets means faster queries for unique tetrahedra
646 : : ! but more memory due to the initial size TETRA_SIZE of the buckets
647 : : ! when changing the number of buckets one should also change the hash function
648 : : ! to distribute the tetrahedra in the buckets as uniformly as possible
649 : : ! the simplest hash (not the best!) is:
650 : : ! ihash = mod(sum(tetra_ibz),nbuckts)
651 : : ! the value of sum(tetra_ibz) is between 1 and 4*nkibz so I use nkibz nbuckets
652 : : ! a larger number of buckets should speed up finding the irreducible tetrahedra
653 : : ! but with more memory allocated
654 : 243 : tetra%nbuckets = nkpt_ibz
655 : 243 : ierr = 0
656 [ - + + - : 225265 : ABI_CALLOC(tetra_hash_count,(tetra%nbuckets))
+ - + - -
+ - + +
+ ]
657 : :
658 : : ! Determine the smallest diagonal in k-space
659 : : min_length = huge(min_length)
660 [ + + ]: 1215 : do idiag = 1,4
661 : : diag(:) = gprimd(:,1)*main_diagonals(1,idiag)+&
662 : : gprimd(:,2)*main_diagonals(2,idiag)+&
663 [ + + ]: 3888 : gprimd(:,3)*main_diagonals(3,idiag)
664 : 972 : length = sqrt(diag(1)*diag(1) + diag(2)*diag(2) + diag(3)*diag(3))
665 [ + + ]: 1215 : if (length < min_length) then
666 : 246 : min_length = length
667 : 246 : min_idiag = idiag
668 : : end if
669 : : end do
670 : :
671 : : ! HM TODO: Avoid krank and map the k-point grid to indexes
672 : : ! Make full k-point rank arrays
673 : : !oct = octree_init(kpt_fullbz,2**4,[-one,-one,-one],[two,two,two])
674 : 243 : call krank%init(nkpt_fullbz, kpt_fullbz)
675 : : !
676 : : ! HM (13/04/2019): I implement two different versions:
677 : : ! 1. I only use 24 tetrahedra around the IBZ k-point
678 : : ! following the approach of A. Togo (phonopy, spglib, kspclib).
679 : : ! 2. I generate tetrahedra on the full Brillouin zone
680 : : ! and keep track of how many are contributing to the IBZ point and the multiplicities,
681 : : ! these can be more than 24 tetrahedra.
682 : : ! This is equivalent to what Matthieu implemented but avoids large memory allocations.
683 : : !
684 : : ! The two implementations differ specially when using low k-point sampling
685 : : ! (the second yields the same results using IBZ or FBZ, the first one not).
686 : : ! For large sampling the two approaches yield similar results, with the first
687 : : ! one using less memory, faster to generate and compute
688 : : !
689 [ - + + - : 225265 : ABI_MALLOC(tetra%unique_tetra,(tetra%nbuckets))
+ - + - -
+ - + - +
+ + ]
690 [ + + ]: 224779 : do ihash=1,tetra%nbuckets
691 [ - + - + : 8308075 : ABI_CALLOC(tetra%unique_tetra(ihash)%indexes,(0:4,TETRA_SIZE))
+ + + + ]
692 : : end do
693 [ - + ]: 243 : tetra%opt = 2; if (present(opt)) tetra%opt = opt
694 : :
695 : 243 : select case(tetra%opt)
696 : : case (1)
697 : : ! For each k-point in the IBZ store 24 tetrahedra each referring to 4 k-points
698 [ # # ]: 0 : do ikibz=1,tetra%nkibz
699 : : !if (mod(ikibz,nprocs) /= my_rank) cycle
700 [ # # ]: 0 : k1 = kpt_ibz(:,ikibz)
701 [ # # ]: 0 : tetra_loop1: do itetra=1,24
702 [ # # ]: 0 : do isummit=1,4
703 : : ! Find the index of the neighbouring k-points in the BZ
704 : : k2 = k1 + tetra_shifts(1,isummit,itetra,min_idiag)*klatt(:,1) + &
705 : : tetra_shifts(2,isummit,itetra,min_idiag)*klatt(:,2) + &
706 [ # # ]: 0 : tetra_shifts(3,isummit,itetra,min_idiag)*klatt(:,3)
707 : : ! Find full kpoint which is summit isummit of tetrahedron itetra around full kpt ikpt_full !
708 : : !ikpt2 = octree_find(oct,k2,dist)
709 : : !ikpt2 = octree_find_nearest_pbc(oct,k2,dist,shift)
710 : : !if (dist>tol12) call exit(1)
711 : 0 : ikpt2 = krank%get_index(k2)
712 : : ! Find the index of those points in the BZ and IBZ
713 : 0 : tetra_ibz(isummit) = bz2ibz(ikpt2)
714 : : end do
715 : : ! Sort index of irr k-point edges (need this so the comparison works)
716 : 0 : call sort_4tetra_int(tetra_ibz)
717 : :
718 : : ! Store only unique tetrahedra
719 : : ! Compute a very simple hash for each tetrahedron
720 : 0 : ihash = compute_hash(tetra,tetra_ibz) !mod(sum(tetra_ibz),tetra%nbuckets)+1
721 : : ! Loop over all tetrahedrons that contain this ikibz as first element
722 [ # # ]: 0 : do jtetra=1,tetra_hash_count(ihash)
723 : : ! if tetrahedron already exists add multiplicity
724 [ # # ]: 0 : if (tetra%unique_tetra(ihash)%indexes(1,jtetra)/=tetra_ibz(1)) cycle
725 [ # # ]: 0 : if (tetra%unique_tetra(ihash)%indexes(2,jtetra)/=tetra_ibz(2)) cycle
726 [ # # ]: 0 : if (tetra%unique_tetra(ihash)%indexes(3,jtetra)/=tetra_ibz(3)) cycle
727 [ # # ]: 0 : if (tetra%unique_tetra(ihash)%indexes(4,jtetra)/=tetra_ibz(4)) cycle
728 : 0 : tetra%unique_tetra(ihash)%indexes(0,jtetra) = tetra%unique_tetra(ihash)%indexes(0,jtetra)+1
729 : 0 : cycle tetra_loop1
730 : : end do
731 : : ! Otherwise store new tetrahedron
732 : 0 : tetra_hash_count(ihash) = tetra_hash_count(ihash)+1
733 : 0 : max_ntetra = size(tetra%unique_tetra(ihash)%indexes,2)
734 : : ! The contents don't fit the array so I have to resize it
735 [ # # ]: 0 : if (tetra_hash_count(ihash)>max_ntetra) then
736 [ # # # # : 0 : ABI_MALLOC(indexes,(0:4,max_ntetra+TETRA_STEP))
# # # # #
# # # #
# ]
737 [ # # # # ]: 0 : indexes(0:4,:max_ntetra) = tetra%unique_tetra(ihash)%indexes
738 [ # # # # ]: 0 : indexes(:,max_ntetra+1:) = 0
739 [ # # ]: 0 : ABI_MOVE_ALLOC(indexes,tetra%unique_tetra(ihash)%indexes)
740 : : end if
741 [ # # ]: 0 : tetra%unique_tetra(ihash)%indexes(1:,tetra_hash_count(ihash)) = tetra_ibz(:)
742 : 0 : tetra%unique_tetra(ihash)%indexes(0, tetra_hash_count(ihash)) = 1
743 : : end do tetra_loop1
744 : : end do
745 : : ! HM: The multiplicity of the tetrahedrons computed so far is wrong because we are using IBZ
746 : : ! I compute the k-point multiplicity so I can fix this later on
747 : : ! Only needed in blochl_weights* interface for looping over tetrahedra.
748 : : ! in the onewk routines the weight is known outside
749 [ # # # # : 0 : ABI_CALLOC(tetra%ibz_multiplicity,(tetra%nkibz))
# # # # #
# # # # #
# # ]
750 [ # # ]: 0 : do ikbz=1,nkpt_fullbz
751 : 0 : ikibz = bz2ibz(ikbz)
752 : 0 : tetra%ibz_multiplicity(ikibz) = tetra%ibz_multiplicity(ikibz) + 1
753 : : end do
754 : :
755 : : case(2)
756 : 243 : min_idiag = 1
757 : : ! For each k-point in the BZ generate the 6 tetrahedra that tessellate a microzone
758 [ + + ]: 1409584 : do ikbz=1,tetra%nkbz
759 [ + + ]: 5637364 : k1 = kpt_fullbz(:,ikbz)
760 [ + + ]: 9865630 : tetra_loop2: do itetra=1,6
761 : : ! Determine tetrahedron
762 [ + + ]: 42280230 : do isummit=1,4
763 : : ! Find the index of the neighbouring k-points in the BZ
764 : : k2 = k1 + tetra_shifts_6(1,isummit,itetra,min_idiag)*klatt(:,1) + &
765 : : tetra_shifts_6(2,isummit,itetra,min_idiag)*klatt(:,2) + &
766 [ + + ]: 135296736 : tetra_shifts_6(3,isummit,itetra,min_idiag)*klatt(:,3)
767 : : ! Find full kpoint which is summit isummit of tetrahedron itetra around full kpt ikpt_full !
768 : : !ikpt2 = octree_find(oct,k2,dist)
769 : : !ikpt2 = octree_find_nearest_pbc(oct,k2,dist,shift)
770 : : !if (dist>tol12) call exit(1)
771 : 33824184 : ikpt2 = krank%get_index(k2)
772 : : ! Find the index of those points in the BZ and IBZ
773 : 42280230 : tetra_ibz(isummit) = bz2ibz(ikpt2)
774 : : end do
775 : : ! Sort index of irr k-point edges (need this so the comparison works)
776 : 8456046 : call sort_4tetra_int(tetra_ibz)
777 : :
778 : : ! Store only unique tetrahedra
779 : : ! Compute a very simple hash for each tetrahedron
780 : 8456046 : ihash = compute_hash(tetra,tetra_ibz) !mod(sum(tetra_ibz),tetra%nbuckets)+1
781 : : ! Loop over all tetrahedrons that contain this ikibz as first element
782 [ + + ]: 156269209 : do jtetra=1,tetra_hash_count(ihash)
783 : : ! if tetrahedron already exists add multiplicity
784 [ + + ]: 151530110 : if (tetra%unique_tetra(ihash)%indexes(1,jtetra)/=tetra_ibz(1)) cycle
785 [ + + ]: 4805680 : if (tetra%unique_tetra(ihash)%indexes(2,jtetra)/=tetra_ibz(2)) cycle
786 [ + + ]: 3930585 : if (tetra%unique_tetra(ihash)%indexes(3,jtetra)/=tetra_ibz(3)) cycle
787 [ - + ]: 3716947 : if (tetra%unique_tetra(ihash)%indexes(4,jtetra)/=tetra_ibz(4)) cycle
788 : 3716947 : tetra%unique_tetra(ihash)%indexes(0,jtetra) = tetra%unique_tetra(ihash)%indexes(0,jtetra)+1
789 : 156269209 : cycle tetra_loop2
790 : : end do
791 : : ! Otherwise store new tetrahedron
792 : 4739099 : tetra_hash_count(ihash) = tetra_hash_count(ihash)+1
793 : 4739099 : max_ntetra = size(tetra%unique_tetra(ihash)%indexes,2)
794 : : ! The contents don't fit the array so I have to resize it
795 [ + + ]: 4739099 : if (tetra_hash_count(ihash)>max_ntetra) then
796 [ + - - + : 1975152 : ABI_MALLOC(indexes,(0:4,max_ntetra+TETRA_STEP))
+ - + - +
- - + -
+ ]
797 [ + + + + ]: 71822824 : indexes(0:4,:max_ntetra) = tetra%unique_tetra(ihash)%indexes
798 [ + + + + ]: 24360208 : indexes(:,max_ntetra+1:) = 0
799 [ + - ]: 658384 : ABI_MOVE_ALLOC(indexes,tetra%unique_tetra(ihash)%indexes)
800 : : end if
801 [ + + ]: 23695495 : tetra%unique_tetra(ihash)%indexes(1:,tetra_hash_count(ihash)) = tetra_ibz(:)
802 : 6148440 : tetra%unique_tetra(ihash)%indexes(0, tetra_hash_count(ihash)) = 1
803 : : end do tetra_loop2
804 : : end do
805 : : case default
806 : 0 : ierr = 1
807 : 0 : write(errorstring,*) 'Invalid option for the generation of tetrahedra,',ch10,&
808 : 0 : 'possible options are:',ch10,&
809 : 0 : '1. Generate 24 tetrahedra per k-point',ch10,&
810 : 0 : '2. Generate tetrahedra in the FBZ a map to IBZ (default)'
811 [ - + - ]: 243 : return
812 : : end select
813 : :
814 : : !ierr = octree_free(oct)
815 [ - + ]: 243 : ABI_FREE(tetra_hash_count)
816 : 243 : call krank%free()
817 : :
818 : : ! Do some maintenance: free unused memory and count unique tetrahedra per IBZ point
819 : 243 : tetra%nunique_tetra = 0
820 [ + + ]: 224779 : do ihash=1,tetra%nbuckets
821 : : ! Count tetrahedra in this bucket
822 [ + + + + ]: 5522056 : ntetra = count(tetra%unique_tetra(ihash)%indexes(0,:)>0)
823 : 224536 : tetra%nunique_tetra = tetra%nunique_tetra + ntetra
824 : : ! Allocate array with right size
825 [ + + + - : 673608 : ABI_MALLOC(indexes,(0:4,ntetra))
+ - + + -
+ - + ]
826 [ + - + - : 28883666 : indexes = tetra%unique_tetra(ihash)%indexes(:,:ntetra)
- + - - +
+ + + ]
827 [ + - ]: 224779 : ABI_MOVE_ALLOC(indexes, tetra%unique_tetra(ihash)%indexes)
828 : : end do
829 : :
830 : : ! Sum the multiplicity
831 [ - + + - : 729 : ABI_MALLOC(tetra%tetra_count,(tetra%nkibz))
+ - + - -
+ - + -
+ ]
832 [ - + + - : 729 : ABI_MALLOC(tetra%tetra_total,(tetra%nkibz))
+ - + - -
+ - + -
+ ]
833 [ + + ]: 224779 : tetra%tetra_count = 0
834 [ + + ]: 224779 : tetra%tetra_total = 0
835 [ + + ]: 224779 : do ihash=1,tetra%nbuckets
836 : 224536 : ntetra = size(tetra%unique_tetra(ihash)%indexes,2)
837 [ + + ]: 4963878 : do itetra=1,ntetra
838 [ + + ]: 28434594 : tetra_mibz = tetra%unique_tetra(ihash)%indexes(:,itetra)
839 [ + + ]: 23920031 : do isummit=1,4
840 : 18956396 : ikibz = tetra_mibz(isummit)
841 : 18956396 : tetra%tetra_total(ikibz) = tetra%tetra_total(ikibz) + tetra_mibz(0)
842 : 23695495 : tetra%tetra_count(ikibz) = tetra%tetra_count(ikibz) + 1
843 : : end do
844 : : end do
845 : : end do
846 [ + + ]: 224779 : tetra%nibz_tetra = sum(tetra%tetra_count)
847 : :
848 : : ! HM: This was being allocated here, however this is only used when we loop over kpoints
849 : : ! I will only allocate this memory if the htetra_get_onewk_* routines are called (lazy evaluation)
850 : : !call htetra_init_mapping_ibz(tetra)
851 : :
852 : : ! Calculate the volume of the tetrahedra
853 : : rcvol = abs(gprimd(1,1)*(gprimd(2,2)*gprimd(3,3)-gprimd(3,2)*gprimd(2,3))- &
854 : : gprimd(2,1)*(gprimd(1,2)*gprimd(3,3)-gprimd(3,2)*gprimd(1,3))+ &
855 : 243 : gprimd(3,1)*(gprimd(1,2)*gprimd(2,3)-gprimd(2,2)*gprimd(1,3)))
856 : :
857 : : ! Volume of all tetrahedra should be the same as that of tetra 1
858 : : ! this is the volume of 1 tetrahedron, should be coherent with notation in Lehmann & Taut
859 [ + + ]: 972 : k1(:) = gprimd(:,1)*klatt(1,1) + gprimd(:,2)*klatt(2,1) + gprimd(:,3)*klatt(3,1)
860 [ + + ]: 972 : k2(:) = gprimd(:,1)*klatt(1,2) + gprimd(:,2)*klatt(2,2) + gprimd(:,3)*klatt(3,2)
861 [ + + ]: 972 : k3(:) = gprimd(:,1)*klatt(1,3) + gprimd(:,2)*klatt(2,3) + gprimd(:,3)*klatt(3,3)
862 : : tetra%vv = abs(k1(1)*(k2(2)*k3(3)-k2(3)*k3(2))- &
863 : : k1(2)*(k2(1)*k3(3)-k2(3)*k3(1))+ &
864 [ - - - + : 243 : k1(3)*(k2(1)*k3(2)-k2(2)*k3(1))) / 6.d0 / rcvol
- + - + -
- - - -
- ]
865 : :
866 : : contains
867 : 8456046 : integer function compute_hash(tetra,t) result(ihash)
868 : : class(htetra_t),intent(in) :: tetra
869 : : integer,intent(in) :: t(4)
870 [ - - + + ]: 42280230 : ihash = mod(sum(t), tetra%nbuckets) + 1
871 : : ! TODO: should use a more general hash function that supports more buckets
872 : : ! Something like:
873 : : ! id = t(1)*nk3+t(2)*nk2+t(3)*nk1+t(4)
874 : : ! where nk is the number of points in the IBZ
875 : : ! Computing this leads to overflow so should use
876 : : ! mod computation operations
877 : : ! (A + B) mod C = (A mod C + B mod C) mod C
878 : : ! (A * B) mod C = (A mod C * B mod C) mod C
879 : : ! A^B mod C = ( (A mod C)^B ) mod C
880 : : end function compute_hash
881 : :
882 : : end subroutine htetra_init
883 : : !!***
884 : :
885 : : !----------------------------------------------------------------------
886 : :
887 : : !!****f* m_htetra/htetra_init_mapping_ibz
888 : : !! NAME
889 : : !! htetra_init_mapping_ibz
890 : : !!
891 : : !! FUNCTION
892 : : !! The mapping to the IBZ has its own allocation routine.
893 : : !! I will only allocate this memory if the htetra_get_onewk_* routines are called (lazy evaluation)
894 : : !!
895 : : !! SOURCE
896 : :
897 : 157 : subroutine htetra_init_mapping_ibz(tetra)
898 : :
899 : : class(htetra_t),intent(inout) :: tetra
900 : :
901 : : integer :: ikibz, itetra, isummit, ihash, ntetra
902 : 157 : integer :: tetra_count(tetra%nkibz),tetra_mibz(0:4)
903 : : real(dp) :: mem_mb
904 : :
905 : : ! Only execute the following if not yet allocated
906 [ - + ]: 157 : if (allocated(tetra%ibz)) return
907 : :
908 : : ! Allocate IBZ to tetrahedron mapping
909 [ - + + - : 21562 : ABI_MALLOC(tetra%ibz, (tetra%nkibz))
+ - + - -
+ - + - +
+ + ]
910 [ + + ]: 314 : mem_mb = ABI_MEM_MB(tetra%ibz)
911 [ + + ]: 21248 : do ikibz=1,tetra%nkibz
912 [ - + + - : 63273 : ABI_MALLOC(tetra%ibz(ikibz)%indexes, (2, tetra%tetra_count(ikibz)))
+ - + - -
+ - + -
+ ]
913 : 21248 : mem_mb = mem_mb + 2 * tetra%tetra_count(ikibz) * 4 * b2Mb
914 : : end do
915 : :
916 : 157 : call wrtout(std_out, sjoin(" Allocating tetra%ibz%indexes with memory:", ftoa(mem_mb, fmt="f8.1"), " [Mb] <<< MEM"))
917 : :
918 : : ! Create mapping from IBZ to unique tetrahedra
919 [ + + ]: 21248 : tetra_count = 0
920 [ + + ]: 21248 : do ihash=1,tetra%nbuckets
921 : 21091 : ntetra = size(tetra%unique_tetra(ihash)%indexes, dim=2)
922 [ + + ]: 869866 : do itetra=1,ntetra
923 [ + + ]: 5091708 : tetra_mibz = tetra%unique_tetra(ihash)%indexes(:,itetra)
924 [ + + ]: 4264181 : do isummit=1,4
925 : 3394472 : ikibz = tetra_mibz(isummit)
926 : 3394472 : tetra_count(ikibz) = tetra_count(ikibz) + 1
927 : 3394472 : tetra%ibz(ikibz)%indexes(1, tetra_count(ikibz)) = ihash
928 : 4243090 : tetra%ibz(ikibz)%indexes(2, tetra_count(ikibz)) = itetra
929 : : end do
930 : : end do
931 : : end do
932 : :
933 : : end subroutine htetra_init_mapping_ibz
934 : : !!***
935 : :
936 : : !----------------------------------------------------------------------
937 : :
938 : : !!****f* m_htetra/htetra_get_ibz
939 : : !! NAME
940 : : !! htetra_get_ibz
941 : : !!
942 : : !! FUNCTION
943 : : !! Get the itetra tetrahedron contributing to the ikibz k-point
944 : : !!
945 : : !! SOURCE
946 : :
947 : 15710160 : pure subroutine htetra_get_ibz(tetra, ikibz, itetra, tetra_mibz)
948 : :
949 : : class(htetra_t), intent(in) :: tetra
950 : : integer,intent(in) :: ikibz, itetra
951 : : integer,intent(out) :: tetra_mibz(0:4)
952 : : integer :: ihash, jtetra
953 : :
954 : 15710160 : ihash = tetra%ibz(ikibz)%indexes(1,itetra)
955 : 15710160 : jtetra = tetra%ibz(ikibz)%indexes(2,itetra)
956 [ + + ]: 94260960 : tetra_mibz = tetra%unique_tetra(ihash)%indexes(:,jtetra)
957 : :
958 : 15710160 : end subroutine htetra_get_ibz
959 : : !!***
960 : :
961 : : !----------------------------------------------------------------------
962 : :
963 : : !!****f* m_htetra/htetra_print
964 : : !! NAME
965 : : !! htetra_print
966 : : !!
967 : : !! FUNCTION
968 : : !! write information about the tetrahedra object
969 : : !!
970 : : !! SOURCE
971 : :
972 : 62 : subroutine htetra_print(self, unit)
973 : :
974 : : class(htetra_t), intent(in) :: self
975 : : integer,intent(in) :: unit
976 : :
977 : : real(dp) :: total_size, unique_tetra_size, ibz_pointer_size
978 : :
979 [ - + ]: 62 : if (unit == dev_null) return
980 : :
981 : 62 : unique_tetra_size = self%nunique_tetra * 5* four / 1024 ** 2
982 : 62 : total_size = unique_tetra_size
983 : : !write(unit,'(a,i0)') ' htetra unique_tetra:', self%nunique_tetra
984 : : !write(unit,'(a,f12.1,a)') ' htetra unique_tetra_size ', unique_tetra_size, ' [Mb] <<< MEM'
985 [ - + ]: 62 : if (allocated(self%ibz)) then
986 : 0 : ibz_pointer_size = self%nibz_tetra*2*four / 1024 ** 2
987 : 0 : write(unit,'(a,i0)') ' ibz_tetra: ', self%nibz_tetra
988 : 0 : write(unit,'(a,f12.1,a)') ' ibz_tetra_size: ', ibz_pointer_size, ' [Mb] <<< MEM'
989 : 0 : total_size = total_size + ibz_pointer_size
990 : : end if
991 : : ! integer arrays
992 : 62 : total_size = total_size + 3 * (self%nkibz * 4) / 1024**2
993 : 62 : write(unit,'(a,f12.1,a)') ' htetra total size:', total_size, ' [Mb] <<< MEM'
994 : :
995 : : end subroutine htetra_print
996 : : !!***
997 : :
998 : : !----------------------------------------------------------------------
999 : :
1000 : : !!****f* m_htetra/htetra_free
1001 : : !! NAME
1002 : : !! htetra_free
1003 : : !!
1004 : : !! FUNCTION
1005 : : !! deallocate tetrahedra pointers if needed
1006 : : !!
1007 : : !! SOURCE
1008 : :
1009 : 374 : subroutine htetra_free(tetra)
1010 : :
1011 : : class(htetra_t), intent(inout) :: tetra
1012 : : integer :: ikibz,ihash
1013 : :
1014 [ + + ]: 374 : ABI_SFREE(tetra%tetra_count)
1015 [ + + ]: 374 : ABI_SFREE(tetra%tetra_total)
1016 [ - + ]: 374 : ABI_SFREE(tetra%ibz_multiplicity)
1017 : :
1018 [ + + ]: 374 : if (allocated(tetra%unique_tetra)) then
1019 [ + + ]: 224779 : do ihash=1,tetra%nbuckets
1020 [ + - ]: 224779 : ABI_SFREE(tetra%unique_tetra(ihash)%indexes)
1021 : : end do
1022 [ + - + + : 224779 : ABI_FREE(tetra%unique_tetra)
- + - + ]
1023 : : end if
1024 : :
1025 [ + + ]: 374 : if (allocated(tetra%ibz)) then
1026 [ + + ]: 21248 : do ikibz=1,tetra%nkibz
1027 [ + - ]: 21248 : ABI_SFREE(tetra%ibz(ikibz)%indexes)
1028 : : end do
1029 [ + - + + : 21248 : ABI_FREE(tetra%ibz)
- + - + ]
1030 : : end if
1031 : :
1032 : 374 : end subroutine htetra_free
1033 : : !!***
1034 : :
1035 : : !----------------------------------------------------------------------
1036 : :
1037 : : !!****f* m_htetra/get_onetetra_blochl
1038 : : !! NAME
1039 : : !! get_onetetra_blochl
1040 : : !!
1041 : : !! FUNCTION
1042 : : !! Private function to calculate the contributions to the weights due to a single tetrahedron.
1043 : : !! Extracted from get_tetra_weight
1044 : : !!
1045 : : !! SOURCE
1046 : :
1047 : 138582926 : pure subroutine get_onetetra_blochl(eig, energies, nene, bcorr, tweight, dweight)
1048 : :
1049 : : !Arguments ------------------------------------
1050 : : !scalars
1051 : : integer,intent(in) :: nene,bcorr
1052 : : !arrays
1053 : : real(dp),intent(in) :: eig(4), energies(nene)
1054 : : real(dp), intent(out) :: tweight(4, nene), dweight(4, nene)
1055 : :
1056 : : !Local variables-------------------------------
1057 : : integer :: ieps
1058 : : real(dp) :: cc,cc1,cc2,cc3
1059 : : real(dp) :: dcc1de,dcc2de,dcc3de,dccde,eps
1060 : : real(dp) :: e21,e31,e32,e41,e42,e43
1061 : : real(dp) :: inv_e32,inv_e41,inv_e42,inv_e43,inv_e21,inv_e31
1062 : : real(dp) :: deleps1,deleps2,deleps3,deleps4
1063 : : real(dp) :: e1,e2,e3,e4
1064 : : real(dp) :: invepsum, cc_pre, dccde_pre
1065 : : real(dp) :: cc1_pre, cc2_pre, cc3_pre
1066 : : real(dp) :: dccde_tmp
1067 : : real(dp) :: bcorr_fact
1068 : : ! *********************************************************************
1069 : :
1070 : : ! This is output
1071 [ + + + + : >13491*10^7 : tweight = zero; dweight = zero
+ + + + ]
1072 : :
1073 : : ! all notations are from Blochl PRB 49 16223 [[cite:Bloechl1994a]] Appendix B
1074 : 138582926 : e1 = eig(1)
1075 : 138582926 : e2 = eig(2)
1076 : 138582926 : e3 = eig(3)
1077 : 138582926 : e4 = eig(4)
1078 : 138582926 : e21 = e2-e1
1079 : 138582926 : e31 = e3-e1
1080 : 138582926 : e41 = e4-e1
1081 : 138582926 : e32 = e3-e2
1082 : 138582926 : e42 = e4-e2
1083 : 138582926 : e43 = e4-e3
1084 [ + + ]: 138582926 : inv_e21 = zero; if (e21 > tol14) inv_e21 = 1.d0 / e21
1085 [ + + ]: 138582926 : inv_e31 = zero; if (e31 > tol14) inv_e31 = 1.d0 / e31
1086 [ + + ]: 138582926 : inv_e41 = zero; if (e41 > tol14) inv_e41 = 1.d0 / e41
1087 [ + + ]: 138582926 : inv_e32 = zero; if (e32 > tol14) inv_e32 = 1.d0 / e32
1088 [ + + ]: 138582926 : inv_e42 = zero; if (e42 > tol14) inv_e42 = 1.d0 / e42
1089 [ + + ]: 138582926 : inv_e43 = zero; if (e43 > tol14) inv_e43 = 1.d0 / e43
1090 : :
1091 [ + + ]: 7878293144 : do ieps=1,nene
1092 : 7770985705 : eps = energies(ieps)
1093 : :
1094 : : !
1095 : : ! eps < e1 nothing to do
1096 : : !
1097 [ + + ]: 7770985705 : if (eps < e1) cycle
1098 : :
1099 : : !
1100 : : ! e1 < eps < e2
1101 : : !
1102 [ + + ]: 510470751 : if (eps < e2) then
1103 : 172325526 : deleps1 = eps-e1
1104 : 172325526 : invepsum = inv_e21+inv_e31+inv_e41
1105 : :
1106 : : ! Heaviside
1107 : 172325526 : cc = inv_e21*inv_e31*inv_e41*deleps1**3
1108 : 172325526 : tweight(1,ieps) = cc*(4.d0-deleps1*invepsum)
1109 : 172325526 : tweight(2,ieps) = cc*deleps1*inv_e21
1110 : 172325526 : tweight(3,ieps) = cc*deleps1*inv_e31
1111 : 172325526 : tweight(4,ieps) = cc*deleps1*inv_e41
1112 : :
1113 : : ! Delta
1114 : 172325526 : dccde_pre = 3.d0*inv_e21*inv_e31*inv_e41
1115 : 172325526 : dccde = dccde_pre*deleps1**2
1116 : 172325526 : dweight(1,ieps) = dccde*(4.d0-deleps1*invepsum)-cc*invepsum
1117 : 172325526 : dweight(2,ieps) = (dccde*deleps1+cc) * inv_e21
1118 : 172325526 : dweight(3,ieps) = (dccde*deleps1+cc) * inv_e31
1119 : 172325526 : dweight(4,ieps) = (dccde*deleps1+cc) * inv_e41
1120 : :
1121 [ - + ]: 172325526 : if (bcorr == 1) then
1122 : : ! bxu, correction terms based on Bloechl's paper
1123 : 0 : bcorr_fact = 4.d0/40.d0*dccde_pre*deleps1*deleps1
1124 : 0 : tweight(1,ieps) = tweight(1,ieps) + bcorr_fact*( e21+e31+e41)
1125 : 0 : tweight(2,ieps) = tweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
1126 : 0 : tweight(3,ieps) = tweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
1127 : 0 : tweight(4,ieps) = tweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
1128 : :
1129 : 0 : bcorr_fact = 8.d0/40.d0*dccde_pre*deleps1
1130 : 0 : dweight(1,ieps) = dweight(1,ieps) + bcorr_fact*( e21+e31+e41)
1131 : 0 : dweight(2,ieps) = dweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
1132 : 0 : dweight(3,ieps) = dweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
1133 : 0 : dweight(4,ieps) = dweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
1134 : : end if
1135 : :
1136 : : cycle
1137 : : endif
1138 : :
1139 : : !
1140 : : ! e2 < eps < e3
1141 : : !
1142 [ + + ]: 338145225 : if (eps < e3) then
1143 : 144551565 : deleps1 = eps-e1
1144 : 144551565 : deleps2 = eps-e2
1145 : 144551565 : deleps3 = e3-eps
1146 : 144551565 : deleps4 = e4-eps
1147 : 144551565 : cc1_pre = inv_e31*inv_e41
1148 : 144551565 : cc2_pre = inv_e41*inv_e32*inv_e31
1149 : 144551565 : cc3_pre = inv_e42*inv_e32*inv_e41
1150 : :
1151 : : ! Heaviside
1152 : 144551565 : cc1 = cc1_pre*deleps1*deleps1
1153 : 144551565 : cc2 = cc2_pre*deleps1*deleps2*deleps3
1154 : 144551565 : cc3 = cc3_pre*deleps2*deleps2*deleps4
1155 : :
1156 : : tweight(1,ieps) = (cc1)+&
1157 : : (cc1+cc2)*deleps3*inv_e31+&
1158 : 144551565 : (cc1+cc2+cc3)*deleps4*inv_e41
1159 : : tweight(2,ieps) = (cc1+cc2+cc3)+&
1160 : : (cc2+cc3)*deleps3*inv_e32+&
1161 : 144551565 : (cc3)*deleps4*inv_e42
1162 : : tweight(3,ieps) = (cc1+cc2)*deleps1*inv_e31+&
1163 : 144551565 : (cc2+cc3)*deleps2*inv_e32
1164 : : tweight(4,ieps) = (cc1+cc2+cc3)*deleps1*inv_e41+&
1165 : 144551565 : (cc3)*deleps2*inv_e42
1166 : :
1167 : : ! Delta
1168 : 144551565 : dcc1de = cc1_pre*(2.d0*deleps1)
1169 : 144551565 : dcc2de = cc2_pre*( -deleps1*deleps2+deleps1*deleps3+deleps2*deleps3)
1170 : 144551565 : dcc3de = cc3_pre*(2.d0*deleps2*deleps4-deleps2*deleps2)
1171 : : dweight(1,ieps) = dcc1de+&
1172 : : ((dcc1de+dcc2de)*deleps3-(cc1+cc2))*inv_e31+&
1173 : 144551565 : ((dcc1de+dcc2de+dcc3de)*deleps4-(cc1+cc2+cc3))*inv_e41
1174 : : dweight(2,ieps) = (dcc1de+dcc2de+dcc3de)+&
1175 : : ((dcc2de+dcc3de)*deleps3-(cc2+cc3))*inv_e32+&
1176 : 144551565 : (dcc3de*deleps4-cc3)*inv_e42
1177 : : dweight(3,ieps) = ((dcc1de+dcc2de)*deleps1+(cc1+cc2))*inv_e31+&
1178 : 144551565 : ((dcc2de+dcc3de)*deleps2+(cc2+cc3))*inv_e32
1179 : : dweight(4,ieps) = ((dcc1de+dcc2de+dcc3de)*deleps1+(cc1+cc2+cc3))*inv_e41+&
1180 : 144551565 : (dcc3de*deleps2+cc3)*inv_e42
1181 : :
1182 [ - + ]: 144551565 : if (bcorr == 1) then
1183 : : ! bxu, correction terms based on Bloechl's paper
1184 : : ! The correction terms may cause the dweight become negative
1185 : 0 : bcorr_fact = 4.d0/40.d0*cc1_pre*(3.d0*e21+6.d0*deleps2-3.d0*(e31+e42)*deleps2*deleps2*inv_e32*inv_e42)
1186 : 0 : tweight(1,ieps) = tweight(1,ieps) + bcorr_fact*( e21+e31+e41)
1187 : 0 : tweight(2,ieps) = tweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
1188 : 0 : tweight(3,ieps) = tweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
1189 : 0 : tweight(4,ieps) = tweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
1190 : :
1191 : 0 : bcorr_fact = 4.d0/40.d0*cc1_pre*(6.d0-6.d0*(e31+e42)*deleps2*inv_e32*inv_e42)
1192 : 0 : dweight(1,ieps) = dweight(1,ieps) + bcorr_fact*( e21+e31+e41)
1193 : 0 : dweight(2,ieps) = dweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
1194 : 0 : dweight(3,ieps) = dweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
1195 : 0 : dweight(4,ieps) = dweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
1196 : : end if
1197 : :
1198 : : cycle
1199 : : endif
1200 : :
1201 : : !
1202 : : ! e3 < eps < e4
1203 : : !
1204 [ + + ]: 193593660 : if (eps < e4) then
1205 : 162310083 : deleps4 = e4-eps
1206 : 162310083 : invepsum = inv_e41+inv_e42+inv_e43
1207 : :
1208 : : ! Heaviside
1209 : 162310083 : cc_pre = inv_e41*inv_e42*inv_e43
1210 : 162310083 : cc = cc_pre*deleps4**3
1211 : 162310083 : tweight(1,ieps) = one - deleps4*cc*inv_e41
1212 : 162310083 : tweight(2,ieps) = one - deleps4*cc*inv_e42
1213 : 162310083 : tweight(3,ieps) = one - deleps4*cc*inv_e43
1214 : 162310083 : tweight(4,ieps) = one - cc*(4.d0-deleps4*invepsum)
1215 : :
1216 : : ! Delta
1217 : 162310083 : dccde = -3.d0*cc_pre*deleps4**2
1218 : 162310083 : dccde_tmp = dccde*deleps4 - cc
1219 : 162310083 : dweight(1,ieps) = -dccde_tmp * inv_e41
1220 : 162310083 : dweight(2,ieps) = -dccde_tmp * inv_e42
1221 : 162310083 : dweight(3,ieps) = -dccde_tmp * inv_e43
1222 : 162310083 : dweight(4,ieps) = -4.d0*dccde + dccde_tmp*invepsum
1223 : :
1224 [ - + ]: 162310083 : if (bcorr == 1) then
1225 : : ! bxu, correction terms based on Bloechl's paper
1226 : : ! The correction terms may cause the dweight become negative
1227 : 0 : bcorr_fact = 12.d0/40.d0*cc_pre*deleps4*deleps4
1228 : 0 : tweight(1,ieps) = tweight(1,ieps) + bcorr_fact*( e21+e31+e41)
1229 : 0 : tweight(2,ieps) = tweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
1230 : 0 : tweight(3,ieps) = tweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
1231 : 0 : tweight(4,ieps) = tweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
1232 : :
1233 : 0 : bcorr_fact = - 24.d0/40.d0*cc_pre*deleps4
1234 : 0 : dweight(1,ieps) = dweight(1,ieps) + bcorr_fact*( e21+e31+e41)
1235 : 0 : dweight(2,ieps) = dweight(2,ieps) + bcorr_fact*(-e21+e32+e42)
1236 : 0 : dweight(3,ieps) = dweight(3,ieps) + bcorr_fact*(-e31-e32+e43)
1237 : 0 : dweight(4,ieps) = dweight(4,ieps) + bcorr_fact*(-e41-e42-e43)
1238 : : end if
1239 : :
1240 : : cycle
1241 : : endif
1242 : :
1243 : : !
1244 : : ! e4 < eps
1245 : : !
1246 [ + + ]: 138591016 : if (e4 < eps) then
1247 : :
1248 : : ! Heaviside
1249 [ + + + + ]: 28719032867 : tweight(:,ieps:) = one
1250 : :
1251 : : ! Delta unchanged by this tetrahedron
1252 : : exit
1253 : : end if
1254 : :
1255 : : ! if we have a fully degenerate tetrahedron,
1256 : : ! 1) the tweight is a Heaviside (step) function, which is correct above, but
1257 : : ! 2) the dweight should contain a Dirac function
1258 : : !
1259 : : end do
1260 : :
1261 : 138582926 : end subroutine get_onetetra_blochl
1262 : : !!***
1263 : :
1264 : : !!****f* m_htetra/get_onetetra_lambinvigneron
1265 : : !! NAME
1266 : : !! get_onetetra_lambinvigneron
1267 : : !!
1268 : : !! FUNCTION
1269 : : !! Compute the complex weights according to: P. Lambin and J.P. Vigneron, Phys. Rev. B 29, 3430 (1984)
1270 : : !! This routine is adapted from tdep where it was implemented
1271 : : !! by Olle Hellman, all credits go to him
1272 : : !!
1273 : : !! INPUTS
1274 : : !!
1275 : : !! OUTPUT
1276 : : !!
1277 : : !! SOURCE
1278 : :
1279 : : !pure
1280 : 0 : subroutine get_onetetra_lambinvigneron(eig, z, cw)
1281 : :
1282 : : ! dispersion values at the corners of the tetrahedron
1283 : : real(dp), intent(in) :: eig(4)
1284 : : ! energy to evaluate the weights at
1285 : : complex(dp), intent(in) :: z
1286 : : ! complex weights
1287 : : complex(dp), intent(out) :: cw(4)
1288 : : complex(dp) :: EZ1,EZ2,EZ3,EZ4
1289 : : real(dp) :: tol = tol14
1290 : : !real(dp) :: tol = tol10
1291 : : !real(dp) :: tol = tol6
1292 : : real(dp) :: Emin,Emax,Zdist
1293 : : real(dp) :: E12,E13,E14,E23,E24,E34
1294 : : real(dp) :: a,b,c,d,e,f
1295 : : complex(dp) zmE(4), verli(4) !, verm(4)
1296 : : !integer :: ii, jj
1297 : :
1298 : 0 : cw = zero
1299 : :
1300 : : ! Min and max energy
1301 : 0 : Emin=eig(1)
1302 : 0 : Emax=eig(4)
1303 : :
1304 : : ! First the complex energy differences
1305 : 0 : zmE = z - eig(:)
1306 : 0 : EZ1=z-eig(1)
1307 : 0 : EZ2=z-eig(2)
1308 : 0 : EZ3=z-eig(3)
1309 : 0 : EZ4=z-eig(4)
1310 : : ! Smallest distance |z-Ei|, to determine whether I should switch to the
1311 : : ! asymptotic behavior for numerical stability.
1312 : : Zdist=huge(Zdist)
1313 : : Zdist=min(Zdist,abs(EZ2))
1314 : : Zdist=min(Zdist,abs(EZ3))
1315 : : Zdist=min(Zdist,abs(EZ4))
1316 : : !@TODO add asymptotic thing with continued fractions
1317 : :
1318 : : ! Then the energy differences, for the coefficients. Must always be positive, I hope.
1319 : 0 : E12=eig(2)-eig(1)
1320 : 0 : E13=eig(3)-eig(1)
1321 : 0 : E14=eig(4)-eig(1)
1322 : 0 : E23=eig(3)-eig(2)
1323 : 0 : E24=eig(4)-eig(2)
1324 : 0 : E34=eig(4)-eig(3)
1325 : 0 : a=zero; if ( E12 .gt. tol ) a=one/E12
1326 : 0 : b=zero; if ( E13 .gt. tol ) b=one/E13
1327 : 0 : c=zero; if ( E14 .gt. tol ) c=one/E14
1328 : 0 : d=zero; if ( E23 .gt. tol ) d=one/E23
1329 : 0 : e=zero; if ( E24 .gt. tol ) e=one/E24
1330 : 0 : f=zero; if ( E34 .gt. tol ) f=one/E34
1331 : :
1332 : : ! Now get the actual weights
1333 : : ! e1=e2=e3=e4
1334 [ # # ]: 0 : if ( E12+E23+E34 .lt. tol ) then
1335 : : #if 0
1336 : : !print *, "e1=e2=e3=e4"
1337 : : cw(1)=0.25_dp/EZ1
1338 : : cw(2)=0.25_dp/EZ2
1339 : : cw(3)=0.25_dp/EZ3
1340 : : cw(4)=0.25_dp/EZ4
1341 : : #else
1342 [ # # ]: 0 : call SIM0TWOI(cw, VERLI, z-eig)
1343 : : #endif
1344 : : ! e2=e3=e4 ! diff wrt simteta
1345 [ # # ]: 0 : elseif ( E23+E34 .lt. tol ) then
1346 : : #if 0
1347 : : !print *, "e2=e3=e4"
1348 : : cw(1)=-a - (3*a**2*EZ2)*half + 3*a**3*EZ1*EZ2 + 3*a**4*EZ1**2*EZ2*Log(EZ2/EZ1)
1349 : : cw(2)=-a - (3*a**2*EZ2)*half + 3*a**3*EZ1*EZ2 + 3*a**4*EZ1**2*EZ2*Log(EZ2/EZ1)
1350 : : cw(3)=-a - (3*a**2*EZ2)*half + 3*a**3*EZ1*EZ2 + 3*a**4*EZ1**2*EZ2*Log(EZ2/EZ1)
1351 : : cw(4)=-a*third + (a**2*EZ1)*half - a**3*EZ1**2 + a**4*EZ1**3*Log(EZ2/EZ1)
1352 : : #else
1353 [ # # ]: 0 : call SIM0TWOI(cw, VERLI, z-eig)
1354 : : #endif
1355 : :
1356 : : ! e1=e2=e3
1357 [ # # ]: 0 : elseif ( E12+E23 .lt. tol ) then
1358 : : #if 0
1359 : : !print *, "e1=e2=e3" ! diff wrt simteta
1360 : : cw(1)=f*third - (EZ4*f**2)*half + EZ4**2*f**3 + EZ4**3*f**4*Log(EZ4/EZ3)
1361 : : cw(2)=f*third - (EZ4*f**2)*half + EZ4**2*f**3 + EZ4**3*f**4*Log(EZ4/EZ3)
1362 : : cw(3)=f*third - (EZ4*f**2)*half + EZ4**2*f**3 + EZ4**3*f**4*Log(EZ4/EZ3)
1363 : : cw(4)=-f + (3*EZ3*f**2)*half - 3*EZ3*EZ4*f**3 + 3*EZ3*EZ4**2*f**4*Log(EZ3/EZ4)
1364 : : #else
1365 [ # # ]: 0 : call SIM0TWOI(cw, VERLI, z-eig)
1366 : : #endif
1367 : : ! e1=e2 e3=e4
1368 [ # # ]: 0 : elseif ( E12+E34 .lt. tol ) then
1369 : : #if 0
1370 : : !print *, "e1=e2 e3=e4" ! FIXME This is Buggy, does not work even with parabolic dispersion
1371 : : cw(1)=-d - (3*d**2*EZ2)*half + 3*d**3*EZ2*EZ3 + 3*d**4*EZ2*EZ3**2*Log(EZ2/EZ3)
1372 : : cw(2)=-d - (3*d**2*EZ2)*half + 3*d**3*EZ2*EZ3 + 3*d**4*EZ2*EZ3**2*Log(EZ2/EZ3)
1373 : : cw(3)=d - (3*d**2*EZ3)*half - 3*d**3*EZ2*EZ3 + 3*d**4*EZ2**2*EZ3*Log(EZ3/EZ2)
1374 : : cw(4)=d - (3*d**2*EZ3)*half - 3*d**3*EZ2*EZ3 + 3*d**4*EZ2**2*EZ3*Log(EZ3/EZ2)
1375 : : #else
1376 : : !cw(1) = nine * EZ3**2 * EZ2 / E23**4 * log(EZ2/EZ3) * EZ2 * (EZ3 -E23)/E23**3 - one/E23
1377 : : !cw(2) = cw(1)
1378 : : !cw(3) = nine * EZ2**2 * EZ3 / E23**4 * log(EZ3/EZ2) * EZ3 * (EZ2 +E23)/E23**3 + one/E23
1379 : : !cw(4) = cw(3)
1380 [ # # ]: 0 : call SIM0TWOI(cw, VERLI, z-eig)
1381 : : !cw = zero
1382 : : #endif
1383 : :
1384 : : ! e3=e4
1385 [ # # ]: 0 : elseif ( E34 .lt. tol ) then
1386 : : !print *, "e3=e4"
1387 : : #if 0
1388 : : cw(1)=-(a*b**2*EZ1**2*(-1 + (a*EZ2 + 2*b*EZ3)*Log(EZ1))) + a**2*d**2*EZ2**3*Log(EZ2) - &
1389 : : b**2*d*EZ3**2*(1 + (2*b*EZ1 + d*EZ2)*Log(EZ3))
1390 : : cw(2)=a**2*b**2*EZ1**3*Log(EZ1) - a*d**2*EZ2**2*(1 + (a*EZ1 - 2*d*EZ3)*Log(EZ2)) - &
1391 : : b*d**2*EZ3**2*(1 + (b*EZ1 + 2*d*EZ2)*Log(EZ3))
1392 : : cw(3)=a*b**3*EZ1**3*Log(EZ1) - a*d**3*EZ2**3*Log(EZ2) + b*d*EZ3*(half + b*EZ1 + d*EZ2 + &
1393 : : (b**2*EZ1**2 + b*d*EZ1*EZ2 + d**2*EZ2**2)*Log(EZ3))
1394 : : cw(4)=a*b**3*EZ1**3*Log(EZ1) - a*d**3*EZ2**3*Log(EZ2) + b*d*EZ3*(half + b*EZ1 + d*EZ2 + &
1395 : : (b**2*EZ1**2 + b*d*EZ1*EZ2 + d**2*EZ2**2)*Log(EZ3))
1396 : : #else
1397 [ # # ]: 0 : call SIM0TWOI(cw, VERLI, z-eig)
1398 : : #endif
1399 : : ! e2=e3
1400 [ # # ]: 0 : elseif ( E23 .lt. tol ) then
1401 : : #if 0
1402 : : !print *, "e2=e3"
1403 : : cw(1)=-(a**2*c*EZ1**2*(-1 + (2*a*EZ2 + c*EZ4)*Log(EZ1))) + &
1404 : : a**2*e*EZ2**2*(1 + (2*a*EZ1 - e*EZ4)*Log(EZ2)) + c**2*e**2*EZ4**3*Log(EZ4)
1405 : : cw(2)=a**3*c*EZ1**3*Log(EZ1) - &
1406 : : a*e*EZ2*(half + a*EZ1 - e*EZ4 + (a**2*EZ1**2 - a*e*EZ1*EZ4 + e**2*EZ4**2)*Log(EZ2)) + c*e**3*EZ4**3*Log(EZ4)
1407 : : cw(3)=a**3*c*EZ1**3*Log(EZ1) - &
1408 : : a*e*EZ2*(half + a*EZ1 - e*EZ4 + (a**2*EZ1**2 - a*e*EZ1*EZ4 + e**2*EZ4**2)*Log(EZ2)) + c*e**3*EZ4**3*Log(EZ4)
1409 : : cw(4)=a**2*c**2*EZ1**3*Log(EZ1) - &
1410 : : a*e**2*EZ2**2*(1 + (a*EZ1 - 2*e*EZ4)*Log(EZ2)) - c*e**2*EZ4**2*(1 + (c*EZ1 + 2*e*EZ2)*Log(EZ4))
1411 : : #else
1412 [ # # ]: 0 : call SIM0TWOI(cw, VERLI, z-eig)
1413 : : #endif
1414 : :
1415 : : ! e1=e2
1416 [ # # ]: 0 : elseif ( E12 .lt. tol ) then
1417 : : !print *, "e1=e2"
1418 : : #if 0
1419 : : cw(1)=b*c*EZ1*(half - b*EZ3 - c*EZ4 + (b**2*EZ3**2 + b*c*EZ3*EZ4 + c**2*EZ4**2)*Log(EZ1)) - &
1420 : : b**3*EZ3**3*f*Log(EZ3) + c**3*EZ4**3*f*Log(EZ4)
1421 : : cw(2)=b*c*EZ1*(half - b*EZ3 - c*EZ4 + (b**2*EZ3**2 + b*c*EZ3*EZ4 + c**2*EZ4**2)*Log(EZ1)) - &
1422 : : b**3*EZ3**3*f*Log(EZ3) + c**3*EZ4**3*f*Log(EZ4)
1423 : : cw(3)=-(b**2*c*EZ1**2*(-1 + (2*b*EZ3 + c*EZ4)*Log(EZ1))) + &
1424 : : b**2*EZ3**2*f*(1 + (2*b*EZ1 - EZ4*f)*Log(EZ3)) + c**2*EZ4**3*f**2*Log(EZ4)
1425 : : cw(4)=-(b*c**2*EZ1**2*(-1 + (b*EZ3 + 2*c*EZ4)*Log(EZ1))) + &
1426 : : b**2*EZ3**3*f**2*Log(EZ3) - c**2*EZ4**2*f*(1 + (2*c*EZ1 + EZ3*f)*Log(EZ4))
1427 : : #else
1428 [ # # ]: 0 : call SIM0TWOI(cw, VERLI, z-eig)
1429 : : #endif
1430 : : ! e1<e2<e3<e4
1431 : : else
1432 : : !print *, "e1<e2<e3<e4"
1433 : : #if 0
1434 : : cw(1)=a**2*d*e*EZ2**3*Log(EZ2/EZ1) - b**2*d*EZ3**3*f*Log(EZ3/EZ1) + c*(a*b*EZ1**2 + c*e*EZ4**3*f*Log(EZ4/EZ1))
1435 : : cw(2)=a**2*b*c*EZ1**3*Log(EZ1/EZ2) - b*d**2*EZ3**3*f*Log(EZ3/EZ2) + e*(-(a*d*EZ2**2) + c*e*EZ4**3*f*Log(EZ4/EZ2))
1436 : : cw(3)=a*b**2*c*EZ1**3*Log(EZ1/EZ3) - a*d**2*e*EZ2**3*Log(EZ2/EZ3) + f*(b*d*EZ3**2 + c*e*EZ4**3*f*Log(EZ4/EZ3))
1437 : : cw(4)=a*b*c**2*EZ1**3*Log(EZ1/EZ4) - a*d*e**2*EZ2**3*Log(EZ2/EZ4) + f*(-(c*e*EZ4**2) + b*d*EZ3**3*f*Log(EZ3/EZ4))
1438 : : #else
1439 : : !do ii=1,4
1440 : : ! cw(ii) = zme(ii) ** 2 / prod_wo(ii)
1441 : : ! do jj=1,4
1442 : : ! if (jj == ii) cycle
1443 : : ! cw(ii) = cw(ii) + (zme(jj)**3 / prod_wo(jj) * log(zme(jj) / zme(ii)) / (eig(ii) - eig(jj)))
1444 : : ! end do
1445 : : !end do
1446 : :
1447 [ # # ]: 0 : call SIM0TWOI(cw, VERLI, z-eig)
1448 : : #endif
1449 : : endif
1450 : :
1451 : : ! HM:check this
1452 : : !cw = cw * two
1453 : :
1454 : : contains
1455 : : pure real(dp) function prod_wo(ii)
1456 : : integer,intent(in) :: ii
1457 : : integer :: kk
1458 : :
1459 : : prod_wo = one
1460 : : do kk=1,4
1461 : : if (kk == ii) cycle
1462 : : prod_wo = prod_wo * (eig(kk) - eig(ii))
1463 : : end do
1464 : : end function prod_wo
1465 : :
1466 : : end subroutine get_onetetra_lambinvigneron
1467 : : !!***
1468 : :
1469 : : !!****f* m_htetra/get_ontetratra_lambinvigneron_imag
1470 : : !! NAME
1471 : : !! get_ontetratra_lambinvigneron_imag
1472 : : !!
1473 : : !! FUNCTION
1474 : : !! Compute the complex weights according to:
1475 : : !! P. Lambin and J.P. Vigneron, Phys. Rev. B 29, 3430 (1984)
1476 : : !! This routine is adapted from tdep where it was implemented
1477 : : !! by Olle Hellman, all credits go to him
1478 : : !!
1479 : : !! INPUTS
1480 : : !!
1481 : : !! OUTPUT
1482 : : !!
1483 : : !! SOURCE
1484 : :
1485 : 0 : pure subroutine get_onetetetra_lambinvigneron_imag(eig, energies, nene, wt)
1486 : :
1487 : : ! dispersion values at the corners of the tetrahedron
1488 : : real(dp), intent(in), dimension(4) :: eig
1489 : : ! number of energies
1490 : : integer, intent(in) :: nene
1491 : : ! energy to evaluate the weights at
1492 : : real(dp), intent(in) :: energies(nene)
1493 : : ! integration weights
1494 : : real(dp), intent(out) :: wt(4,nene)
1495 : :
1496 : : integer :: ie
1497 : : real(dp) :: z
1498 : : real(dp) :: EZ1,EZ2,EZ3,EZ4
1499 : : real(dp) :: Emin,Emax
1500 : : real(dp) :: E12,E13,E14,E23,E24,E34
1501 : : real(dp) :: a,b,c,d,e,f,ff0,ff1,ff2,ff3,gg0,gg1,gg2,gg3,hh0,hh1,hh2,hh3,ii0,ii1,ii2,ii3
1502 : :
1503 [ # # # # ]: 0 : wt = zero
1504 : : Emin = eig(1)
1505 : : Emax = eig(4)
1506 : :
1507 [ # # ]: 0 : do ie=1,nene
1508 : 0 : z = energies(ie)
1509 [ # # ]: 0 : if (z<eig(1)) then ! e<e1<e2<e3<e4
1510 : : cycle
1511 [ # # ]: 0 : else if (z .lt. eig(2)) then ! e1<e<e2<e3<e4
1512 : 0 : EZ1=z-eig(1)
1513 : 0 : EZ2=z-eig(2)
1514 : 0 : EZ3=z-eig(3)
1515 : 0 : EZ4=z-eig(4)
1516 : 0 : E12=eig(2)-eig(1)
1517 : 0 : E13=eig(3)-eig(1)
1518 : 0 : E14=eig(4)-eig(1)
1519 : 0 : a=one/E12
1520 : 0 : b=one/E13
1521 : 0 : c=one/E14
1522 : 0 : wt(1,ie)=a*b*c*EZ1**2*(-a*EZ2 - b*EZ3 - c*EZ4)
1523 : 0 : wt(2,ie)=a**2*b*c*EZ1**3
1524 : 0 : wt(3,ie)=a*b**2*c*EZ1**3
1525 : 0 : wt(4,ie)=a*b*c**2*EZ1**3
1526 : 0 : cycle
1527 [ # # ]: 0 : else if (z .lt. eig(3)) then ! e1<e2<e<e3<e4
1528 : 0 : EZ1=z-eig(1)
1529 : 0 : EZ2=z-eig(2)
1530 : 0 : EZ3=z-eig(3)
1531 : 0 : EZ4=z-eig(4)
1532 : 0 : E13=eig(3)-eig(1)
1533 : 0 : E14=eig(4)-eig(1)
1534 : 0 : E23=eig(3)-eig(2)
1535 : 0 : E24=eig(4)-eig(2)
1536 : 0 : b=one/E13
1537 : 0 : c=one/E14
1538 : 0 : d=one/E23
1539 : 0 : e=one/E24
1540 : 0 : ff0=-b**2*EZ3
1541 : 0 : ff2=-c**2*EZ4
1542 : 0 : gg0=-d**2*EZ3
1543 : 0 : gg2=-e**2*EZ4
1544 : 0 : hh0=d**2*EZ2
1545 : 0 : hh2=b**2*EZ1
1546 : 0 : ii0=e**2*EZ2
1547 : 0 : ii2=c**2*EZ1
1548 : 0 : ff1=-c*d*EZ1*EZ3-d*e*EZ2*EZ3-c*e*EZ1*EZ4
1549 : 0 : ff3=-b*d*EZ1*EZ3-b*e*EZ1*EZ4-d*e*EZ2*EZ4
1550 : 0 : gg1=-b*c*EZ1*EZ3-b*e*EZ2*EZ3-c*e*EZ2*EZ4
1551 : 0 : gg3=-b*d*EZ2*EZ3-b*c*EZ1*EZ4-c*d*EZ2*EZ4
1552 : 0 : hh1=-b*c*EZ1*EZ3-b*e*EZ2*EZ3-c*e*EZ2*EZ4
1553 : 0 : hh3=-c*d*EZ1*EZ3-d*e*EZ2*EZ3-c*e*EZ1*EZ4
1554 : 0 : ii1=-b*d*EZ2*EZ3-b*c*EZ1*EZ4-c*d*EZ2*EZ4
1555 : 0 : ii3=-b*d*EZ1*EZ3-b*e*EZ1*EZ4-d*e*EZ2*EZ4
1556 : 0 : wt(1,ie)=half*(ff0*ff1+ff2*ff3)
1557 : 0 : wt(2,ie)=half*(gg0*gg1+gg2*gg3)
1558 : 0 : wt(3,ie)=half*(hh0*hh1+hh2*hh3)
1559 : 0 : wt(4,ie)=half*(ii0*ii1+ii2*ii3)
1560 : 0 : cycle
1561 [ # # ]: 0 : else if (z .lt. eig(4)) then ! e1<e2<e3<e<e4
1562 : 0 : EZ1=z-eig(1)
1563 : 0 : EZ2=z-eig(2)
1564 : 0 : EZ3=z-eig(3)
1565 : 0 : EZ4=z-eig(4)
1566 : 0 : E14=eig(4)-eig(1)
1567 : 0 : E24=eig(4)-eig(2)
1568 : 0 : E34=eig(4)-eig(3)
1569 : 0 : c=one/E14
1570 : 0 : e=one/E24
1571 : 0 : f=one/E34
1572 : 0 : wt(1,ie)=-(c**2*e*EZ4**3*f)
1573 : 0 : wt(2,ie)=-(c*e**2*EZ4**3*f)
1574 : 0 : wt(3,ie)=-(c*e*EZ4**3*f**2)
1575 : 0 : wt(4,ie)=c*e*EZ4**2*f*(c*EZ1 + e*EZ2 + EZ3*f)
1576 : 0 : cycle
1577 : : else
1578 : 0 : exit
1579 : : end if
1580 : : end do
1581 [ # # # # ]: 0 : wt = wt*4.0_dp
1582 : :
1583 : 0 : end subroutine get_onetetetra_lambinvigneron_imag
1584 : : !!***
1585 : :
1586 : : !----------------------------------------------------------------------
1587 : :
1588 : : !!****f* m_htetra/htetra_get_onewk_wvals
1589 : : !! NAME
1590 : : !! htetra_get_onewk_wvals
1591 : : !!
1592 : : !! FUNCTION
1593 : : !! Calculate integration weights and their derivatives for a single k-point in the IBZ.
1594 : : !!
1595 : : !! INPUTS
1596 : : !! ik_ibz=Index of the k-point in the IBZ array
1597 : : !! bcorr=1 to include Blochl correction else 0.
1598 : : !! nw=number of energies in wvals
1599 : : !! nibz=number of irreducible kpoints
1600 : : !! wvals(nw)=Frequency points.
1601 : : !! eigen_ibz(nkibz)=eigenenergies for each k point
1602 : : !!
1603 : : !! OUTPUT
1604 : : !! weights(nw,2) = integration weights for
1605 : : !! Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
1606 : : !! for a given (band, k-point, spin).
1607 : : !!
1608 : : !! SOURCE
1609 : :
1610 : 100721 : subroutine htetra_get_onewk_wvals(tetra, ik_ibz, opt, nw, wvals, max_occ, nkibz, eig_ibz, weights)
1611 : :
1612 : : !Arguments ------------------------------------
1613 : : !scalars
1614 : : class(htetra_t), intent(inout) :: tetra
1615 : : integer,intent(in) :: ik_ibz,nw,nkibz,opt
1616 : : real(dp),intent(in) :: max_occ
1617 : : !arrays
1618 : : real(dp),intent(in) :: wvals(nw), eig_ibz(nkibz)
1619 : : real(dp),intent(out) :: weights(nw, 2)
1620 : :
1621 : : !Local variables-------------------------------
1622 : : !scalars
1623 : : integer :: itetra,isummit,tetra_count,tetra_total
1624 : : real(dp) :: tweight
1625 : : !arrays
1626 : : integer :: ind_ibz(4),tetra_mibz(0:4)
1627 : 100721 : real(dp) :: eig(4), tweight_tmp(4,nw),dweight_tmp(4,nw)
1628 : : ! *********************************************************************
1629 : :
1630 [ + + + + ]: 224806779 : weights = zero
1631 : : ! lazy evaluation of the mapping from k-points to tetrahedra
1632 [ + + ]: 100721 : if (.not.allocated(tetra%ibz)) call htetra_init_mapping_ibz(tetra)
1633 : :
1634 : : ! For each tetrahedron that belongs to this k-point
1635 : 100721 : tetra_count = tetra%tetra_count(ik_ibz)
1636 : 100721 : tetra_total = tetra%tetra_total(ik_ibz)
1637 [ + + ]: 15810881 : do itetra=1,tetra_count
1638 : :
1639 : 15710160 : call htetra_get_ibz(tetra, ik_ibz, itetra, tetra_mibz)
1640 : 15710160 : tweight = one*tetra_mibz(0) / tetra_total
1641 [ + + ]: 78550800 : do isummit=1,4
1642 : : ! Get mapping of each summit to eig_ibz
1643 : 62840640 : ind_ibz(isummit) = tetra_mibz(isummit)
1644 : 78550800 : eig(isummit) = eig_ibz(ind_ibz(isummit))
1645 : : end do
1646 : :
1647 : : ! Sort energies before calling get_onetetra_blochl
1648 : 15710160 : call sort_4tetra(eig, ind_ibz)
1649 : :
1650 : : ! HM: Here we should only compute what we will use!
1651 : 31420320 : select case (opt)
1652 : : case (0:1)
1653 : 15710160 : call get_onetetra_blochl(eig, wvals, nw, opt, tweight_tmp, dweight_tmp)
1654 : : case (2)
1655 : 0 : call get_onetetetra_lambinvigneron_imag(eig, wvals, nw, dweight_tmp)
1656 [ + - - - : 15710160 : tweight_tmp = zero
- - - ]
1657 : : end select
1658 : :
1659 : : ! Accumulate contributions to ik_ibz (there might be multiple vertices that map onto ik_ibz)
1660 [ + - ]: 38922106 : do isummit=1,4
1661 [ + + ]: 38821385 : if (ind_ibz(isummit) /= ik_ibz) cycle
1662 [ + + ]: 13286034336 : weights(:,1) = weights(:,1) + dweight_tmp(isummit,:)*tweight*max_occ
1663 [ + + ]: 13286034336 : weights(:,2) = weights(:,2) + tweight_tmp(isummit,:)*tweight*max_occ
1664 : : ! HM: This exit is important, avoids summing the same contribution more than once
1665 : 23111225 : exit
1666 : : end do
1667 : : end do ! itetra
1668 : :
1669 : 100721 : end subroutine htetra_get_onewk_wvals
1670 : : !!***
1671 : :
1672 : : !----------------------------------------------------------------------
1673 : :
1674 : : !!****f* m_htetra/tetra_get_onewk
1675 : : !! NAME
1676 : : !! tetra_get_onewk
1677 : : !!
1678 : : !! FUNCTION
1679 : : !! Calculate integration weights and their derivatives for a single k-point in the IBZ.
1680 : : !! Same as above but different calling arguments.
1681 : : !! IBZ Weights are not included
1682 : : !! HM: The above is preferred but I keep this one to ease the transition
1683 : : !!
1684 : : !! INPUTS
1685 : : !!
1686 : : !! OUTPUT
1687 : : !!
1688 : : !! SOURCE
1689 : :
1690 : 12326 : subroutine htetra_get_onewk(tetra, ik_ibz, bcorr, nw, nkibz, eig_ibz, enemin, enemax, max_occ, weights)
1691 : :
1692 : : !Arguments ------------------------------------
1693 : : !scalars
1694 : : class(htetra_t), intent(inout) :: tetra
1695 : : integer,intent(in) :: ik_ibz,nw,nkibz,bcorr
1696 : : real(dp) ,intent(in) :: enemin,enemax,max_occ
1697 : : !arrays
1698 : : real(dp),intent(in) :: eig_ibz(nkibz)
1699 : : real(dp),intent(out) :: weights(nw,2)
1700 : :
1701 : : !Local variables-------------------------------
1702 : : !scalars
1703 : 12326 : real(dp) :: wvals(nw)
1704 : : ! *********************************************************************
1705 : :
1706 [ + + + + ]: 63510798 : weights = zero
1707 : 12326 : wvals = linspace(enemin, enemax, nw)
1708 : 12326 : call htetra_get_onewk_wvals(tetra, ik_ibz, bcorr, nw, wvals, max_occ, nkibz, eig_ibz, weights)
1709 : :
1710 : 12326 : end subroutine htetra_get_onewk
1711 : : !!***
1712 : :
1713 : : !----------------------------------------------------------------------
1714 : :
1715 : : !!****f* m_htetra/htetra_get_onewk_wvals_zinv
1716 : : !! NAME
1717 : : !! htetra_get_onewk_wvals_zinv
1718 : : !!
1719 : : !! FUNCTION
1720 : : !! Calculate integration weights for 1/(z-E(k)) for a single k-point in the IBZ.
1721 : : !! Using either the implementation from:
1722 : : !! S. Kaprzyk, Computer Physics Communications 183, 347 (2012).
1723 : : !! or (TODO)
1724 : : !! P. Lambin and J.P. Vigneron, Phys. Rev. B 29, 3430 (1984).
1725 : : !!
1726 : : !! INPUTS
1727 : : !! ik_ibz=Index of the k-point in the IBZ array
1728 : : !! bcorr=1 to include Blochl correction else 0.
1729 : : !! nw=number of energies in wvals
1730 : : !! nibz=number of irreducible kpoints
1731 : : !! wvals(nw)=Frequency points.
1732 : : !! eigen_ibz(nkibz)=eigenenergies for each k point
1733 : : !! opt: 1 for S. Kaprzyk routines, 2 for Lambin.
1734 : : !!
1735 : : !! OUTPUT
1736 : : !! weights(nw,2) = integration weights for
1737 : : !! Dirac delta (derivative of theta wrt energy) and Theta (Heaviside function)
1738 : : !! for a given (band, k-point, spin).
1739 : : !! [erange(2)]: if present, weights are computed with an approximated asyntotic expression if
1740 : : !! real(z) is outside of this interval and with tetra if inside.
1741 : : !!
1742 : : !! SOURCE
1743 : :
1744 : 0 : subroutine htetra_get_onewk_wvals_zinv(tetra, ik_ibz, nz, zvals, max_occ, nkibz, eig_ibz, opt, cweights, erange)
1745 : :
1746 : : !Arguments ------------------------------------
1747 : : !scalars
1748 : : class(htetra_t), intent(inout) :: tetra
1749 : : integer,intent(in) :: ik_ibz,nz,nkibz,opt
1750 : : real(dp) ,intent(in) :: max_occ
1751 : : !arrays
1752 : : complex(dp),intent(in) :: zvals(nz)
1753 : : real(dp),optional,intent(in) :: erange(2)
1754 : : real(dp),intent(in) :: eig_ibz(nkibz)
1755 : : complex(dp),intent(out) :: cweights(nz)
1756 : :
1757 : : !Local variables-------------------------------
1758 : : !scalars
1759 : : integer :: itetra,isummit,tetra_total,tetra_count,iz
1760 : : real(dp) :: tweight
1761 : : !arrays
1762 : : integer :: ind_ibz(4),tetra_mibz(0:4)
1763 : : real(dp) :: eig(4), my_erange(2)
1764 : : complex(dp) :: verm(4), cw(4), verli(4)
1765 : : ! *********************************************************************
1766 : :
1767 [ # # ]: 0 : cweights = zero
1768 : : ! lazy evaluation of the mapping from k-points to tetrahedra
1769 [ # # ]: 0 : if (.not.allocated(tetra%ibz)) call htetra_init_mapping_ibz(tetra)
1770 : :
1771 [ # # ]: 0 : if (all(opt /= [1, 2])) then
1772 : 0 : ABI_ERROR(sjoin("Invalid opt:", itoa(opt)))
1773 : : end if
1774 : :
1775 [ # # ]: 0 : my_erange = [-huge(one), huge(one)]; if (present(erange)) my_erange = erange
1776 : :
1777 : : ! For each tetrahedron that belongs to this k-point
1778 : 0 : tetra_count = tetra%tetra_count(ik_ibz)
1779 : 0 : tetra_total = tetra%tetra_total(ik_ibz)
1780 [ # # ]: 0 : do itetra=1,tetra_count
1781 : :
1782 : 0 : call htetra_get_ibz(tetra, ik_ibz, itetra, tetra_mibz)
1783 : 0 : tweight = one * tetra_mibz(0) / tetra_total
1784 [ # # ]: 0 : do isummit=1,4
1785 : : ! Get mapping of each summit to eig_ibz
1786 : 0 : ind_ibz(isummit) = tetra_mibz(isummit)
1787 : 0 : eig(isummit) = eig_ibz(ind_ibz(isummit))
1788 : : end do
1789 : :
1790 : : ! Loop over frequencies
1791 [ # # ]: 0 : do iz=1,nz
1792 : :
1793 [ # # # # ]: 0 : if (real(zvals(iz)) >= my_erange(1) .and. real(zvals(iz)) <= my_erange(2)) then
1794 : 0 : select case(opt)
1795 : : case (1)
1796 [ # # ]: 0 : verm = zvals(iz) - eig
1797 : 0 : call SIM0TWOI(cw, VERLI, VERM)
1798 : : case (2)
1799 [ # # # ]: 0 : call get_onetetra_lambinvigneron(eig, zvals(iz), cw)
1800 : : end select
1801 : : else
1802 [ # # ]: 0 : cw = (one / (zvals(iz) - eig)) / four !* tetra%vv
1803 : : end if
1804 : :
1805 [ # # ]: 0 : do isummit=1,4
1806 [ # # ]: 0 : if (ind_ibz(isummit) /= ik_ibz) cycle
1807 : 0 : cweights(iz) = cweights(iz) + cw(isummit) * tweight * max_occ
1808 : : ! HM: This exit is important, avoids summing the same contribution more than once
1809 : 0 : exit
1810 : : end do
1811 : : end do
1812 : : end do ! itetra
1813 : :
1814 : 0 : end subroutine htetra_get_onewk_wvals_zinv
1815 : : !!***
1816 : :
1817 : : !----------------------------------------------------------------------
1818 : :
1819 : : !!****f* m_htetra/htetra_get_delta_mask
1820 : : !! NAME
1821 : : !! htetra_get_delta_mask
1822 : : !!
1823 : : !! FUNCTION
1824 : : !! Get a mask for the kpoints where the delta is finite
1825 : : !!
1826 : :
1827 : : subroutine htetra_get_delta_mask(tetra, eig_ibz, wvals, nw, nkpt, kmask, comm)
1828 : :
1829 : : !Arguments
1830 : : class(htetra_t), intent(in) :: tetra
1831 : : integer,intent(in) :: nw,nkpt,comm
1832 : : real(dp),intent(in) :: wvals(nw)
1833 : : real(dp),intent(in) :: eig_ibz(nkpt)
1834 : : integer,intent(out) :: kmask(nkpt)
1835 : :
1836 : : !Local variables-------------------------------
1837 : : integer :: ik_ibz,nprocs,my_rank,ierr, contrib
1838 : : integer :: tetra_count, itetra, isummit, ihash
1839 : : real(dp) :: emin,emax
1840 : : integer :: ind_ibz(4)
1841 : : real(dp) :: eig(4)
1842 : :
1843 : : nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
1844 : : kmask = 0
1845 : : ! For each bucket of tetrahedra
1846 : : do ihash=1,tetra%nbuckets
1847 : : if (mod(ihash,nprocs) /= my_rank) cycle
1848 : :
1849 : : ! For each tetrahedron
1850 : : tetra_count = size(tetra%unique_tetra(ihash)%indexes, dim=2)
1851 : : do itetra=1,tetra_count
1852 : :
1853 : : ! Get mapping of each summit to eig_ibz
1854 : : do isummit=1,4
1855 : : ind_ibz(isummit) = tetra%unique_tetra(ihash)%indexes(isummit, itetra)
1856 : : eig(isummit) = eig_ibz(ind_ibz(isummit))
1857 : : end do
1858 : :
1859 : : ! Determine the energy range of the tetrahedra
1860 : : emin = minval(eig)
1861 : : emax = maxval(eig)
1862 : :
1863 : : ! Check if any value in wvals is between emin and emax
1864 : : contrib = 0; if (any(emin < wvals .and. wvals < emax)) contrib = 1
1865 : :
1866 : : ! Compute the union
1867 : : do isummit=1,4
1868 : : ik_ibz = ind_ibz(isummit)
1869 : : kmask(ik_ibz) = kmask(ik_ibz) + contrib
1870 : : end do
1871 : : end do ! itetra
1872 : : end do
1873 : :
1874 : : call xmpi_sum(kmask, comm, ierr)
1875 : :
1876 : : end subroutine htetra_get_delta_mask
1877 : : !!***
1878 : :
1879 : : !----------------------------------------------------------------------
1880 : :
1881 : : !!****f* m_htetra/htetra_wvals_weights
1882 : : !! NAME
1883 : : !! htetra_wvals_weights
1884 : : !!
1885 : : !! FUNCTION
1886 : : !! Emulates the behaviour of the previous tetrahedron implementation but
1887 : : !! taking a list of energies as input.
1888 : : !!
1889 : : !! HM: I find that in many routines its better to change the implementation
1890 : : !! and accumulate the tetrahedron weights in the same way as the
1891 : : !! gaussian smearing weights using htetra_get_onewk_wvals. However this requires
1892 : : !! some refactoring of the code. I provide this routine to make it easier
1893 : : !! to transition to the new tetrahedron implementation without refactoring.
1894 : : !! Looping over tetrahedra (i.e. using tetra_blochl_weights) is currently faster
1895 : : !! than looping over k-points.
1896 : : !!
1897 : : !! MG: Note, however, that tetra_blochl_weights requires more memory as
1898 : : !! one has to allocate dweight(nw,nkpt),tweight(nw,nkpt) and the size of the arrays increases
1899 : : !! quickly with the k-mesh and the number of frequencies (propto mband)
1900 : : !!
1901 : : !! INPUTS
1902 : : !!
1903 : : !! OUTPUT
1904 : : !!
1905 : : !! SOURCE
1906 : :
1907 : 118 : subroutine htetra_wvals_weights(tetra, eig_ibz, nw, wvals, max_occ, nkpt, opt, tweight, dweight, comm)
1908 : :
1909 : : !Arguments ------------------------------------
1910 : : !scalars
1911 : : integer,intent(in) :: nw,nkpt,opt,comm
1912 : : class(htetra_t), intent(in) :: tetra
1913 : : real(dp) ,intent(in) :: max_occ
1914 : : !arrays
1915 : : real(dp),intent(in) :: eig_ibz(nkpt)
1916 : : real(dp),intent(out) :: dweight(nw,nkpt),tweight(nw,nkpt)
1917 : :
1918 : : !Local variables-------------------------------
1919 : : !scalars
1920 : : integer :: ik_ibz,multiplicity,nprocs,my_rank,ierr
1921 : : integer :: tetra_count, itetra, isummit, ihash
1922 : : !arrays
1923 : : integer :: ind_ibz(4)
1924 : 118 : real(dp) :: eig(4), wvals(nw), dweight_tmp(4,nw),tweight_tmp(4,nw)
1925 : : ! *********************************************************************
1926 : :
1927 [ + + + + : 10409956 : tweight = zero; dweight = zero
+ + + + ]
1928 : 118 : nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
1929 : :
1930 : : ! For each bucket of tetrahedra
1931 [ + + ]: 5994 : do ihash=1,tetra%nbuckets
1932 [ + - ]: 5876 : if (mod(ihash, nprocs) /= my_rank) cycle
1933 : :
1934 : : ! For each tetrahedron
1935 : 5876 : tetra_count = size(tetra%unique_tetra(ihash)%indexes, dim=2)
1936 [ + + ]: 105152 : do itetra=1,tetra_count
1937 : :
1938 : : ! Get mapping of each summit to eig_ibz
1939 [ + + ]: 495790 : do isummit=1,4
1940 : 396632 : ind_ibz(isummit) = tetra%unique_tetra(ihash)%indexes(isummit, itetra)
1941 : 495790 : eig(isummit) = eig_ibz(ind_ibz(isummit))
1942 : : end do
1943 : :
1944 : : ! Sort energies before calling get_onetetra_blochl
1945 : 99158 : call sort_4tetra(eig, ind_ibz)
1946 : :
1947 : : ! Get tetrahedron weights
1948 : 198316 : select case (opt)
1949 : : case (0:1)
1950 : 99158 : call get_onetetra_blochl(eig, wvals, nw, opt, tweight_tmp, dweight_tmp)
1951 : : case (2)
1952 : 0 : call get_onetetetra_lambinvigneron_imag(eig, wvals, nw, dweight_tmp)
1953 [ + - - - : 99158 : tweight_tmp = zero
- - - ]
1954 : : end select
1955 : :
1956 : : ! Accumulate the contributions
1957 : 99158 : multiplicity = tetra%unique_tetra(ihash)%indexes(0, itetra)
1958 [ + + ]: 501666 : do isummit=1,4
1959 : 396632 : ik_ibz = ind_ibz(isummit)
1960 [ + + ]: 337052272 : dweight(:,ik_ibz) = dweight(:,ik_ibz) + dweight_tmp(isummit,:) * multiplicity * max_occ
1961 [ + + ]: 337151430 : tweight(:,ik_ibz) = tweight(:,ik_ibz) + tweight_tmp(isummit,:) * multiplicity * max_occ
1962 : : end do
1963 : : end do ! itetra
1964 : : end do
1965 : :
1966 : : ! Rescale weights
1967 : 118 : select case(tetra%opt)
1968 : : case (1)
1969 [ # # ]: 0 : do ik_ibz=1,tetra%nkibz
1970 [ # # ]: 0 : dweight(:,ik_ibz) = dweight(:,ik_ibz) * tetra%ibz_multiplicity(ik_ibz) / tetra%tetra_total(ik_ibz) / tetra%nkbz
1971 [ # # ]: 0 : tweight(:,ik_ibz) = tweight(:,ik_ibz) * tetra%ibz_multiplicity(ik_ibz) / tetra%tetra_total(ik_ibz) / tetra%nkbz
1972 : : end do
1973 : : case (2)
1974 [ + + + + ]: 5204978 : dweight = dweight*tetra%vv / 4.0_dp
1975 [ - + - + : 5205096 : tweight = tweight*tetra%vv / 4.0_dp
+ + + ]
1976 : : end select
1977 : :
1978 : 118 : call xmpi_sum(dweight, comm, ierr)
1979 : 118 : call xmpi_sum(tweight, comm, ierr)
1980 : :
1981 : 118 : end subroutine htetra_wvals_weights
1982 : : !!***
1983 : :
1984 : : !----------------------------------------------------------------------
1985 : :
1986 : : !!****f* m_htetra/htetra_wvals_weights_delta
1987 : : !! NAME
1988 : : !! htetra_wvals_weights_delta
1989 : : !!
1990 : : !! FUNCTION
1991 : : !! Same as above but computing only delta for performance and memory
1992 : : !! HM: Should find a clean way to avoid copy paste routine
1993 : : !!
1994 : : !! SOURCE
1995 : :
1996 : 30216 : subroutine htetra_wvals_weights_delta(tetra, eig_ibz, nw, wvals, max_occ, nkpt, opt, dweight, comm)
1997 : :
1998 : : !Arguments ------------------------------------
1999 : : !scalars
2000 : : class(htetra_t), intent(in) :: tetra
2001 : : integer,intent(in) :: nw, nkpt, opt, comm
2002 : : real(dp),intent(in) :: max_occ
2003 : : !arrays
2004 : : real(dp),intent(in) :: eig_ibz(nkpt), wvals(nw)
2005 : : real(dp),intent(out) :: dweight(nw, nkpt)
2006 : :
2007 : : !Local variables-------------------------------
2008 : : !scalars
2009 : : integer :: ik_ibz,multiplicity,nprocs,my_rank,ierr
2010 : : integer :: tetra_count, itetra, isummit, ihash
2011 : : !arrays
2012 : : integer :: ind_ibz(4)
2013 : 30216 : real(dp) :: eig(4), dweight_tmp(4,nw),tweight_tmp(4,nw)
2014 : : ! *********************************************************************
2015 : :
2016 [ + + + + ]: 13066728 : dweight = zero
2017 : 30216 : nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
2018 : :
2019 : : ! For each bucket of tetrahedra
2020 [ + + ]: 6548472 : do ihash=1,tetra%nbuckets
2021 [ + - ]: 6518256 : if (mod(ihash, nprocs) /= my_rank) cycle
2022 : :
2023 : : ! For each tetrahedron
2024 : 6518256 : tetra_count = size(tetra%unique_tetra(ihash)%indexes, dim=2)
2025 [ + + ]: 129322080 : do itetra=1,tetra_count
2026 : :
2027 : : ! Get mapping of each summit to eig_ibz
2028 [ + + ]: 613868040 : do isummit=1,4
2029 : 491094432 : ind_ibz(isummit) = tetra%unique_tetra(ihash)%indexes(isummit,itetra)
2030 : 613868040 : eig(isummit) = eig_ibz(ind_ibz(isummit))
2031 : : end do
2032 : :
2033 : : ! Sort energies before calling get_onetetra_blochl
2034 : 122773608 : call sort_4tetra(eig, ind_ibz)
2035 : :
2036 : : ! Get tetrahedron weights
2037 : 245547216 : select case (opt)
2038 : : case (0:1)
2039 : 122773608 : call get_onetetra_blochl(eig, wvals, nw, opt, tweight_tmp, dweight_tmp)
2040 : : case (2)
2041 [ + - - ]: 122773608 : call get_onetetetra_lambinvigneron_imag(eig, wvals, nw, dweight_tmp)
2042 : : end select
2043 : :
2044 : : ! Accumulate the contributions
2045 : 122773608 : multiplicity = tetra%unique_tetra(ihash)%indexes(0,itetra)
2046 [ + + ]: 620386296 : do isummit=1,4
2047 : 491094432 : ik_ibz = ind_ibz(isummit)
2048 [ + + ]: 1104962472 : dweight(:,ik_ibz) = dweight(:,ik_ibz) + dweight_tmp(isummit,:)*multiplicity*max_occ
2049 : : end do
2050 : : end do ! itetra
2051 : : end do
2052 : :
2053 : : ! Rescale weights
2054 : 30216 : select case(tetra%opt)
2055 : : case (1)
2056 [ # # ]: 0 : do ik_ibz=1,tetra%nkibz
2057 [ # # ]: 0 : dweight(:,ik_ibz) = dweight(:,ik_ibz) * tetra%ibz_multiplicity(ik_ibz) / tetra%tetra_total(ik_ibz) / tetra%nkbz
2058 : : end do
2059 : : case (2)
2060 [ - + - + : 13066728 : dweight = dweight * tetra%vv / 4.0_dp
+ + + ]
2061 : : end select
2062 : :
2063 : 30216 : call xmpi_sum(dweight, comm, ierr)
2064 : :
2065 : 30216 : end subroutine htetra_wvals_weights_delta
2066 : : !!***
2067 : :
2068 : : !----------------------------------------------------------------------
2069 : :
2070 : : !!****f* m_htetra/htetra_blochl_weights
2071 : : !! NAME
2072 : : !! htetra_blochl_weights
2073 : : !!
2074 : : !! FUNCTION
2075 : : !! Emulates the behaviour of the previous tetrahedron implementation.
2076 : : !! IBZ weights are included.
2077 : : !!
2078 : : !! INPUTS
2079 : : !!
2080 : : !! OUTPUT
2081 : : !!
2082 : : !! SOURCE
2083 : :
2084 : 118 : subroutine htetra_blochl_weights(tetra, eig_ibz, enemin, enemax, max_occ, nw, nkpt, bcorr, tweight, dweight, comm)
2085 : :
2086 : : !Arguments ------------------------------------
2087 : : !scalars
2088 : : class(htetra_t), intent(in) :: tetra
2089 : : integer,intent(in) :: nw,nkpt, bcorr, comm
2090 : : real(dp),intent(in) :: enemax, enemin, max_occ
2091 : : !arrays
2092 : : real(dp),intent(in) :: eig_ibz(nkpt)
2093 : : real(dp),intent(out) :: dweight(nw,nkpt), tweight(nw,nkpt)
2094 : :
2095 : : !Local variables-------------------------------
2096 : 236 : real(dp) :: wvals(nw)
2097 : : ! *********************************************************************
2098 : :
2099 : 118 : wvals = linspace(enemin, enemax, nw)
2100 : 118 : call htetra_wvals_weights(tetra,eig_ibz,nw,wvals,max_occ,nkpt,bcorr,tweight,dweight,comm)
2101 : :
2102 : 118 : end subroutine htetra_blochl_weights
2103 : : !!***
2104 : :
2105 : : !----------------------------------------------------------------------
2106 : :
2107 : : !!****f* m_htetra/htetra_blochl_weights_wvals_zinv
2108 : : !! NAME
2109 : : !! htetra_blochl_weights_wvals_zinv
2110 : : !!
2111 : : !! FUNCTION
2112 : : !! The same as htetra_get_onewk_wvals_zinv but looping over tetrahedra
2113 : : !! which is more efficient
2114 : : !!
2115 : : !! INPUTS
2116 : : !! nz: Number of frequencies
2117 : : !! zvals(nw): z-values
2118 : : !! max_occ=maximal occupation number (2 for nsppol=1, 1 for nsppol=2)
2119 : : !! nkpt=number of irreducible kpoints
2120 : : !! zinv_opt:
2121 : : !! 1 for S. Kaprzyk routines,
2122 : : !! 2 for Lambin-Vigneron.
2123 : : !! [erange(2)]: if present, weights are computed with a standard quadrature method if
2124 : : !! real(z) is outside of this interval and with tetra if inside.
2125 : : !! comm=MPI communicator
2126 : : !!
2127 : : !! OUTPUT
2128 : : !!
2129 : : !! SOURCE
2130 : :
2131 : 18048 : subroutine htetra_weights_wvals_zinv(tetra, eig_ibz, nz, zvals, max_occ, nkpt, zinv_opt, cweight, comm, erange)
2132 : :
2133 : : !Arguments ------------------------------------
2134 : : !scalars
2135 : : integer,intent(in) :: nz, nkpt, zinv_opt, comm
2136 : : class(htetra_t), intent(in) :: tetra
2137 : : real(dp) ,intent(in) :: max_occ
2138 : : !arrays
2139 : : real(dp),intent(in) :: eig_ibz(nkpt)
2140 : : real(dp),optional,intent(in) :: erange(2)
2141 : : complex(dp),intent(in) :: zvals(nz)
2142 : : complex(dp),intent(out) :: cweight(nz, nkpt)
2143 : :
2144 : : !Local variables-------------------------------
2145 : : !scalars
2146 : : integer :: ik_ibz, iz, multiplicity, nprocs, my_rank, ierr, ii, jj, kk, esumk
2147 : : integer :: tetra_count, itetra, isummit, ihash
2148 : : !arrays
2149 : : integer :: ind_ibz(4)
2150 : : real(dp) :: eig(4), my_erange(2)
2151 : : complex(dp) :: cw(4), verli(4), verm(4), aw(4), bw(4) !, cw_lw(4)
2152 : 36096 : real(dp) :: rwg(nz, 4)
2153 : : ! *********************************************************************
2154 : :
2155 : 18048 : nprocs = xmpi_comm_size(comm); my_rank = xmpi_comm_rank(comm)
2156 [ + + + + ]: 8541696 : cweight = zero
2157 : :
2158 [ + - ]: 18048 : my_erange = [-huge(one), huge(one)]; if (present(erange)) my_erange = erange
2159 : :
2160 : : ! For each bucket of tetrahedra
2161 [ + + ]: 207552 : do ihash=1,tetra%nbuckets
2162 [ + - ]: 189504 : if (mod(ihash, nprocs) /= my_rank) cycle
2163 : :
2164 : : ! For each tetrahedron that belongs to this k-point
2165 : 189504 : tetra_count = size(tetra%unique_tetra(ihash)%indexes, dim=2)
2166 [ + + ]: 1461888 : do itetra=1,tetra_count
2167 : :
2168 : : ! Get mapping of each summit to eig_ibz
2169 [ + + ]: 6271680 : do isummit=1,4
2170 : 5017344 : ind_ibz(isummit) = tetra%unique_tetra(ihash)%indexes(isummit, itetra)
2171 : 6271680 : eig(isummit) = eig_ibz(ind_ibz(isummit))
2172 : : end do
2173 : :
2174 : : ! Get multiplicity
2175 : 1254336 : multiplicity = tetra%unique_tetra(ihash)%indexes(0, itetra)
2176 : :
2177 : : ! Sort energies before calling get_onetetra_lambinvigneron
2178 : : ! SIM0TWOI does not require sorted energies but since we call the routine
2179 : : ! to fix get_onetetra_lambinvigneron we need to sort here.
2180 : 1254336 : call sort_4tetra(eig, ind_ibz)
2181 : :
2182 [ + - ]: 1443840 : if (zinv_opt == 1) then
2183 : : ! Loop over frequencies
2184 [ + + ]: 56418432 : do iz=1,nz
2185 : :
2186 : : ! Get tetrahedron weights
2187 [ - + - + ]: 55164096 : if (real(zvals(iz)) >= my_erange(1) .and. real(zvals(iz)) <= my_erange(2)) then
2188 : :
2189 : 55164096 : select case(zinv_opt)
2190 : : case (1)
2191 [ + + ]: 275820480 : verm = zvals(iz) - eig
2192 : 55164096 : call SIM0TWOI(cw, VERLI, VERM)
2193 : :
2194 : : !call get_onetetra_lambinvigneron(eig, zvals(iz), cw_lw)
2195 : : !if (any(abs(real(cw_lw(:)) / (real(cw(:)))) > 1.1)) then
2196 : : ! do ierr=1,4
2197 : : ! !write(std_out, *) "simte vs lw:", cw(ierr), cw_lw(ierr)
2198 : : ! write(std_out, *) "cw_lw / (simtet)", cw_lw(ierr) / (cw(ierr))
2199 : : ! end do
2200 : : !end if
2201 : :
2202 : : case (2)
2203 : : call get_onetetra_lambinvigneron(eig, zvals(iz), cw)
2204 : : end select
2205 : :
2206 : : else
2207 : : ! Use asymptotic expansion of integral for large z.
2208 [ # # # # ]: 0 : aw = (eig + sum(eig)) / five
2209 [ # # ]: 0 : do ii=1,4
2210 : 0 : bw(ii) = zero
2211 [ # # ]: 0 : do jj=1,4
2212 [ # # ]: 0 : if (jj == ii) cycle
2213 : : esumk = zero
2214 [ # # ]: 0 : do kk=1,4
2215 [ # # ]: 0 : if (kk == jj) cycle
2216 : 0 : esumk = esumk + (eig(kk) - eig(jj)) ** 2
2217 : : end do
2218 : 0 : bw(ii) = bw(ii) + three * (eig(jj) - eig(ii)) ** 2 + esumk
2219 : : end do
2220 : : end do
2221 [ # # ]: 0 : bw = bw / 300_dp
2222 [ # # ]: 0 : cw = one / (zvals(iz) - aw - bw / zvals(iz)) / four
2223 : : !This for naive integration
2224 : : !cw = (one / (zvals(iz) - eig)) / four
2225 : : end if
2226 : :
2227 : : ! Accumulate contributions
2228 [ + + ]: 277074816 : do isummit=1,4
2229 : 220656384 : ik_ibz = ind_ibz(isummit)
2230 : 275820480 : cweight(iz, ik_ibz) = cweight(iz, ik_ibz) + cw(isummit) * multiplicity * max_occ
2231 : : end do
2232 : :
2233 : : end do ! iz
2234 : :
2235 : : else
2236 [ # # # # : 0 : call get_onetetra_ppart_lv(nz, real(zvals), eig, rwg)
# # ]
2237 : :
2238 [ # # ]: 0 : do iz=1,nz
2239 : : ! Accumulate contributions
2240 [ # # ]: 0 : do isummit=1,4
2241 : 0 : ik_ibz = ind_ibz(isummit)
2242 : 0 : cweight(iz, ik_ibz) = cweight(iz, ik_ibz) + rwg(iz, isummit) * multiplicity * max_occ
2243 : : end do
2244 : : end do
2245 : : endif
2246 : :
2247 : : end do ! itetra
2248 : : end do
2249 : :
2250 : : ! Rescale weights
2251 : 18048 : select case(tetra%opt)
2252 : : case (1)
2253 [ # # ]: 0 : do ik_ibz=1,tetra%nkibz
2254 [ # # ]: 0 : cweight(:,ik_ibz) = cweight(:,ik_ibz) * tetra%ibz_multiplicity(ik_ibz) / tetra%nkbz / tetra%tetra_total(ik_ibz)
2255 : : end do
2256 : : case (2)
2257 [ - + - + : 8541696 : cweight = cweight * tetra%vv
+ + + ]
2258 : : end select
2259 : :
2260 : 18048 : call xmpi_sum(cweight, comm, ierr)
2261 : :
2262 : 18048 : end subroutine htetra_weights_wvals_zinv
2263 : : !!***
2264 : :
2265 : : !----------------------------------------------------------------------
2266 : :
2267 : : !!****f* m_htetra/sort_4tetra
2268 : : !! NAME
2269 : : !! sort_4tetra
2270 : : !!
2271 : : !! FUNCTION
2272 : : !! Sort double precision array list(4) into ascending numerical order
2273 : : !! while making corresponding rearrangement of the integer array iperm.
2274 : : !!
2275 : : !! Taken from: https://stackoverflow.com/questions/6145364/sort-4-number-with-few-comparisons
2276 : : !!
2277 : : !! INPUTS
2278 : : !! list(4) intent(inout) list of double precision numbers to be sorted
2279 : : !! perm(4) intent(inout) iperm(i)=i (very important)
2280 : : !!
2281 : : !! OUTPUT
2282 : : !! list(4) sorted list
2283 : : !! perm(4) index of permutation given the right ascending order
2284 : : !!
2285 : : !! SOURCE
2286 : :
2287 : 139837262 : pure subroutine sort_4tetra(list, perm)
2288 : :
2289 : : integer, intent(inout) :: perm(4)
2290 : : real(dp), intent(inout) :: list(4)
2291 : :
2292 : : !Local variables-------------------------------
2293 : : integer :: ia,ib,ic,id,ilow1,ilow2,ihigh1,ihigh2
2294 : : integer :: ilowest,ihighest,imiddle1,imiddle2
2295 : : real(dp) :: va,vb,vc,vd,vlow1,vlow2,vhigh1,vhigh2
2296 : : real(dp) :: vlowest,vhighest,vmiddle1,vmiddle2
2297 : :
2298 : 139837262 : va = list(1); ia = perm(1)
2299 : 139837262 : vb = list(2); ib = perm(2)
2300 : 139837262 : vc = list(3); ic = perm(3)
2301 : 139837262 : vd = list(4); id = perm(4)
2302 : :
2303 [ + + ]: 139837262 : if (va < vb) then
2304 : : vlow1 = va; vhigh1 = vb
2305 : : ilow1 = ia; ihigh1 = ib
2306 : : else
2307 : 72940132 : vlow1 = vb; vhigh1 = va
2308 : 72940132 : ilow1 = ib; ihigh1 = ia
2309 : : endif
2310 : :
2311 [ + + ]: 139837262 : if (vc < vd) then
2312 : : vlow2 = vc; vhigh2 = vd
2313 : : ilow2 = ic; ihigh2 = id
2314 : : else
2315 : 73080767 : vlow2 = vd; vhigh2 = vc
2316 : 73080767 : ilow2 = id; ihigh2 = ic
2317 : : endif
2318 : :
2319 [ + + ]: 139837262 : if (vlow1 < vlow2) then
2320 : : vlowest = vlow1; vmiddle1 = vlow2
2321 : : ilowest = ilow1; imiddle1 = ilow2
2322 : : else
2323 : 71288294 : vlowest = vlow2; vmiddle1 = vlow1
2324 : 71288294 : ilowest = ilow2; imiddle1 = ilow1
2325 : : endif
2326 : :
2327 [ + + ]: 139837262 : if (vhigh1 > vhigh2) then
2328 : : vhighest = vhigh1; vmiddle2 = vhigh2
2329 : : ihighest = ihigh1; imiddle2 = ihigh2
2330 : : else
2331 : 69068729 : vhighest = vhigh2; vmiddle2 = vhigh1
2332 : 69068729 : ihighest = ihigh2; imiddle2 = ihigh1
2333 : : endif
2334 : :
2335 [ + + ]: 139837262 : if (vmiddle1 < vmiddle2) then
2336 [ + + ]: 365584920 : list = [vlowest, vmiddle1, vmiddle2, vhighest]
2337 [ + + ]: 365584920 : perm = [ilowest, imiddle1, imiddle2, ihighest]
2338 : : else
2339 [ + + ]: 333601390 : list = [vlowest, vmiddle2, vmiddle1, vhighest]
2340 [ + + ]: 333601390 : perm = [ilowest, imiddle2, imiddle1, ihighest]
2341 : : endif
2342 : :
2343 : 139837262 : end subroutine sort_4tetra
2344 : : !!***
2345 : :
2346 : : !----------------------------------------------------------------------
2347 : :
2348 : : !!****f* m_numeric_tools/sort_4tetra_int
2349 : : !! NAME
2350 : : !! sort_4tetra_int
2351 : : !!
2352 : : !! FUNCTION
2353 : : !!
2354 : : !! INPUTS
2355 : : !!
2356 : : !! OUTPUT
2357 : : !!
2358 : : !! SOURCE
2359 : :
2360 : 8456046 : pure subroutine sort_4tetra_int(list)
2361 : :
2362 : : integer, intent(inout) :: list(4)
2363 : :
2364 : : !Local variables-------------------------------
2365 : : integer :: va,vb,vc,vd, vlow1,vlow2,vhigh1,vhigh2
2366 : : integer :: vlowest,vhighest, vmiddle1,vmiddle2
2367 : :
2368 : 8456046 : va = list(1)
2369 : 8456046 : vb = list(2)
2370 : 8456046 : vc = list(3)
2371 : 8456046 : vd = list(4)
2372 : :
2373 [ + + ]: 8456046 : if (va < vb) then
2374 : : vlow1 = va; vhigh1 = vb
2375 : : else
2376 : 4340218 : vlow1 = vb; vhigh1 = va
2377 : : endif
2378 : :
2379 [ + + ]: 8456046 : if (vc < vd) then
2380 : : vlow2 = vc; vhigh2 = vd
2381 : : else
2382 : 4257565 : vlow2 = vd; vhigh2 = vc
2383 : : endif
2384 : :
2385 [ + + ]: 8456046 : if (vlow1 < vlow2) then
2386 : : vlowest = vlow1; vmiddle1 = vlow2
2387 : : else
2388 : 4421792 : vlowest = vlow2; vmiddle1 = vlow1
2389 : : endif
2390 : :
2391 [ + + ]: 8456046 : if (vhigh1 > vhigh2) then
2392 : : vhighest = vhigh1; vmiddle2 = vhigh2
2393 : : else
2394 : 4589119 : vhighest = vhigh2; vmiddle2 = vhigh1
2395 : : endif
2396 : :
2397 [ + + ]: 8456046 : if (vmiddle1 < vmiddle2) then
2398 [ + + ]: 24813400 : list = [vlowest, vmiddle1, vmiddle2, vhighest]
2399 : : else
2400 [ + + ]: 17466830 : list = [vlowest, vmiddle2, vmiddle1, vhighest]
2401 : : endif
2402 : :
2403 : 8456046 : end subroutine sort_4tetra_int
2404 : : !!***
2405 : :
2406 : : !!****f* m_htetra/get_onetetra_ppart_lv
2407 : : !! NAME
2408 : : !! get_onetetra_ppart_lv
2409 : : !!
2410 : : !! FUNCTION
2411 : : !! Compute the complex weights according to: P. Lambin and J.P. Vigneron, Phys. Rev. B 29, 3430 (1984)
2412 : : !!
2413 : : !! INPUTS
2414 : : !! nw
2415 : : !! wvals: energy to evaluate the weights at
2416 : : !! eig: eigenvalues at the corners of the tetrahedron
2417 : : !!
2418 : : !! OUTPUT
2419 : : !! rwg(nw, 4)
2420 : : !!
2421 : : !! SOURCE
2422 : :
2423 : 0 : pure subroutine get_onetetra_ppart_lv(nw, wvals, eig, rwg)
2424 : :
2425 : : integer,intent(in) :: nw
2426 : : real(dp), intent(in) :: wvals(nw), eig(4)
2427 : : real(dp), intent(out) :: rwg(nw, 4)
2428 : :
2429 : : !Local variables-------------------------------
2430 : : integer :: ii, iw !jj,
2431 : : real(dp),parameter :: tol = tol14
2432 : : !real(dp),parameter :: tol = tol20
2433 : : !real(dp),parameter :: tol = tol30
2434 : : real(dp) :: D12,D13,D14,D23,D24,D34
2435 : : real(dp) :: e10, e20, e30, e31, e32, e21
2436 : : real(dp) :: inv_e10, inv_e21, inv_e20, inv_e30, inv_e31, inv_e32
2437 : 0 : real(dp) :: E0(nw), E1(nw), E2(nw), E3(nw)
2438 : : ! *********************************************************************
2439 : :
2440 : : ! Then the energy differences, for the coefficients. Must always be positive, I hope.
2441 : 0 : D12 = eig(2) - eig(1)
2442 : 0 : D13 = eig(3) - eig(1)
2443 : 0 : D14 = eig(4) - eig(1)
2444 : 0 : D23 = eig(3) - eig(2)
2445 : 0 : D24 = eig(4) - eig(2)
2446 : 0 : D34 = eig(4) - eig(3)
2447 : :
2448 : : ! Now get the actual weights
2449 : : ! Notations
2450 : : ! eij = e_i - e_j
2451 : : ! Ej = E - e_j
2452 : :
2453 : 0 : e10 = huge(one); e20 = huge(one); e30 = huge(one);
2454 : 0 : e31 = huge(one); e32 = huge(one); e21 = huge(one)
2455 : 0 : inv_e10 = huge(one); inv_e21 = huge(one); inv_e20 = huge(one)
2456 : 0 : inv_e30 = huge(one); inv_e31 = huge(one); inv_e32 = huge(one)
2457 : :
2458 [ # # ]: 0 : E0 = wvals(:) - eig(1)
2459 [ # # ]: 0 : E1 = wvals(:) - eig(2)
2460 [ # # ]: 0 : E2 = wvals(:) - eig(3)
2461 [ # # ]: 0 : E3 = wvals(:) - eig(4)
2462 : :
2463 : : #if 0
2464 : : where (abs(E0) < tol1)
2465 : : E0 = tol1
2466 : : end where
2467 : : where (abs(E1) < tol1)
2468 : : E1 = tol1
2469 : : end where
2470 : : where (abs(E2) < tol1)
2471 : : E2 = tol1
2472 : : end where
2473 : : where (abs(E3) < tol1)
2474 : : E3 = tol1
2475 : : end where
2476 : : #endif
2477 : :
2478 : : ! e1=e2=e3=e4
2479 [ # # ]: 0 : if (D12 + D23 + D34 < tol) then
2480 [ # # ]: 0 : do ii=1,4
2481 : : !rwg(:, ii) = 0.25_dp / (wvals - eig(ii))
2482 [ # # ]: 0 : rwg(:, ii) = 0.25_dp / E0
2483 : : end do
2484 : :
2485 : : ! e2=e3=e4
2486 [ # # ]: 0 : else if (D23 + D34 < tol) then
2487 : 0 : e10 = eig(2) - eig(1); inv_e10 = one / e10
2488 : :
2489 [ # # ]: 0 : do iw=1,nw
2490 : : rwg(iw, 1) = &
2491 : : three * E0(iw)**2 * E1(iw) * inv_e10**4 * log(abs(E1(iw) / E0(iw))) &
2492 : 0 : + 1.5_dp * E1(iw) * (two * E0(iw) + e10) * inv_e10**3 + inv_e10
2493 : : end do
2494 : :
2495 [ # # ]: 0 : do iw=1,nw
2496 : : rwg(iw, 2) = &
2497 : : E0(iw) ** 3 * inv_e10**4 * log(abs(E0(iw) / E1(iw))) &
2498 : 0 : - (six * E0(iw)**2 + three * E0(iw) * e10 + two * e10**2) * inv_e10**3 / six
2499 : : end do
2500 [ # # ]: 0 : rwg(:,3) = rwg(:,2)
2501 [ # # ]: 0 : rwg(:,4) = rwg(:,2)
2502 : :
2503 : : !rwg = zero
2504 : :
2505 : : ! e1=e2=e3
2506 [ # # ]: 0 : else if (D12 + D23 < tol) then
2507 : :
2508 : 0 : e30 = eig(4) - eig(1); inv_e30 = one / e30
2509 : :
2510 [ # # ]: 0 : do iw=1,nw
2511 : : rwg(iw, 1) = &
2512 : : E3(iw)**3 * inv_e30**4 * log(abs(E3(iw) / E0(iw))) &
2513 : 0 : + (six * E3(iw)**2 - three * E3(iw) * e30 + two * e30**2) * inv_e30**3 / six
2514 : : end do
2515 [ # # ]: 0 : rwg(:,2) = rwg(:,1)
2516 [ # # ]: 0 : rwg(:,3) = rwg(:,1)
2517 : :
2518 [ # # ]: 0 : do iw=1,nw
2519 : : rwg(iw, 4) = &
2520 : : three * E0(iw) * E3(iw)**2 * inv_e30**4 * log(abs(E0(iw) / E3(iw))) &
2521 : 0 : - 1.5_dp * E0(iw) * (two * E3(iw) - e30) * inv_e30**3 - inv_e30
2522 : : end do
2523 : :
2524 : : !rwg = zero
2525 : :
2526 : : ! e1=e2 < e3=e4
2527 [ # # ]: 0 : else if (D12 + D34 < tol) then
2528 : :
2529 : 0 : e20 = eig(3) - eig(1); inv_e20 = one / e20
2530 : :
2531 [ # # ]: 0 : do iw=1,nw
2532 : : rwg(iw, 1) = &
2533 : : three * E0(iw) * E2(iw)**2 * inv_e20**4 * log(abs(E0(iw) / E2(iw))) &
2534 : 0 : - 1.5_dp * E0(iw) * (two * E2(iw) - e20) * inv_e20**3 - inv_e20
2535 : : end do
2536 [ # # ]: 0 : rwg(:,2) = rwg(:,1)
2537 : :
2538 [ # # ]: 0 : do iw=1,nw
2539 : : rwg(iw, 3) = &
2540 : : three * E0(iw)** 2 * E2(iw) * inv_e20**4 * log(abs(E2(iw) / E0(iw))) &
2541 : 0 : + 1.5_dp * E2(iw) * (two * E0(iw) + e20) * inv_e20**3 + inv_e20
2542 : : end do
2543 [ # # ]: 0 : rwg(:,4) = rwg(:,3)
2544 : :
2545 : : !rwg = zero
2546 : :
2547 : : ! e3=e4
2548 [ # # ]: 0 : else if (D34 < tol) then
2549 : :
2550 : 0 : e10 = eig(2) - eig(1); inv_e10 = one / e10
2551 : 0 : e20 = eig(3) - eig(1); inv_e20 = one / e20
2552 : 0 : e21 = eig(3) - eig(2); inv_e21 = one / e21
2553 : :
2554 [ # # ]: 0 : do iw=1,nw
2555 : : rwg(iw, 1) = &
2556 : : E0(iw)**2 * inv_e20**2 * inv_e10 &
2557 : : * (one + (-two * E2(iw) * inv_e20 - E1(iw) * inv_e10) * log(abs(E0(iw)))) &
2558 : : - E2(iw)**2 * inv_e20**2 * inv_e21 &
2559 : : * (one + (two * E0(iw) * inv_e20 + E1(iw) * inv_e21) * log(abs(E2(iw)))) &
2560 : 0 : + E1(iw)**3 * inv_e10**2 * inv_e21**2 * log(abs(E1(iw)))
2561 : : end do
2562 : :
2563 [ # # ]: 0 : do iw=1,nw
2564 : : rwg(iw, 2) = &
2565 : : -E1(iw)**2 * inv_e21**2 * inv_e10 &
2566 : : * (one + (-two * E2(iw) * inv_e21 + E0(iw) * inv_e10) * log(abs(E1(iw)))) &
2567 : : - E2(iw)**2 * inv_e21**2 * inv_e20 &
2568 : : * (one + (two * E1(iw) * inv_e21 + E0(iw) * inv_e20) * log(abs(E2(iw)))) &
2569 : 0 : + E0(iw)**3 * inv_e10**2 * inv_e20**2 * log(abs(E0(iw)))
2570 : : end do
2571 : :
2572 [ # # ]: 0 : do iw=1,nw
2573 : : rwg(iw, 3) = &
2574 : : +E0(iw)**3 * inv_e10 * inv_e20**3 * log(abs(E0(iw))) &
2575 : : -E1(iw)**3 * inv_e10 * inv_e21**3 * log(abs(E1(iw))) &
2576 : : +E2(iw) * inv_e20 * inv_e21 &
2577 : : * (half + E0(iw) * inv_e20 + E1(iw) * inv_e21 &
2578 : : +(E0(iw)**2 * inv_e20**2 + E1(iw)**2 * inv_e21**2 + &
2579 : 0 : E0(iw) * E1(iw) * inv_e20 * inv_e21) * log(abs(E2(iw))))
2580 : : end do
2581 : :
2582 [ # # ]: 0 : rwg(:,4) = rwg(:,3)
2583 : :
2584 : : !rwg = zero
2585 : :
2586 : : ! e2=e3
2587 [ # # ]: 0 : else if (D23 < tol) then
2588 : :
2589 : 0 : e10 = eig(2) - eig(1); inv_e10 = one / e10
2590 : 0 : e30 = eig(4) - eig(1); inv_e30 = one / e30
2591 : 0 : e31 = eig(4) - eig(2); inv_e31 = one / e31
2592 : :
2593 [ # # ]: 0 : do iw=1,nw
2594 : : rwg(iw, 1) = &
2595 : : E0(iw)**2 * inv_e10**2 * inv_e30 &
2596 : : * (one - (two * E1(iw) * inv_e10 + E3(iw) * inv_e30) * log(abs(E0(iw)))) &
2597 : : + E1(iw)**2 * inv_e10**2 * inv_e31 &
2598 : : * (one + (+two * E0(iw) * inv_e10 - E3(iw) * inv_e31) * log(abs(E1(iw)))) &
2599 : 0 : + E3(iw)**3 * inv_e30**2 * inv_e31**2 * log(abs(E3(iw)))
2600 : : end do
2601 : :
2602 [ # # ]: 0 : do iw=1,nw
2603 : : rwg(iw, 2) = &
2604 : : E0(iw)**3 * inv_e30 * inv_e10**3 * log(abs(E0(iw))) &
2605 : : + E3(iw)**3 * inv_e30 * inv_e31**3 * log(abs(E3(iw))) &
2606 : : - E1(iw) * inv_e10 * inv_e31 &
2607 : : * (half + E0(iw) * inv_e10 - E3(iw) * inv_e31 + &
2608 : 0 : (E0(iw)**2 * inv_e10**2 + E3(iw)**2 * inv_e31**2 - E0(iw) * E3(iw) * inv_e10 * inv_e31) * log(abs(E1(iw))))
2609 : : end do
2610 [ # # ]: 0 : rwg(:,3) = rwg(:,2)
2611 : :
2612 [ # # ]: 0 : do iw=1,nw
2613 : : rwg(iw, 4) = &
2614 : : -E3(iw)**2 * inv_e31**2 * inv_e30 &
2615 : : * (one + (two * E1(iw) * inv_e31 + E0(iw) * inv_e30) * log(abs(E3(iw)))) &
2616 : : - E1(iw)**2 * inv_e31**2 * inv_e10 &
2617 : : * (one + (-two * E3(iw) * inv_e31 + E0(iw) * inv_e10) * log(abs(E1(iw)))) &
2618 : 0 : + E0(iw)**3 * inv_e30**2 * inv_e10**2 * log(abs(E0(iw)))
2619 : : end do
2620 : :
2621 : : !rwg = zero
2622 : :
2623 : : ! e1=e2
2624 [ # # ]: 0 : else if (D12 < tol) then
2625 : :
2626 : 0 : e20 = eig(3) - eig(1); inv_e20 = one / e20
2627 : 0 : e30 = eig(4) - eig(1); inv_e30 = one / e30
2628 : 0 : e32 = eig(4) - eig(3); inv_e32 = one / e32
2629 : :
2630 [ # # ]: 0 : do iw=1,nw
2631 : : rwg(iw, 1) = &
2632 : : -E2(iw)**3 * inv_e32 * inv_e20**3 * log(abs(E2(iw))) &
2633 : : + E3(iw)**3 * inv_e32 * inv_e30**3 * log(abs(E3(iw))) &
2634 : : + E0(iw) * inv_e20 * inv_e30 &
2635 : : * (half - E2(iw) * inv_e20 - E3(iw) * inv_e30 + &
2636 : 0 : (E2(iw)**2 * inv_e20**2 + E3(iw)**2 * inv_e30**2 + E2(iw) * E3(iw) * inv_e20 * inv_e30) * log(abs(E0(iw))))
2637 : : end do
2638 [ # # ]: 0 : rwg(:,2) = rwg(:,1)
2639 : :
2640 [ # # ]: 0 : do iw=1,nw
2641 : : rwg(iw, 3) = &
2642 : : E2(iw)**2 * inv_e20**2 * inv_e32 &
2643 : : * (one + (two * E0(iw) * inv_e20 - E3(iw) * inv_e32) * log(abs(E2(iw)))) &
2644 : : + E0(iw)**2 * inv_e20**2 * inv_e30 &
2645 : : * (one - (two * E2(iw) * inv_e20 + E3(iw) * inv_e30) * log(abs(E0(iw)))) &
2646 : 0 : + (E3(iw)**3 * inv_e32**2 * inv_e30**2 * log(abs(E3(iw))))
2647 : : end do
2648 : : ! This was wrong due to a misplaced parantes
2649 : : !rwg(:,3) = zero
2650 : :
2651 [ # # ]: 0 : do iw=1,nw
2652 : : rwg(iw, 4) = &
2653 : : -E3(iw)**2 * inv_e30**2 * inv_e32 &
2654 : : * (one + (two * E0(iw) * inv_e30 + E2(iw) * inv_e32) * log(abs(E3(iw)))) &
2655 : : + E0(iw)**2 * inv_e30**2 * inv_e20 &
2656 : : * (one - (two * E3(iw) * inv_e30 + E2(iw) * inv_e20) * log(abs(E0(iw)))) &
2657 : 0 : + (E2(iw)**3 * inv_e32**2 * inv_e20**2 * log(abs(E2(iw))))
2658 : : end do
2659 : :
2660 : : !rwg = zero
2661 : :
2662 : : ! e1<e2<e3<e4
2663 : : else
2664 : :
2665 : 0 : e10 = eig(2) - eig(1); inv_e10 = one / e10
2666 : 0 : e20 = eig(3) - eig(1); inv_e20 = one / e20
2667 : 0 : e21 = eig(3) - eig(2); inv_e21 = one / e21
2668 : 0 : e30 = eig(4) - eig(1); inv_e30 = one / e30
2669 : 0 : e31 = eig(4) - eig(2); inv_e31 = one / e31
2670 : 0 : e32 = eig(4) - eig(3); inv_e32 = one / e32
2671 : :
2672 [ # # ]: 0 : do iw=1,nw
2673 : : rwg(iw, 1) = &
2674 : : E0(iw)**2 * inv_e10 * inv_e20 * inv_e30 &
2675 : : * (one - (E1(iw) * inv_e10 + E2(iw) * inv_e20 + E3(iw) * inv_e30) * log(abs(E0(iw)))) &
2676 : : + E1(iw)**3 * inv_e10**2 * inv_e21 * inv_e31 * log(abs(E1(iw))) &
2677 : : - E2(iw)**3 * inv_e20**2 * inv_e21 * inv_e32 * log(abs(E2(iw))) &
2678 : 0 : + E3(iw)**3 * inv_e30**2 * inv_e31 * inv_e32 * log(abs(E3(iw)))
2679 : : end do
2680 : :
2681 [ # # ]: 0 : do iw=1,nw
2682 : : rwg(iw, 2) = &
2683 : : -E1(iw)**2 * inv_e10 * inv_e21 * inv_e31 &
2684 : : * (one + (E0(iw) * inv_e10 - E2(iw) * inv_e21 - E3(iw) * inv_e31) * log(abs(E1(iw)))) &
2685 : : + E0(iw)**3 * inv_e10**2 * inv_e20 * inv_e30 * log(abs(E0(iw))) &
2686 : : - E2(iw)**3 * inv_e20 * inv_e21**2 * inv_e32 * log(abs(E2(iw))) &
2687 : 0 : + E3(iw)**3 * inv_e30 * inv_e31**2 * inv_e32 * log(abs(E3(iw)))
2688 : : end do
2689 : :
2690 [ # # ]: 0 : do iw=1,nw
2691 : : rwg(iw, 3) = &
2692 : : E2(iw)**2 * inv_e20 * inv_e21 * inv_e32 &
2693 : : * (one + (E0(iw) * inv_e20 + E1(iw) * inv_e21 - E3(iw) * inv_e32) * log(abs(E2(iw)))) &
2694 : : + E0(iw)**3 * inv_e10 * inv_e20**2 * inv_e30 * log(abs(E0(iw))) &
2695 : : - E1(iw)**3 * inv_e10 * inv_e21**2 * inv_e31 * log(abs(E1(iw))) &
2696 : 0 : + E3(iw)**3 * inv_e30 * inv_e31 * inv_e32**2 * log(abs(E3(iw)))
2697 : : end do
2698 : :
2699 [ # # ]: 0 : do iw=1,nw
2700 : : rwg(iw, 4) = &
2701 : : -E3(iw)**2 * inv_e30 * inv_e31 * inv_e32 &
2702 : : * (one + (E0(iw) * inv_e30 + E1(iw) * inv_e31 + E2(iw) * inv_e32) * log(abs(E3(iw)))) &
2703 : : + E0(iw)**3 * inv_e10 * inv_e20 * inv_e30**2 * log(abs(E0(iw))) &
2704 : : - E1(iw)**3 * inv_e10 * inv_e21 * inv_e31**2 * log(abs(E1(iw))) &
2705 : 0 : + E2(iw)**3 * inv_e20 * inv_e21 * inv_e32**2 * log(abs(E2(iw)))
2706 : : end do
2707 : : !rwg = zero
2708 : :
2709 : : end if
2710 : :
2711 : 0 : end subroutine get_onetetra_ppart_lv
2712 : : !!***
2713 : :
2714 [ - + - - : 729 : end module m_htetra
+ + - + +
- - + - +
+ - - + -
+ - - - -
- + - + -
- - - -
+ ]
2715 : : !!***
|