Search code examples
arraysmatrixfortrancellfortran90

Fortran array inside an array


I want to obtain an array but this array include more array its inside. I will describe in an example! I want to create 4 matrix. Main matrix is E.

   Program array1
   !*************************************************! 
   implicit none

   INTEGER, PARAMETER :: m=2 !rows
   INTEGER, PARAMETER :: n=2 !cols
   Real, DIMENSION(m,n) :: A,D
   Real, DIMENSION(1,2) :: B,C

   REAL, allocatable,DIMENSION(:,:) :: E
   allocate(E(4,4))
   ! Assign values to the matrix
   A(1,:)=(/ 1,  1 /)   
   A(2,:)=(/ 1, 2/)  
   B(1,:)=(/ 1, 2/)   
   C(1,:)=(/ 1,  1 /)   
   D(1,:)=(/ 1,  1 /)   
   D(2,:)=(/ 1,  3 /)  

   !E=(/A, B
   !    C, D)
   ! This shape of array
   !E=[A B
   !   C D]
   !Result should be as under
   !E=[1 1 1 2
   !   1 2 0 0
   !   1 1 1 1
   !   0 0 1 3]
  print *,E
  End program array1

How can I obtain this array(E) in Fortran? I am working on f90 and f95. I create a new array which is array(E). Important thing obtain E and I can improve after the array because I don't know which case or function I will use for inside an array. If it is matlab, It is easy but for fotran I don't know!


Solution

  • I wrote a function, catmat, that gets two 2d arrays and concatenates them along a common dimension. See E and F to understand how it works. The array you want is G.

    Notice that the allocation is done inside catmat.

    program main
      implicit none
      real, dimension(2,2) :: A
      real, dimension(1,2) :: B
      real, dimension(1,2) :: C
      real, dimension(2,2) :: D
      real, dimension(:,:), allocatable :: E
      real, dimension(:,:), allocatable :: F
      real, dimension(:,:), allocatable :: G
      integer :: i
    
      A = reshape( [1, 2, 3, 4], [2,2] )
      B(1,:) = [ -1, -2 ]
      C(1,:) = [ -3, -4 ]
      D = reshape( [5, 6, 7, 8], [2,2] )
    
    
      write(*,*) ( A(i,:), NEW_LINE('a'), i = 1, size(A,dim=1) )
    
      write(*,*) ( D(i,:), NEW_LINE('a'), i = 1, size(D,dim=1) )
    
    
      E = catmat( A, D, 1)
    
      write(*,*) "size of E", size(E, dim=1), size(E, dim=2)
      write(*,*) ( E(i,:), NEW_LINE('a'), i = 1, size(E,dim=1) )
    
      F = catmat( A, D, 2)
    
      write(*,*) "size of F", size(F, dim=1), size(F, dim=2)
      write(*,*) ( F(i,:), NEW_LINE('a'), i = 1, size(F,dim=1) )
    
      G = catmat( catmat( A, B, 1), catmat( C, D, 1), 2)
    
      write(*,*) "size of G", size(G, dim=1), size(G, dim=2)
      write(*,*) ( G(i,:), NEW_LINE('a'), i = 1, size(G,dim=1) )
    
    
    
    contains
      function catmat(matl, matr, cdim) result(res)
        real, dimension(:,:), intent(in)  :: matl
        real, dimension(:,:), intent(in)  :: matr
        integer, intent(in)               :: cdim
        real, dimension(:,:), allocatable :: res
        integer                           :: max_dim
    
        ! Assuming 2d arrays
        if( cdim .ne. 1 .and. cdim .ne. 2 ) then
          write(*,*) "ERROR"
          stop
        end if
    
        max_dim =  size(matl,dim=cdim)
        if ( size(matr,dim=cdim) .gt. size(matl,dim=cdim) ) max_dim = size(matr,dim=cdim)
    
    
        if( cdim .eq. 1 ) then
          allocate( res( max_dim, size(matl,dim=2) + size(matr,dim=2) ) )
        else
          allocate( res( size(matl,dim=1) + size(matr,dim=1), max_dim ) )
        end if
    
        res = 0
    
        if(cdim .eq.1 ) then
          res(:,1:size(matl,dim=2)) = matl
          res(:,size(matl,dim=2)+1:size(matl,dim=2)+size(matr,dim=2)) = matr
        else
          res(1:size(matl,dim=1),:) = matl
          res(size(matl,dim=1)+1:size(matl,dim=1)+size(matr,dim=1),:) = matr
        end if
    
      end function catmat
    
    end program main