Initialize derived data types

Initialize derived data types

Hello,

I would like to initialize an array of derived data types with constant values. Since the routines should run in parallel I have to prevent access conflicts and want a static initialization of the constant values only once in a module. Below is a code example:

module myModule

type myType

  character(len=10) :: name

  double precision :: value

  logical :: exist

end type myType

type(myType), dimension(100) ::

  typeArray(1)%name = 'name1',

  typeArray(1)%value = '1',

  typeArray(2)%name = 'name2',

...

end module myModule

Subroutine mySub

use myModule

...

The compiler complains with the error message:

Syntax error, found '%' when expecting one of: * , <END-OF-STATEMENT> ; [ / = =>

Please can anyone point me to another way to initialize an array of derived data types.

Best regards

dieter

12 posts / novo 0
Último post
Para obter mais informações sobre otimizações de compiladores, consulte Aviso sobre otimizações.
imagem de Steve Lionel (Intel)

You have to use "constructors" for the initialization value. For example:


type(mytype) :: typeScalar = mytype(name='Name1', value=1, exist=.true.)

For components that don't have default values in the type declaration, you must specify them in the constructor.

However, doing this for an array of 100 is rather awkward - you'd have an array constructor of type constructors. Might you instead use an initialization routine that is called only once at program start?

Note that you can specify default values in the type declaration, but every object of that type will be initialized to those values.

Steve

Thank you Steve, it works!

but only w/o variable names ;-)
type(mytype) :: typeScalar = mytype('Name1', 1, .true.)

Dieter

imagem de Steve Lionel (Intel)

Works fine for me with the names. You need to make sure the component names in the constructor match those in your actual type declaration.

Steve
imagem de Repeat Offender


   type(myType), dimension(100) :: typeArray = [(myType('Name'// &

      trim(merge(achar(48+mod(i,1000)/100),' ',i>=100))// &

      trim(merge(achar(48+mod(i,100)/10),' ',i>=10))// &

      achar(48+mod(i,10)),i,.TRUE.),i=1,size(typeArray))]

Hello Steve,
if I compile the following example program with ifort 10.1 I receive the error:

fortcom: Error: initType.f, line 25: An equals sign (=) is invalid in this context. [NAME]
typeScalar(5) = myType(name='Name5', value=5.d0, exist=.false.)
-----------------------------^
fortcom: Error: initType.f, line 25: An equals sign (=) is invalid in this context. [VALUE]
typeScalar(5) = myType(name='Name5', value=5.d0, exist=.false.)
-------------------------------------------^
fortcom: Error: initType.f, line 25: An equals sign (=) is invalid in this context. [EXIST]
typeScalar(5) = myType(name='Name5', value=5.d0, exist=.false.)
-------------------------------------------------------^
compilation aborted for initType.f (code 1)

program:
module myMod

implicit none

type myType
character(len=5) :: name
double precision :: value = 1.d0
logical :: exist = .false.
end type myType

end module myMod

program initType

use myMod

implicit none

type(myType), dimension(5) :: typeScalar

typeScalar(1) = myType('Name1', 1.d0, .false.)
typeScalar(2) = myType('Name2', 2.d0, .true.)
typeScalar(3) = myType('Name3', 3.d0, .false.)
typeScalar(4) = myType('Name4', 4.d0, .true.)
typeScalar(5) = myType(name='Name5', value=5.d0, exist=.false.)

write(*,'(a,e12.5,l)') typeScalar

end

imagem de Steve Lionel (Intel)

Wow - 10.1. That's old. The use of component names was added in Fortran 2003 and has been accepted by the compiler for several releases now.

Steve
imagem de Repeat Offender

Some other compilers seem to experience difficulties with the following program:


program init_data

   implicit none

   type myType

      character(10) name

      double precision value

      logical exist

   end type myType

   integer i, j

   type(myType), dimension(100) :: typeArray = [(myType('Name'// &

      transfer(achar(48+mod(i/[(10**j,j=int(log10(i+0.5d0)),0,-1)],10)), &

      repeat('A',int(log10(i+0.5d0))+1)), &

      i,.TRUE.),i=1,size(typeArray))]

   write(*,'(a,1x,f5.1,1x,L1)') typeArray

end program init_data


Is ifort OK with this?

imagem de Steve Lionel (Intel)

No - our support for transformational intrinsics in constant expressions is incomplete, so we don't allow TRANSFER and REPEAT there. It's probably the third biggest F03 feature we're missing.

Steve
imagem de Repeat Offender

Are you sure that's the correct diagnosis? TRANSFER and REPEAT are specifically called out in F95 as allowed in initialization expressions. It seem more probable that int(log10(i+0.5d0)), which is new to F03 initialization expressions, is the culprit. We can work around this, however. What about:


program init_data

   implicit none

   type myType

      character(10) name

      double precision value

      logical exist

   end type myType

   integer i, j

   type(myType), dimension(100) :: typeArray = [(myType('Name'// &

      transfer(achar(48+mod(i/[(10**j,j= &

      (1-sign(1,-i/1000))/2+ (1-sign(1,-i/100))/2+ &

      (1-sign(1,-i/10))/2,0,-1)],10)), &

      repeat('A', &

      (1-sign(1,-i/1000))/2+ (1-sign(1,-i/100))/2+ &

      (1-sign(1,-i/10))/2+ 1)), &

      i,.TRUE.),i=1,size(typeArray))]

   write(*,'(a,1x,f5.1,1x,L1)') typeArray

end program init_data

imagem de Repeat Offender

A little more experimentation and I found two examples which are F95-conforming and work in LF95 but not in gfortran, g95, and ftn95. First example:


program init_data

   implicit none

   type myType

      character(10) name

      double precision value

      logical exist

   end type myType

   integer i, j

   type(myType), dimension(100) :: typeArray

   typeArray = (/(myType('Name'//transfer(achar(48+mod(i/(/(10**j, &

      j=int(log10(i+0.5d0)),0,-1)/),10)),repeat('A', &

      int(log10(i+0.5d0))+1)),i,.TRUE.),i=1,size(typeArray))/)

   write(*,'(a,1x,f5.1,1x,L1)') typeArray

end program init_data


Second example:

program init_data

   implicit none

   type myType

      character(10) name

      double precision value

      logical exist

   end type myType

   integer i, j

   type(myType), dimension(100) :: typeArray = (/(myType('Name'// &

      adjustl(transfer(achar(32+(/((1-sign(1,-i/10**j))/2* &

      (16+mod(i/10**j,10)),j=range(i),0,-1)/)), repeat('A', &

      range(i)+1))),i,.TRUE.),i=1,size(typeArray))/)

   write(*,'(a,1x,f5.1,1x,L1)') typeArray

end program init_data


How does ifort fare with these examples?

Hello,
thank you very much for your hints. For my purpose I use Steves suggestion without variable names.

I have to program only in strict fortran standard and using clear and easy code, so that everybody can understand the logic of the program. In the past I have several problems using nested intrinsic functions, because often there is no fortran standard defined. In addition some extensions to compilers are also without fortran standard. Therefore if they change or I change the compiler, it breaks my code.

BTW: The variable names in my real code are not in ascendig order, but rather arbitrary. The consecutive names I have only used for demonstration in my example program.

Faça login para deixar um comentário.