TABLE OF CONTENTS


ABINIT/m_iterators [ Modules ]

[ Top ] [ Modules ]

NAME

  m_iterators

FUNCTION

  This module defines objects (iterators) that are used to facilitate the
  iteration over the elements of an ensemble e.g. set of transitions.

COPYRIGHT

 Copyright (C) 2009-2024 ABINIT group (MG)
 This file is distributed under the terms of the
 GNU General Public License, see ~abinit/COPYING
 or http://www.gnu.org/copyleft/gpl.txt .

NOTES

  Iterators are used to obtain an indirect indexing that can be used to access array elements
  or array sections. An iterator is an object that contains the list of indices that should
  be treated. Each processor has its own local version initialized according the the distribution
  of the data across the nodes.
  Using iterators for looping facilitates the implementation of MPI algorithms since all the
  information on the distribution of the tasks is stored in the iterator itself
  For example an MPI loop over spins, k-points and bands can be written in terms of iterators using:

   do isp=1,iter_len(Iter_bks)
     spin = iter_yield(Iter_bks,idx3=isp)

     do ikp=1,iter_len(Iter_bks,idx3=isp)
       ik_ibz = iter_yield(Iter_bks,idx2=ikp,idx3=isp)

       do ibn=1,iter_len(Iter_bks,idx2=ikp,idx3=isp)
         band = iter_yield(Iter_bks,entry1=ibn,idx2=ikp,idx3=isp)

  iter_len gives the number of non-zero entries
  iter_yield returns the global indices used to access the data.

  The main advantage is seen in sections of code that are MPI parallelized because each node
  will have its own iterator (to be initialized by the programmer).
  Therefore it is very easy to distribute the workload among the nodes without having to
  to use "cycle" of "if then" instruction in the inners loops.
  Another important advantage is that the MPI implementation will continue to work even
  if the data distribution is changed, only the iterator has to be modified.

SOURCE

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

m_iterators/indices_free [ Functions ]

[ Top ] [ m_iterators ] [ Functions ]

NAME

  indices_free

FUNCTION

INPUTS

OUTPUT

SOURCE

197 subroutine indices_free(Ids)
198 
199 !Arguments ------------------------------------
200  type(indices_t),intent(inout) :: Ids
201 
202 ! *************************************************************************
203 
204  Ids%leng=0
205  ABI_SFREE(Ids%indx)
206 
207 end subroutine indices_free

m_iterators/indices_t [ Types ]

[ Top ] [ m_iterators ] [ Types ]

NAME

  indices_t

FUNCTION

  A base datatype for constructing ragged arrays.

SOURCE

73  type,private :: indices_t
74    integer :: leng
75    integer, allocatable :: indx(:)
76    ! indx(leng) The set of indices.
77  end type indices_t

m_iterators/iter2_alloc [ Functions ]

[ Top ] [ m_iterators ] [ Functions ]

NAME

  iter2_alloc

FUNCTION

INPUTS

OUTPUT

SOURCE

224 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  s1=1; s2=1
240  if (PRESENT(starts)) then
241    s1=starts(1)
242    s2=starts(2)
243  end if
244 
245  Iter2%starts=(/s1,s2/)
246  Iter2%sizes =sizes
247 
248  ABI_MALLOC( Iter2%slice,(s1:s1+sizes(1)-1, s2:s2+sizes(2)-1))
249 
250  do i2=LBOUND(Iter2%slice,DIM=2),UBOUND(Iter2%slice,DIM=2)
251    do i1=LBOUND(Iter2%slice,DIM=1),UBOUND(Iter2%slice,DIM=1)
252      Iter2%slice(i1,i2)%leng=0
253    end do
254  end do
255 
256 end subroutine iter2_alloc

m_iterators/iter2_free [ Functions ]

[ Top ] [ m_iterators ] [ Functions ]

NAME

  iter2_free

FUNCTION

INPUTS

OUTPUT

SOURCE

