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

declaring derived type rank-2 arrays for linked list

Bob_Fratantonio
Beginner
827 Views

Hello,
I am writing a program that loops through a file with many instances of data taken at different times. I use a derived data type to create the linked list. See the code below.

module types

type

:: wavedat

real, dimension(:, :) :: espt

real :: winddir

real :: windspeed

real :: time

type (wavedat), pointer :: p

end type wavedat

end module

types

So I then have a module that reads in a data file and gets values for winddir, windspeed, and time. The value for wavedat%espt is given inReadOWI by the transpose of spec2d. Spec2d is a rank-2 array of size (nfreq,nang).How can I initialize wavedat%espt to dimension(nfreq,nang)?

module

ReadOWI

contains

subroutine

OWI(freqz,owidat)

use

types

integer :: OPEN_STATUS,yr,mo,da,hr,mm,nfreq,nang,count

real

:: TWD,U10,stime,dep

real

, allocatable, dimension(:,:) :: dummy,spec2d

real

, allocatable, dimension(:), intent(out) :: freqz

real

, allocatable, dimension(:) :: thetad

type

(wavedat), pointer :: tail

type

(wavedat), pointer :: head

type

(wave dat), pointer :: ptr

type

(wavedat), allocatable, dimension(:), intent(out) :: owidat

!Initialize loop count

count = 0

!Open file for read only

open(UNIT=2,FILE=sample.asc,STATUS='OLD',&

ACTION='READ',IOSTAT=OPEN_STATUS)

if(OPEN_STATUS>0)STOP "----Error, File not opened properly-----"

! This section reads in the number of frequencies and directions (angles)

read(2,'(11X,I,12X,I)'), nfreq,nang !These values define size of owidat%espt

read(2,'(A)') !Blank Line

!Now allocate dimensions to arrays

allocate (freqz(nfreq))

allocate (thetad(nang))

allocate (spec2d(nang,nfreq))

allocate (dummy(nang,nfreq+1))

! Main loop

do

count = count+1

if (count == 1) then

read(2,'(64X,F9.4)'),dep !Depth

else

read(2,'(A)') !First Header Line

end if

read(2,'(A)') !Second Header Line

!Now read year, month, day, hour, minute, wind direction, and wind speed

read(2,'(1X,I4,I2,1X,3I2,7X,F6.1,F7.3)'),yr,mo,da,hr,mm,TWD,U10

read(2,'(A)') !Fourth Header Line

read(2,'(7X)',ADVANCE='NO') !Unwanted Characters

stime = datenum(yr,mo,da,hr,mm)

!Serial date number

!Read in the frequencies to vector freq

if (count==1) then

do p=1,nfreq

read(2,'(F7.4)',ADVANCE='NO') , freqz(p)

end do

end if

!Read directions and spec2d data to 'dummy' variable

do k=1,nang

read(2,'(A)')

do j=1,nfreq+1

if (j==1) then

read(2,'(F7.2)',ADVANCE='NO'),dummy(k,j)

else

read(2,'(F7.4)',ADVANCE='NO'),dummy(k,j)

end if

end do

end do

!Sort Directions and spectrum

dummy = Sort(dummy,nang,nfreq+1)

!Sorted Directions vector

thetad = dummy(:,1)

!Rotate spectrum angles to direction 'From'

spec2d(1:(nang/2),:) = dummy((nang/2)+1:nang,2:nfreq+1)

spec2d((nang/2)+1:nang,:) = dummy(1:nang/2,2:nfreq+1)

read(2,'(A)',IOSTAT=OPEN_STATUS) !Blank Line

!Update owidat structure with this observation

if (.NOT. ASSOCIATED(head)) then

allocate (head,STAT=istat)

! allocate (head%espt(nfreq,nang))

tail => head

nullify (tail%p)

tail%espt =

transpose(spec2d)

tail%winddir = TWD

tail%windspeed = U10

tail%time = stime

else

allocate(tail%p,STAT=istat)

tail => tail%p

nullify (tail%p)

tail%espt =

transpose(spec2d)

tail%winddir = TWD

tail%windspeed = U10

tail%time = stime

end if

!End loop at the end of file

end do

!Determine if loop terminated because of a READ error or the end of the input file

if (OPEN_STATUS>0) then

print *,'An Error Occurred While Reading File'

else

print *,'End of file Reached'

end if

allocate

(owidat(count))

ptr => head

do

i=1,count

owidat(i)%espt = ptr%espt

owidat(i)%winddir = ptr%winddir

