LCOV - code coverage report
Current view: top level - shared/common/src/27_toolbox_oop - m_iterators.F90 (source / functions) Coverage Total Hit
Test: coverage.info Lines: 55.0 % 60 33
Test Date: 2026-09-20 15:27:41 Functions: 50.0 % 12 6

            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         3475 : subroutine indices_free(Ids)
     198              : 
     199              : !Arguments ------------------------------------
     200              :  type(indices_t),intent(inout) :: Ids
     201              : 
     202              : ! *************************************************************************
     203              : 
     204         3475 :  Ids%leng=0
     205         3475 :  ABI_SFREE(Ids%indx)
     206              : 
     207         3475 : 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          459 : 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          459 :  s1=1; s2=1
     240          459 :  if (PRESENT(starts)) then
     241            0 :    s1=starts(1)
     242            0 :    s2=starts(2)
     243              :  end if
     244              : 
     245         1377 :  Iter2%starts=(/s1,s2/)
     246         1377 :  Iter2%sizes =sizes
     247              : 
     248         5779 :  ABI_MALLOC( Iter2%slice,(s1:s1+sizes(1)-1, s2:s2+sizes(2)-1))
     249              : 
     250         1845 :  do i2=LBOUND(Iter2%slice,DIM=2),UBOUND(Iter2%slice,DIM=2)
     251         5338 :    do i1=LBOUND(Iter2%slice,DIM=1),UBOUND(Iter2%slice,DIM=1)
     252         3943 :      Iter2%slice(i1,i2)%leng=0
     253              :    end do
     254              :  end do
     255              : 
     256          459 : 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         3475 : 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         3475 :  leng = SIZE(list)
     289              : 
     290         3475 :  if (allocated( Iter2%slice(i1,i2)%indx) ) then
     291            0 :    ABI_ERROR("Iter2%slice already allocated")
     292              :  end if
     293              : 
     294         3475 :  Iter2%slice(i1,i2)%leng = leng
     295        10425 :  ABI_MALLOC(Iter2%slice(i1,i2)%indx,(leng))
     296        15912 :  Iter2%slice(i1,i2)%indx(:) = list
     297              : 
     298         3475 : 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          459 : 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         1845 :  do i2=LBOUND(Iter2%slice,DIM=2),UBOUND(Iter2%slice,DIM=2)
     328         5338 :    do i1=LBOUND(Iter2%slice,DIM=1),UBOUND(Iter2%slice,DIM=1)
     329         3943 :      call indices_free(Iter2%slice(i1,i2))
     330              :    end do
     331              :  end do
     332              : 
     333         3934 :  ABI_SFREE(Iter2%slice)
     334              : 
     335          459 : 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         3475 : 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         3475 :  iter2_len = Iter2%slice(i1,i2)%leng
     362              : 
     363         3475 : 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        12437 : 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        12437 :  iter2_yield = Iter2%slice(i1,i2)%indx(idx)
     477              : 
     478        12437 : 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              : !!***
        

Generated by: LCOV version 2.3-1