315 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  do i2=LBOUND(Iter2%slice,DIM=2),UBOUND(Iter2%slice,DIM=2)
328    do i1=LBOUND(Iter2%slice,DIM=1),UBOUND(Iter2%slice,DIM=1)
329      call indices_free(Iter2%slice(i1,i2))
330    end do
331  end do
332 
333  ABI_SFREE(Iter2%slice)
334 
335 end subroutine iter2_free

m_iterators/iter2_lbound [ Functions ]

[ Top ] [ m_iterators ] [ Functions ]

NAME

  iter2_lbound

FUNCTION

INPUTS

OUTPUT

SOURCE

380 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  iter2_lbound = Iter2%starts(dim)
391 
392 end function iter2_lbound

m_iterators/iter2_len [ Functions ]

[ Top ] [ m_iterators ] [ Functions ]

NAME

  iter2_len

FUNCTION

INPUTS

OUTPUT

SOURCE

352 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  iter2_len = Iter2%slice(i1,i2)%leng
362 
363 end function iter2_len

m_iterators/iter2_print [ Functions ]

[ Top ] [ m_iterators ] [ Functions ]

NAME

  iter2_print

FUNCTION

INPUTS

OUTPUT

SOURCE

495 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  my_unt   =std_out; if (PRESENT(unit      )) my_unt   =unit
511  my_prtvol=0      ; if (PRESENT(prtvol    )) my_prtvol=prtvol
512  my_mode  ='COLL' ; if (PRESENT(mode_paral)) my_mode  =mode_paral
513 
514  msg=' ==== Content of the iter2_t object ==== '
515  if (PRESENT(header)) msg=' ==== '//TRIM(ADJUSTL(header))//' ==== '
516  call wrtout(my_unt,msg,my_mode)
517 
518  ntot = PRODUCT(Iter2%sizes)
519  write(std_out,*)"total number of elements:",ntot
520  write(std_out,*)"list of indices: "
521 
522  do i2=iter2_lbound(Iter2,DIM=2),iter2_ubound(Iter2,DIM=2)
523    do i1=iter2_lbound(Iter2,DIM=1),iter2_lbound(Iter2,DIM=1)
524       write(std_out,*) (iter_yield(Iter2,idx,i1,i2), idx=1,iter_len(Iter2,i1,i2))
525    end do
526  end do
527 
528 end subroutine iter2_print
529 
530 END MODULE m_iterators

m_iterators/iter2_push [ Functions ]

[ Top ] [ m_iterators ] [ Functions ]

NAME

  iter2_push

FUNCTION

INPUTS

OUTPUT

SOURCE

273 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  leng = SIZE(list)
289 
290  if (allocated( Iter2%slice(i1,i2)%indx) ) then
291    ABI_ERROR("Iter2%slice already allocated")
292  end if
293 
294  Iter2%slice(i1,i2)%leng = leng
295  ABI_MALLOC(Iter2%slice(i1,i2)%indx,(leng))
296  Iter2%slice(i1,i2)%indx(:) = list
297 
298 end subroutine iter2_push

m_iterators/iter2_size [ Functions ]

[ Top ] [ m_iterators ] [ Functions ]

NAME

  iter2_size

FUNCTION

INPUTS

OUTPUT

SOURCE

438 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  iter2_size = iter2_ubound(Iter2,dim) - iter2_lbound(Iter2,dim) + 1
449 
450 end function iter2_size

m_iterators/iter2_t [ Types ]

[ Top ] [ m_iterators ] [ Types ]

NAME

  iter2_t

FUNCTION

SOURCE

 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.

m_iterators/iter2_ubound [ Functions ]

[ Top ] [ m_iterators ] [ Functions ]

NAME

  iter2_ubound

FUNCTION

INPUTS

OUTPUT

SOURCE

409 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  iter2_ubound = Iter2%starts(dim) + Iter2%sizes(dim) -1
420 
421 end function iter2_ubound

m_iterators/iter2_yield [ Functions ]

[ Top ] [ m_iterators ] [ Functions ]

NAME

  iter2_yield

FUNCTION

INPUTS

OUTPUT

SOURCE

467 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  iter2_yield = Iter2%slice(i1,i2)%indx(idx)
477 
478 end function iter2_yield