TABLE OF CONTENTS
- ABINIT/m_iterators
- m_iterators/indices_free
- m_iterators/indices_t
- m_iterators/iter2_alloc
- m_iterators/iter2_free
- m_iterators/iter2_lbound
- m_iterators/iter2_len
- m_iterators/iter2_print
- m_iterators/iter2_push
- m_iterators/iter2_size
- m_iterators/iter2_t
- m_iterators/iter2_ubound
- m_iterators/iter2_yield
ABINIT/m_iterators [ 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