Branch data Line data Source code
1 : : !!****m* ABINIT/m_iterators
2 : : !! NAME
3 : : !! m_iterators
4 : : !!
5 : : !! FUNCTION
6 : : !! This module defines objects (iterators) that are used to facilitate the
7 : : !! iteration over the elements of an ensemble e.g. set of transitions.
8 : : !!
9 : : !! COPYRIGHT
10 : : !! Copyright (C) 2009-2026 ABINIT group (MG)
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 : : !! NOTES
16 : : !! Iterators are used to obtain an indirect indexing that can be used to access array elements
17 : : !! or array sections. An iterator is an object that contains the list of indices that should
18 : : !! be treated. Each processor has its own local version initialized according the the distribution
19 : : !! of the data across the nodes.
20 : : !! Using iterators for looping facilitates the implementation of MPI algorithms since all the
21 : : !! information on the distribution of the tasks is stored in the iterator itself
22 : : !! For example an MPI loop over spins, k-points and bands can be written in terms of iterators using:
23 : : !!
24 : : !! do isp=1,iter_len(Iter_bks)
25 : : !! spin = iter_yield(Iter_bks,idx3=isp)
26 : : !!
27 : : !! do ikp=1,iter_len(Iter_bks,idx3=isp)
28 : : !! ik_ibz = iter_yield(Iter_bks,idx2=ikp,idx3=isp)
29 : : !!
30 : : !! do ibn=1,iter_len(Iter_bks,idx2=ikp,idx3=isp)
31 : : !! band = iter_yield(Iter_bks,entry1=ibn,idx2=ikp,idx3=isp)
32 : : !!
33 : : !! iter_len gives the number of non-zero entries
34 : : !! iter_yield returns the global indices used to access the data.
35 : : !!
36 : : !! The main advantage is seen in sections of code that are MPI parallelized because each node
37 : : !! will have its own iterator (to be initialized by the programmer).
38 : : !! Therefore it is very easy to distribute the workload among the nodes without having to
39 : : !! to use "cycle" of "if then" instruction in the inners loops.
40 : : !! Another important advantage is that the MPI implementation will continue to work even
41 : : !! if the data distribution is changed, only the iterator has to be modified.
42 : : !!
43 : : !! SOURCE
44 : :
45 : : #if defined HAVE_CONFIG_H
46 : : #include "config.h"
47 : : #endif
48 : :
49 : : #include "abi_common.h"
50 : :
51 : : MODULE m_iterators
52 : :
53 : : use defs_basis
54 : : use m_abicore
55 : : use m_errors
56 : :
57 : : implicit none
58 : :
59 : : private
60 : : !!***
61 : :
62 : : !----------------------------------------------------------------------
63 : :
64 : : !!****t* m_iterators/indices_t
65 : : !! NAME
66 : : !! indices_t
67 : : !!
68 : : !! FUNCTION
69 : : !! A base datatype for constructing ragged arrays.
70 : : !!
71 : : !! SOURCE
72 : :
73 : : type,private :: indices_t
74 : : integer :: leng
75 : : integer, allocatable :: indx(:)
76 : : ! indx(leng) The set of indices.
77 : : end type indices_t
78 : : !!***
79 : :
80 : : !----------------------------------------------------------------------
81 : :
82 : : !!****t* m_iterators/iter2_t
83 : : !! NAME
84 : : !! iter2_t
85 : : !!
86 : : !! FUNCTION
87 : : !!
88 : : !! SOURCE
89 : :
90 : : type,public :: iter2_t
91 : : private
92 : : integer :: sizes(2)
93 : : integer :: starts(2)
94 : : type(indices_t),allocatable :: slice(:,:)
95 : : ! Temporary structure to store the indices in full storage mode.
96 : :
97 : : #if 0
98 : : integer :: len3
99 : : ! The number of non-zero entries in the last dimension.
100 : :
101 : : integer,allocatable :: map3(:)
102 : : ! map3(len3)
103 : : ! Indirect indexing packed --> full for the last dimension.
104 : :
105 : : integer,allocatable :: len2(:)
106 : : ! len2(len3)
107 : : ! Gives the number of non-zero entries along the second dimension for each non-null index along the 3-dimension.
108 : :
109 : : type(indices_t),allocatable :: map2(:)
110 : : ! map2(len3)%indices
111 : : ! Indirect indexing packed --> full for the second dimension.
112 : :
113 : : type(indices_t),allocatable :: len1(:,:)
114 : : ! len1(MAX(len2),len3)
115 : : ! Gives the number of non-zero entries along the first dimension.
116 : :
117 : : type(indices_t),allocatable :: map1(:)
118 : : ! map1(MAX(len2),len3)%indices
119 : : ! Indirect indexing packed --> full for the first dimension.
120 : : #endif
121 : :
122 : : end type iter2_t
123 : :
124 : : public :: iter_alloc ! Allocate the iterator.
125 : : public :: iter_push ! Copy a set of indices in the iterator
126 : : public :: iter_free ! Deallocate the iterator.
127 : : public :: OPERATOR(.LBOUND.) !
128 : : public :: OPERATOR(.UBOUND.) !
129 : : public :: OPERATOR(.SIZE.) !
130 : : public :: iter_len ! The number of indices in a slice of the iterator
131 : : public :: iter_yield ! Return the indices in of the slice of the iterator.
132 : : public :: iter_print ! Printout of the iterator, just for debugging purposes.
133 : : !!***
134 : :
135 : : interface iter_alloc
136 : : module procedure iter2_alloc
137 : : !module procedure iter3_alloc
138 : : end interface iter_alloc
139 : :
140 : : interface iter_push
141 : : module procedure iter2_push
142 : : !module procedure iter3_push
143 : : end interface iter_push
144 : :
145 : : interface iter_free
146 : : module procedure iter2_free
147 : : !module procedure iter3_free
148 : : end interface iter_free
149 : :
150 : : interface operator(.lbound.)
151 : : module procedure iter2_lbound
152 : : !module procedure iter3_lbound
153 : : end interface
154 : :
155 : : interface operator(.ubound.)
156 : : module procedure iter2_ubound
157 : : !module procedure iter3_ubound
158 : : end interface
159 : :
160 : : interface operator(.size.)
161 : : module procedure iter2_size
162 : : !module procedure iter3_size
163 : : end interface
164 : :
165 : : interface iter_len
166 : : module procedure iter2_len
167 : : !module procedure iter3_len
168 : : end interface iter_len
169 : :
170 : : interface iter_yield
171 : : module procedure iter2_yield
172 : : !module procedure iter3_yield
173 : : end interface iter_yield
174 : :
175 : : interface iter_print
176 : : module procedure iter2_print
177 : : !module procedure iter3_print
178 : : end interface iter_print
179 : :
180 : : CONTAINS !===========================================================
181 : : !!***
182 : :
183 : : !----------------------------------------------------------------------
184 : :
185 : : !!****f* m_iterators/indices_free
186 : : !! NAME
187 : : !! indices_free
188 : : !!
189 : : !! FUNCTION
190 : : !!
191 : : !! INPUTS
192 : : !!
193 : : !! OUTPUT
194 : : !!
195 : : !! SOURCE
196 : :
197 : 3495 : subroutine indices_free(Ids)
198 : :
199 : : !Arguments ------------------------------------
200 : : type(indices_t),intent(inout) :: Ids
201 : :
202 : : ! *************************************************************************
203 : :
204 : 3495 : Ids%leng=0
205 [ + - ]: 3495 : ABI_SFREE(Ids%indx)
206 : :
207 : 3495 : end subroutine indices_free
208 : : !!***
209 : :
210 : : !----------------------------------------------------------------------
211 : :
212 : : !!****f* m_iterators/iter2_alloc
213 : : !! NAME
214 : : !! iter2_alloc
215 : : !!
216 : : !! FUNCTION
217 : : !!
218 : : !! INPUTS
219 : : !!
220 : : !! OUTPUT
221 : : !!
222 : : !! SOURCE
223 : :
224 : 466 : subroutine iter2_alloc(Iter2,sizes,starts)
225 : :
226 : :
227 : : !Arguments ------------------------------------
228 : : !scalars
229 : : type(iter2_t),intent(inout) :: Iter2
230 : : !arrays
231 : : integer,intent(in) :: sizes(2)
232 : : integer,optional,intent(in) :: starts(2)
233 : :
234 : : !Local variables ------------------------------
235 : : !scalars
236 : : integer :: s1,s2,i1,i2
237 : :
238 : : !************************************************************************
239 : 466 : s1=1; s2=1
240 [ - + ]: 466 : if (PRESENT(starts)) then
241 : 0 : s1=starts(1)
242 : 0 : s2=starts(2)
243 : : end if
244 : :
245 [ + + ]: 1398 : Iter2%starts=(/s1,s2/)
246 [ + + ]: 1398 : Iter2%sizes =sizes
247 : :
248 [ - + + - : 5834 : ABI_MALLOC( Iter2%slice,(s1:s1+sizes(1)-1, s2:s2+sizes(2)-1))
- + + - +
- + - - +
- + - + +
+ + + +
- ]
249 : :
250 [ + - + - : 1873 : do i2=LBOUND(Iter2%slice,DIM=2),UBOUND(Iter2%slice,DIM=2)
+ + ]
251 [ + - + - : 5386 : do i1=LBOUND(Iter2%slice,DIM=1),UBOUND(Iter2%slice,DIM=1)
+ + ]
252 : 3970 : Iter2%slice(i1,i2)%leng=0
253 : : end do
254 : : end do
255 : :
256 : 466 : end subroutine iter2_alloc
257 : : !!***
258 : :
259 : : !----------------------------------------------------------------------
260 : :
261 : : !!****f* m_iterators/iter2_push
262 : : !! NAME
263 : : !! iter2_push
264 : : !!
265 : : !! FUNCTION
266 : : !!
267 : : !! INPUTS
268 : : !!
269 : : !! OUTPUT
270 : : !!
271 : : !! SOURCE
272 : :
273 [ - + ]: 3495 : subroutine iter2_push(Iter2,i1,i2,list)
274 : :
275 : : !Arguments ------------------------------------
276 : : !scalars
277 : : integer,intent(in) :: i1,i2
278 : : type(iter2_t),intent(inout) :: Iter2
279 : : !arrays
280 : : integer,intent(in) :: list(:)
281 : :
282 : : !Local variables ------------------------------
283 : : !scalars
284 : : integer :: leng
285 : :
286 : : !************************************************************************
287 : :
288 : 3495 : leng = SIZE(list)
289 : :
290 [ - + ]: 3495 : if (allocated( Iter2%slice(i1,i2)%indx) ) then
291 : 0 : ABI_ERROR("Iter2%slice already allocated")
292 : : end if
293 : :
294 : 3495 : Iter2%slice(i1,i2)%leng = leng
295 [ + + + - : 10485 : ABI_MALLOC(Iter2%slice(i1,i2)%indx,(leng))
+ - + + -
+ - + -
+ ]
296 [ + + ]: 16057 : Iter2%slice(i1,i2)%indx(:) = list
297 : :
298 : 3495 : end subroutine iter2_push
299 : : !!***
300 : :
301 : : !----------------------------------------------------------------------
302 : :
303 : : !!****f* m_iterators/iter2_free
304 : : !! NAME
305 : : !! iter2_free
306 : : !!
307 : : !! FUNCTION
308 : : !!
309 : : !! INPUTS
310 : : !!
311 : : !! OUTPUT
312 : : !!
313 : : !! SOURCE
314 : :
315 : 466 : subroutine iter2_free(Iter2)
316 : :
317 : : !Arguments ------------------------------------
318 : : !scalars
319 : : type(iter2_t),intent(inout) :: Iter2
320 : :
321 : : !Local variables ------------------------------
322 : : !scalars
323 : : integer :: i1,i2
324 : :
325 : : !************************************************************************
326 : :
327 [ + - + - : 1873 : do i2=LBOUND(Iter2%slice,DIM=2),UBOUND(Iter2%slice,DIM=2)
+ + ]
328 [ + - + - : 5386 : do i1=LBOUND(Iter2%slice,DIM=1),UBOUND(Iter2%slice,DIM=1)
+ + ]
329 : 3970 : call indices_free(Iter2%slice(i1,i2))
330 : : end do
331 : : end do
332 : :
333 [ + - + + : 3961 : ABI_SFREE(Iter2%slice)
- + - + ]
334 : :
335 : 466 : end subroutine iter2_free
336 : : !!***
337 : :
338 : : !----------------------------------------------------------------------
339 : :
340 : : !!****f* m_iterators/iter2_len
341 : : !! NAME
342 : : !! iter2_len
343 : : !!
344 : : !! FUNCTION
345 : : !!
346 : : !! INPUTS
347 : : !!
348 : : !! OUTPUT
349 : : !!
350 : : !! SOURCE
351 : :
352 : 3495 : function iter2_len(Iter2,i1,i2)
353 : :
354 : : !Arguments ------------------------------------
355 : : integer,intent(in) :: i1,i2
356 : : integer :: iter2_len
357 : : type(iter2_t),intent(in) :: Iter2
358 : :
359 : : ! *************************************************************************
360 : :
361 : 3495 : iter2_len = Iter2%slice(i1,i2)%leng
362 : :
363 : 3495 : end function iter2_len
364 : : !!***
365 : :
366 : : !----------------------------------------------------------------------
367 : :
368 : : !!****f* m_iterators/iter2_lbound
369 : : !! NAME
370 : : !! iter2_lbound
371 : : !!
372 : : !! FUNCTION
373 : : !!
374 : : !! INPUTS
375 : : !!
376 : : !! OUTPUT
377 : : !!
378 : : !! SOURCE
379 : :
380 : 0 : function iter2_lbound(Iter2,dim)
381 : :
382 : : !Arguments ------------------------------------
383 : : !scalars
384 : : integer,intent(in) :: dim
385 : : integer :: iter2_lbound
386 : : type(iter2_t),intent(in) :: Iter2
387 : :
388 : : !************************************************************************
389 : :
390 : 0 : iter2_lbound = Iter2%starts(dim)
391 : :
392 : 0 : end function iter2_lbound
393 : : !!***
394 : :
395 : : !----------------------------------------------------------------------
396 : :
397 : : !!****f* m_iterators/iter2_ubound
398 : : !! NAME
399 : : !! iter2_ubound
400 : : !!
401 : : !! FUNCTION
402 : : !!
403 : : !! INPUTS
404 : : !!
405 : : !! OUTPUT
406 : : !!
407 : : !! SOURCE
408 : :
409 : 0 : function iter2_ubound(Iter2,dim)
410 : :
411 : : !Arguments ------------------------------------
412 : : !scalars
413 : : integer,intent(in) :: dim
414 : : integer :: iter2_ubound
415 : : type(iter2_t),intent(in) :: Iter2
416 : :
417 : : !************************************************************************
418 : :
419 : 0 : iter2_ubound = Iter2%starts(dim) + Iter2%sizes(dim) -1
420 : :
421 : 0 : end function iter2_ubound
422 : : !!***
423 : :
424 : : !----------------------------------------------------------------------
425 : :
426 : : !!****f* m_iterators/iter2_size
427 : : !! NAME
428 : : !! iter2_size
429 : : !!
430 : : !! FUNCTION
431 : : !!
432 : : !! INPUTS
433 : : !!
434 : : !! OUTPUT
435 : : !!
436 : : !! SOURCE
437 : :
438 : 0 : function iter2_size(Iter2,dim)
439 : :
440 : : !Arguments ------------------------------------
441 : : !scalars
442 : : integer,intent(in) :: dim
443 : : integer :: iter2_size
444 : : type(iter2_t),intent(in) :: Iter2
445 : :
446 : : !************************************************************************
447 : :
448 : 0 : iter2_size = iter2_ubound(Iter2,dim) - iter2_lbound(Iter2,dim) + 1
449 : :
450 : 0 : end function iter2_size
451 : : !!***
452 : :
453 : : !----------------------------------------------------------------------
454 : :
455 : : !!****f* m_iterators/iter2_yield
456 : : !! NAME
457 : : !! iter2_yield
458 : : !!
459 : : !! FUNCTION
460 : : !!
461 : : !! INPUTS
462 : : !!
463 : : !! OUTPUT
464 : : !!
465 : : !! SOURCE
466 : :
467 : 12562 : function iter2_yield(Iter2,idx,i1,i2)
468 : :
469 : : !Arguments ------------------------------------
470 : : integer,intent(in) :: idx,i1,i2
471 : : integer :: iter2_yield
472 : : type(iter2_t),intent(in) :: Iter2
473 : :
474 : : ! *************************************************************************
475 : :
476 : 12562 : iter2_yield = Iter2%slice(i1,i2)%indx(idx)
477 : :
478 : 12562 : end function iter2_yield
479 : : !!***
480 : :
481 : : !----------------------------------------------------------------------
482 : :
483 : : !!****f* m_iterators/iter2_print
484 : : !! NAME
485 : : !! iter2_print
486 : : !!
487 : : !! FUNCTION
488 : : !!
489 : : !! INPUTS
490 : : !!
491 : : !! OUTPUT
492 : : !!
493 : : !! SOURCE
494 : :
495 : 0 : subroutine iter2_print(Iter2,header,unit,mode_paral,prtvol)
496 : :
497 : : !Arguments ------------------------------------
498 : : !scalars
499 : : integer,optional,intent(in) :: unit,prtvol
500 : : character(len=4),optional,intent(in) :: mode_paral
501 : : character(len=*),optional,intent(in) :: header
502 : : type(iter2_t),intent(in) :: Iter2
503 : :
504 : : !Local variables-------------------------------
505 : : integer :: my_unt,my_prtvol,ntot,i1,i2,idx
506 : : character(len=4) :: my_mode
507 : : character(len=500) :: msg
508 : : ! *********************************************************************
509 : :
510 : 0 : my_unt =std_out; if (PRESENT(unit )) my_unt =unit
511 : 0 : my_prtvol=0 ; if (PRESENT(prtvol )) my_prtvol=prtvol
512 [ # # ]: 0 : my_mode ='COLL' ; if (PRESENT(mode_paral)) my_mode =mode_paral
513 : :
514 : 0 : msg=' ==== Content of the iter2_t object ==== '
515 [ # # # # : 0 : if (PRESENT(header)) msg=' ==== '//TRIM(ADJUSTL(header))//' ==== '
# # ]
516 : 0 : call wrtout(my_unt,msg,my_mode)
517 : :
518 [ # # ]: 0 : ntot = PRODUCT(Iter2%sizes)
519 : 0 : write(std_out,*)"total number of elements:",ntot
520 : 0 : write(std_out,*)"list of indices: "
521 : :
522 [ # # ]: 0 : do i2=iter2_lbound(Iter2,DIM=2),iter2_ubound(Iter2,DIM=2)
523 [ # # ]: 0 : do i1=iter2_lbound(Iter2,DIM=1),iter2_lbound(Iter2,DIM=1)
524 [ # # # # ]: 0 : write(std_out,*) (iter_yield(Iter2,idx,i1,i2), idx=1,iter_len(Iter2,i1,i2))
525 : : end do
526 : : end do
527 : :
528 [ # # ]: 0 : end subroutine iter2_print
529 : :
530 [ # # # # : 0 : END MODULE m_iterators
# # # # #
# # # # #
# # # # ]
531 : : !!***
|