I have nine matrices whose dimension as (N by N)
A1(i,j),A2(i,j),A3(i,j),A4(i,j),A5(i,j),A6(i,j),A7(i,j),A8(i,j),A9(i,j)
Then I want to construct a larger matrix (3N by 3N) including these nine matrices as:
A = [A1 A2 A3
A4 A5 A6
A7 A8 A9]
In fortran, can I use the command line as
do i=1,FN
do j=1,FML
A(i,j) = [A1(i,j),A2(i,j),A3(i,j);A4(i,j),A5(i,j),A6(i,j);A7(i,j),A8(i,j),A9(i,j)]
end do
end do
Just for fun, you can also make the large A matrix by using do-loops as
do i = 1, N
A( i, : ) = [ A1( i,: ), A2( i,: ), A3( i,: ) ]
A( i + N, : ) = [ A4( i,: ), A5( i,: ), A6( i,: ) ]
A( i + N*2, : ) = [ A7( i,: ), A8( i,: ), A9( i,: ) ]
enddo
which fills the A matrix in row-major way and so the small matrices also appear in that way. If really really necessary, this could also be written as one-liner as
A = transpose( reshape( &
[ ( [ A1( i,: ), A2( i,: ), A3( i,: ) ], i=1,N ), &
( [ A4( i,: ), A5( i,: ), A6( i,: ) ], i=1,N ), &
( [ A7( i,: ), A8( i,: ), A9( i,: ) ], i=1,N ) ], [N*3, N*3] ))
which turns out to be the transpose of the second array constructor in the @francescalus answer (in one-liner form)
A = reshape( &
[ ( [ A1( :,i ), A4( :,i ), A7( :,i ) ], i=1,N ), &
( [ A2( :,i ), A5( :,i ), A8( :,i ) ], i=1,N ), &
( [ A3( :,i ), A6( :,i ), A9( :,i ) ], i=1,N ) ], [N*3, N*3] )
To go one-step further, we may define hcat
and vcat
routines as in other languages (note here that explicit interface is necessary):
function hcat( A, B, C ) result( X )
integer, dimension(:,:) :: A, B, C
integer :: X( size(A,1), size(A,2)+size(B,2)+size(C,2) )
X = reshape( [ A, B, C ], shape( X ) )
endfunction
function vcat( A, B, C ) result( X )
integer, dimension(:,:) :: A, B, C
integer :: X( size(A,1)+size(B,1)+size(C,1), size(A,2) )
X = transpose( reshape( &
[ transpose(A), transpose(B), transpose(C) ], &
[ size(X,2), size(X,1) ] ) )
endfunction
then we can write
A = vcat( hcat( A1, A2, A3 ), hcat( A4, A5, A6 ), hcat( A7, A8, A9 ) )
which is somewhat more similar to the desired form in the question:
A = [ A1 A2 A3 ; A4 A5 A6 ; A7 A8 A9 ]
Although Fortran is helpful when it comes to array manipulation, creation of block matrices isn't as elegant as you want from your examples (and would come from certain other languages).
It's possible to use an array constructors to create your desired matrix, much as would be done with scalar elements. That is, RESHAPE([A1, A2, A3, ..., A9],[3*N,3*N])
will give you a 3*N
x3*N
matrix. It's just that it won't be the one you want.
As with the other question/answers the array constructor [...]
considers the array element order to create a rank-1 array of length 9*N**2
, which is then reshape
d to a square matrix. Where those other examples used scalar elements here you have arrays for the data in the constructor. The elements of the constructor are themselves taken in array element order, which would be equivalent to
[A1(1,1), A1(2,1), ..., A1(1,2), A1(2,2), ..., A2(1,1), ... ]
which is unwanted.
So, a constructor would be something like
[A1(:,1), A4(:,1), A7(:,1), A1(:,2), ..., A6(:,3), A9(:,3)]
which works, but is unwieldy.
There may be other tricks to get something more "elegant" into the constructor, but as Vladimir F comments, it may be much nicer to just do direct assignment to the various blocks:
A(1:N,1:N) = A1
A(1:N,N+1:2*N) = A2
A(1:N,2*N+1:3*N) = A3
A(N+1:2*N,1:N) = A4
....
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With