Pass derived type as array

597 views Asked by At

In Fortran, one can operate on arrays, but how can one treat the indices of a derived type as part of an array too? Code would explain what I want to do best:

type mytype
    integer :: b(3,3)
    real :: c(4)
endtype

integer :: a(3,3)
real :: d(2,4)
type(mytype) :: mat(2)

!do stuff so that 'mat' gets values
....

!usually one does this
a = matmul(mat(1)%b, transpose(mat(2)%b))

!multiplying two 3x3 matrices

!but how does one do this? Note the "array"
d = matmul(mat(:)%c, mat(:)%c)

I assumed that the final line is analogous to a 2x4 matrix being multiplied with itself. However, when I try to compile, gfortran complains

Error: Two or more part references with nonzero rank must not be specified

Is this possible to do in Fortran?

2

There are 2 answers

0
M. S. B. On BEST ANSWER

You want the compiler to regard mat(:)%c as a 2 x 4 matrix? It doesn't work that way. mat and c are different objects and their ranks don't merge into a single array. mat is a user-defined type and c is a real matrix. Just because you are only using the c-component of mat doesn't mean the compiler will promote c to a higher dimensional real array, based on the dimension of mat.

You could create a new array via X = [ mat(1)%c, mat(2)%c ]. You could use reshape to control the shape.

3
Vladimir F Героям слава On

You can't multiply nonsquare matrices by themselves. You have to transpose one of them.

You also mix reals and integers. Your matrices are supposed to be real and your result is integer.

It's possible to reference the matrix with a small FORTRAN STYLE hack (equivalence and sequence, assuming same storage size for default integer and real). This one compiles :))))

type mytype
    !!!
    sequence
    integer :: b(3,3)
    real :: c(4)
endtype

integer :: a(3,3)
real :: d(4,4)

type(mytype) :: mat(2)
real,dimension(13,2) :: newmat

!!!
equivalence (mat,newmat)

!do stuff so that 'mat' gets values
! ....

!usually one does this
a = matmul(mat(1)%b, mat(2)%b)

!multiplying two 3x3 matrices

!but how does one do this? Note the "array"
 d = matmul(reshape(newmat(10:13,:),(/4,2/)),transpose(reshape(newmat(10:13,:),(/4,2/))))

end