3

I would like to convert upper triangle part of the matrix to the vector.

For example I have the following matrix (4x4 for simplicity):

 1     2     3     4  
 5     6     7     8 
 9     10    11    12
 13    14    15    16 
  1. How can I get upper triangle part of the matrix, written 'by rows':

    1 2 3 4 6 7 8 11 12 16

  2. And how can I get upper triangle part of the matrix, written 'by columns':

    1 2 6 3 7 11 4 8 12 16

Thanks for your help!

Edited: Here is a code generating identity matrix:

    program main

    use constants  ! global vairables and conventional constants
    use trans      ! transformation between different frames

    implicit none
    integer ::  ii, ij
    real*8,dimension(4,4) :: R_reg

    !call cpu_time(tic)


    write(*,*) "check1" !check-point

    !creating diagonal unity matrix
    DO ii = 1, 4  
        DO ij = 1, 4 
            R_reg(ij,ii) = (ij/ii)*(ii/ij) !integer division
        END DO
    END DO
    
    write(*,*) "check2" !check-point
    
    
    !create the test .txt file: 
    open(50, file='R_reg.txt', status='replace')
        DO ii=1, 4
            write(50,*) R_reg(ii,:)
        END DO  
    close(50)

    write(*,*) "check3" !check-point
 end program
Abracadabra
  • 201
  • 1
  • 10
  • 1
    Do you have any code? At least the declaration of your matrix and of the vector? Did you try anything? You definitely should at least show what the matrix and the vectors are in your code. Fortran only knows arrays, not matrices and vectors. The solution will be two simple nested do-loops. – Vladimir F Героям слава Apr 05 '22 at 12:55
  • @VladimirFГероямслава I am totaly new to Fortran. I have a code in Matlab, but I don't think that will help here: "I = [1,2,3,4;5,6,7,8;9,10,11,12;13,14,15,16]; It = I.'; m = tril(true(size(It))); v_u = It(m).'; " – Abracadabra Apr 05 '22 at 12:57
  • 2
    That leaves my quite confused with what you actually need, because normally one does not do such a conversion just because with having any surrounding code. If you really lack the very Fortran basics, you will first have to start with how arrays are declared in Fortran and how do loops work in Fortran (because there is no such intrinsic function to do it in one step). Writing the loop in the right order is then quite trivial once you know the basics. – Vladimir F Героям слава Apr 05 '22 at 13:35
  • @VladimirFГероямслава I've added a code snippet that generating identity matrix in fortran. And I only want to transfer upper triangular part of it into the vector. I need specifically this format because of further calculations that I have to do in this specific format. Could you tell me please, how (at least approximately) that two nested do -loops should look like? – Abracadabra Apr 05 '22 at 13:40

3 Answers3

4

It is really just going through the array in the right order and storing the elements that you go through. It may just take a bit of experimenting to get the loop bounds correct.

integer : n    
real*8,dimension(10) :: ut_c, ut_r    


DO ii = 1, 4  
    DO ij = 1, 4 
        R_reg(ij,ii) = ii + (ij-1)*4
    END DO
END DO

n = 0
DO ij = 1, 4 
    DO ii = ij, 4  
        n = n + 1
        ut_r(n) = R_reg(ij,ii)
    END DO
END DO


n = 0
DO ii = 1, 4
   DO ij = 1, ii
        n = n + 1
        ut_c(n) = R_reg(ij,ii)
    END DO
END DO

print *, "rows:", ut_r
print *, "columns:", ut_c

Note that the real*8 syntax is not standard Fortran. See Fortran: integer*4 vs integer(4) vs integer(kind=4) and Fortran 90 kind parameter

3

As has been noted, one can go row-by-row or column-by-column selecting the desired elements. Using array constructors one needn't worry about keeping track of at least one index:

  implicit none
  integer, parameter :: N=4
  
  integer A(N,N), i, j

  A = reshape([(i,i=1,N**2)], [N, N], order=[2,1])

  print '("Matrix:")'
  do i=1,N
     print '(*(I5))', A(i,:)
  end do

  print '(/,"By rows:",/,*(I5))', [((A(i,j), j=i,N), i=1,N)]
  print '(/,"By columns:",/,*(I5))', [((A(j,i), j=1,i), i=1,N)]

end program

To store the upper-triangular parts in an array, the array constructor can easily be assigned to an allocatable rank-1 array instead of simply being printed.

francescalus
  • 30,576
  • 16
  • 61
  • 96
3

As concisely as possible, "by rows":

[(R_reg(i, i:), i=1, 4)]

and "by cols":

[(R_reg(:i, i), i=1, 4)]
veryreverie
  • 2,871
  • 2
  • 13
  • 26