|
|
 |
 |
 |
 |
Fortran Programming Language
|
 |
 |
 |
 |
 |
 |
 |
 |
Allocatable array of allocatable defined types?
I want to do something that I rather suspect I can't do in Fortran; I'm seeking contradiction or confirmation. I would like to have a defined data type some of whose constituents are allocatable arrays. The space allocated for a given constituent would be the same of all instances of the given type. I would then like to have an allocatable array of these data types. Example: Power generating unit data are conveniently dealt with in unit-specific "records" which are then treated as elements of an array. One constituent of each unit's record is an array of unit- specific rates of removal of various types of emissions, and the dimension of this array is equal to the number of types of emission considered in the given study: so2, co2, nox, hg, and so forth. From study to study, I have variable numbers of generating units and variable numbers of emissions types that I wish to consider. I would like not to have to recompile to deal with this, but to rely instead on dynamic allocation. I'm not sure I can do that AND preserve the convenience of using defined data types, however. One quite inelegant solution has occured to me, which is to define the constituents of the defined data types with >fixed< size, large enough to contain the maximum number of elements that I would want to use. Ugly and wasteful, but perhaps necessary?
"Mark Morss" <mfmo @aep.com> wrote in message news:1177940777.206704.63760@y5g2000hsa.googlegroups.com... >I want to do something that I rather suspect I can't do in Fortran; > I'm seeking contradiction or confirmation. > I would like to have a defined data type some of whose constituents > are allocatable arrays. The space allocated for a given constituent > would be the same of all instances of the given type. I would then > like to have an allocatable array of these data types.
Is this what you mean: type alloc real, dimension(:), allocatable :: a1 real, dimension(:), allocatable :: a2 end type alloc type(alloc), dimension(:), allocatable :: work integer, parameter :: ll = 3 allocate(work(2)) do i = 1, 2 allocate(work(i)%a1(ll), work(i)%a2(ll)) end do ? This depends on your compiler implementing the relevant TR, which almost all now do. Regards, Mike Metcalf
On Apr 30, 9:46 am, Mark Morss <mfmo@aep.com> wrote: > I want to do something that I rather suspect I can't do in Fortran; > I'm seeking contradiction or confirmation. > I would like to have a defined data type some of whose constituents > are allocatable arrays. The space allocated for a given constituent > would be the same of all instances of the given type. I would then > like to have an allocatable array of these data types.
I don't see the problem. Given an array type foo real, allocatable :: y(:) end type foo type(foo), allocatable :: x(:) one could write a subroutine that allocates x and which allocates each component y to have some size ny. Components of derived types can be declared PRIVATE, so one could ensure that the ONLY way the components y get allocated is through the subroutine. You could define a derived type type foo_vec type(foo), allocatable :: x(:) integer :: ny end type foo_vec where the ny is used to set the size of all the y components of the x's. <snip> > One quite inelegant solution has occured to me, which is to define the > constituents of the defined data types with >fixed< size, large enough > to contain the maximum number of elements that I would want to use. > Ugly and wasteful, but perhaps necessary?
You could make x in foo_vec above have a fixed size with little cost, because unless the components y of the elements of x are ALLOCATED, little or no memory will be used.
On Apr 30, 10:21 am, "Michael Metcalf" <michaelmetc@compuserve.com> wrote:
> "Mark Morss" <mfmo @aep.com> wrote in message > news:1177940777.206704.63760@y5g2000hsa.googlegroups.com...>I want to do something that I rather suspect I can't do in Fortran; > > I'm seeking contradiction or confirmation. > > I would like to have a defined data type some of whose constituents > > are allocatable arrays. The space allocated for a given constituent > > would be the same of all instances of the given type. I would then > > like to have an allocatable array of these data types. > Is this what you mean: > type alloc > real, dimension(:), allocatable :: a1 > real, dimension(:), allocatable :: a2 > end type alloc > type(alloc), dimension(:), allocatable :: work > integer, parameter :: ll = 3 > allocate(work(2)) > do i = 1, 2 > allocate(work(i)%a1(ll), work(i)%a2(ll)) > end do > ? > This depends on your compiler implementing the relevant TR, which almost all > now do. > Regards, > Mike Metcalf
Thanks! That appears to work using IBM's xlf95 compiler on AIX 5.2. I am surprised that this works, but I won't complain about it. It surprises me that you can allocate an array "before" the size of its elements is known. Apparently the compiler looks ahead and figures this out?! Thanks again.
On Apr 30, 10:30 am, Beliavsky <beliav@aol.com> wrote:
> On Apr 30, 9:46 am, Mark Morss <mfmo @aep.com> wrote: > > I want to do something that I rather suspect I can't do in Fortran; > > I'm seeking contradiction or confirmation. > > I would like to have a defined data type some of whose constituents > > are allocatable arrays. The space allocated for a given constituent > > would be the same of all instances of the given type. I would then > > like to have an allocatable array of these data types. > I don't see the problem. Given an array > type foo > real, allocatable :: y(:) > end type foo > type(foo), allocatable :: x(:) > one could write a subroutine that allocates x and which allocates each > component y to have some size ny. > Components of derived types can be declared PRIVATE, so one could > ensure that the ONLY way the components y get allocated is through the > subroutine. > You could define a derived type > type foo_vec > type(foo), allocatable :: x(:) > integer :: ny > end type foo_vec > where the ny is used to set the size of all the y components of the > x's. > <snip> > > One quite inelegant solution has occured to me, which is to define the > > constituents of the defined data types with >fixed< size, large enough > > to contain the maximum number of elements that I would want to use. > > Ugly and wasteful, but perhaps necessary? > You could make x in foo_vec above have a fixed size with little cost, > because unless the components y of the elements of x are ALLOCATED, > little or no memory will be used.
Thanks for those observations. Apparently my confusion is my belief that if an array is of defined types, each instance of the type found in the array must have the same size. Yet the following code works without error when compiled with xlf95: PROGRAM test IMPLICIT NONE TYPE foo INTEGER :: key INTEGER,ALLOCATABLE,DIMENSION(:) :: a END TYPE foo TYPE(foo),ALLOCATABLE,DIMENSION(:) :: fooarray INTEGER i,j ALLOCATE (fooarray(3)) DO i=1,3 ALLOCATE(fooarray(i)%a(i)) ! array of variable size elements END DO DO i=1,3 fooarray(i)%key=i DO j=1,i fooarray(i)%a(j)=i-j END DO WRITE(*,*) fooarray(i)%key,fooarray(i)%a(1:i) END DO END PROGRAM test Why this code works is a mystery to me, since I had thought that Fortran arrays were highly regular, by which I mean that the space in a row was a fixed constant for all rows.
On Apr 30, 10:54 am, Mark Morss <mfmo@aep.com> wrote:
> On Apr 30, 10:30 am, Beliavsky <beliav @aol.com> wrote: > > On Apr 30, 9:46 am, Mark Morss <mfmo @aep.com> wrote: > > > I want to do something that I rather suspect I can't do in Fortran; > > > I'm seeking contradiction or confirmation. > > > I would like to have a defined data type some of whose constituents > > > are allocatable arrays. The space allocated for a given constituent > > > would be the same of all instances of the given type. I would then > > > like to have an allocatable array of these data types. > > I don't see the problem. Given an array > > type foo > > real, allocatable :: y(:) > > end type foo > > type(foo), allocatable :: x(:) > > one could write a subroutine that allocates x and which allocates each > > component y to have some size ny. > > Components of derived types can be declared PRIVATE, so one could > > ensure that the ONLY way the components y get allocated is through the > > subroutine. > > You could define a derived type > > type foo_vec > > type(foo), allocatable :: x(:) > > integer :: ny > > end type foo_vec > > where the ny is used to set the size of all the y components of the > > x's. > > <snip> > > > One quite inelegant solution has occured to me, which is to define the > > > constituents of the defined data types with >fixed< size, large enough > > > to contain the maximum number of elements that I would want to use. > > > Ugly and wasteful, but perhaps necessary? > > You could make x in foo_vec above have a fixed size with little cost, > > because unless the components y of the elements of x are ALLOCATED, > > little or no memory will be used. > Thanks for those observations. Apparently my confusion is my belief > that if an array is of defined types, each instance of the type found > in the array must have the same size. Yet the following code works > without error when compiled with xlf95: > PROGRAM test > IMPLICIT NONE > TYPE foo > INTEGER :: key > INTEGER,ALLOCATABLE,DIMENSION(:) :: a > END TYPE foo > TYPE(foo),ALLOCATABLE,DIMENSION(:) :: fooarray > INTEGER i,j > ALLOCATE (fooarray(3)) > DO i=1,3 > ALLOCATE(fooarray(i)%a(i)) ! array of variable size elements > END DO > DO i=1,3 > fooarray(i)%key=i > DO j=1,i > fooarray(i)%a(j)=i-j > END DO > WRITE(*,*) fooarray(i)%key,fooarray(i)%a(1:i) > END DO > END PROGRAM test > Why this code works is a mystery to me, since I had thought that > Fortran arrays were highly regular, by which I mean that the space in > a row was a fixed constant for all rows.
That is true for a 2-D array, but an array of derived types, each of which has an allocatable component, is not the same thing.
Mark Morss <mfmo @aep.com> wrote: > On Apr 30, 10:21 am, "Michael Metcalf" <michaelmetc @compuserve.com> > wrote: > > type alloc > > real, dimension(:), allocatable :: a1 > > real, dimension(:), allocatable :: a2 > > end type alloc > > type(alloc), dimension(:), allocatable :: work > > integer, parameter :: ll = 3 > > allocate(work(2)) > > do i = 1, 2 > > allocate(work(i)%a1(ll), work(i)%a2(ll)) > > end do ... > It surprises me that you can allocate an array "before" the size of > its elements is known. Apparently the compiler looks ahead and > figures this out?!
No. It isn't a matter of looking ahead, which wouldn't be possible except in the most trivial cases. When the derived type array is allocated, the elements are initially all created as unallocated. There is no data space for them at all until they are, in turn allocated. I suspect you are not seeing that the implementation of an allocatable component will look a lot like a pointer in that the actual data space for the component will be elsewhere in memory rather than embedded in with the rest of the components. Somethingh that looks much like a pointer is all that is in the memory space with with the rest of the components. The low-level use of constructs like those of pointers is "hidden" from you. The compiler takes care of the details in a way that works out much better than if you have to directly use pointers yourself (as does much code from days before the TR was widely supported, which has only been relatively recently). -- Richard Maine | Good judgement comes from experience; email: last name at domain . net | experience comes from bad judgement. domain: summertriangle | -- Mark Twain
On Apr 30, 11:21 am, nos@see.signature (Richard Maine) wrote:
> Mark Morss <mfmo @aep.com> wrote: > > On Apr 30, 10:21 am, "Michael Metcalf" <michaelmetc @compuserve.com> > > wrote: > > > type alloc > > > real, dimension(:), allocatable :: a1 > > > real, dimension(:), allocatable :: a2 > > > end type alloc > > > type(alloc), dimension(:), allocatable :: work > > > integer, parameter :: ll = 3 > > > allocate(work(2)) > > > do i = 1, 2 > > > allocate(work(i)%a1(ll), work(i)%a2(ll)) > > > end do > ... > > It surprises me that you can allocate an array "before" the size of > > its elements is known. Apparently the compiler looks ahead and > > figures this out?! > No. It isn't a matter of looking ahead, which wouldn't be possible > except in the most trivial cases. When the derived type array is > allocated, the elements are initially all created as unallocated. There > is no data space for them at all until they are, in turn allocated. > I suspect you are not seeing that the implementation of an allocatable > component will look a lot like a pointer in that the actual data space > for the component will be elsewhere in memory rather than embedded in > with the rest of the components. Somethingh that looks much like a > pointer is all that is in the memory space with with the rest of the > components. > The low-level use of constructs like those of pointers is "hidden" from > you. The compiler takes care of the details in a way that works out much > better than if you have to directly use pointers yourself (as does much > code from days before the TR was widely supported, which has only been > relatively recently). > -- > Richard Maine | Good judgement comes from experience; > email: last name at domain . net | experience comes from bad judgement. > domain: summertriangle | -- Mark Twain
That's very useful to know, thank you.
Mark Morss wrote: > On Apr 30, 11:21 am, nos @see.signature (Richard Maine) wrote: >> Mark Morss <mfmo @aep.com> wrote: >>> On Apr 30, 10:21 am, "Michael Metcalf" <michaelmetc @compuserve.com> >>> wrote: >>>> type alloc >>>> real, dimension(:), allocatable :: a1 >>>> real, dimension(:), allocatable :: a2 >>>> end type alloc >>>> type(alloc), dimension(:), allocatable :: work >>>> integer, parameter :: ll = 3 >>>> allocate(work(2)) >>>> do i = 1, 2 >>>> allocate(work(i)%a1(ll), work(i)%a2(ll)) >>>> end do >> ... >>> It surprises me that you can allocate an array "before" the size of >>> its elements is known. Apparently the compiler looks ahead and >>> figures this out?! >> No. It isn't a matter of looking ahead, which wouldn't be possible >> except in the most trivial cases. When the derived type array is >> allocated, the elements are initially all created as unallocated. There >> is no data space for them at all until they are, in turn allocated. >> I suspect you are not seeing that the implementation of an allocatable >> component will look a lot like a pointer in that the actual data space >> for the component will be elsewhere in memory rather than embedded in >> with the rest of the components. Somethingh that looks much like a >> pointer is all that is in the memory space with with the rest of the >> components. >> The low-level use of constructs like those of pointers is "hidden" from >> you. The compiler takes care of the details in a way that works out much >> better than if you have to directly use pointers yourself (as does much >> code from days before the TR was widely supported, which has only been >> relatively recently). >> -- >> Richard Maine | Good judgement comes from experience; >> email: last name at domain . net | experience comes from bad judgement. >> domain: summertriangle | -- Mark Twain > That's very useful to know, thank you.
Hello, Just an anecdotal point: I still use pointers for the derived type components (I can't rely on the TR support) and using allocatables is much much much more convenient and, most importantly, safer. cheers, paulv -- Paul van Delst Ride lots. CIMSS @ NOAA/NCEP/EMC Eddy Merckx Ph: (301)763-8000 x7748 Fax:(301)763-8545
|
 |
 |
 |
 |
|