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-11-10 13:31:01 Functions: 50.0 % 12 6
Branches: 44.3 % 122 54

             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                 :             : !!***
        

Generated by: LCOV version 2.3-1