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.