Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28618 Discussions

Parameterized derived type with namelists?

jwmwalrus
New Contributor I
889 Views

This one should probably qualify as the most impopular combination of Fortran features ---i.e., namelists have always felt like second-class citizens in Fortran, even though they actually beat JSON in a few aspects; and parameterized derived types seem to have had the lowest priority in implementation ever, everywhere.

The above disclaimer is tied to the fact that, due to said lack in popularity, I'm not completely sure if the code samples below are valid. So...

 

 

The code below shows how some information might be lost for namelist purposes, even though the dummy argument contains such information:

 

implicit none

type :: t(ni, nc)
    integer, len :: ni, nc
    integer :: i(ni)
    character(nc) :: c
end type

type(t(10, 20)) :: a

namelist /list_a/a

a%i = 1
a%c = 'Hello, world'

print list_a

call do_write(a)

contains
    subroutine do_write(x)
        type(t(*,*)), intent(in) :: x

        namelist /list_x/x

        print*,'passed x='
        print*,x

        print list_x
    end subroutine
end

 

The result is:

 

$ ifort actual-to-dummy-arg.f90 && ./a.out 
 &LIST_A
 A%NI      =          10,
 A%NC      =          20,
 A%I       = 10*1,
 A%C       = Hello, world        
 /
 passed x=
           1           1           1           1           1           1
           1           1           1           1 Hello, world        
 &LIST_X
 X%NI      =          10,
 X%NC      =          20,
 X%I       = 10*1,
 /

 

Using ifx makes no difference.

 

 

For the code below

 

module mod1
    implicit none

    type :: t(n)
        integer, len :: n = 20
        ! character(n) :: first, second  ! Compiler throws an error with this line
        character(n) :: first
        character(n) :: second
    contains
        procedure :: load
    end type

contains
    subroutine load(this)
        class(t(*)), intent(in) :: this

        integer :: unit, ios
        type(t(this%n)) :: x
        namelist /list/ x

        open (NEWUNIT = unit, FILE = 'no-read.nml', STATUS = 'OLD', ACTION = 'READ', IOSTAT = ios)
        print*,'open ios=',ios
        read (unit, list, IOSTAT = ios)
        print*,'read ios=',ios
        close (unit)

        print list
    end subroutine
end module mod1

use mod1
implicit none

type(t) :: a

call a%load()
end

 

The commented line (line 6) throws an error when used instead of lines 7 and 8 ---but I'm not sure if that's because the code at line 6 is invalid.

When the code above is ran with the following input file:

 

 &list
 x%first = 'Hello',
 x%second = 'World',
 /

 

I get the following:

 

$ ifort no-read.f90 && ./a.out 
 open ios=           0
 read ios=           0
 &LIST
 X%N       =          20,
 /

 

And using ifx makes no difference.

But, again, I'm not sure if line 19 in the code sample is valid.

One thing I noticed, is that the namelist always includes the parameters, but (imho) it shouldn't ---since, by analogy, LEN and KIND are never print for any non-parameterized derived type variable in a namelist. And also for write vs. read consistency.

 

The version info is:

 

$ ifort -V && ifx -V
Intel(R) Fortran Intel(R) 64 Compiler Classic for applications running on Intel(R) 64, Version 2021.10.0 Build 20230609_000000
Copyright (C) 1985-2023 Intel Corporation.  All rights reserved.

Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2023.2.0 Build 20230622
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

 

 

9 Replies
FortranFan
Honored Contributor III
858 Views

@jwmwalrus ,

You make valid points.  If you have paid support subscription, please consider submitting a support request with Intel Software Center () with what you state in consultation with the Fortran standard.  If not, the Intel Support team will follow up once they read your post.

In the meantime, you are right in that the type parameters are not type components and the NAMELIST formatting in the standard which also goes with list-directed formatting does not state the type parameters be transferred, it only refers to type components in component order.

So depending on how the Intel Support team in conjunction with the compiler team view this, but this may lead to compiler incident which may take a while to resolve.

Until then, you may want to consider a home brew using defined IO facility in the language if you want to work with NAMELIST with parameterized derived types.  You will know how to achieve this, but for other readers, here's a hignly simplified example illustration:

module m
   type :: t(n)
      integer, len :: n = 12
      character(len=n) :: s
   contains
      private
      procedure, pass(this) :: write_t
      generic, public :: write(formatted) => write_t
   end type
