Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

derived data type with allocatable element 1

Status
Not open for further replies.

albi73

Programmer
Sep 16, 2010
18
IT
please help me to understand this point before I will waste time.

I'd like to understand if it is possible to use allocatable into a "type structure". I tested this easy code:

program test_allocation
type elettrone
real,allocatable, dimension :),:) :: vx
!real,pointer, dimension :),:) :: vx
end type

type(elettrone) :: mpi
allocate(mpi%vx(1:2,1:3))
mpi%vx=reshape((/1,2,3,4,5,6/),(/2,3/))


print *,mpi%vx
!print *,mpi
read (*,*)
end program

It well works, but if i use the line "print *,mpi" (above commented), I obtain the following error message: .... a derived type ultimately contains an allocatable component cannot be specified in the i/o item.

My question is:
may I use allocatable array in to a "type structure"? Why above - in same cases - it seems to work but on books I read that it is not permitted and that one must use pointers? (again above using the pointer the result is the same)
Can I go ahead using the allocatable array as i did before thinking to use a more structurated programming?

I hope you'll halp me to figure out this point.

Thanks, Albi73
 
The use of allocatable arrays has been made much more flexible in F2003 than in F95. In particular, they are authorized as dummy arguments or within derived types.

Fortunately, as this extension was the subject of a rather old technical recommendation, most of f95 compilers implement it (I call that F95+).

Do not hesitate to use, if possible, allocatable in place of pointer ! The memory management is much safer with allocatable than pointer (no risk of memory leak).

I always try to limit the use of pointers to their basic function : pointing to (more exactly aliasing) a memory area already allocated.

About print or write statements concerning whole derived type variables, they are limited to the ones without allocatable or pointer elements. Why ? I don't remember. I just remember having seen an explanation in the past but I forgot it.

So, if you replace ALLOCATABLE by POINTER, you will get a similar error message.
 
Thanks a lot dear FJacq, but clearly -just starting to construct my structure - I stopped on a point that makes me mad.
I hope you will give a look to these few lines:
program test_allocation
type elettrone
real,pointer, dimension :)) :: gene
integer :: id
end type

type(elettrone),dimension(1:3) :: mpi
allocate(mpi%gene(1:2))
!allocate(mpi(1)%gene(1:2))
!allocate(mpi(2)%gene(1:2))
mpi(1)%gene=(/1,2/)
mpi(2)%gene=(/1,4/)
mpi(1)%id=10

print *,mpi(1)%gene:))
print *,mpi(2)%gene:))
!print *,mpi(1)%id
read (*,*)
end program

error: Component mpi to right of part references with nonzero rank must not have pointer attribute

changing the three lines:
!allocate(mpi%gene(1:2))
allocate(mpi(1)%gene(1:2))
allocate(mpi(2)%gene(1:2))
it works!

I can't believe that to overcome this point one needs to write a loop something like:
do i= ...
allocate(mpi(i)%gene(1:2))
end do
I'd like to think that there is a much smart way to allocate this array derived type

Ciao, Albi73
 
Sorry but you need the loop !

The limitation is much deeper than you could think. FORTRAN makes invalid any reference to an array of array.

The reason is in fact simple : the distance between two successive elements of an array among each dimension must be constant. This is necessary to keep in the same time high performances and a pointer enough simple (a pointer contains that distance over each dimension).

With an array of array, this cannot be warranted.

Even after the allocation, you cannot set all the arrays with a single instruction :

Code:
      allocate(mpi(1)%gene(1:2))
      allocate(mpi(2)%gene(1:2))
      mpi%gene=0 ! => error

The error does not come from the POINTER attribute but from the reason I have indicated. Change POINTER into ALLOCATABLE and you will get the same trouble.

Even if the array GENE has a constant size, you cannot use mpi%gene. In theory, this is the only case which could be acceptable but there are many corner cases which make it too dangerous. So the rule is strict : no array of array !

Code:
PROGRAM tt
  TYPE t
    INTEGER :: tab(10)
  END TYPE
  TYPE(t) :: o(3)
  o%tab=0
  write(*,*) o%tab
END PROGRAM

tt.f90(6): error #6159: A component cannot be an array if the encompassing structure is an array. [TAB]

Now, look at the following programming which is OK :

Code:
 PROGRAM test
  TYPE t
    INTEGER :: tab(:)
  END TYPE
  TYPE(t) :: o(3)
  DO i=1,3
    o(i)%tab=i
  ENDDO
  write(*,*) o%tab(4)
END PROGRAM

Indeed, o%tab(4) is a vector of 3 values, all successive elements being the same distance.

For the same reason, the next example is forbidden again :

Code:
PROGRAM test
  TYPE t
    INTEGER,ALLOCATABLE :: tab(:)
  END TYPE
  TYPE(t) :: o(3)
  DO i=1,3
    ALLOCATE(o(i)%tab(10))
    o(i)%tab=i
  ENDDO
  write(*,*) o%tab(4)
END PROGRAM

Error message :
tt.f90(10): error #7828: The part-name to the right of a part-ref with nonzero rank has the ALLOCATABLE attribute (6.1.2). [TAB]

Changing ALLOCATABLE into POINTER does not change the result : the compiler cannot warrant a constant distance between two successive elements in the "vector" o%tab(4).

 
Ok so if I find a trick to load an array of arrays - loading the components one by one (like with a loop) - it works; what is important into the code -if i have well understood- is that one must never write the espresion of array of arrays ... this has sense.
I suppose in your test program :

PROGRAM test
TYPE t
INTEGER :: tab:))
END TYPE
TYPE(t) :: o(3)
DO i=1,3
o(i)%tab=i
ENDDO
write(*,*) o%tab(4)
END PROGRAM

The third line have to be: INTEGER :: tab(10)
;with dimension specified.

Your suggestions are always very precious.
Thanks, Albi

 
Right ! Sorry for the typo ...

As you have surely noticed, the last example did not concern array of array but the restriction about array expressions in a more general manner : even a "vector" expression may be invalid if the compiler cannot insure a constant stride.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top