File: tetra_mod2.f90

package info (click to toggle)
espresso 6.7-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 311,068 kB
  • sloc: f90: 447,429; ansic: 52,566; sh: 40,631; xml: 37,561; tcl: 20,077; lisp: 5,923; makefile: 4,503; python: 4,379; perl: 1,219; cpp: 761; fortran: 618; java: 568; awk: 128
file content (302 lines) | stat: -rw-r--r-- 11,727 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
MODULE tetra_ip
!this module provides rouitnes for the tetrahedra method

  USE kinds, ONLY : dp

contains
  !---------------------------------------------------------------------------
  subroutine tetrahedra1 (nk1, nk2, nk3, ntetra, tetra)
    !-------------------------------------------------------------------------
    !
    ! Tetrahedron method according to P. E. Bloechl et al, PRB49, 16223 (1994)
    !
    !-------------------------------------------------------------------------
    implicit none
    
    integer, intent(in):: nk1, nk2, nk3, ntetra
    integer, intent(out) :: tetra(4,ntetra) 
    integer :: nkr, i,j,k, n, ip1,jp1,kp1, &
         n1,n2,n3,n4,n5,n6,n7,n8
    integer, parameter :: stderr = 0
    
    ! Total number of k-points
    nkr = nk1*nk2*nk3

    !  Construct tetrahedra

    do i=1,nk1
       do j=1,nk2
          do k=1,nk3
             !  n1-n8 are the indices of k-point 1-8 forming a cube
             ip1 = mod(i,nk1)+1
             jp1 = mod(j,nk2)+1
             kp1 = mod(k,nk3)+1
             n1 = (  k-1) + (  j-1)*nk3 + (  i-1)*nk2*nk3 + 1
             n2 = (  k-1) + (  j-1)*nk3 + (ip1-1)*nk2*nk3 + 1
             n3 = (  k-1) + (jp1-1)*nk3 + (  i-1)*nk2*nk3 + 1
             n4 = (  k-1) + (jp1-1)*nk3 + (ip1-1)*nk2*nk3 + 1
             n5 = (kp1-1) + (  j-1)*nk3 + (  i-1)*nk2*nk3 + 1
             n6 = (kp1-1) + (  j-1)*nk3 + (ip1-1)*nk2*nk3 + 1
             n7 = (kp1-1) + (jp1-1)*nk3 + (  i-1)*nk2*nk3 + 1
             n8 = (kp1-1) + (jp1-1)*nk3 + (ip1-1)*nk2*nk3 + 1
             !  there are 6 tetrahedra per cube (and nk1*nk2*nk3 cubes)
             n  = 6 * ( (k-1) + (j-1)*nk3 + (i-1)*nk3*nk2 )
             
             tetra (1,n+1) = n1
             tetra (2,n+1) = n2
             tetra (3,n+1) = n3
             tetra (4,n+1) = n6
             
             tetra (1,n+2) = n2
             tetra (2,n+2) = n3
             tetra (3,n+2) = n4
             tetra (4,n+2) = n6
             
             tetra (1,n+3) = n1
             tetra (2,n+3) = n3
             tetra (3,n+3) = n5
             tetra (4,n+3) = n6
             
             tetra (1,n+4) = n3
             tetra (2,n+4) = n4
             tetra (3,n+4) = n6
             tetra (4,n+4) = n8
             
             tetra (1,n+5) = n3
             tetra (2,n+5) = n6
             tetra (3,n+5) = n7
             tetra (4,n+5) = n8
             
             tetra (1,n+6) = n3
             tetra (2,n+6) = n5
             tetra (3,n+6) = n6
             tetra (4,n+6) = n7
          enddo
       enddo
    enddo
    
    !  check
    do n=1, ntetra
       do i=1,4        
          if ( tetra(i,n)<1 .or. tetra(i,n)> (nk1*nk2*nk3) ) then
             write(stderr,*) 'Something wrong with the construction of tetrahedra' 
             call exit(1)
          endif
       enddo
    enddo
  end subroutine tetrahedra1
  
  !-----------------------------------------------------------------------
  subroutine hpsort1 (n, ra, ind)  
    !---------------------------------------------------------------------
    ! sort an array ra(1:n) into ascending order using heapsort algorithm.
    ! n is input, ra is replaced on output by its sorted rearrangement.
    ! create an index table (ind) by making an exchange in the index array
    ! whenever an exchange is made on the sorted data array (ra).
    ! in case of equal values in the data array (ra) the values in the
    ! index array (ind) are used to order the entries.
    ! if on input ind(1)  = 0 then indices are initialized in the routine,
    ! if on input ind(1) != 0 then indices are assumed to have been
    !                initialized before entering the routine and these
    !                indices are carried around during the sorting process
    !
    ! no work space needed !
    ! free us from machine-dependent sorting-routines !
    !
    ! adapted from Numerical Recipes pg. 329 (new edition)
    !
    !---------------------------------------------------------------------
    implicit none  
    !-input/output variables
    integer :: n  
    integer :: ind (*)  
    real(kind=dp) :: ra (*)  
    !-local variables
    integer :: i, ir, j, l, iind  
    real(kind=dp) :: rra  
    ! initialize index array
    if (ind (1) .eq.0) then  
       do i = 1, n  
          ind (i) = i  
       enddo
    endif
    ! nothing to order
    if (n.lt.2) return  
    ! initialize indices for hiring and retirement-promotion phase
    l = n / 2 + 1  
    ir = n  
