Are Fortran derived type members as assumed shape arrays possible?

64 Views Asked by At

I need to turn a specific Fortran procedure into a generic one to be used many times without changes.

It takes a couple of derived types as dummy arguments, containing several arrays, whose dimension are unknown at compiling time (I need to add it to a static lib).

Can I declare member arrays as assumed shape arrays inside the subroutine? I.e.

subroutine(TF_Model_V)
type TF_Model_V
    sequence
    real*8 , dimension (:) ::A
    real*8 , dimension (:) ::ACONE
    real*8 , dimension (:) ::ADM
    ...
End type
...

It seems that is not possible since the compilation fails. Is there any way of doing this?

1

There are 1 best solutions below

1
francescalus On

Array components of a derived type cannot have assumed shape.

The shape specification of a derived type component must be either explicit or deferred, this latter being for pointer or allocatable components.

For dummy arguments, explicit shape specifications do not need to be constant expressions. This gives us a way to have the shape of a component vary at run-time.

We do this using length type parameters for the type, which can be assumed:

program assumed
  implicit none

  type :: t(n)
     integer, len :: n
     real :: x(n)
  end type t

  type(t(5)) :: a
  type(t(8)) :: b

  call sub(a)
  call sub(b)

contains

  subroutine sub(x)
    type(t(*)), intent(in) :: x

    print '(A,I0)', "Size of dummy's component: ", SIZE(x%x)
  end subroutine sub
  
end program assumed

Additional length type parameters can be included and assumed, to handle further components of different shapes.

Sequence types cannot have type parameters, so the definition of the derived type must be unique.

Alternatively, using deferred shape for components:

program deferred
  implicit none

  type :: t
     real, allocatable :: x(:)
  end type t

  type(t) :: a
  type(t) :: b

  allocate(a%x(5))
  allocate(b%x(8))

  call sub(a)
  call sub(b)

contains

  subroutine sub(x)
    type(t), intent(in) :: x

    print '(A,I0)', "Size of dummy's component: ", SIZE(x%x)
  end subroutine sub
  
end program deferred

Your choice really comes down to how you want to set/process the dynamic shape of the components.