Fortran derived data type two dimensional array storage

608 views Asked by At

In Fortran the two dimensional array is stored in column major format, for example:

integer, allocatable, dimension(:,:)::A
allocate(A(3,4))

Array "A" would be stored in memory as A(1,1),A(2,1),A(3,1),A(1,2),A(2,2),A(3,2),... and so on.

But what happens when I have a derived data type, for example:

type :: innerdata
 integer :: i
 real :: j       
end type innerdata
type(innerdata), allocatable, dimension(:,:) :: A
allocate(A(3,4))

How does the array "A" is stored now in the memory? Thanks!

1

There are 1 answers

0
Vladimir F Героям слава On BEST ANSWER

The array of derived type is stored in the same column-major order.

You may wonder where are the individual components stored. Their offset from the address of the array element is unspecified, the order can differ from the order of declaration and there may be various gaps between them. But once you establish the value of the offset (by calling loc() or c_loc()) it is constant for all instances of that type, no matter if inside that array or anywhere else.

So, the sequence of the components can be

A(1,1)%i,optional_padding,A(1,1)%j,optional_padding,A(2,1)%i,optional_padding,A(2,1)%j,optional_padding,...

but also

A(1,1)%j,optional_padding,A(1,1)%i,optional_padding,A(2,1)%j,optional_padding,A(2,1)%i,optional_padding,...

By defining the type as a sequence type using

type :: innerdata
 sequence
 integer :: i
 real :: j       
end type innerdata

you can force the sequence

A(1,1)%i,A(1,1)%j,A(2,1)%i,A(2,1)%j,...

but that is not recommended, because the access to the elements or components can be slower and some platforms may not allow memory accesses which are not aligned to some number of bytes (leading to very slow accesses).

If you want to know the storage size of the type, use the storage_size() intrinsic (Fortran 2008). The result is in bits. You can also try the non-standard, but common extension, function loc() which gives the address of the variable. The difference of loc of two neighbouring elements id the element size. The same can be done by using c_loc() (Fortan 2003) and transfer()-ing the result to integer(c_intptr_t). In MPI the MPI_Sizeof() function can help too.