I have a code where I want to loop over all points in a grid, and for each point check if a given condition holds for a sufficient number of neighbouring points. Additionally, I have periodic boundaries on the grid.
The problem is very similar to the Game of Life.
My current code looks something like this
do k=1,ksize; do j=1,jsize; do i=1,isize ! Loop over all points
ncount = 0
kkloop: do kk=k-1,k+1 ! Loop over neighbours
ktmp = kk
if(kk>ksize) ktmp = 1 ! Handle periodic boundary
if(kk<1) ktmp = ksize
do jj=j-1,j+1
jtmp = jj
if(jj>jsize) jtmp = 1
if(jj<1) jtmp = jsize
do ii=i-1,i+1
if(ii == 0 .and. jj == 0 .and. kk == 0) cycle ! Skip self
itmp = ii
if(ii>isize) itmp = 1
if(ii<1) itmp = isize
if(grid(itmp,jtmp,ktmp)) ncount = ncount + 1 ! Check condition for neighbour
if(ncount > threshold) then ! Enough neigbours with condition?
do_stuff(i,j,k)
break kkloop
end if
end do
end do
end do
end do; end do; end do
This is neither elegant, nor probably very efficient. Is there a better way to do this? This code will be repeated a lot, so I would like to make it as fast as possible.
I’ll work this out in 2D, leave it to you to inflate to 3D.
The first thing I’d do is pad the array with a halo of depth equal to the depth of the neighbourhood you are interested in. So, if your array is declared as, say
and you are interested in the 8 immediate neighbours of each cell,
This will save a lot of time checking for the boundary and will be worth doing whether or not you follow the next suggestion. You could do this ‘in place’ if you like, I mean just expand
my_arrayrather than copy it.For an elegant solution you could write something like this
Here,
logical_function_of()returns true when the neighbourhood ofmy_array(i,j)satisfies your criteria. I got tired after listing the N,S,E,W neighbours and for production code I’d probably write this as a function of the indices anyway. In my experienceforallis elegant (to some) but not as high-performing as nested loops.