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

Initialize derived data types

dnoack
Beginner
2,778 Views

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

0 Kudos
11 Replies
Steven_L_Intel1
Employee
2,778 Views
You have to use "constructors" for the initialization value. For example: [fortran] type(mytype) :: typeScalar = mytype(name='Name1', value=1, exist=.true.) [/fortran] 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.
0 Kudos
dnoack
Beginner
2,778 Views
Thank you Steve, it works! but only w/o variable names ;-) type(mytype) :: typeScalar = mytype('Name1', 1, .true.) Dieter
0 Kudos
Steven_L_Intel1
Employee
2,778 Views
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.
0 Kudos
JVanB
Valued Contributor II
2,778 Views
[fortran] 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))] [/fortran]
0 Kudos
dnoack
Beginner
2,778 Views
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
0 Kudos
Steven_L_Intel1
Employee
2,778 Views
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.
0 Kudos
JVanB
Valued Contributor II
2,778 Views
Some other compilers seem to experience difficulties with the following program: [fortran] 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 [/fortran] Is ifort OK with this?
0 Kudos
Steven_L_Intel1
Employee
2,778 Views
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.
0 Kudos
JVanB
Valued Contributor II
2,778 Views
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: [fortran] 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 [/fortran]
0 Kudos
JVanB
Valued Contributor II
2,778 Views
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: [fortran] 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 [/fortran] Second example: [fortran] 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 [/fortran] How does ifort fare with these examples?
0 Kudos
dnoack
Beginner
2,778 Views
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.
0 Kudos
Reply