A gfortran issue with parameterized derived types

Hi, I ran into something problematic and I have no idea how to fix it. Here is the minimum code that generates the error:

program main
   use iso_fortran_env, only: real32
   implicit none

   type :: arr_o_rarr(k)
      integer, kind :: k
      real(k), allocatable :: arr(:)
   end type arr_o_rarr

   type(arr_o_rarr(real32)), allocatable :: arrs(:)
   integer :: i, j, dims

   dims = 10
   allocate (arrs(dims))
   do i = 1, dims
      arrs(i)%arr = [(j*1., j = 1, i)]
   end do
end program main

It seems ifort can compile and run this code happily but gfortran will end up with core dumped. How could I fix it if I want to use gfortran?

You’re using parameterized derived type (PDT) facility introduced since the Fortran 2003 standard. The implementation of this facility in gfortran has gaps. See this.

If you can join the GCC/gfortran community and do compiler development (it’s open source initiative as you may know), that may be your fastest route to resolving this problem.

1 Like

There is definitely a bug here or better as @FortranFan said its implementation in gfortran is not complete yet. However, there is a walkaround but not the exact solution you would expect.
In short: you cannot have both allocatable: the internal array and the PDT (parameterized derived type) and actually the latter case I couldn’t make it work.

The following module is common for both the following examples:

module m_matrix
    implicit none
    type :: t_matrix(rows, k)
        integer, len :: rows
        integer, kind :: k 
        real(kind = k):: values(rows) ! note that I am not declaring it here as allocatable!!!
    end type 
end module m_matrix

First (working) example with an allocatable internal array (link):

program test_matrix
    use iso_fortran_env, only:real32
    use m_matrix
    implicit none
    type(t_matrix(k=real32,rows=:)), allocatable :: m
    integer :: dims, i

    dims = 10
    allocate(t_matrix(k=real32, rows=dims) :: m)

    m%values = [(i*1., i = 1, dims)]
    print*, m%values
end program test_matrix

Second (non-working) example with allocatable PDT (link):

program test_matrix
    use iso_fortran_env, only:real32
    use m_matrix
    implicit none
    integer, parameter :: rr = 5
    type(t_matrix(k=real32, rows=rr)), allocatable ::  m(:)
    integer :: dims, i

    dims = 10
    allocate(m(dims)) ! Program compiles until here provided 
    ! the below lines are commented, and I have no idea why it does so.
    
    ! but if you try to access the allocated memory, as I do below, it throws a 
    ! segmentation fault (see link above)
    !do i = 1, dims
    !    m(i)%values = 0.
    !    print*,m(i)%values
    !end do
end program test_matrix

Even with the first working example, if I am being honest, I am not sure why it compiles or if it should.

ps1. Regarding the second case, I also tried to wrap the t_matrix in another derived type but not matter what I tried I was getting the same error.

ps2. Regardless of the current state of PDT, I personally never found a good reason to use them, nothing I cannot code with a simple DT, and since most times the parameters are known at run time this feature as it is, is just useless. Also, the parameter integer, kind :: k must always be known at compile-time, which is what really matters for me. Of course, if that wasn’t the case then we would be talking about the first template feature of Fortran.

1 Like

Just to clarify for the benefit of readers who may not be fully familiar with the topic on hand: the above comment suggesting the “the internal array and the PDT (parameterized derived type)” “cannot have both allocatable” may only apply to the current state of gfortran implementation.

Fortran language as well as other compiler implementations do support both to have the ALLOCATABLE attribute. As mentioned by @han190, the code in the original post works as expected per the Fortran standard with Intel Fortran compiler.

1 Like

I disagree entirely with the above assertion.

Given a robust compiler implementation, the parameterized derived type (PDT) facility is rather convenient and useful in design of good scientific software. Here’re some immediate use cases that come to my mind:

  1. The “problem size(s)” in several computations and simulations in scientific and technical computing are themselves parameterized in terms of numbers of certain things that are known right at the start of the calculation e.g., number of species and their elemental composition in chemical physics calculations, say CO2 and other molecular components in climate systems (whether it be atmosphere, ocean, etc.) modeling. PDTs lend themselves nicely to such needs: allocation of an object of a PDT type ensures all the subobjects are all immediately allocated to the right sizes. The code for the PDT type can be simplified considerably relative to code designs that rely on subobjects that have the ALLOCATABLE attribute.
  2. Computations requiring improved performance based on vectorization and SIMD intrinsics, etc. can benefit from code designs with SoA (structure of arrays) approach whereas the conceptualization, abstraction, and problem formulation and other calculation modes are often more amenable to AoS (arrays of structure) approach. For certain problems, PDTs with length-type parameters can offer a design solution that combines the two yielding the typical convenience with performance benefits.
  3. Higher-level abstraction of applications of the only intrinsic ‘container’ class in Fortran which is arrays. Such as matrices including toward sparse matrix designs. Or certain needs involving limited heterogeneity e.g., hashing in encryption, etc. PDTs can serve as a convenient encapsulation ‘class’ for these applications.
  4. Packaging of utility ‘classes’ which are known ‘a priori’ to only support certain variants e.g., a solver class that works with the supported floating-point precision options in a processor implementation that is usually only in the range of 3 to 4 kinds (e.g., Intel supports 3 as given by REAL_KINDS constant in ISO_FORTRAN_ENV). Or a pre or postprocessing utility toward spatial transformations that may only support 1D, 2D, and 3D modes. The use of PDTs with kind-type parameters toward such ‘classes’ prove really convenient.

Of course, all of the use cases can be improved greatly with better support for generics in Fortran. I can only hope any work toward in a future Fortran standard (202Y?) will build and expand upon the current PDT facility in the language.

1 Like

I just want to clarify that this assertion was based on my personal opinion and (limited) experience.

  1. Where I come from, in our codes, there is not a single hardcoded/compile-time known parameter with the only exception that of a couple of physical constants (Boltzmann and Avogadro number) and pi.
  2. No objection about SoAs. I agree. But I do not see how the concept of SoAs is only or better served by PDTs and not just simple DTs.

Can you give an example, or explain how this can work? This is a genuine question, I really do not know how PDTs can be a middle solution.

  1. Same as 2.
  2. This is indeed a case and most probably one of many others that I am not familiar with and I will take your word for it.
2 Likes

The use case for PDT that I encountered is letting the user choose the real type kind at run time rather than compile time in the client code rather than using a pre-processor when compiling the library . Alternatively this could be accomplished with generic procedures, but for a derived type with many methods that work on the real array component of the type, the code quickly explodes in size.

1 Like

My point in the earlier post is PDTs can be more convenient and efficient with both design and consumption compared to type components of ALLOCATABLE attribute and as such PDTs are rather valuable in Fortran.

In this link in the post dated “02-17-2019 08:07 AM”, I post a generic, simple example involving PDTs that hints at how SoA approach can be achieved in what may be primarily an AoS based ‘class’ design. I don’t have the rights to share an actual example from industry that employs a similar design approach but in more elaborate fashion.

Similarly, in this thread - scroll way down in the thread to comment dated Thu, 10/26/2017 - 21:46 - I show a simple case of a utility class that can work with different precision of the ‘data’ of interest, such as the molar volume of a fluid, in the same program.

1 Like