Reputation: 1070
I am trying to reshape 4-dimensional array in Fortran to 2 dimensional one:
do k=1,nA
do m=1,nA
do l=1,nB
do n=1,nB
p = k * nA + m
q = l * nB + n
Lpq(p,q) = Aij(k,m,l,n)
end do
end do
end do
end do
What is the proper way of defining indexes p
and q
?
Upvotes: 2
Views: 100
Reputation: 151
It depends of what you want to do with Aij and Lpq. If you just want to change the indexing to have easier access to the array elements and want to use Lpq as a read-only array, you might well use the EQUIVALENCE statement. Moreover, this will save memory space, because it only re-interprets the array. If you want to treat them as independ arrays you can make a copy of Lpq next, and use the copy.
integer Aij(nA,nA,nB,nB)
integer Lpq(nA*nA,nB*nB), Lpq_copy(nA*nA,nB*nB)
equivalence (Aij, Lpq)
! fill Aij with test data
do k=1,nA
do m=1,nA
do l=1,nB
do n=1,nB
Aij(k,m,l,n) = k*10000+m*1000+l*100+n
end do
end do
end do
end do
print *, Lpq
! make a copy if needed
Lpq_copy = Lpq
Lpq(1,1) = 1 ! this will affect Aij, but not Lpq_copy
Upvotes: 3
Reputation: 26471
The following answer makes the following assumption:
Both Aij
and Lpq
have default start and end indices (i.e. start indices are ONE and end indices are the corresponding dimensions. I.e.
TYPE, DIMENSION(nA,nA,nB,nB) :: Aij
TYPE, DIMENSION(nA*nA,nB*nB) :: Lpq
There are many ways you can map Aij
on Lpq
, but the one you defined is where the second and fourth index in Aij
(referenced as m
and n
) are the fastest running indices in Lpq
. This means:
Aij(1,1 ,1,1) => Lpq(1,1)
...
Aij(1,nA ,1,1) => Lpq(nA,1)
Aij(2,1 ,1,1) => Lpq(nA+1,1)
...
Aij(2,nA ,1,1) => Lpq(2*nA,1)
...
Aij(nA,nA,1,1) => Lpq(nA*nA,1)
A similar mapping exists for the other dimensions.
The current mapping you implemented (i.e. p = k * nA + m
) sets p=nA+1
when k=m=1
and returns p=(nA+1)*nA
for k=m=nA
. So you are missing the lower range and overshoot the upper range.
you have to define the mapping as:
p = (k-1) * nA + m
q = (l-1) * nB + n
Note, however, as mentioned in the comments, Fortran has a intrinsic procedure reshape
that could do these kind of mappings for you. Sadly, in your particular case it is not as handy due to the choice of the fastest index.
If you would choose the fastest indices to be k
and l
, then you can use a single reshape
as the system is already in column-major-order:
Lpq = reshape(Aij,[nA*nA,nB*nB])
If you choose the fastest indices to be m
and n
, then you need two calls to reshape
. The first to swap two indices and bring the system in a column manjor order, and the second to do the real reshape.
Bij = reshape(Aij,[nA,nA,nB,nB],order=[2,1,4,3])
Lpq = reshape(Bij,[nA*nA,nB*nB])
Upvotes: 3