Branch data Line data Source code
1 : : !!****m* ABINIT/m_double_grid
2 : : !! NAME
3 : : !! m_double_grid
4 : : !!
5 : : !! FUNCTION
6 : : !! This module defines the double grid object. This object contains the coarse mesh
7 : : !! and the dense mesh used for the interpolation of the BSE Hamiltonian,
8 : : !! and contains the mapping between the two meshes.
9 : : !!
10 : : !! COPYRIGHT
11 : : !! Copyright (C) 2008-2026 ABINIT group (YG, SP, MJV)
12 : : !! This file is distributed under the terms of the
13 : : !! GNU General Public License, see ~abinit/COPYING
14 : : !! or http://www.gnu.org/copyleft/gpl.txt .
15 : : !!
16 : : !! SOURCE
17 : :
18 : : #if defined HAVE_CONFIG_H
19 : : #include "config.h"
20 : : #endif
21 : :
22 : : #include "abi_common.h"
23 : :
24 : : MODULE m_double_grid
25 : :
26 : : use defs_basis
27 : : use m_errors
28 : : use m_abicore
29 : : use m_hide_blas
30 : : use m_bz_mesh
31 : : use m_krank
32 : :
33 : : use m_numeric_tools, only : wrap2_zero_one, interpol3d_indices
34 : : use m_matrix, only : matr3inv
35 : :
36 : : implicit none
37 : :
38 : : private
39 : : !!***
40 : :
41 : : !!****t* m_double_grid/double_grid_t
42 : : !! NAME
43 : : !! double_grid_t
44 : : !!
45 : : !! FUNCTION
46 : : !! The double grid contains a coarse mesh and a dense mesh
47 : : !! It also contains the mapping between the two meshes
48 : : !!
49 : : !! SOURCE
50 : :
51 : : type,public :: double_grid_t
52 : :
53 : : integer :: kmult(3)
54 : : ! Number of subdivisions in the coarse box in each direction
55 : :
56 : : integer :: ndiv
57 : : ! Total number of small sub-boxes in the large box associated to the coarse k-mesh.
58 : : ! i.e. product(kmult)
59 : :
60 : : integer :: maxcomp_coarse(3)
61 : : ! Dimensions of the box containing the coarse points in integer coord
62 : :
63 : : integer :: nbz_coarse
64 : : ! Number of k-points in the coarse BZ (open mesh)
65 : :
66 : : integer :: nbz_closedcoarse
67 : : ! Number of k-points inside the coarse BZ (closed mesh)
68 : : ! = PROD(maxcomp_coarse+1)
69 : :
70 : : integer :: nbz_dense
71 : : ! Number of k-point inside the dense BZ (open mesh)
72 : : ! = PROD(maxcomp_coarse.*kmult)
73 : :
74 : : integer, allocatable :: inttoik_coarse(:)
75 : : ! inttoik_coarse(nbz_closedcoarse)
76 : : ! Index of the kpoint in the coarse BZ.
77 : :
78 : : integer, allocatable :: iktoint_coarse(:)
79 : : ! iktoint_coarse(nbz_coarse)
80 : : ! Index of int by kpoint
81 : :
82 : : integer, allocatable :: inttoik_dense(:)
83 : :
84 : : integer, allocatable :: iktoint_dense(:)
85 : :
86 : : integer,allocatable :: indices_coarse(:,:)
87 : : ! indices_coarse(3,nbz_closedcoarse)
88 : : ! Indices (i1,i2,i3) for each point, ordinated by the integer coord
89 : :
90 : : integer,allocatable :: indices_dense(:,:)
91 : : ! indices_dense(6,nbz_dense)
92 : : ! Indices (i1,i2,i3);(j1,j2,j3) for each point, ordinated by integer coord
93 : :
94 : : integer :: kptrlatt_dense(3,3)
95 : : ! kptrlatt of the dense mesh
96 : :
97 : : real(dp) :: klatt_dense(3,3)
98 : :
99 : : integer :: nshiftk_dense
100 : : ! Number of shifts in the dense mesh.
101 : :
102 : : real(dp),allocatable :: shiftk_dense(:,:)
103 : : ! shift_dense(3,nshiftk_dense)
104 : : ! Shifts of the dense mesh.
105 : :
106 : : ! Dense lattice
107 : : integer :: kptrlatt_coarse(3,3)
108 : : ! kptrlatt of the coarse mesh
109 : :
110 : : real(dp) :: klatt_coarse(3,3)
111 : :
112 : : integer :: nshiftk_coarse
113 : : ! Number of shifts in the coarse mesh.
114 : :
115 : : real(dp),allocatable :: shiftk_coarse(:,:)
116 : : ! shift_coarse(3,nshiftk_coarse)
117 : : ! Shifts of the coarse mesh.
118 : :
119 : : ! Coarse lattice
120 : : integer, allocatable :: g0_coarse(:,:)
121 : : integer, allocatable :: g0_dense(:,:)
122 : : ! g0_dense/coarse(3,nkpt_closedcoarse/dense)
123 : : ! G0 vector between the kpt obtained with indices
124 : : ! and the kpt obtained insize bz
125 : :
126 : : integer, allocatable :: dense_to_coarse(:)
127 : : ! dense_to_coarse(nbz_dense)
128 : : ! Give the ibz_coarse corresponding to the dense mesh (the (0,0,0) point)
129 : :
130 : : integer, allocatable :: coarse_to_dense(:,:)
131 : : ! coarse_to_dense(nbz_coarse,ndiv)
132 : : ! Give all the ibz_dense corresponding to the (0,0,0) coarse point
133 : :
134 : : end type double_grid_t
135 : :
136 : : public :: double_grid_init ! Initializes the double grid with coarse mesh and dense mesh read from file
137 : : public :: double_grid_free ! Deallocate all memory
138 : : public :: get_kpt_from_indices_coarse ! Returns the k-point index and g0 vector associated to the set of indices
139 : : public :: compute_corresp ! Compute correspondance data between k-dense and k-coarse
140 : : !public :: get_kpt_from_indices_dense
141 : :
142 : : public :: kptfine_av ! Find the k-points of a fine grid that are around a k-point of a coarse mesh.
143 : : public :: k_neighbors ! Find 8 neighbors of given k-point on a coarse grid, and return
144 : : !!***
145 : :
146 : : !----------------------------------------------------------------------
147 : :
148 : : CONTAINS !=============================================================================
149 : : !!***
150 : :
151 : : !!****f* m_double_grid/double_grid_init
152 : : !! NAME
153 : : !! double_grid_init
154 : : !!
155 : : !! FUNCTION
156 : : !! Initialize the double_grid datatype "grid" from coarse and dense mesh
157 : : !!
158 : : !! INPUTS
159 : : !! Kmesh_coarse = descriptor of the coarse BZ sampling
160 : : !! Kmesh_dense = descriptor of the dense BZ sampling
161 : : !! kptrlatt_coarse(3,3) = vectors in R space that defines the reciprocal cell
162 : : !! kmult(3) = multiplication factors from coarse to dense
163 : : !!
164 : : !! OUTPUT
165 : : !! grid = double_grid to be created
166 : : !!
167 : : !! SOURCE
168 : :
169 [ - + - + : 4 : subroutine double_grid_init(Kmesh_coarse, Kmesh_dense, kptrlatt_coarse, kmult, grid)
- + - + -
+ - + - +
- + - + -
+ - + -
+ ]
170 : :
171 : : !Argument ------------------------------------
172 : : !scalars
173 : : type(double_grid_t),intent(out) :: grid
174 : : type(kmesh_t),intent(in) :: Kmesh_coarse,Kmesh_dense
175 : : !arrays
176 : : integer,intent(in) :: kptrlatt_coarse(3,3),kmult(3)
177 : :
178 : : !Local variables -----------------------------
179 : : !scalars
180 : : integer :: ii, info
181 : : !arrays
182 : : integer :: ipiv(3)
183 : : real(dp) :: rlatt_coarse(3,3),klatt_coarse(3,3),curmat(3,3)
184 : : !*********************************************
185 : :
186 [ - + ]: 4 : ABI_CHECK(Kmesh_coarse%nshift == 1, "Coarse mesh works only with nshiftk=1")
187 [ - + ]: 4 : ABI_CHECK(Kmesh_dense%nshift == 1, "Dense mesh : Works only with nshiftk=1")
188 : :
189 : 4 : grid%nshiftk_coarse = Kmesh_coarse%nshift
190 : 4 : grid%nshiftk_dense = Kmesh_dense%nshift
191 : :
192 : 4 : grid%nbz_coarse = Kmesh_coarse%nbz
193 : :
194 [ - + + - : 12 : ABI_MALLOC(grid%shiftk_coarse,(3,grid%nshiftk_coarse))
+ - + - -
+ - + -
+ ]
195 [ - + + - : 12 : ABI_MALLOC(grid%shiftk_dense,(3,grid%nshiftk_dense))
+ - + - -
+ - + -
+ ]
196 : :
197 [ + + + + ]: 20 : grid%shiftk_coarse(:,:) = Kmesh_coarse%shift(:,:)
198 [ + + + + ]: 20 : grid%shiftk_dense(:,:) = Kmesh_dense%shift(:,:)
199 : :
200 [ + + + + ]: 52 : grid%kptrlatt_coarse(:,:) = kptrlatt_coarse(:,:)
201 [ + + + + ]: 52 : rlatt_coarse(:,:) = kptrlatt_coarse(:,:)
202 : 4 : call matr3inv(rlatt_coarse,klatt_coarse)
203 [ + + + + ]: 52 : grid%klatt_coarse(:,:) = klatt_coarse(:,:)
204 : :
205 : 4 : grid%nbz_dense = Kmesh_dense%nbz
206 : 4 : grid%nbz_coarse = Kmesh_coarse%nbz
207 : :
208 [ + + ]: 16 : grid%kmult(:) = kmult(:)
209 : 4 : grid%ndiv = kmult(1)*kmult(2)*kmult(3)
210 : :
211 [ - + + - : 12 : ABI_MALLOC(grid%indices_dense,(6,Kmesh_dense%nbz))
+ - + - -
+ - + -
+ ]
212 [ - + + - : 12 : ABI_MALLOC(grid%g0_dense,(3,Kmesh_dense%nbz))
+ - + - -
+ - + -
+ ]
213 [ - + + - : 12 : ABI_MALLOC(grid%iktoint_dense,(Kmesh_dense%nbz))
+ - + - -
+ - + -
+ ]
214 [ - + + - : 8 : ABI_MALLOC(grid%inttoik_dense,(Kmesh_dense%nbz))
- + - + -
+ ]
215 : :
216 [ + + ]: 16 : grid%maxcomp_coarse(:) = -1
217 : :
218 [ + + + + ]: 52 : curmat(:,:) = grid%kptrlatt_coarse(:,:)
219 : :
220 : : ! Gaussian elimination
221 : 4 : call dgetrf(3,3,curmat,3,ipiv,info)
222 : :
223 : 4 : grid%nbz_closedcoarse = 1
224 : :
225 [ + + ]: 16 : do ii = 1,3
226 : 12 : grid%maxcomp_coarse(ii) = ABS(NINT(curmat(ipiv(ii),ipiv(ii))))
227 : 16 : grid%nbz_closedcoarse = grid%nbz_closedcoarse*(grid%maxcomp_coarse(ii)+1)
228 : : end do
229 : :
230 [ - + + - : 12 : ABI_MALLOC(grid%indices_coarse,(3,grid%nbz_closedcoarse))
+ - + - -
+ - + -
+ ]
231 [ - + + - : 8 : ABI_MALLOC(grid%g0_coarse,(3,grid%nbz_closedcoarse))
- + - + -
+ ]
232 [ - + + - : 12 : ABI_MALLOC(grid%iktoint_coarse,(Kmesh_coarse%nbz))
+ - + - -
+ - + -
+ ]
233 [ - + + - : 12 : ABI_MALLOC(grid%inttoik_coarse,(grid%nbz_closedcoarse))
+ - + - -
+ - + -
+ ]
234 : :
235 : : ! We should pass 'grid' at this stage !
236 : :
237 : : call create_indices_coarse(Kmesh_coarse%bz, Kmesh_coarse%nbz, grid%klatt_coarse, &
238 : : & grid%nshiftk_coarse, grid%shiftk_coarse, grid%maxcomp_coarse, grid%nbz_closedcoarse, grid%indices_coarse, &
239 : 4 : & grid%g0_coarse,grid%iktoint_coarse,grid%inttoik_coarse)
240 : :
241 : : call create_indices_dense(grid%klatt_coarse, grid%maxcomp_coarse, Kmesh_dense%bz, Kmesh_dense%nbz, &
242 : : & grid%nshiftk_dense, grid%shiftk_dense, grid%kmult, grid%indices_dense, grid%g0_dense, grid%iktoint_dense, &
243 : 4 : & grid%inttoik_dense)
244 : :
245 [ - + + - : 8 : ABI_MALLOC(grid%dense_to_coarse,(Kmesh_dense%nbz))
- + - + -
+ ]
246 [ - + + - : 16 : ABI_MALLOC(grid%coarse_to_dense,(Kmesh_coarse%nbz,grid%ndiv))
- + + - +
- + - - +
- + - + ]
247 : :
248 : : call compute_neighbours(grid%nbz_dense, grid%iktoint_dense, grid%indices_dense, &
249 : : & grid%maxcomp_coarse, grid%inttoik_coarse, grid%g0_coarse, grid%nbz_closedcoarse, grid%nbz_coarse,&
250 : 4 : & grid%ndiv, grid%dense_to_coarse, grid%coarse_to_dense)
251 : :
252 : 4 : end subroutine double_grid_init
253 : : !!***
254 : :
255 : : !----------------------------------------------------------------------------
256 : :
257 : : !!****f* m_double_grid/create_indices_coarse
258 : : !! NAME
259 : : !! create_indices_coarse
260 : : !!
261 : : !! FUNCTION
262 : : !! Create mapping between kpoints and integer indexing
263 : : !!
264 : : !! INPUTS
265 : : !! bz(3,nbz) = k-points in the Brillouin Zone
266 : : !! nbz = number of k-points
267 : : !! klatt(3,3) = reciprocal space vectors defining the reciprocal cell
268 : : !! nshiftk = Number of shifts
269 : : !! shiftk(3,nshiftk) = Shiftks of the Brillouin Zone
270 : : !! maxcomp(3) = Maximum int along each direction
271 : : !! nbz_closed = Number of k-points inside the closed Brillouin Zone (adding periodic images)
272 : : !!
273 : : !! OUTPUT
274 : : !! indices(3,nbz_closed) = indices for each k-point in the closed BZ
275 : : !! g0(3,nbz_closed) = g vectors between k-point inside bz and k-point given by indices
276 : : !! iktoint(nbz) = mapping between k-points in the bz and int indices
277 : : !! inttoik(nbz_closed) = mapping between int indices and k-points in the bz
278 : : !!
279 : : !! SOURCE
280 : :
281 : 4 : subroutine create_indices_coarse(bz, nbz, klatt, nshiftk, shiftk, maxcomp, nbz_closed, indices, g0, iktoint, inttoik)
282 : :
283 : : !Argument ------------------------------------
284 : : !scalars
285 : : integer,intent(in) :: nbz,nshiftk,nbz_closed
286 : : !arrays
287 : : integer,intent(in) :: maxcomp(3)
288 : : integer,intent(out) :: indices(3,nbz_closed)
289 : : integer,intent(out) :: g0(3,nbz_closed)
290 : : integer,intent(out) :: iktoint(nbz), inttoik(nbz_closed)
291 : : real(dp),intent(in) :: bz(3,nbz),klatt(3,3),shiftk(3,nshiftk)
292 : :
293 : : !Local variables -----------------------------
294 : : !scalars
295 : : integer :: ik,ii,i1,i2, i3
296 : : logical :: found
297 : : !arrays
298 : : integer :: curg0(3)
299 : : real(dp) :: curk1(3),ktoget(3)
300 : : !*********************************************
301 : :
302 [ - + ]: 4 : ABI_CHECK(nshiftk==1,"nshiftk != 1 not supported")
303 : :
304 [ + + ]: 16 : do i1 = 0,maxcomp(1)
305 [ + + ]: 52 : do i2 = 0,maxcomp(2)
306 [ + + ]: 156 : do i3 = 0,maxcomp(3)
307 : 108 : ii = (i1*(maxcomp(2)+1)+i2)*(maxcomp(3)+1)+i3+1
308 [ + + ]: 432 : ktoget(:) = shiftk(:,1)+(/i1,i2,i3/)
309 [ + + + + ]: 1404 : curk1(:) = MATMUL(klatt(:,:),ktoget(:))
310 : 360 : found = .FALSE.
311 [ + - ]: 360 : do ik = 1,nbz
312 [ + + ]: 360 : if(isamek(curk1(:),bz(:,ik),curg0)) then
313 [ + + ]: 432 : indices(:,ii) = (/i1,i2,i3/)
314 [ + + ]: 432 : g0(:,ii) = curg0
315 [ + + + + : 108 : if (i1 /= maxcomp(1) .and. i2 /= maxcomp(2) .and. i3 /= maxcomp(3)) then
+ + ]
316 : 32 : iktoint(ik) = ii
317 : : end if
318 : 108 : inttoik(ii) = ik
319 : 108 : found = .TRUE.
320 : : exit
321 : : end if
322 : : end do
323 : 36 : if (.not. found) then
324 : 0 : write(std_out,*) "curk1 = ",curk1
325 : 0 : write(std_out,*) bz
326 : 0 : ABI_ERROR("A k-point generated from kptrlatt cannot be found in the BZ")
327 : : end if
328 : : end do
329 : : end do
330 : : end do
331 : :
332 : 4 : end subroutine create_indices_coarse
333 : : !!***
334 : :
335 : : !----------------------------------------------------------------------
336 : :
337 : : !!****f* m_double_grid/get_kpt_from_indices_coarse
338 : : !! NAME
339 : : !! get_kpt_from_indices_coarse
340 : : !!
341 : : !! FUNCTION
342 : : !! Returns the k-point index and g0 vector associated to the set of indices
343 : : !!
344 : : !! INPUTS
345 : : !! indices(3) = index of the searched k-point
346 : : !! maxcomp(3) = Maximum int along each direction
347 : : !! inttoik(nkpt) = mapping between int indices and k-points in the bz
348 : : !! allg0(3,nkpt) = g vectors between k-point inside bz and k-point given by indices
349 : : !! nkpt = number of k-points
350 : : !!
351 : : !! OUTPUT
352 : : !! ikpt = index of k-point we search
353 : : !! g0(3) = g-vector obtained
354 : : !!
355 : : !! SOURCE
356 : :
357 : 21056 : subroutine get_kpt_from_indices_coarse(indices,maxcomp,inttoik,allg0,nkpt,ikpt,g0)
358 : :
359 : : !Argument ------------------------------------
360 : : !scalars
361 : : integer,intent(in) :: nkpt
362 : : integer,intent(out) :: ikpt
363 : : !arrays
364 : : integer,intent(in) :: indices(3),maxcomp(3)
365 : : integer,intent(in) :: inttoik(nkpt),allg0(3,nkpt)
366 : : integer,intent(out) :: g0(3)
367 : :
368 : : !Local variables -----------------------------
369 : : !scalars
370 : : integer :: curicoord
371 : : !*********************************************
372 : :
373 : 21056 : curicoord = (indices(1)*(maxcomp(2)+1)+indices(2))*(maxcomp(3)+1)+indices(3)+1
374 : 21056 : ikpt = inttoik(curicoord)
375 [ + + ]: 84224 : g0 = allg0(:,curicoord)
376 : :
377 : 21056 : end subroutine get_kpt_from_indices_coarse
378 : : !!***
379 : :
380 : : !----------------------------------------------------------------------
381 : :
382 : : !!****f* m_double_grid/create_indices_dense
383 : : !! NAME
384 : : !! create_indices_dense
385 : : !!
386 : : !! FUNCTION
387 : : !! Create mapping between kpoints and integer indexing
388 : : !!
389 : : !! INPUTS
390 : : !! klatt_coarse(3,3) = reciprocal space vectors defining the reciprocal cell of coarse BZ
391 : : !! maxcomp(3) = Maximum int along each direction
392 : : !! bz_dense(3,nbz_dense) = k-points in the dense BZ
393 : : !! nbz_dense = number of k-points in the dense BZ
394 : : !! nshiftk = Number of shifts
395 : : !! shiftk(3,nshiftk) = Shiftks of the Brillouin Zone
396 : : !! kmult(3) = multiplication factors
397 : : !! nbz_coarse = number of k-points in the coarse BZ
398 : : !! kptrlatt_coarse(3,3) = real space vectors defining the reciprocal cell of coarse BZ
399 : : !!
400 : : !! OUTPUT
401 : : !! indices(6,nbz_dense) = indices for each k-point in the closed BZ
402 : : !! g0(3,nbz_dense) = g vectors between k-point inside bz and k-point given by indices
403 : : !! iktoint(nbz_dense) = mapping between k-points in the bz and int indices
404 : : !! inttoik(nbz_dense) = mapping between int indices and k-points in the bz
405 : : !!
406 : : !! SOURCE
407 : :
408 : 4 : subroutine create_indices_dense(klatt_coarse, maxcomp, &
409 : 4 : & bz_dense, nbz_dense, nshiftk, shiftk, kmult, indices, g0, inttoik, iktoint)
410 : :
411 : : !Argument ------------------------------------
412 : : !scalars
413 : : integer,intent(in) :: nbz_dense, nshiftk
414 : : !arrays
415 : : integer,intent(in) :: kmult(3),maxcomp(3)
416 : : integer,intent(out) :: indices(6,nbz_dense),g0(3,nbz_dense)
417 : : integer,intent(out) :: inttoik(nbz_dense),iktoint(nbz_dense)
418 : : real(dp),intent(in) :: bz_dense(3,nbz_dense),klatt_coarse(3,3)
419 : : real(dp),intent(in) :: shiftk(3,nshiftk)
420 : :
421 : : !Local variables -----------------------------
422 : : integer :: ik,ii,ii_coarse
423 : : integer :: i1,i2,i3,j1,j2,j3
424 : : logical :: found
425 : : !arrays
426 : : integer :: curg0(3)
427 : : real(dp) :: curk1(3),ktoget(3)
428 : : !*********************************************
429 : :
430 : 4 : call wrtout(std_out, "Create Indices Dense", "COLL")
431 : :
432 [ - + ]: 4 : ABI_CHECK(nshiftk==1,"nshiftk != 1 not supported")
433 : :
434 [ + + ]: 12 : do i1 = 0,maxcomp(1)-1
435 [ + + ]: 28 : do i2 = 0,maxcomp(2)-1
436 [ + + ]: 56 : do i3 = 0,maxcomp(3)-1
437 : 32 : ii_coarse = (i1*(maxcomp(2)+1)+i2)*(maxcomp(3)+1)+i3+1
438 : :
439 [ + + ]: 112 : do j1 = 0,kmult(1)-1
440 [ + + ]: 224 : do j2 = 0,kmult(2)-1
441 [ + + ]: 448 : do j3 = 0,kmult(3)-1
442 : : ii = ((i1*kmult(1)+j1)*(maxcomp(2)*kmult(2)) +&
443 : : & (i2*kmult(2)+j2))*(maxcomp(3)*kmult(3))+&
444 : 256 : & (i3*kmult(3)+j3)+1
445 : :
446 : 256 : ktoget(1) = i1+((REAL(j1)+shiftk(1,1))/kmult(1))
447 : 256 : ktoget(2) = i2+((REAL(j2)+shiftk(2,1))/kmult(2))
448 : 256 : ktoget(3) = i3+((REAL(j3)+shiftk(3,1))/kmult(3))
449 : :
450 [ + + + + ]: 3328 : curk1(:) = MATMUL(klatt_coarse(:,:),ktoget(:))
451 : 8320 : found = .FALSE.
452 [ + - ]: 8320 : do ik = 1,nbz_dense
453 [ + + ]: 8320 : if(isamek(curk1(:),bz_dense(:,ik),curg0)) then
454 [ + + ]: 1792 : indices(:,ii) = (/i1,i2,i3,j1,j2,j3/)
455 [ + + ]: 1024 : g0(:,ii) = curg0
456 : 256 : inttoik(ii) = ik
457 : 256 : iktoint(ik) = ii
458 : 256 : found = .TRUE.
459 : : exit
460 : : end if
461 : : end do
462 : 128 : if(.not. found) then
463 : 0 : write(std_out,*) "curk1 = ",curk1
464 : 0 : write(std_out,*) bz_dense
465 : 0 : ABI_ERROR("Problem when creating indices")
466 : : end if
467 : : end do
468 : : end do
469 : : end do
470 : :
471 : : end do
472 : : end do
473 : : end do
474 : :
475 : 4 : end subroutine create_indices_dense
476 : : !!***
477 : :
478 : : !----------------------------------------------------------------------
479 : :
480 : : !!****f* m_double_grid/get_kpt_from_indices_dense
481 : : !! NAME
482 : : !! get_kpt_from_indices_coarse
483 : : !!
484 : : !! FUNCTION
485 : : !! Returns the k-point index and g0 vector associated to the set of indices
486 : : !!
487 : : !! INPUTS
488 : : !! indices(6) = index of the searched k-point
489 : : !! maxcomp(3) = Maximum int along each direction
490 : : !! kmult(3) = multiplication factors
491 : : !! inttoik(nkpt) = mapping between int indices and k-points in the bz
492 : : !! allg0(3,nkpt) = g vectors between k-point inside bz and k-point given by indices
493 : : !! nkpt = number of k-points
494 : : !!
495 : : !! OUTPUT
496 : : !! ikpt = index of k-point we search
497 : : !! g0(3) = g-vector obtained
498 : : !!
499 : : !! SOURCE
500 : :
501 : : subroutine get_kpt_from_indices_dense(indices,maxcomp,kmult,inttoik,allg0,nkpt,ikpt,g0)
502 : :
503 : : !Argument ------------------------------------
504 : : !scalars
505 : : integer, intent(in) :: nkpt
506 : : integer, intent(out) :: ikpt
507 : : !arrays
508 : : integer, intent(in) :: indices(6),maxcomp(3),inttoik(nkpt)
509 : : integer, intent(in) :: allg0(3,nkpt),kmult(3)
510 : : integer, intent(out) :: g0(3)
511 : :
512 : : !Local variables -----------------------------
513 : : !scalars
514 : : integer :: curicoord
515 : : !*********************************************
516 : :
517 : : curicoord = ((indices(1)*kmult(1)+indices(4))*(maxcomp(2)*kmult(2))+&
518 : : (indices(2)*kmult(2)+indices(5)))*(maxcomp(3)*kmult(3))+&
519 : : (indices(3)*kmult(3)+indices(6))+1
520 : :
521 : : ikpt = inttoik(curicoord)
522 : : g0 = allg0(:,curicoord)
523 : :
524 : : end subroutine get_kpt_from_indices_dense
525 : : !!***
526 : :
527 : : !----------------------------------------------------------------------
528 : :
529 : : !!****f* m_double_grid/compute_neighbours
530 : : !! NAME
531 : : !! compute_neighbours
532 : : !!
533 : : !! FUNCTION
534 : : !! Compute correspondance between points in the dense BZ and in the coarse BZ
535 : : !!
536 : : !! INPUTS
537 : : !! nbz_dense, nbz_closedcoarse, nbz_coarse, ndiv
538 : : !! iktoint_dense(nbz_dense)
539 : : !! indices_dense(6,nbz_dense)
540 : : !! maxcomp_coarse(3)
541 : : !! inttoik_coarse(nbz_closedcoarse)
542 : : !! g0_coarse(3,nbz_closedcoarse)
543 : : !!
544 : : !! OUTPUT
545 : : !! dense_to_coarse(nbz_dense)
546 : : !! coarse_to_dense(nbz_coarse,ndiv)
547 : : !!
548 : : !! SOURCE
549 : :
550 : 4 : subroutine compute_neighbours(nbz_dense, iktoint_dense, indices_dense, maxcomp_coarse, &
551 : 4 : & inttoik_coarse, g0_coarse, nbz_closedcoarse, nbz_coarse, ndiv, dense_to_coarse, coarse_to_dense)
552 : :
553 : : !Argument ------------------------------------
554 : : !scalars
555 : : integer,intent(in) :: nbz_dense, nbz_closedcoarse, nbz_coarse, ndiv
556 : : !arrays
557 : : integer,intent(in) :: iktoint_dense(nbz_dense)
558 : : integer,intent(in) :: indices_dense(6,nbz_dense)
559 : : integer,intent(in) :: maxcomp_coarse(3)
560 : : integer,intent(in) :: inttoik_coarse(nbz_closedcoarse)
561 : : integer,intent(in) :: g0_coarse(3,nbz_closedcoarse)
562 : : integer,intent(out) :: dense_to_coarse(nbz_dense)
563 : : integer,intent(out) :: coarse_to_dense(nbz_coarse,ndiv)
564 : :
565 : : !Local variables -----------------------------
566 : : !scalars
567 : : integer :: ik_dense, iorder, ik_coarse
568 : : !arrays
569 : 4 : integer :: curindex(nbz_coarse)
570 : : integer :: curindices_dense(6), curindices_coarse(3)
571 : : integer :: g0(3)
572 : : !*********************************************
573 : :
574 : : DBG_ENTER("COLL")
575 : :
576 [ + + + + ]: 292 : coarse_to_dense = 1
577 [ + + ]: 260 : dense_to_coarse = 1
578 : :
579 [ + + ]: 36 : curindex = 1
580 [ + + ]: 260 : do ik_dense = 1, nbz_dense
581 : : ! From ik_ibz in the dense mesh -> indices_dense
582 : 256 : iorder = iktoint_dense(ik_dense)
583 : :
584 : : ! From indices_dense -> indices_coarse
585 [ + + ]: 1792 : curindices_dense = indices_dense(:,iorder)
586 [ + + ]: 1024 : curindices_coarse = curindices_dense(1:3)
587 : : ! From indices_coarse -> ik_ibz in the coarse mesh
588 : : call get_kpt_from_indices_coarse(curindices_coarse,maxcomp_coarse,&
589 : 256 : & inttoik_coarse,g0_coarse,nbz_closedcoarse,ik_coarse,g0)
590 : :
591 : 256 : dense_to_coarse(ik_dense) = ik_coarse
592 : 256 : coarse_to_dense(ik_coarse, curindex(ik_coarse)) = ik_dense
593 : :
594 : 260 : curindex(ik_coarse) = curindex(ik_coarse) + 1
595 : : end do
596 : :
597 : : DBG_EXIT("COLL")
598 : :
599 : 4 : end subroutine compute_neighbours
600 : : !!***
601 : :
602 : : !---------------------------------------------------------------------
603 : :
604 : : !!****f* m_double_grid/compute_corresp
605 : : !! NAME
606 : : !! compute_corresp
607 : : !!
608 : : !! FUNCTION
609 : : !! Pre-process tables with mapping between divisions and coarse k-points
610 : : !!
611 : : !! INPUTS
612 : : !! double_grid
613 : : !!
614 : : !! OUTPUT
615 : : !! div2kdense(double_grid%nbz_coarse,double_grid%ndiv)
616 : : !! (k_coarse,idiv) -> k_dense
617 : : !! kdense2div(double_grid%nbz_dense)
618 : : !! k_dense -> idiv
619 : : !!
620 : : !! SOURCE
621 : :
622 : 4 : subroutine compute_corresp(double_grid, div2kdense, kdense2div)
623 : :
624 : : !Argument ------------------------------------
625 : : !scalars
626 : : class(double_grid_t),intent(in) :: double_grid
627 : : !arrays
628 : : integer,intent(out) :: div2kdense(double_grid%nbz_coarse,double_grid%ndiv)
629 : : integer,intent(out) :: kdense2div(double_grid%nbz_dense)
630 : :
631 : : !Local variables -----------------------------
632 : : !scalars
633 : : integer :: iorder,ik_dense,ik_coarse
634 : : !arrays
635 : : integer :: curindices_dense(6)
636 : 4 : integer,allocatable :: curindex(:)
637 : : !*********************************************
638 : :
639 [ - + + - : 12 : ABI_MALLOC(curindex,(double_grid%nbz_coarse))
+ - + - -
+ + - ]
640 [ + + ]: 36 : curindex = 1
641 : :
642 [ + + ]: 260 : do ik_dense = 1,double_grid%nbz_dense
643 : : ! From ik_ibz in the dense mesh -> indices_dense
644 : 256 : iorder = double_grid%iktoint_dense(ik_dense)
645 : : !g01 = double_grid%g0_dense(:,iorder)
646 : :
647 : : ! From indices_dense -> indices_coarse
648 : : curindices_dense = double_grid%indices_dense(:,iorder)
649 : :
650 : 256 : ik_coarse = double_grid%dense_to_coarse(ik_dense)
651 : 256 : div2kdense(ik_coarse,curindex(ik_coarse)) = ik_dense
652 : 256 : kdense2div(ik_dense) = curindex(ik_coarse)
653 : :
654 : 260 : curindex(ik_coarse) = curindex(ik_coarse) + 1
655 : : end do
656 : :
657 [ - + ]: 4 : ABI_FREE(curindex)
658 : :
659 : 4 : end subroutine compute_corresp
660 : : !!***
661 : :
662 : : !----------------------------------------------------------------------
663 : :
664 : : !!****f* m_double_grid/double_grid_free
665 : : !! NAME
666 : : !! double_grid_free
667 : : !!
668 : : !! FUNCTION
669 : : !! Deallocate all dynamics entities present in a double_grid structure.
670 : : !!
671 : : !! SOURCE
672 : :
673 : 4 : subroutine double_grid_free(grid)
674 : :
675 : : !Arguments ------------------------------------
676 : : class(double_grid_t),intent(inout) :: grid
677 : : ! *********************************************************************
678 : :
679 : : !integer
680 [ + - ]: 4 : ABI_SFREE(grid%inttoik_coarse)
681 [ + - ]: 4 : ABI_SFREE(grid%inttoik_dense)
682 [ + - ]: 4 : ABI_SFREE(grid%iktoint_coarse)
683 [ + - ]: 4 : ABI_SFREE(grid%iktoint_dense)
684 [ + - ]: 4 : ABI_SFREE(grid%indices_coarse)
685 [ + - ]: 4 : ABI_SFREE(grid%indices_dense)
686 [ + - ]: 4 : ABI_SFREE(grid%g0_coarse)
687 [ + - ]: 4 : ABI_SFREE(grid%g0_dense)
688 [ + - ]: 4 : ABI_SFREE(grid%dense_to_coarse)
689 [ + - ]: 4 : ABI_SFREE(grid%coarse_to_dense)
690 : :
691 : : !real
692 [ + - ]: 4 : ABI_SFREE(grid%shiftk_dense)
693 [ + - ]: 4 : ABI_SFREE(grid%shiftk_coarse)
694 : :
695 : 4 : end subroutine double_grid_free
696 : : !!***
697 : :
698 : : !----------------------------------------------------------------------
699 : :
700 : : !!****f* m_double_grid/kptfine_av
701 : : !! NAME
702 : : !! kptfine_av
703 : : !!
704 : : !! FUNCTION
705 : : !! Find the k-points of a fine grid that are around a k-point of a coarse mesh.
706 : : !!
707 : : !! INPUTS
708 : : !! center(3) = the point of the coarse mesh around which you want know which
709 : : !! k-points of the fine mesh belong to.
710 : : !! qptrlatt(3,3) = qptrlatt of the considered calculation (this is obtained
711 : : !! from the input variable ngqpt and shiftq.
712 : : !! kpt_fine(3,nkpt_fine) = this table contain all the k-points of the fine grid
713 : : !! in the full BZ (no sym op. allowed) and is read from the header
714 : : !! of the dense WF file.
715 : : !! nkpt_fine = number of k-points of the fine grid read from the header of the
716 : : !! dense WF file.
717 : : !!
718 : : !! OUTPUT
719 : : !! kpt_fine_sub(nkpt_sub) = k-points of the fine grid that are around center(3)
720 : : !! nkpt_sub = number of k-points of the fine grid that are around center(3)
721 : : !! wgt_sub(nkpt_sub) = weight of the k-points of the fine grid that are around center(3).
722 : : !!
723 : : !! SOURCE
724 : :
725 : 24 : subroutine kptfine_av(center,qptrlatt,kpt_fine,nkpt_fine,kpt_fine_sub,nkpt_sub,wgt_sub)
726 : :
727 : : !Arguments ------------------------------------
728 : : !scalars
729 : : integer,intent(in) :: nkpt_fine
730 : : integer,intent(out) :: nkpt_sub
731 : : !arrays
732 : : integer,intent(in) :: qptrlatt(3,3)
733 : : real(dp),intent(in) :: kpt_fine(3,nkpt_fine)
734 : : real(dp),intent(in) :: center(3)
735 : : integer,pointer :: kpt_fine_sub(:)
736 : : real(dp),pointer :: wgt_sub(:)
737 : :
738 : : !Local variables-------------------------------
739 : : !scalars
740 : : integer :: ikpt,aa,bb,cc
741 : : integer :: ii,jj
742 : : !arrays
743 : : real(dp) :: center_ref(3)
744 : : real(dp) :: kpt_fine_ref(3)
745 : : real(dp) :: kpt_tmp(3),kpt_tmp2(3)
746 : 24 : integer,allocatable :: kpt_fine_sub_tmp(:)
747 : 24 : real(dp),allocatable :: wgt_sub_tmp(:)
748 : : logical :: found(3)
749 : : ! *************************************************************************
750 : :
751 [ - + + - : 72 : ABI_MALLOC(kpt_fine_sub_tmp,(nkpt_fine))
+ - + - -
+ - + ]
752 [ - + + - : 72 : ABI_MALLOC(wgt_sub_tmp,(nkpt_fine))
+ - + - -
+ + - ]
753 : :
754 : : !It is easier to work in real space using the qptrlatt matrices because in this
755 : : !referential any k-points sampling will be cast into an orthorhombic shape.
756 : : !In that space we can simply take all k-points of the fine grid that between
757 : : !center_ref-0.5 and center_ref+0.5
758 : :
759 [ + + + + : 600 : center_ref = MATMUL(qptrlatt,center)
+ + + + ]
760 : :
761 : : !When considering points center(3) that lying close or on a BZ edge we need to
762 : : !take the k-points of the fine grid taking into account unklamp vectors. This
763 : : !is done with the aa, bb and cc loops.
764 : :
765 : : ii = 1
766 [ + + ]: 1560 : do ikpt=1,nkpt_fine
767 [ + + ]: 6144 : kpt_tmp = kpt_fine(:,ikpt)
768 [ + + ]: 6168 : do aa=-1,1
769 : 4608 : kpt_tmp2(1) = kpt_tmp(1)+aa
770 [ + + ]: 19968 : do bb=-1,1
771 : 13824 : kpt_tmp2(2) = kpt_tmp(2)+bb
772 [ + + ]: 59904 : do cc=-1,1
773 : 41472 : kpt_tmp2(3) = kpt_tmp(3)+cc
774 [ + + + + : 1036800 : kpt_fine_ref = MATMUL(qptrlatt,kpt_tmp2)
+ + + + ]
775 [ + + + + ]: 41472 : if((kpt_fine_ref(1)>=center_ref(1)-0.5-tol8).and.&
776 : 13824 : & (kpt_fine_ref(1)<=center_ref(1)+0.5+tol8)) then
777 [ + + + + ]: 10368 : if((kpt_fine_ref(2)>=center_ref(2)-0.5-tol8).and.&
778 : : & (kpt_fine_ref(2)<=center_ref(2)+0.5+tol8)) then
779 [ + + + + ]: 2592 : if((kpt_fine_ref(3)>=center_ref(3)-0.5-tol8).and.&
780 : : & (kpt_fine_ref(3)<=center_ref(3)+0.5+tol8)) then
781 : 648 : kpt_fine_sub_tmp(ii) = ikpt
782 : 648 : ii = ii +1
783 : : end if
784 : : end if
785 : : end if
786 : : end do
787 : : end do
788 : : end do
789 : : end do
790 : :
791 : 24 : nkpt_sub = ii-1
792 [ - + + - : 72 : ABI_MALLOC(kpt_fine_sub,(nkpt_sub))
+ - + - -
+ - + ]
793 [ - + + - : 72 : ABI_MALLOC(wgt_sub,(nkpt_sub))
+ - + - -
+ - + ]
794 : :
795 [ + + ]: 672 : do jj=1,nkpt_sub
796 : 672 : kpt_fine_sub(jj) = kpt_fine_sub_tmp(jj)
797 : : end do
798 : :
799 : : !We then compute a weight function. This weight function is simply a
800 : : !rectangular weight function that take the value 1 for k-points of the fine
801 : : !grid inside the cube, 0.5 for k-points that are lying on one face of the cube,
802 : : !0.25 for k-points that are lying on an edge of the cube and 0.125 for k-points
803 : : !that are lying on a peak of the cube.
804 : :
805 [ + + ]: 672 : wgt_sub(:) = 1.0
806 : :
807 [ + + ]: 672 : do ikpt=1,nkpt_sub
808 [ + + ]: 2592 : found(:) = .True.
809 [ + + ]: 2592 : kpt_tmp = kpt_fine(:,kpt_fine_sub(ikpt))
810 [ + + ]: 2616 : do aa=-1,1
811 : 1944 : kpt_tmp2(1) = kpt_tmp(1)+aa
812 [ + + ]: 8424 : do bb=-1,1
813 : 5832 : kpt_tmp2(2) = kpt_tmp(2)+bb
814 [ + + ]: 25272 : do cc=-1,1
815 : 17496 : kpt_tmp2(3) = kpt_tmp(3)+cc
816 [ + + + + : 437400 : kpt_fine_ref = MATMUL(qptrlatt,kpt_tmp2)
+ + + + ]
817 [ + + + + ]: 17496 : if((ABS(kpt_fine_ref(1)-center_ref(1)-0.5)< tol8) .or.&
818 : : (ABS(kpt_fine_ref(1)-center_ref(1)+0.5) < tol8)) then
819 [ + + ]: 3888 : if(found(1)) then
820 : 432 : wgt_sub(ikpt) = wgt_sub(ikpt)*0.5; found(1) = .False.
821 : : end if
822 : : end if
823 [ + + + + ]: 17496 : if((ABS(kpt_fine_ref(2)-center_ref(2)-0.5) < tol8) .or.&
824 : : (ABS(kpt_fine_ref(2)-center_ref(2)+0.5) < tol8)) then
825 [ + + ]: 3888 : if(found(2)) then
826 : 432 : wgt_sub(ikpt) = wgt_sub(ikpt)*0.5; found(2) = .False.
827 : : end if
828 : : end if
829 [ + + + + ]: 17496 : if((ABS(kpt_fine_ref(3)-center_ref(3)-0.5)< tol8) .or.&
830 : 5832 : (ABS(kpt_fine_ref(3)-center_ref(3)+0.5) < tol8)) then
831 [ + + ]: 3888 : if(found(3)) then
832 : 432 : wgt_sub(ikpt) = wgt_sub(ikpt)*0.5; found(3) = .False.
833 : : end if
834 : : end if
835 : : end do
836 : : end do
837 : : end do
838 : : end do
839 : :
840 [ - + ]: 24 : ABI_FREE(kpt_fine_sub_tmp)
841 [ - + ]: 24 : ABI_FREE(wgt_sub_tmp)
842 : :
843 : 24 : end subroutine kptfine_av
844 : : !!***
845 : :
846 : : !!****f* m_double_grid/k_neighbors
847 : : !!
848 : : !! NAME
849 : : !! k_neighbors
850 : : !!
851 : : !! FUNCTION
852 : : !! find 8 neighbors of given k-point on a coarse grid, and return
853 : : !! them along with relative k-shift within coarse grid cell
854 : : !!
855 : : !! INPUTS
856 : : !! kpt = k-point to be interpolated to, in full BZ
857 : : !! kptrlatt = lattice vectors for coarse k-grid
858 : : !! invrankkpt = rank list to find k-points
859 : : !!
860 : : !! OUTPUT
861 : : !! rel_kpt = k-point coordinates renormalized to coarse grid cell
862 : : !! kpt_phon_indices = indices of k-points on corners of cell
863 : : !!
864 : : !! TODO
865 : : !! This routine is not used anymore. Deprecate or Remove?
866 : : !!
867 : : !! SOURCE
868 : :
869 : 0 : subroutine k_neighbors(kpt, kptrlatt,krank, rel_kpt, kpt_phon_indices)
870 : :
871 : : ! inputs
872 : : real(dp), intent(in) :: kpt(3)
873 : : integer, intent(in) :: kptrlatt(3,3)
874 : : type(krank_t), intent(in) :: krank
875 : :
876 : : ! outputs
877 : : real(dp), intent(out) :: rel_kpt(3)
878 : : integer, intent(out) :: kpt_phon_indices(8)
879 : : ! local vars
880 : : integer :: symrankkpt
881 : : integer :: ir1,ir2,ir3, pr1,pr2,pr3
882 : : real(dp) :: redkpt(3), cornerkpt(3), res
883 : : ! *************************************************************************
884 : :
885 : : !wrap fine kpt to [0,1]
886 : 0 : call wrap2_zero_one(kpt(1),redkpt(1),res)
887 : 0 : call wrap2_zero_one(kpt(2),redkpt(2),res)
888 : 0 : call wrap2_zero_one(kpt(3),redkpt(3),res)
889 : : !find 8 indices of points neighboring ikpt_phon, for interpolation
890 : : call interpol3d_indices (redkpt,kptrlatt(1,1),kptrlatt(2,2),kptrlatt(3,3), &
891 : 0 : ir1,ir2,ir3, pr1,pr2,pr3)
892 : :
893 : : !transpose ir pr to ikpt_phon indices
894 : : !order of kpt_phons:
895 : : !ir1 ir2 ir3
896 [ # # ]: 0 : cornerkpt = (/real(ir1-1)/kptrlatt(1,1),real(ir2-1)/kptrlatt(2,2), real(ir3-1)/kptrlatt(3,3)/)
897 : 0 : symrankkpt = krank%get_rank(cornerkpt)
898 : 0 : kpt_phon_indices(1) = krank%invrank(symrankkpt)
899 : : !pr1 ir2 ir3
900 [ # # ]: 0 : cornerkpt = (/real(pr1-1)/kptrlatt(1,1),real(ir2-1)/kptrlatt(2,2), real(ir3-1)/kptrlatt(3,3)/)
901 : 0 : symrankkpt = krank%get_rank (cornerkpt)
902 : 0 : kpt_phon_indices(2) = krank%invrank(symrankkpt)
903 : : !ir1 pr2 ir3
904 [ # # ]: 0 : cornerkpt = (/real(ir1-1)/kptrlatt(1,1),real(pr2-1)/kptrlatt(2,2), real(ir3-1)/kptrlatt(3,3)/)
905 : 0 : symrankkpt = krank%get_rank (cornerkpt)
906 : 0 : kpt_phon_indices(3) = krank%invrank(symrankkpt)
907 : : !pr1 pr2 ir3
908 [ # # ]: 0 : cornerkpt = (/real(pr1-1)/kptrlatt(1,1),real(pr2-1)/kptrlatt(2,2), real(ir3-1)/kptrlatt(3,3)/)
909 : 0 : symrankkpt = krank%get_rank (cornerkpt)
910 : 0 : kpt_phon_indices(4) = krank%invrank(symrankkpt)
911 : : !ir1 ir2 pr3
912 [ # # ]: 0 : cornerkpt = (/real(ir1-1)/kptrlatt(1,1),real(ir2-1)/kptrlatt(2,2), real(pr3-1)/kptrlatt(3,3)/)
913 : 0 : symrankkpt = krank%get_rank (cornerkpt)
914 : 0 : kpt_phon_indices(5) = krank%invrank(symrankkpt)
915 : : !pr1 ir2 pr3
916 [ # # ]: 0 : cornerkpt = (/real(pr1-1)/kptrlatt(1,1),real(ir2-1)/kptrlatt(2,2), real(pr3-1)/kptrlatt(3,3)/)
917 : 0 : symrankkpt = krank%get_rank (cornerkpt)
918 : 0 : kpt_phon_indices(6) = krank%invrank(symrankkpt)
919 : : !ir1 pr2 pr3
920 [ # # ]: 0 : cornerkpt = (/real(ir1-1)/kptrlatt(1,1),real(pr2-1)/kptrlatt(2,2), real(pr3-1)/kptrlatt(3,3)/)
921 : 0 : symrankkpt = krank%get_rank (cornerkpt)
922 : 0 : kpt_phon_indices(7) = krank%invrank(symrankkpt)
923 : : !pr1 pr2 pr3
924 [ # # ]: 0 : cornerkpt = (/real(pr1-1)/kptrlatt(1,1),real(pr2-1)/kptrlatt(2,2), real(pr3-1)/kptrlatt(3,3)/)
925 : 0 : symrankkpt = krank%get_rank (cornerkpt)
926 : 0 : kpt_phon_indices(8) = krank%invrank(symrankkpt)
927 : :
928 : : !retrieve the gkq matrix for all q, at the neighbor k vectors
929 : 0 : rel_kpt(1) = redkpt(1)*kptrlatt(1,1)-real(ir1-1)
930 : 0 : rel_kpt(2) = redkpt(2)*kptrlatt(2,2)-real(ir2-1)
931 : 0 : rel_kpt(3) = redkpt(3)*kptrlatt(3,3)-real(ir3-1)
932 : :
933 : 0 : end subroutine k_neighbors
934 : : !!***
935 : :
936 [ # # # # : 0 : END MODULE m_double_grid
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
937 : : !!***
|