10  continue  
    ! still in hiring phase
    if (l.gt.1) then  
       l = l - 1  
       rra = ra (l)  
       iind = ind (l)  
       ! in retirement-promotion phase.
    else  
       ! clear a space at the end of the array
       rra = ra (ir)  
       !
       iind = ind (ir)  
       ! retire the top of the heap into it
       ra (ir) = ra (1)  
       !
       ind (ir) = ind (1)  
       ! decrease the size of the corporation
       ir = ir - 1  
       ! done with the last promotion
       if (ir.eq.1) then  
          ! the least competent worker at all !
          ra (1) = rra  
          !
          ind (1) = iind  
          return  
       endif
    endif
    ! wheter in hiring or promotion phase, we
    i = l  
    ! set up to place rra in its proper level
    j = l + l  
    !
    do while (j.le.ir)  
       if (j.lt.ir) then  
          ! compare to better underling
          if (ra (j) .lt.ra (j + 1) ) then  
             j = j + 1  
          elseif (ra (j) .eq.ra (j + 1) ) then  
             if (ind (j) .lt.ind (j + 1) ) j = j + 1  
          endif
       endif
       ! demote rra
       if (rra.lt.ra (j) ) then  
          ra (i) = ra (j)  
          ind (i) = ind (j)  
          i = j  
          j = j + j  
       elseif (rra.eq.ra (j) ) then  
          ! demote rra
          if (iind.lt.ind (j) ) then  
             ra (i) = ra (j)  
             ind (i) = ind (j)  
             i = j  
             j = j + j  
          else  
             ! set j to terminate do-while loop
             j = ir + 1  
          endif
          ! this is the right place for rra
       else  
          ! set j to terminate do-while loop
          j = ir + 1  
       endif
    enddo
    ra (i) = rra  
    ind (i) = iind  
    goto 10  
    !
  end subroutine hpsort1
  
  !--------------------------------------------------------------------
  subroutine weights_delta1 (energy, band,  ntetra, tetra, nkpoints,  weights)
    !--------------------------------------------------------------------
    !
    ! ... calculates weights with the tetrahedron method (P.E.Bloechl)
    !     assuming the integrand is convoluted with a delta function
    !     centered about the band 
    !
    !--------------------------------------------------------------------
    
    implicit none
    ! I/O variables
    integer, intent(in) :: nkpoints, ntetra, tetra(4, ntetra)
    real(kind=dp), intent(in) :: energy, band(nkpoints)
    real(kind=dp), intent(out) :: weights(nkpoints)
    ! local variables
    real(kind=dp) :: e1, e2, e3, e4, fact, etetra (4)
    integer :: ik, ibnd, nt, nk, ns, i, kp1, kp2, kp3, kp4, itetra (4)
    
    ! Initialize to zero the weights
    weights = 0.0d0
    
    do nt = 1, ntetra      
       !
       ! etetra are the energies at the vertexes of the nt-th tetrahedron
       !
       do i = 1, 4
          etetra (i) = band (tetra (i, nt))
       enddo
       itetra (1) = 0
       call hpsort1 (4, etetra, itetra)
       !
       ! ...sort in ascending order: e1 < e2 < e3 < e4
       !
       e1 = etetra (1)
       e2 = etetra (2)
       e3 = etetra (3)
       e4 = etetra (4)
       !
       ! kp1-kp4 are the irreducible k-points corresponding to e1-e4
       !
       kp1 = tetra (itetra (1), nt) 
       kp2 = tetra (itetra (2), nt) 
       kp3 = tetra (itetra (3), nt) 
       kp4 = tetra (itetra (4), nt) 
       !
       ! calculate weights 
       !
       ! Remember that if energy.lt.e1 or energy.ge.e4 
       ! there is no contribution in this case
       if (energy.lt.e4.and.energy.ge.e3) then                                
          fact = 1.0d0/ntetra *  (e4 - energy)**2 / (e4 - e1) / (e4 - e2) &
               / (e4 - e3)
          weights (kp1) = weights (kp1) + fact * (e4 - energy) / (e4 - e1)
          weights (kp2) = weights (kp2) + fact * (e4 - energy) / (e4 - e2)
          weights (kp3) = weights (kp3) + fact * (e4 - energy) / (e4 - e3)
          weights (kp4) = weights (kp4) + fact * ( 3.0d0 - (e4 - energy) * &
               (1.d0 / (e4 - e1) + 1.d0 / (e4 - e2) + 1.d0 / (e4 - e3) ) )
       elseif (energy.lt.e3.and.energy.ge.e2) then
          weights (kp1) = weights (kp1) + 1.0d0/ntetra * ( &
               (energy - e2)**3 * (1.0d0/ (e3 - e1)**2 / (e3 - e2) / (e4 - e2) + &
               1.0d0/ (e3 - e1) / (e4 - e1)**2 / (e4 - e2) + &
               1.0d0/ (e3 - e1)**2 / (e4 - e1) / (e4 - e2))  &
               -3.0d0 * (energy - e2)**2 * (1.0d0/ (e3 - e1)**2 / (e4 - e1) + &
               1.0d0/ (e3 - e1) / (e4 - e1)**2)  &
               -3.0d0 * (energy - e2) * ((e2 - e1)**2 - (e3 - e2)*(e4 - e2))  &
               / (e3 - e1)**2 / (e4 - e1)**2         &                                            
               +(e2 - e1) * ( (e3 - e2)/(e3 - e1) + (e4 - e2)/(e4 - e1)) & 
               / (e3 - e1) / (e4 - e1))
          weights (kp2) = weights (kp2) + 1.0d0/ntetra * ( &
               (energy - e2)**3 * (1.0d0/ (e3 - e1) / (e4 - e1) / (e4 - e2)**2 + &
               1.0d0/ (e3 - e1) / (e3 - e2) / (e4 - e2)**2 + &
               1.0d0/ (e3 - e1) / (e3 - e2)**2 / (e4 - e2))  &
               -3.0d0 * (energy - e2)**2 * (1.0d0/ (e3 - e1) / (e4 - e1) / (e4 - e2) + &
               1.0d0/ (e3 - e1) / (e3 - e2) / (e4 - e2))  &
               +3.0d0 * (energy - e2) * (1.0d0/ (e3 - e1) / (e4 - e1))  &
               +(e2 - e1) / (e3 - e1) / (e4 - e1))
          weights (kp3) = weights (kp3) + 1.0d0/ntetra * ( &
               -(energy - e2)**3 * (1.0d0/ (e3 - e1)**2 / (e4 - e1) / (e4 - e2) + &
               1.0d0/ (e3 - e1) / (e3 - e2)**2 / (e4 - e2) + &
               1.0d0/ (e3 - e1)**2 / (e3 - e2) / (e4 - e2))  &
               +3.0d0 * (energy - e2)**2 * (1.0d0/ (e3 - e1)**2 / (e4 - e1)) &
               +3.0d0 * (energy - e2) * ((e2 - e1)/ (e3 - e1)**2 / (e4 - e1))  &
               +(e2 - e1)**2 / (e3 - e1)**2 / (e4 - e1))
          weights (kp4) = weights (kp4) + 1.0d0/ntetra * ( &
               -(energy - e2)**3 * (1.0d0/ (e3 - e1) / (e3 - e2) / (e4 - e1)**2 + &
               1.0d0/ (e3 - e2) / (e4 - e1) / (e4 - e2)**2 + &
               1.0d0/ (e3 - e2) / (e4 - e1)**2 / (e4 - e2))  &
               +3.0d0 * (energy - e2)**2 * (1.0d0/ (e3 - e1) / (e4 - e1)**2) &
               +3.0d0 * (energy - e2) * ((e2 - e1)/ (e3 - e1) / (e4 - e1)**2)  &
               +(e2 - e1)**2 / (e3 - e1) / (e4 - e1)**2)
       elseif (energy.lt.e2.and.energy.ge.e1) then
          fact = 1.0d0 / ntetra * (energy - e1) **2 / (e2 - e1) / (e3 - e1) &
               / (e4 - e1)
          weights (kp1) = weights (kp1) + fact * (3.d0 - (energy - e1) * &
               (1.d0 / (e2 - e1) + 1.d0 / (e3 - e1) + 1.d0 / (e4 - e1) ) )
          weights (kp2) = weights (kp2) + fact * (energy - e1) / (e2 - e1) 
          weights (kp3) = weights (kp3) + fact * (energy - e1) / (e3 - e1) 
          weights (kp4) = weights (kp4) + fact * (energy - e1) / (e4 - e1)
       endif
    enddo
  end subroutine weights_delta1

END MODULE tetra_ip