SKPS
SKPS

Reputation: 5847

Fortran implied do loop: append array

I want to write my data for a periodic boundary, implying the zero-th index needs to written at the end for both i and j direction. Also, rho(m+1,n+1)=rho(0,0) needs to be written. The current code for writing data is:

do j=0,n
write(2,"(F16.8)")(rho(i,j),i=0,m)
end do

How can the data be written in such a way I mentioned above? Something like the following

  j ...
i 1 2 3
. 4 5 6
. 7 8 9

  1 2 3 1
  4 5 6 4
  7 8 9 7
  1 2 3 1

Upvotes: 2

Views: 691

Answers (3)

chw21
chw21

Reputation: 8140

An implied do loop has to be in parentheses inside an array declaration:

! These are the same
[  (i, i=1, 3) ]
(/ (i, i=1, 3) /)

If you have a many-dimensional one, you have to wrap them

[ ( [ (i*j, i=1, 3) ], j = 1, 3 ) ]
!   ^^^^^^^^^^^^^^^^^

For your periodicity, I simply use mod(idx, len) to get back to 0 for the last one. Here's my idea on how to do it with implicit do loops.

program periodic_boundary
    implicit none
    integer :: d(0:2, 0:2), i, j

    d = reshape( [(i, i=1, 9)], [3, 3] )

    print '(4I4)',                                 &
        [ (                                        &
            [ (d(mod(i, 3), mod(j, 3)), i=0, 3) ]  &
        , j=0, 3) ]

end program periodic_boundary

For readability, I use continuation lines to separate the inner from the outer loop.

Upvotes: 1

roygvib
roygvib

Reputation: 7395

If the computational speed does not matter, wrapping the indices with periodic boundary condition might be another option. (As for modulo(), please see this page, which gives [0,P-1] for negative as well as positive arguments. By changing the return value 0 to P, it always maps the result to [1,P].)

program main
    implicit none
    integer, parameter :: m = 3, n = 3
    integer rho( m, n ), i, j

    rho(1,:) = [1,2,3]
    rho(2,:) = [4,5,6]
    rho(3,:) = [7,8,9]

    do i = -2,m+3
        print "(*(i2))", ( rho( pbc(i,m), pbc(j,n) ), j = -2,n+3 )
    enddo

contains
    integer function pbc( k, P )
        integer :: k, P
        pbc = modulo( k, P )
        if ( pbc == 0 ) pbc = P
    endfunction
end

$ gfortran -fcheck=all test.f90

 1 2 3 1 2 3 1 2 3
 4 5 6 4 5 6 4 5 6
 7 8 9 7 8 9 7 8 9
 1 2 3 1 2 3 1 2 3
 4 5 6 4 5 6 4 5 6
 7 8 9 7 8 9 7 8 9
 1 2 3 1 2 3 1 2 3
 4 5 6 4 5 6 4 5 6
 7 8 9 7 8 9 7 8 9

Upvotes: 0

High Performance Mark
High Performance Mark

Reputation: 78374

Maybe something like this (untested)

integer, dimension(4,4) :: arr1
...
arr1(1:3,1:3) = transpose(reshape([(i,i=1,9)],[3,3]))
arr1(:,4) = arr1(:,1)
arr1(4,:) = arr1(1,:)

but drop the madness of thinking about 0-th indices in Fortran.

Upvotes: 0

Related Questions