contains
   subroutine write_t(this, lun, iotype, vlist, istat, imsg)
      ! Argument list
      class(t(n=*)), intent(in)      :: this
      integer, intent(in)            :: lun
      character(len=*), intent(in)   :: iotype
      integer, intent(in)            :: vlist(:)
      integer, intent(out)           :: istat
      character(len=*),intent(inout) :: imsg
      ! Complete data transfer
      if (iotype == "NAMELIST") then
         write(lun, fmt="(*(g0))", iostat=istat, iomsg=imsg) "<&nml_t t%s = ", trim(this%s), " />"
      end if
      ! elided are the instructions for other IOTYPE values
      return
   end subroutine write_t
end module
   use m, only : t
   type(t) :: x
   namelist / nml_x / x
   x%s = "Hello World!"
   write( *, nml=nml_x )
end
C:\temp>ifx /free /standard-semantics p.f
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2023.2.0 Build 20230627
Copyright (C) 1985-2023 Intel Corporation. All rights reserved.

Microsoft (R) Incremental Linker Version 14.36.32537.0
Copyright (C) Microsoft Corporation.  All rights reserved.

-out:p.exe
-subsystem:console
p.obj

C:\temp>p.exe
 &NML_X
 X= <&nml_t t%s = Hello World! />
 /

C:\temp>

 

0 Kudos
jwmwalrus
New Contributor I
810 Views

Hi.

I was simply checking if the two features could be used together in fairly recent versions of the Intel compiler ---so, I guess the answer, for now, is "not really".

0 Kudos
jwmwalrus
New Contributor I
541 Views

Hi @Barbara_P_Intel . Thanks for the notification.

With the latest ifx I now get sort-of-ok results for the code as is.

The issue with the parameters being part of the namelist output is still there.

And also, the commented line for the second reproducer still throws an error. That is, the following code:

module mod1
    implicit none

    type :: t(n)
        integer, len :: n = 20
        character(n) :: first, second  ! Compiler throws an error with this line
        ! character(n) :: first
        ! character(n) :: second
    contains
        procedure :: load
    end type

contains
    subroutine load(this)
        class(t(*)), intent(in) :: this

        integer :: unit, ios
        type(t(this%n)) :: x
        namelist /list/ x

        open (NEWUNIT = unit, FILE = 'no-read.nml', STATUS = 'OLD', ACTION = 'READ', IOSTAT = ios)
        print*,'open ios=',ios
        read (unit, list, IOSTAT = ios)
        print*,'read ios=',ios
        close (unit)

        print list
    end subroutine
end module mod1

use mod1
implicit none

type(t) :: a

call a%load()
end

Throws the misleading error:

$ ifx -V no-read.f90 
Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version 2024.1.0 Build 20240308
Copyright (C) 1985-2024 Intel Corporation. All rights reserved.

 Intel(R) Fortran 24.0-1472.3
no-read.f90(6): error #8237: The character length in a component declaration shall either be a colon, be an initialization expression, or be a specification expression.   [SECOND]
        character(n) :: first, second  ! Compiler throws an error with this line
-------------------------------^
compilation aborted for no-read.f90 (code 1)

Commenting line 6 and uncommenting lines 7 and 8 (which are equivalent to line 6) makes the error go away.

 

0 Kudos
Barbara_P_Intel
Employee
792 Views

According to the Fortran team, there are no restrictions in the Fortran standard regarding PDT and NAMELIST. This is a bit of a corner case. I'm glad it's not a show stopper for you!

I filed a bug report, CMPLRLLVM-49990; it's a low priority.



0 Kudos
Barbara_P_Intel
Employee
556 Views

This issue with NAMELIST and other more modern Fortran features is fixed for ifx and ifort in 2024.1 that was released last week.

Please give it a try!



0 Kudos
Barbara_P_Intel
Employee
523 Views

@jwmwalrus, I see the false error message that you do with this new reproducer.

However, when I comment out line 6 and uncomment 7 and 8 and compile, it hangs when I run it. I think it's waiting at the read. I get "open ios = 29" and then it sits.

My NAMELIST skills are horribly rusty. Is this right?

 

0 Kudos
jwmwalrus
New Contributor I
520 Views

Oh, the reproducer is not new. It's in the first post of this thread. The input file contents are there, but here it is again:

$ cat no-read.nml 
 &list
 x%first = 'Hello',
 x%second = 'World',
 /

 

 

Barbara_P_Intel
Employee
467 Views

AH! I see what I did. I filed a bug report for actual-to-dummy-arg.f90. Let me work on no-read.f90.

Thank you!

 

0 Kudos
Barbara_P_Intel
Employee
459 Views

New bug filed, CMPLRLLVM-57425.

 

0 Kudos
Reply