Reputation: 413
I am struggling to come up with an algorithm for outputting a 3D array. I basically have an array of 9 2D arrays that i need to combine into a 3X3 grid and output into a text file as a matrix. So i have:
real:: array3D(9,16,16)
And I need to sequentially(left to right, top to bottom) put these 9, 16x16 arrays together into a 3x3 grid:
real:: array2D(48,48)
Any help would be great.
[Edit: info for comments]: This is part of an MPI program where a 48x48 matrix is being split into 9 16x16 matrices, where each of 9 processes is being assigned to one 'sub-grid' of the larger array. Like a sudoku grid as mentioned in the comments, with each process applying a formula to each element within its own sub-grid. The final values calculated by each process then need to be put back into a 48x48 matrix in order to be displayed in a text file. This currently looks like this:
if(procID.ne.0)then!Send all arrays to root
call MPI_SEND (array, row*col, MPI_REAL, 0, procID+1000, MPI_COMM_WORLD, ierr)
else
complete(1,:,:)=array(:,:)
do i=2, 9
call MPI_RECV (recvArray, row*col, MPI_REAL, i-1, (i-1)+1000, MPI_COMM_WORLD, status, ierr)
complete(i,:,:)=recvArray
end do
What I am trying to get is an algorithm that I can use to display complete
in a text file as a matrix in such a way that it makes sense for me to read. (I know the variables names are different from above but I tried to simplify/ generalise my original problem as much as possible. Here array
again has dimensions 48x48
but i am only interested with a 16x16
block within each one(9 sudoku puzzles, only want one sub-grid from each) which 16x16 block i want is defined by the first indices of complete
/array3D
:1-9, i want to take these sub-blocks and arrange them in another 48x48
array say arrayOut
/array2D
). I will try and put a graphical explanation of the problem up when i get chance if what i have written doesn't make much sense.
Thanks to @george whose answer is below, to put this in an array you need:
do majorRow=1,3
do majorCol=1,3
subBlock=(majorRow-1)*3+majorCol
do minorRow=majorRow*16-(16-1),majorRow*16
do minorCol=majorCol*16-(16-1),majorCol*16
outArray(minorRow,minorCol)=complete(subBlock,minorRow,minorCol)
end do
end do
end do
end do
Upvotes: 0
Views: 283
Reputation: 6989
no need to copy to a new array just to output.
pseudocode: (I may have transposed rows/columns but thats easily fixed)
do majorrow=1,3
do minorrow=1,16
do majorcol=1,3
subblock=(majorrow-1)*3+majorcol
do minorcol=1,16
write(advance=no)array3D(subblock,minorrow,minorcol)
enddo
enddo !end of row
write() ! to advance line at end of row.
enddo
enddo
note the innermost loop can be replaced by
write(advance=no)array3D(subblock,minorrow,:)
you still need no advance since you have three writes per line.
Upvotes: 1
Reputation: 6888
If you resort to simple do-loop constructs, you just need to loop over the large 2d array in a block-wise fashion, then store the corresponding elements from the 3d array in the correct block of the 2d array.
BLKSZ=16
NBLOCK=3
DO IB=1,NBLOCK
ISTA=BLKSZ*(IB-1)+1
IEND=ISTA+BLKSZ-1
DO JB=1,NBLOCK
JSTA=BLKSZ*(JB-1)+1
JEND=JSTA+BLKSZ-1
array2D(ISTA:IEND,JSTA:JEND)=array3D(JB+NBLOCK*(IB-1),:,:)
END DO
END DO
Note that the 3d array isn't very efficiently ordered, since the block index is the fastest index. Preferably, it should be the last index (avoiding cache misses).
Upvotes: 0