Branch data Line data Source code
1 : : !!****m* ABINIT/m_getshell
2 : : !! NAME
3 : : !! m_getshell
4 : : !!
5 : : !! FUNCTION
6 : : !!
7 : : !!
8 : : !! COPYRIGHT
9 : : !! Copyright (C) 1999-2026 ABINIT group (MVeithen)
10 : : !! This file is distributed under the terms of the
11 : : !! GNU General Public License, see ~abinit/COPYING
12 : : !! or http://www.gnu.org/copyleft/gpl.txt .
13 : : !!
14 : : !! SOURCE
15 : :
16 : : #if defined HAVE_CONFIG_H
17 : : #include "config.h"
18 : : #endif
19 : :
20 : : #include "abi_common.h"
21 : :
22 : : module m_getshell
23 : :
24 : : use defs_basis
25 : : use m_abicore
26 : : use m_xmpi
27 : : use m_errors
28 : : use m_linalg_interfaces
29 : :
30 : : use m_kpts, only : getkgrid
31 : :
32 : : implicit none
33 : :
34 : : private
35 : : !!***
36 : :
37 : : public :: getshell
38 : : !!***
39 : :
40 : : contains
41 : : !!***
42 : :
43 : : !!****f* ABINIT/getshell
44 : : !! NAME
45 : : !! getshell
46 : : !!
47 : : !! FUNCTION
48 : : !! For each k-point, set up the shells of first neighbours and find
49 : : !! the weigths required for the finite difference expression
50 : : !! of Marzari and Vanderbilt (see PRB 56, 12847 (1997) [[cite:Marzari1997]]).
51 : : !!
52 : : !! INPUTS
53 : : !! gmet(3,3) = metric tensor of reciprocal space
54 : : !! kptopt = option for the generation of k points
55 : : !! kptrlatt = k-point lattice specification
56 : : !! kpt2(3,nkpt2) = reduced coordinates of the k-points in the
57 : : !! reduced part of the BZ (see below)
58 : : !! mkmem = number of k points which can fit in memory
59 : : !! nkpt2 = number of k-points in the reduced BZ
60 : : !! nkpt3 = number of k-points in the full BZ
61 : : !! nshiftk = number of kpoint grid shifts
62 : : !! rmet(3,3) = metric tensor of real space
63 : : !! rprimd(3,3) = dimensional primitive translations (bohr)
64 : : !! shiftk = shift vectors for k point generation
65 : : !! wtk2 = weight assigned to each k point
66 : : !! comm=MPI communicator
67 : : !!
68 : : !! OUTPUT
69 : : !! kneigh(30,nkpt2) = for each k-point in the reduced part of the BZ
70 : : !! kneigh stores the index (ikpt) of the neighbouring
71 : : !! k-points
72 : : !! kg_neigh(30,nkpt2,3) = kg-neigh takes values of -1, 0 or 1,
73 : : !! and can be non-zero only for a single k-point,
74 : : !! a line of k-points or a plane of k-points.
75 : : !! The vector joining the ikpt2-th k-point to its
76 : : !! ineigh-th nearest neighbour is :
77 : : !! dk(:)-nint(dk(:))+real(kg_neigh(ineigh,ikpt2,:))
78 : : !! with dk(:)=kpt2(:,kneigh(ineigh,ikpt2))-kpt2(:,ikpt2)
79 : : !! kptindex(2,nkpt3)
80 : : !! kptindex(1,ikpt) = ikpt_rbz
81 : : !! ikpt_rbz = index of the k-point in the reduced BZ
82 : : !! ikpt = index of the k-point in the full BZ
83 : : !! kptindex(2,ikpt) = 1: use time-reversal symmetry to transform the
84 : : !! wavefunction at ikpt_rbz to the wavefunction at ikpt
85 : : !! 0: ikpt belongs already to the reduced BZ
86 : : !! (no transformation required)
87 : : !! kpt3(3,nkpt3) = reduced coordinates of the k-points in the full BZ
88 : : !! mvwtk(30,nkpt2) = weights required to evaluate the finite difference
89 : : !! formula of Marzari and Vanderbilt, computed for each
90 : : !! k-point in the reduced part of the BZ
91 : : !! mkmem_max = maximal number of k-points on each processor (MPI //)
92 : : !! nneigh = total number of neighbours required to evaluate the finite
93 : : !! difference formula
94 : : !!
95 : : !! COMMENTS
96 : : !! The array kpt2 holds the reduced coordinates of the k-points in the
97 : : !! reduced part of the BZ. For example, in case time-reversal symmetry is
98 : : !! used (kptopt = 2) kpt2 samples half the BZ. Since some of the neighbours
99 : : !! of these k-points may lie outside the reduced BZ, getshell also needs the
100 : : !! coordinates of the k-points in the full BZ.
101 : : !! The coordinates of the k-points in the full BZ are stored in kpt3.
102 : : !! The weights mvwtk are computed for the k-points kpt2.
103 : : !!
104 : : !! In case no symmetry is used to reduce the number of k-points,
105 : : !! the arrays kpt2 and kpt3 are equal.
106 : : !!
107 : : !! SOURCE
108 : :
109 : 21 : subroutine getshell(gmet,kneigh,kg_neigh,kptindex,kptopt,kptrlatt,kpt2,&
110 : 21 : & kpt3,mkmem,mkmem_max,mvwtk,&
111 : 21 : & nkpt2,nkpt3,nneigh,nshiftk,rmet,rprimd,shiftk,wtk2, comm)
112 : :
113 : : !Arguments ------------------------------------
114 : : !scalars
115 : : integer,intent(in) :: kptopt,mkmem,nkpt2,nkpt3,comm
116 : : integer,intent(inout) :: nshiftk
117 : : integer,intent(out) :: mkmem_max,nneigh
118 : : !arrays
119 : : integer,intent(inout) :: kptrlatt(3,3)
120 : : integer,intent(out) :: kneigh(30,nkpt2),kptindex(2,nkpt3),kg_neigh(30,nkpt2,3)
121 : : real(dp),intent(in) :: gmet(3,3),kpt2(3,nkpt2),rmet(3,3),rprimd(3,3)
122 : : real(dp),intent(in) :: shiftk(3,nshiftk),wtk2(nkpt2)
123 : : real(dp),intent(out) :: kpt3(3,nkpt3),mvwtk(30,nkpt2)
124 : :
125 : : !Local variables-------------------------------
126 : : !scalars
127 : : integer :: bis,flag,ier,ii,ikpt,ikpt2,ikpt3,ineigh,info,irank,is1,ishell
128 : : integer :: jj,kptopt_used,mkmem_cp,nkpt_computed,nshell,nsym1,orig
129 : : integer :: wtkflg, coord1, coord2, coord3
130 : : real(dp) :: dist_,kptrlen,last_dist,max_dist,resdm,s1, max_err, my_tol
131 : : character(len=500) :: msg
132 : : !arrays
133 : : integer :: unts(2)
134 : 42 : integer :: neigh(0:6,nkpt2),symafm_dummy(1),vacuum(3)
135 : 21 : integer,allocatable :: symrel1(:,:,:)
136 : : real(dp) :: dist(6),dk(3),dk_(3),mat(6,6),rvec(6),sgval(6)
137 : : real(dp) :: shiftk_(3,MAX_NSHIFTK),work(30)
138 : 21 : real(dp),allocatable :: tnons1(:,:),wtk3(:)
139 : :
140 : : !************************************************************************
141 : :
142 : : !In case of MPI //: compute maximum number of k-points per processor
143 : : if (xmpi_paral == 1) then
144 : 21 : mkmem_cp=mkmem
145 : 21 : call xmpi_max(mkmem_cp,mkmem_max,comm,ier)
146 : : else
147 : : mkmem_max = mkmem
148 : : end if
149 : :
150 [ + + ]: 63 : unts = [std_out, ab_out]
151 : :
152 : : !------------- In case kptopt = 2 set up the whole k-point grid -------------
153 : :
154 : : !kpt3(3,nkpt3) = reduced coordinates of k-points in the full BZ
155 : :
156 [ - + ]: 21 : if (kptopt == 3) then
157 : :
158 [ # # # # : 0 : ABI_MALLOC(wtk3,(nkpt3))
# # # # #
# # # ]
159 [ # # # # ]: 0 : kpt3(:,:) = kpt2(:,:)
160 [ # # ]: 0 : wtk3(:) = wtk2(:)
161 [ # # ]: 0 : do ikpt = 1,nkpt3
162 : 0 : kptindex(1,ikpt) = ikpt
163 : 0 : kptindex(2,ikpt) = 0
164 : : end do
165 : :
166 [ + - ]: 21 : else if (kptopt == 2) then
167 : :
168 [ - + + - : 63 : ABI_MALLOC(wtk3,(nkpt3))
+ - + - -
+ - + ]
169 : 21 : ii = 5 ; kptopt_used = 3
170 : 21 : symafm_dummy(1) = 1
171 : 21 : shiftk_(:,:) = 0._dp
172 [ + + + + ]: 105 : shiftk_(:,1:nshiftk) = shiftk(:,1:nshiftk)
173 : :
174 : 21 : nsym1 = 1
175 [ - + ]: 21 : ABI_MALLOC(symrel1,(3,3,nsym1))
176 [ - + ]: 21 : ABI_MALLOC(tnons1,(3,nsym1))
177 [ + + + + ]: 273 : symrel1(:,:,1) = 0
178 : 21 : symrel1(1,1,1) = 1 ; symrel1(2,2,1) = 1 ; symrel1(3,3,1) = 1
179 [ + + + + ]: 105 : tnons1(:,:) = 0._dp
180 : 21 : vacuum(:) = 0
181 : :
182 : : call getkgrid(0,0,ii,kpt3,kptopt_used,kptrlatt,&
183 : : kptrlen,nsym1,nkpt3,nkpt_computed,nshiftk,nsym1,&
184 : : rprimd,shiftk_,symafm_dummy,symrel1,&
185 : 21 : vacuum,wtk3)
186 : :
187 [ - + ]: 21 : if (nkpt_computed /= nkpt3) then
188 : : write(msg,'(a,a,a,a,i0,a,a,i0)')&
189 : 0 : ' The number of k-points in the whole BZ, nkpt_computed= ',nkpt_computed,ch10,&
190 : 0 : ' is not twice the number of k-points in half the BZ, nkpt3=',nkpt3
191 : 0 : ABI_BUG(msg)
192 : : end if
193 : :
194 [ + + + + ]: 3966 : kptindex(:,:) = 0
195 [ + + ]: 1336 : do ikpt3 = 1, nkpt3
196 : :
197 : 190511 : flag = 1
198 [ + - ]: 190511 : do ikpt2 = 1, nkpt2
199 : :
200 : : ! In case the k-points differ only by one reciprocal lattice
201 : : ! vector, apply shift of one g-vector to kpt(:,ikpt3)
202 : : ! MJV 10/2019: this appears to be using time reversal sym, instead of the G vector...
203 : : ! could be equivalent to keep points inside the 1st BZ, but the code below is not consistent
204 : : ! with this comment
205 : :
206 : : !
207 : : ! here k3 = k2 + G
208 : : !
209 [ + + ]: 762044 : dk_(:) = kpt3(:,ikpt3) - kpt2(:,ikpt2)
210 [ + + ]: 762044 : dk(:) = dk_(:) - nint(dk_(:))
211 [ + + ]: 190511 : if (dk(1)*dk(1) + dk(2)*dk(2) + dk(3)*dk(3) < tol10) then
212 [ + + ]: 2632 : do ii = 1, 3
213 [ + - - + ]: 2632 : if ((dk(ii)*dk(ii) < tol10).and.(dk_(ii)*dk_(ii) > tol10)) then
214 : : ! transform k3 to -k3
215 : : ! TODO: I suspect this should be k3 -= G!!
216 : 0 : kpt3(ii,ikpt3) = -1._dp*kpt3(ii,ikpt3)
217 : : end if
218 : : end do
219 : : end if
220 : :
221 : : !
222 : : ! here k3 = -k2 + G
223 : : !
224 [ + + ]: 762044 : dk_(:) = kpt3(:,ikpt3) + kpt2(:,ikpt2)
225 [ + + ]: 762044 : dk(:) = dk_(:) - nint(dk_(:))
226 [ + + ]: 190511 : if (dk(1)*dk(1) + dk(2)*dk(2) + dk(3)*dk(3) < tol10) then
227 [ + + ]: 2632 : do ii = 1, 3
228 [ + - + + ]: 2632 : if ((dk(ii)*dk(ii) < tol10).and.(dk_(ii)*dk_(ii) > tol10)) then
229 : : ! transform k3 to -k3
230 : : ! TODO: I suspect this should be k3 -= G!!
231 : 302 : kpt3(ii,ikpt3) = -1._dp*kpt3(ii,ikpt3)
232 : : end if
233 : : end do
234 : : end if
235 : :
236 : :
237 : : !
238 : : ! here k3 = k2
239 : : !
240 [ + + ]: 762044 : dk(:) = kpt3(:,ikpt3) - kpt2(:,ikpt2)
241 [ + + ]: 190511 : if (dk(1)*dk(1) + dk(2)*dk(2) + dk(3)*dk(3) < tol10) then
242 : 658 : kptindex(1,ikpt3) = ikpt2
243 : 658 : kptindex(2,ikpt3) = 0 ! no use of time-reversal symmetry
244 : : flag = 0
245 : : exit
246 : : end if
247 : :
248 : : !
249 : : ! here k3 = -k2
250 : : !
251 [ + + ]: 759412 : dk(:) = kpt3(:,ikpt3) + kpt2(:,ikpt2)
252 [ + + ]: 189853 : if (dk(1)*dk(1) + dk(2)*dk(2) + dk(3)*dk(3) < tol10) then
253 : 657 : kptindex(1,ikpt3) = ikpt2
254 : 657 : kptindex(2,ikpt3) = 1 ! use time-reversal symmetry
255 : : flag = 0
256 : : exit
257 : : end if
258 : :
259 : : end do ! ikpt2
260 : :
261 : 21 : if (flag == 1) then
262 : 0 : write(msg,'(a,i0)')' Could not find a symmetric k-point for ikpt3= ',ikpt3
263 : 0 : ABI_BUG(msg)
264 : : end if
265 : : end do ! ikpt3
266 : :
267 : : else
268 : 0 : ABI_ERROR(' the only values for kptopt that are allowed are 2 and 3 ')
269 : : end if ! condition on kptopt
270 : :
271 : :
272 : : !--------- Compute the weights required for the Marzari-Vanderbilt ---------
273 : : !--------- finite difference formula ---------------------------------------
274 : :
275 : :
276 : : !Initialize distance between k-points
277 : : !The trace of gmet is an upper limit for its largest eigenvalue. Since the
278 : : !components of the distance vectors do not exceed 1, 3. * Tr[gmet] is
279 : : !an upper limit for the squared shell radius.
280 : : !we take something two times larger to make a bug checking.
281 : 21 : dist_ = 0._dp
282 [ + + ]: 84 : do ii = 1,3
283 : 84 : dist_ = dist_ + gmet(ii,ii)
284 : : end do
285 : 21 : max_dist = 3._dp * dist_ * 2._dp
286 : 21 : write(std_out,*)'max_dist',max_dist
287 : :
288 : : !Calculate an upper limit for the residuum
289 : : resdm = rmet(1,1)*rmet(1,1) + rmet(2,2)*rmet(2,2) + rmet(3,3)*rmet(3,3)&
290 : 21 : & + rmet(1,2)*rmet(1,2) + rmet(2,3)*rmet(2,3) + rmet(3,1)*rmet(3,1)
291 : :
292 : : !Initialize shell loop
293 : 21 : ishell = 0
294 : 21 : last_dist = 0._dp
295 : 21 : wtkflg = 0
296 [ + + + + ]: 20419 : kneigh(:,:) = 0
297 [ + + + + : 61278 : kg_neigh(:,:,:) = 0
+ + ]
298 [ + + + + ]: 5285 : neigh(:,:) = 0
299 : :
300 : : !Loop over shells until the residuum is zero
301 [ + - + + ]: 115 : do while ((wtkflg == 0).and.(resdm > tol8))
302 : : ! Advance shell counter
303 : 94 : ishell = ishell + 1
304 : :
305 : : ! Initialize shell radius with upper limit
306 : 94 : dist(ishell) = max_dist
307 : : ! !! border_flag = 1
308 : :
309 : : ! !write(std_out,*)'gmet'
310 : : ! !do ikpt=1,3
311 : : ! !write(std_out,*)gmet(ikpt,:)
312 : : ! !enddo
313 : : ! !write(std_out,*)kpt3(:,1)
314 : :
315 : : ! Find the (squared) radius of the next shell
316 [ + + ]: 2126 : do ikpt = 1,nkpt3
317 : : ! !write(std_out,*)ikpt
318 : : ! !write(std_out,*)kpt3(:,ikpt)
319 [ + + ]: 8128 : dk(:) = kpt3(:,1) - kpt3(:,ikpt)
320 : : ! !!dk_(:) = dk(:) - nint(dk(:))
321 : : ! !!dist_ = 0._dp
322 : : ! !!do ii = 1,3
323 : : ! !! do jj = 1,3
324 : : ! !! dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
325 : : ! !! end do
326 : : ! !!end do
327 : : ! !!write(std_out,*)'dist_1', dist_
328 : : ! !! dist_ = 0._dp
329 : : ! !! do ii = 1,3
330 : : ! !! do jj = 1,3
331 : : ! !! dist_ = dist_ + dk(ii)*gmet(ii,jj)*dk(jj)
332 : : ! !! end do
333 : : ! !! end do
334 : : ! !!write(std_out,*)'dist_2',dist_
335 [ + + ]: 6190 : do coord1 = 0,1 !three loop to search also on the border of the BZ, ie for the k-points (1,k2,k3) and the likes
336 [ + + ]: 14224 : do coord2 = 0,1
337 [ + + ]: 28448 : do coord3 = 0,1
338 : : ! !! if ((coord1/=0).or.(coord2/=0).or.(coord3/=0)) then
339 : 65024 : dist_ = 0._dp
340 [ + + ]: 65024 : dk_(:) = dk(:) - nint(dk(:))
341 : 16256 : dk_(1) = dk_(1) + real(coord1,dp)
342 : 16256 : dk_(2) = dk_(2) + real(coord2,dp)
343 : 16256 : dk_(3) = dk_(3) + real(coord3,dp)
344 [ + + ]: 65024 : do ii = 1,3
345 [ + + ]: 211328 : do jj = 1,3
346 : 195072 : dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
347 : : end do
348 : : end do
349 : : ! Note : for ipkt3 = 1, coord1 = coord2 = coord3 = 0, the distance is 0 ;
350 : : ! but the next "if" statement is false with the tol8 criteria and the k-point
351 : : ! should be ignored even for ishell = 1 and last_dist= 0.
352 : : ! !$write(std_out,*)ikpt,coord1,coord2,coord3
353 : : ! !$write(std_out,*)dk_
354 : : ! !$write(std_out,*)'dist_2', dist_
355 : : ! !! end if
356 [ + + + + ]: 24384 : if ((dist_ < dist(ishell)).and.(dist_ - last_dist > tol8)) then
357 : 360 : dist(ishell) = dist_
358 : : end if
359 : : end do
360 : : end do
361 : : end do
362 : :
363 : : ! !! if ((dist_ < dist(ishell)).and.(dist_ - last_dist > tol8)) then
364 : : ! !! dist(ishell) = dist_
365 : : ! !! border_flag = 0
366 : : ! !! end if
367 : : end do
368 : :
369 : : ! !! if (border_flag==1) then !we haven't found any shell in the interior of the BZ, we need to search on the border
370 : : ! !!write(std_out,*)ch10
371 : : ! !!write(std_out,*)'search on the border'
372 : : ! !! do ikpt = 1,nkpt3
373 : : ! !! dk(:) = kpt3(:,1) - kpt3(:,ikpt)
374 : : ! !! do coord1 = 0,1
375 : : ! !! do coord2 = 0,1
376 : : ! !! do coord3 = 0,1
377 : : ! !! if ((coord1/=0).or.(coord2/=0).or.(coord3/=0)) then
378 : : ! !! dist_ = 0._dp
379 : : ! !! dk_(:) = dk(:) - nint(dk(:))
380 : : ! !! dk_(1) = dk_(1) + real(coord1,dp)
381 : : ! !! dk_(2) = dk_(2) + real(coord2,dp)
382 : : ! !! dk_(3) = dk_(3) + real(coord3,dp)
383 : : ! !! do ii = 1,3
384 : : ! !! do jj = 1,3
385 : : ! !! dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
386 : : ! !! end do
387 : : ! !! end do
388 : : ! !!write(std_out,*)ikpt,coord1,coord2,coord3
389 : : ! !!write(std_out,*)dk_
390 : : ! !!write(std_out,*)'dist_2', dist_
391 : : ! !! end if
392 : : ! !! if ((dist_ < dist(ishell)).and.(dist_ - last_dist > tol8)) then
393 : : ! !! dist(ishell) = dist_
394 : : ! !! end if
395 : : ! !! end do
396 : : ! !! end do
397 : : ! !! end do
398 : : ! !! end do
399 : : ! !! endif
400 : :
401 : : ! DEBUG
402 : : ! !write(std_out,*)ch10
403 : : ! write(std_out,*)'ishell, dist = ',ishell,dist(ishell)
404 : : ! ENDDEBUG
405 : :
406 [ - + ]: 94 : if (max_dist-dist(ishell)<tol8) then
407 : 0 : write(msg,'(a,i0)')' Cannot find shell number',ishell
408 : 0 : ABI_BUG(msg)
409 : : end if
410 : :
411 : 1111 : last_dist = dist(ishell)
412 : :
413 : : ! For each k-point in half the BZ get the shells of nearest neighbours.
414 : : ! These neighbours can be out of the zone sampled by kpt2.
415 : : ! !$write(std_out,*)'nkpt2', nkpt2, 'nkpt3', nkpt3
416 [ + + ]: 1111 : do ikpt2 = 1, nkpt2 ! k-points in half the BZ
417 [ + + ]: 2393 : orig = sum(neigh(0:ishell-1,ikpt2))
418 : : ! !write(std_out,*)'ikpt2, orig', ikpt2,orig
419 : : ! !write(std_out,*) kpt2(:,ikpt2)
420 : 1017 : nneigh = 0
421 [ + + ]: 384289 : do ikpt3 = 1, nkpt3 ! whole k-point grid
422 : : ! !! if(border_flag==0)then
423 [ + + ]: 1533088 : dk(:) = kpt3(:,ikpt3) - kpt2(:,ikpt2)
424 : : ! !! dk_(:) = dk(:) - nint(dk(:))
425 : : ! !! dist_ = 0._dp
426 [ + + ]: 1534105 : do coord1 = -1,1
427 [ + + ]: 4982536 : do coord2 = -1,1
428 [ + + ]: 14947608 : do coord3 = -1,1
429 : : ! !! if ((coord1/=0).or.(coord2/=0).or.(coord3/=0)) then
430 : 41393376 : dist_ = 0._dp
431 [ + + ]: 41393376 : dk_(:) = dk(:) - nint(dk(:))
432 : 10348344 : dk_(1) = dk_(1) + real(coord1,dp)
433 : 10348344 : dk_(2) = dk_(2) + real(coord2,dp)
434 : 10348344 : dk_(3) = dk_(3) + real(coord3,dp)
435 [ + + ]: 41393376 : do ii = 1,3
436 [ + + ]: 134528472 : do jj = 1,3
437 : 124180128 : dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
438 : : end do
439 : : end do
440 [ + + ]: 13797792 : if (abs(dist_ - dist(ishell)) < tol8) then
441 : 4598 : nneigh = nneigh + 1
442 : 4598 : kneigh(orig+nneigh,ikpt2) = ikpt3
443 : 4598 : kg_neigh(orig+nneigh,ikpt2,1) = coord1
444 : 4598 : kg_neigh(orig+nneigh,ikpt2,2) = coord2
445 : 4598 : kg_neigh(orig+nneigh,ikpt2,3) = coord3
446 : : end if
447 : : ! !! end if
448 : : end do
449 : : end do
450 : : end do
451 : : ! !write(std_out,*)'ikpt3', ikpt3
452 : : ! !write(std_out,*) kpt3(:,ikpt3)
453 : : ! write(std_out,*) kpt2(:,ikpt2)
454 : : ! !write(std_out,*) dk
455 : : ! write(std_out,*) dk_
456 : : ! !! do ii = 1,3
457 : : ! !! do jj = 1,3
458 : : ! !! dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
459 : : ! !! end do
460 : : ! !! end do
461 : : ! !write(std_out,*)'dist_', dist_
462 : : ! !! if (abs(dist_ - dist(ishell)) < tol8) then
463 : : ! !! nneigh = nneigh + 1
464 : : ! !! kneigh(orig+nneigh,ikpt2) = ikpt3
465 : : ! !! end if
466 : : ! !! else !search on the border
467 : : ! !! dk(:) = kpt3(:,ikpt3) - kpt2(:,ikpt2)
468 : : ! !! do coord1 = -1,1
469 : : ! !! do coord2 = -1,1
470 : : ! !! do coord3 = -1,1
471 : : ! !! if ((coord1/=0).or.(coord2/=0).or.(coord3/=0)) then
472 : : ! !! dist_ = 0._dp
473 : : ! !! dk_(:) = dk(:) - nint(dk(:))
474 : : ! !! dk_(1) = dk_(1) + real(coord1,dp)
475 : : ! !! dk_(2) = dk_(2) + real(coord2,dp)
476 : : ! !! dk_(3) = dk_(3) + real(coord3,dp)
477 : : ! !! do ii = 1,3
478 : : ! !! do jj = 1,3
479 : : ! !! dist_ = dist_ + dk_(ii)*gmet(ii,jj)*dk_(jj)
480 : : ! !! end do
481 : : ! !! end do
482 : : ! !! if (abs(dist_ - dist(ishell)) < tol8) then
483 : : ! !! nneigh = nneigh + 1
484 : : ! !! kneigh(orig+nneigh,ikpt2) = ikpt3
485 : : ! !! kneigh_border(orig+nneigh,ikpt2,1) = real(coord1,dp)
486 : : ! !! kneigh_border(orig+nneigh,ikpt2,2) = real(coord2,dp)
487 : : ! !! kneigh_border(orig+nneigh,ikpt2,3) = real(coord3,dp)
488 : : ! !! end if
489 : : ! !! end if
490 : : ! !! end do
491 : : ! !! end do
492 : : ! !! end do
493 : : ! !! end if
494 : : end do
495 : 1111 : neigh(ishell,ikpt2) = nneigh
496 : : end do
497 : :
498 : :
499 : : ! Check if the number of points in shell number ishell
500 : : ! is the same for each k-point
501 : :
502 : : flag = 1
503 [ + + ]: 1111 : do ikpt = 1,nkpt2
504 [ - + ]: 1111 : if (neigh(ishell,ikpt) /= nneigh) flag = 0
505 : : end do
506 : :
507 [ - + ]: 94 : if (flag == 0) then
508 : : write(msg,'(a,i0,a,a)')&
509 : 0 : ' The number of points in shell number',ishell,' is not the same',&
510 : 0 : ' for each k-point.'
511 : 0 : ABI_BUG(msg)
512 : : end if
513 : :
514 [ - + ]: 94 : if (nneigh == 0) then
515 : 0 : write(msg,'(a,a,a,a)') ch10,&
516 : 0 : ' getshell: BUG - ',ch10,&
517 : 0 : ' Cannot find enough neighbor shells'
518 : 0 : call wrtout(unts, msg)
519 : 0 : wtkflg = 1
520 : : end if
521 : :
522 : : ! Calculate the total number of neighbors
523 [ + + ]: 261 : nneigh = sum(neigh(1:ishell,1))
524 : : ! DEBUG
525 : : !write(std_out,*)'ishell = ',ishell,'nneigh = ',nneigh
526 : : ! ENDDEBUG
527 : :
528 : : ! Find the weights needed to compute the finite difference expression
529 : : ! of the ddk
530 : : ! **********************************************************************
531 : :
532 : : ! mvwtk(:,:) = 0._dp
533 : :
534 : : ! The weights are calculated for ikpt=1. The results are copied later
535 : 94 : ikpt = 1
536 : :
537 : : ! Calculate the coefficients of the linear system to be solved
538 : 94 : mat(:,:) = 0._dp
539 [ + + ]: 261 : do is1 = 1, ishell
540 [ + + ]: 407 : orig = sum(neigh(0:is1-1,ikpt))
541 : 167 : bis = orig + neigh(is1,ikpt)
542 [ + + ]: 663 : do ineigh = orig+1, bis
543 [ + + ]: 1608 : dk_(:) = kpt3(:,kneigh(ineigh,ikpt)) - kpt2(:,ikpt)
544 [ + + ]: 1608 : dk(:) = dk_(:) - nint(dk_(:))
545 [ + + ]: 1608 : dk(:) = dk(:) + real(kg_neigh(ineigh,ikpt,:),dp)
546 : 402 : mat(1,is1) = mat(1,is1) + dk(1)*dk(1)
547 : 402 : mat(2,is1) = mat(2,is1) + dk(2)*dk(2)
548 : 402 : mat(3,is1) = mat(3,is1) + dk(3)*dk(3)
549 : 402 : mat(4,is1) = mat(4,is1) + dk(1)*dk(2)
550 : 402 : mat(5,is1) = mat(5,is1) + dk(2)*dk(3)
551 : 569 : mat(6,is1) = mat(6,is1) + dk(3)*dk(1)
552 : : end do
553 : : end do
554 : :
555 : 94 : rvec(1) = rmet(1,1)
556 : 94 : rvec(2) = rmet(2,2)
557 : 94 : rvec(3) = rmet(3,3)
558 : 94 : rvec(4) = rmet(1,2)
559 : 94 : rvec(5) = rmet(2,3)
560 : 94 : rvec(6) = rmet(3,1)
561 : :
562 : : ! DEBUG
563 : : !write(std_out,*) " mat(1:6, 1:ishell) : rmet(1:6) for all 6 products dx^2... dxdy..."
564 : : !do ii = 1, 6
565 : : ! write(std_out,*) mat(ii,1:ishell), ' : ', rvec(ii)
566 : : !end do
567 : : ! ENDDEBUG
568 : :
569 : : ! Solve the linear least square problem
570 : 94 : call dgelss(6,ishell,1,mat,6,rvec,6,sgval,tol8,irank,work,30,info)
571 : :
572 [ - + ]: 94 : if( info /= 0 ) then
573 : : write(msg,'(3a,i0,a)')&
574 : 0 : ' Singular-value decomposition of the linear system determining the',ch10,&
575 : 0 : ' weights failed (info).',info,ch10
576 : 0 : ABI_COMMENT(msg)
577 : 0 : wtkflg = 1
578 : : end if
579 : :
580 : : ! Check that the system has maximum rank
581 [ + + ]: 115 : if( irank == ishell ) then
582 : : ! System has full rank. Calculate the residuum
583 : 29 : s1 = resdm
584 : 29 : resdm = 0._dp
585 [ + + ]: 166 : do is1 = ishell + 1, 6
586 : 166 : resdm = resdm + rvec(is1) * rvec(is1)
587 : : end do
588 : :
589 [ + - - - ]: 29 : if( ishell == 6 .and. resdm > tol8 ) then
590 : : write(msg,'(4a)')&
591 : 0 : ' Linear system determining the weights could not be solved',ch10,&
592 : 0 : ' This should not happen.',ch10
593 : 0 : ABI_COMMENT(msg)
594 : : wtkflg = 1
595 : : end if
596 : : else
597 : : ! The system is rank deficient
598 : 65 : ishell = ishell - 1
599 : : ! DEBUG
600 : : !write(std_out,*) 'Shell not linear independent from previous shells. Skipped.'
601 : : ! ENDDEBUG
602 : : end if
603 : :
604 : : ! DEBUG
605 : : !write(std_out,*) "ishell, nneigh, irank, resdm ", ishell, nneigh, irank, resdm
606 : : ! ENDDEBUG
607 : :
608 : : ! end of loop over shells
609 : : end do
610 : :
611 : : !Copy weights
612 : 21 : ikpt=1
613 [ + + ]: 50 : do is1 = 1, ishell
614 [ + + ]: 66 : orig = sum(neigh(0:is1-1,ikpt))
615 : 29 : bis = orig + neigh(is1,ikpt)
616 [ + + ]: 176 : mvwtk(orig+1:bis,1) = rvec(is1)
617 : : end do
618 [ + + ]: 658 : do ikpt = 2,nkpt2
619 [ + + ]: 4480 : mvwtk(1:nneigh,ikpt) = mvwtk(1:nneigh,1)
620 : : end do ! ikpt
621 : :
622 : : !Report weights
623 : 21 : write(std_out,*) 'Neighbors(1:ishell,1) ', neigh(1:ishell,1)
624 : 21 : write(std_out,*) 'Weights (1:ishell) ', rvec(1:ishell)
625 : 21 : write(std_out,*) mvwtk(1:nneigh,1)
626 : :
627 : : !Check the computed weights
628 [ + - ]: 21 : if (wtkflg == 0) then
629 : 21 : max_err = zero
630 : 21 : my_tol = five * tol6
631 [ + + ]: 679 : do ikpt = 1, nkpt2
632 [ + + ]: 2653 : do ii = 1,3
633 [ + + ]: 8554 : do jj = 1,3
634 : 5922 : s1 = 0._dp
635 [ + + ]: 41454 : do ineigh = 1, nneigh
636 [ + + ]: 142128 : dk_(:) = kpt3(:,kneigh(ineigh,ikpt)) - kpt2(:,ikpt)
637 [ + + ]: 142128 : dk(:) = dk_(:) - nint(dk_(:))
638 [ + + ]: 142128 : dk(:) = dk(:) + real(kg_neigh(ineigh,ikpt,:),dp)
639 : 41454 : s1 = s1 + dk(ii)*dk(jj)*mvwtk(ineigh,ikpt)
640 : : end do
641 [ - + ]: 7896 : if (abs(s1 - rmet(ii,jj)) > my_tol) then
642 : 0 : max_err = max(max_err, abs(s1 - rmet(ii,jj)))
643 : 0 : wtkflg = 1
644 : : end if
645 : : end do
646 : : end do
647 : : end do
648 : :
649 [ + - ]: 21 : if (wtkflg /= 0) then
650 : 0 : write(msg,'(5a, 2(a, es16.8))') ch10,&
651 : 0 : ' getshell: BUG -',ch10,&
652 : 0 : ' The calculated weights do not solve the linear system for all k-points.', ch10, &
653 : 0 : " max_err: ", max_err, " > tolerance: ", my_tol
654 : 0 : call wrtout(unts, msg)
655 : : end if
656 : : end if
657 : :
658 : : if (wtkflg /= 0) then
659 : :
660 : : msg = ' There is a problem with the finite difference expression of the ddk '//ch10&
661 : : //' If you are very close to a symmetric structure, you might be confusing the algorithm with'//ch10&
662 : 0 : //' sets of k-points which are not quite part of the same shell. Try rectifying angles and acell.'
663 : 0 : ABI_BUG(msg)
664 : :
665 : : else
666 : :
667 : 21 : nshell = ishell
668 : :
669 : 21 : write(msg,'(a,a,a,a,a,a,a,i3,a,a,f16.7)') ch10,&
670 : 21 : ' getshell : finite difference formula of Marzari and Vanderbilt',ch10,&
671 : 21 : ' (see Marzari and Vanderbilt, PRB 56, 12847 (1997), Appendix B)',& ! [[cite:Marzari1997]]
672 : 21 : ch10,ch10,&
673 : 21 : ' number of first neighbours : ', neigh(1,1),ch10,&
674 : 42 : ' weight : ',mvwtk(1,1)
675 : 21 : call wrtout(unts, msg)
676 : :
677 [ + + ]: 21 : if (nshell > 1) then
678 : 8 : is1 = neigh(1,1) + 1
679 : 8 : write(msg,'(a,a,i3,a,a,f16.7)')ch10,&
680 : 8 : ' number of second neighbours : ', neigh(2,1),ch10,&
681 : 16 : ' weight : ',mvwtk(is1,1)
682 : 8 : call wrtout(unts, msg)
683 : : end if
684 : :
685 [ - + ]: 8 : if (nshell > 2) then
686 [ # # ]: 0 : is1 = sum(neigh(1:2,1)) + 1
687 : 0 : write(msg,'(a,a,i3,a,a,f16.7)')ch10,&
688 : 0 : ' number of third neighbours : ', neigh(3,1),ch10,&
689 : 0 : ' weight : ',mvwtk(is1,1)
690 : 0 : call wrtout(unts, msg)
691 : : end if
692 : :
693 [ # # ]: 0 : if (nshell > 3) then
694 [ # # ]: 0 : is1 = sum(neigh(1:3,1)) + 1
695 : 0 : write(msg,'(a,a,i3,a,a,f16.7)')ch10,&
696 : 0 : ' number of fourth neighbours : ', neigh(4,1),ch10,&
697 : 0 : ' weight : ',mvwtk(is1,1)
698 : 0 : call wrtout(unts, msg)
699 : : end if
700 : :
701 [ # # ]: 0 : if (nshell > 4) then
702 [ # # ]: 0 : is1 = sum(neigh(1:4,1)) + 1
703 : 0 : write(msg,'(a,a,i3,a,a,f16.7)')ch10,&
704 : 0 : ' number of fifth neighbours : ', neigh(5,1),ch10,&
705 : 0 : ' weight : ',mvwtk(is1,1)
706 : 0 : call wrtout(unts, msg)
707 : : end if
708 : :
709 [ # # ]: 0 : if (nshell > 5) then
710 [ # # ]: 0 : is1 = sum(neigh(1:5,1)) + 1
711 : 0 : write(msg,'(a,a,i3,a,a,f16.7)')ch10,&
712 : 0 : ' number of sixth neighbours : ', neigh(6,1),ch10,&
713 : 0 : ' weight : ',mvwtk(is1,1)
714 : 0 : call wrtout(unts, msg)
715 : : end if
716 : :
717 : : end if
718 : :
719 [ + - ]: 21 : ABI_SFREE(tnons1)
720 [ + - ]: 21 : ABI_SFREE(symrel1)
721 : :
722 [ - + ]: 21 : ABI_FREE(wtk3)
723 : :
724 : 21 : end subroutine getshell
725 : : !!***
726 : :
727 : : end module m_getshell
728 : : !!***
|