Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to construct a matrix containing 9 smaller matrix

Tags:

matrix

fortran

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
like image 714
Jeremy_Tamu Avatar asked Dec 14 '15 08:12

Jeremy_Tamu


2 Answers

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 ]
like image 168
roygvib Avatar answered Oct 06 '22 16:10

roygvib


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*Nx3*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 reshaped 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
....
like image 36
francescalus Avatar answered Oct 06 '22 16:10

francescalus