pwdft  0.1
PW-DFT code for education
libtetrabz_occ_mod.F90
Go to the documentation of this file.
1 !
2 ! Copyright (c) 2014 Mitsuaki Kawamura
3 !
4 ! Permission is hereby granted, free of charge, to any person obtaining a
5 ! copy of this software and associated documentation files (the
6 ! "Software"), to deal in the Software without restriction, including
7 ! without limitation the rights to use, copy, modify, merge, publish,
8 ! distribute, sublicense, and/or sell copies of the Software, and to
9 ! permit persons to whom the Software is furnished to do so, subject to
10 ! the following conditions:
11 !
12 ! The above copyright notice and this permission notice shall be included
13 ! in all copies or substantial portions of the Software.
14 !
15 ! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 ! OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 ! MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 ! IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 ! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 ! TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 ! SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 !
24  !
25  IMPLICIT NONE
26  !
27  PRIVATE
29  !
30 CONTAINS
31 !
32 ! Compute occupation
33 !
34 SUBROUTINE libtetrabz_occ(ltetra,bvec,nb,nge,eig,ngw,wght,comm) BIND(C)
35  !
36  USE iso_c_binding
38  IMPLICIT NONE
39  !
40  INTEGER(C_INT),INTENT(IN) :: ltetra, nb, nge(3), ngw(3)
41  REAL(c_double),INTENT(IN) :: bvec(9), eig(nb,product(nge(1:3)))
42  REAL(c_double),INTENT(OUT) :: wght(nb,product(ngw(1:3)))
43  INTEGER(C_INT),INTENT(IN),OPTIONAL :: comm
44  !
45  LOGICAL :: linterpol
46  INTEGER :: nt_local, nk_local, nkbz, ik, kintp(8)
47  INTEGER,ALLOCATABLE :: ik_global(:,:), ik_local(:,:)
48  REAL(8) :: wlsm(4,20), wintp(1,8)
49  REAL(8),ALLOCATABLE :: wghtd(:,:,:), kvec(:,:)
50  !
51  IF(PRESENT(comm)) THEN
52  CALL libtetrabz_initialize(ltetra,nge,ngw,bvec,linterpol,wlsm,nk_local,&
53  & nt_local,nkbz,ik_global,ik_local,kvec,comm)
54  ELSE
55  CALL libtetrabz_initialize(ltetra,nge,ngw,bvec,linterpol,wlsm,nk_local,&
56  & nt_local,nkbz,ik_global,ik_local,kvec)
57  END IF
58  !
59  IF(linterpol) THEN
60  !
61  ALLOCATE(wghtd(nb,1,nk_local))
62  CALL libtetrabz_occ_main(wlsm,nt_local,ik_global,ik_local,nb,nkbz,eig,nk_local,wghtd,0d0)
63  !
64  ! Interpolation
65  !
66  wght(1:nb,1:product(ngw(1:3))) = 0d0
67  DO ik = 1, nk_local
68  CALL libtetrabz_interpol_indx(ngw,kvec(1:3,ik),kintp,wintp)
69  wght(1:nb,kintp(1:8)) = wght(1:nb, kintp(1:8)) &
70  & + matmul(wghtd(1:nb,1:1,ik), wintp(1:1,1:8))
71  END DO ! ik = 1, nk_local
72  DEALLOCATE(wghtd, kvec)
73  !
74  IF(PRESENT(comm)) CALL libtetrabz_mpisum_dv(comm, nb * product(ngw(1:3)), wght)
75  !
76  ELSE
77  CALL libtetrabz_occ_main(wlsm,nt_local,ik_global,ik_local,nb,nkbz,eig,nk_local,wght,0d0)
78  END IF
79  !
80  DEALLOCATE(ik_global, ik_local)
81  !
82 END SUBROUTINE libtetrabz_occ
83 !
84 ! Calculate Fermi energy
85 !
86 SUBROUTINE libtetrabz_fermieng(ltetra,bvec,nb,nge,eig,ngw,wght,ef,nelec,comm) BIND(C)
87  !
88  USE iso_c_binding
91  IMPLICIT NONE
92  !
93  INTEGER(C_INT),INTENT(IN) :: ltetra, nb, nge(3), ngw(3)
94  REAL(c_double),INTENT(IN) :: bvec(9), nelec, eig(nb,product(nge(1:3)))
95  REAL(c_double),INTENT(OUT) :: ef
96  REAL(c_double),INTENT(OUT) :: wght(nb,product(ngw(1:3)))
97  INTEGER(C_INT),INTENT(IN),OPTIONAL :: comm
98  !
99  LOGICAL :: linterpol
100  INTEGER :: nt_local, nk_local, nkbz, ik, kintp(8)
101  INTEGER,ALLOCATABLE :: ik_global(:,:), ik_local(:,:)
102  REAL(8) :: wlsm(4,20), wintp(1,8)
103  REAL(8),ALLOCATABLE :: wghtd(:,:,:), kvec(:,:)
104  !
105  INTEGER :: iter, maxiter = 300
106  REAL(8) :: elw, eup, eps= 1d-10, sumkmid
107  !
108  IF(PRESENT(comm)) THEN
109  CALL libtetrabz_initialize(ltetra,nge,ngw,bvec,linterpol,wlsm,nk_local,&
110  & nt_local,nkbz,ik_global,ik_local,kvec,comm)
111  ELSE
112  CALL libtetrabz_initialize(ltetra,nge,ngw,bvec,linterpol,wlsm,nk_local,&
113  & nt_local,nkbz,ik_global,ik_local,kvec)
114  END IF
115  !
116  IF(linterpol) ALLOCATE(wghtd(nb,1,nk_local))
117  !
118  elw = minval(eig(1:nb,1:product(nge(1:3))))
119  eup = maxval(eig(1:nb,1:product(nge(1:3))))
120  !
121  ! Bisection method
122  !
123  DO iter = 1, maxiter
124  !
125  ef = (eup + elw) / 2.d0
126  !
127  ! Calc. # of electrons
128  !
129  IF(linterpol) THEN
130  CALL libtetrabz_occ_main(wlsm,nt_local,ik_global,ik_local,nb,nkbz,eig,nk_local,wghtd,ef)
131  sumkmid = sum(wghtd(1:nb,1,1:nk_local))
132  !
133  IF(PRESENT(comm)) CALL libtetrabz_mpisum_d(comm,sumkmid)
134  !
135  ELSE
136  CALL libtetrabz_occ_main(wlsm,nt_local,ik_global,ik_local,nb,nkbz,eig,nk_local,wght,ef)
137  sumkmid = sum(wght(1:nb,1:nk_local))
138  END IF
139  !
140  ! convergence check
141  !
142  IF(abs(sumkmid - nelec) < eps) THEN
143  EXIT
144  ELSE IF(sumkmid < nelec) THEN
145  elw = ef
146  ELSE
147  eup = ef
148  ENDIF
149  !
150  END DO ! iter
151  !
152  IF(iter >= maxiter) stop "libtetrabz_fermieng"
153  !
154  IF(linterpol) THEN
155  !
156  ! Interpolation
157  !
158  wght(1:nb,1:product(ngw(1:3))) = 0d0
159  DO ik = 1, nk_local
160  CALL libtetrabz_interpol_indx(ngw,kvec(1:3,ik),kintp,wintp)
161  wght(1:nb,kintp(1:8)) = wght(1:nb, kintp(1:8)) &
162  & + matmul(wghtd(1:nb,1:1,ik), wintp(1:1,1:8))
163  END DO ! ik = 1, nk_local
164  DEALLOCATE(wghtd, kvec)
165  !
166  IF(PRESENT(comm)) CALL libtetrabz_mpisum_dv(comm, nb * product(ngw(1:3)), wght)
167  !
168  END IF ! (linterpol)
169  !
170  DEALLOCATE(ik_global, ik_local)
171  !
172 END SUBROUTINE libtetrabz_fermieng
173 !
174 ! Main SUBROUTINE for occupation : Theta(EF - E1)
175 !
176 SUBROUTINE libtetrabz_occ_main(wlsm,nt_local,ik_global,ik_local,nb,nkBZ,eig,nk_local,occ,ef)
177  !
178  USE libtetrabz_common, ONLY : libtetrabz_sort, &
183  IMPLICIT NONE
184  !
185  INTEGER,INTENT(IN) :: nt_local, nb, nkBZ, nk_local, &
186  & ik_global(20,nt_local), ik_local(20,nt_local)
187  REAL(8),INTENT(IN) :: wlsm(4,20), ef, eig(nb,nkBZ)
188  REAL(8),INTENT(OUT) :: occ(nb,nk_local)
189  !
190  INTEGER :: ib, indx(4), it
191  REAL(8) :: e(4), ei1(4,nb), tsmall(4,4), V, w1(4)
192  !
193  occ(1:nb,1:nk_local) = 0d0
194  !
195  !$OMP PARALLEL DEFAULT(NONE) &
196  !$OMP & SHARED(ef,eig,ik_global,ik_local,nb,nt_local,occ,wlsm) &
197  !$OMP & PRIVATE(e,ei1,ib,indx,it,tsmall,V,w1)
198  !
199  DO it = 1, nt_local
200  !
201  DO ib = 1, nb
202  ei1(1:4,ib) = matmul(wlsm(1:4,1:20), eig(ib,ik_global(1:20,it)))
203  END DO
204  !
205  !$OMP DO
206  DO ib = 1, nb
207  !
208  w1(1:4) = 0d0
209  e(1:4) = ei1(1:4, ib) - ef
210  CALL libtetrabz_sort(4,e,indx)
211  !
212  IF(e(1) <= 0d0 .AND. 0d0 < e(2)) THEN
213  !
214  CALL libtetrabz_tsmall_a1(e,v,tsmall)
215  w1(indx(1:4)) = w1(indx(1:4)) + v * sum(tsmall(1:4,1:4), 1) * 0.25d0
216  !
217  ELSE IF(e(2) <= 0d0 .AND. 0d0 < e(3)) THEN
218  !
219  CALL libtetrabz_tsmall_b1(e,v,tsmall)
220  w1(indx(1:4)) = w1(indx(1:4)) + v * sum(tsmall(1:4,1:4), 1) * 0.25d0
221  !
222  CALL libtetrabz_tsmall_b2(e,v,tsmall)
223  w1(indx(1:4)) = w1(indx(1:4)) + v * sum(tsmall(1:4,1:4), 1) * 0.25d0
224  !
225  CALL libtetrabz_tsmall_b3(e,v,tsmall)
226  w1(indx(1:4)) = w1(indx(1:4)) + v * sum(tsmall(1:4,1:4), 1) * 0.25d0
227  !
228  ELSE IF(e(3) <= 0d0 .AND. 0d0 < e(4)) THEN
229  !
230  CALL libtetrabz_tsmall_c1(e,v,tsmall)
231  w1(indx(1:4)) = w1(indx(1:4)) + v * sum(tsmall(1:4,1:4), 1) * 0.25d0
232  !
233  CALL libtetrabz_tsmall_c2(e,v,tsmall)
234  w1(indx(1:4)) = w1(indx(1:4)) + v * sum(tsmall(1:4,1:4), 1) * 0.25d0
235  !
236  CALL libtetrabz_tsmall_c3(e,v,tsmall)
237  w1(indx(1:4)) = w1(indx(1:4)) + v * sum(tsmall(1:4,1:4), 1) * 0.25d0
238  !
239  ELSE IF(e(4) <= 0d0) THEN
240  !
241  w1(1:4) = 0.25d0
242  !
243  ELSE
244  !
245  cycle
246  !
247  END IF
248  !
249  occ(ib,ik_local(1:20,it)) = occ(ib,ik_local(1:20,it)) &
250  & + matmul(w1(1:4), wlsm(1:4,1:20))
251  !
252  END DO ! ib
253  !$OMP END DO NOWAIT
254  !
255  END DO ! it
256  !
257  !$OMP END PARALLEL
258  !
259  occ(1:nb,1:nk_local) = occ(1:nb,1:nk_local) / dble(6 * nkbz)
260  !
261 END SUBROUTINE libtetrabz_occ_main
262 !
263 END MODULE libtetrabz_occ_mod
libtetrabz_common::libtetrabz_tsmall_b2
subroutine, public libtetrabz_tsmall_b2(e, V, tsmall)
Definition: libtetrabz_common.F90:432
libtetrabz_common::libtetrabz_mpisum_d
subroutine, public libtetrabz_mpisum_d(comm, scaler)
Definition: libtetrabz_common.F90:666
libtetrabz_common::libtetrabz_tsmall_c1
subroutine, public libtetrabz_tsmall_c1(e, V, tsmall)
Definition: libtetrabz_common.F90:484
libtetrabz_common::libtetrabz_mpisum_dv
subroutine, public libtetrabz_mpisum_dv(comm, ndim, vector)
Definition: libtetrabz_common.F90:687
libtetrabz_common::libtetrabz_tsmall_a1
subroutine, public libtetrabz_tsmall_a1(e, V, tsmall)
Definition: libtetrabz_common.F90:380
libtetrabz_common::libtetrabz_tsmall_b1
subroutine, public libtetrabz_tsmall_b1(e, V, tsmall)
Definition: libtetrabz_common.F90:406
libtetrabz_common::libtetrabz_initialize
subroutine, public libtetrabz_initialize(ltetra, nge, ngw, bvec, linterpol, wlsm, nk_local, nt_local, nkBZ, ik_global, ik_local, kvec, comm)
Definition: libtetrabz_common.F90:40
libtetrabz_occ_mod::libtetrabz_fermieng
subroutine, public libtetrabz_fermieng(ltetra, bvec, nb, nge, eig, ngw, wght, ef, nelec, comm)
Definition: libtetrabz_occ_mod.F90:87
libtetrabz_common::libtetrabz_interpol_indx
subroutine, public libtetrabz_interpol_indx(ng, kvec, kintp, wintp)
Definition: libtetrabz_common.F90:340
libtetrabz_common::libtetrabz_tsmall_c3
subroutine, public libtetrabz_tsmall_c3(e, V, tsmall)
Definition: libtetrabz_common.F90:536
libtetrabz_common::libtetrabz_tsmall_c2
subroutine, public libtetrabz_tsmall_c2(e, V, tsmall)
Definition: libtetrabz_common.F90:510
libtetrabz_common
Definition: libtetrabz_common.F90:23
libtetrabz_occ_mod
Definition: libtetrabz_occ_mod.F90:23
libtetrabz_occ_mod::libtetrabz_occ
subroutine, public libtetrabz_occ(ltetra, bvec, nb, nge, eig, ngw, wght, comm)
Definition: libtetrabz_occ_mod.F90:35
libtetrabz_common::libtetrabz_tsmall_b3
subroutine, public libtetrabz_tsmall_b3(e, V, tsmall)
Definition: libtetrabz_common.F90:458
libtetrabz_common::libtetrabz_sort
subroutine, public libtetrabz_sort(n, key, indx)
Definition: libtetrabz_common.F90:308
libtetrabz_occ_mod::libtetrabz_occ_main
subroutine libtetrabz_occ_main(wlsm, nt_local, ik_global, ik_local, nb, nkBZ, eig, nk_local, occ, ef)
Definition: libtetrabz_occ_mod.F90:177