owidat(i)%windspeed = ptr%windspeed

owidat(i)%time = ptr%time

ptr => ptr%p

end do

close

(2)

end subroutine

OWI

end module ReadOWI

0 Kudos
6 Replies
Jugoslav_Dujic
Valued Contributor II
827 Views
Um, one of us is missing the obvious?:
bobfrat@gmail.com:

module types

type :: wavedat

real, dimension(:, :) :: espt

...

This last line is a syntax error, and you need either ALLOCATABLE or POINTER attribute for espt...

bobfrat@gmail.com:
!Update owidat structure with this observation

if (.NOT. ASSOCIATED(head)) then

allocate (head,STAT=istat)

! allocate (head%espt(nfreq,nang))


...and if you uncomment the last line, it should work as expected. Or am I missing something?

I didn't look to carefully at the rest of the code; offhand, I'd say that you don't need spec2d array, as you can do all the operations with espt, so you can avoid one transposition/copying.
0 Kudos
Bob_Fratantonio
Beginner
827 Views
So I had been using the allocate attribute.

module types

type :: wavedat

real, allocatable, dimension(:, :) :: espt


And when I uncomment the line

allocate (head%espt(nfreq,nang))

something doesn't work. I know that it works up until

allocate (owidat(count))

ptr => head

do i=1,count

owidat(i)%espt = ptr%espt

This last line doesn't work, so I tried inserting the following...

allocate (owidat(count))

allocate (owidat%espt(nfreq,nang))

ptr => head

do i=1,count

owidat(i)%espt = ptr%espt

But this produces the following error... "The part-name to the right of a part-ref with nonzero rank has the ALLOCATABLE attribute (6.1.2) [ESPT]
0 Kudos
Jugoslav_Dujic
Valued Contributor II
827 Views
The run-time error occurs because owidat(i)%espt is not ALLOCATEd. You tried to "bulk" allocate all the owidat%espt, but that is not allowed by the rules of the language (The part-name...).

The cleanest way to solve the problem is to allocate espt at the moment when you create the parent type. In the code above, that would be after you ALLOCATE(tail%p).

Actually, I'd say that your code should crash at this line (because tail%espt is not ALLOCATEd):

tail%espt = transpose(spec2d)

And it likely would if you use /check:pointer.
0 Kudos
Bob_Fratantonio
Beginner
827 Views
Why is it that I can allocate a part name when it is a pointer
if (.NOT. ASSOCIATED(head)) then
allocate (head,STAT=istat)
allocate (head%espt(nfreq,nang))

but not when it is a variable?
allocate (owidat(count))
allocate (owidat%espt(nfreq,nang))

The program will run without error (without the previous allocate statement), just without any data in owi%espt. However, the data in owi%winddir, owi%windspeed, and owi%time comes out just fine.
0 Kudos
Bob_Fratantonio
Beginner
827 Views
I figured it out. The additions are marked with an asterisk in case you were interested...

if (.NOT. ASSOCIATED(head)) then
allocate (head,STAT=istat)
allocate (head%espt(nfreq,nang))
tail => head
nullify (tail%p)
tail%espt = transpose(spec2d)
tail%winddir = TWD
tail%windspeed = U10
tail%time = stime
else
allocate(tail%p,STAT=istat)
tail => tail%p
****allocate (tail%espt(nfreq,nang))
nullify (tail%p)
tail%espt = transpose(spec2d)
tail%winddir = TWD
tail%windspeed = U10
tail%time = stime
end if

And also...

allocate
(owidat(count))

ptr => head

do i=1,count
if (.NOT. ASSOCIATED(ptr)) EXIT
**allocate (owidat(i)%espt(nfreq,nang))
owidat(i)%espt = ptr%espt
owidat(i)%winddir = ptr%winddir
owidat(i)%windspeed = ptr%windspeed
owidat(i)%time = ptr%time
ptr => ptr%p
end do

Thanks for the help Jugoslav!
0 Kudos
Jugoslav_Dujic
Valued Contributor II
827 Views
Yes, that's what i had in mind.

A side note: your original code (without the last changes) would work as desired under the Fortran 2003 standard -- %espt component would get automatically allocated (or re-allocated) to the shape of the right-hand expression (transpose(spec2d) or ptr%espt respectively). However, that semantics is not enabled by default in IVF 10.1 -- you need to use /assume:realloc_lhs switch (check the documentation) -- it's very new though, and it doesn't even exist in the Project Settings dialog; that's why I avoided mentioning it initially.
0 Kudos
Reply