next up previous index
Next: Annotating an HDF File Up: Working with Scientific Data Previous: Making Enquiries Against a

Dynamic Memory Allocation in Fortran

Since now we know how to find from the scientific data set itself how much space we need to reserve for the data, we no longer need to size the array data statically, as in:

integer, parameter :: number_of_data = 10
integer(kind=4), dimension(number_of_data) :: data = 0
Instead we can allocate an appropriate amount of memory for the array dynamically, after having found how much is needed.

The following program implements this change. When it runs its output looks exactly the same as before, so we won't repeat it here. But the program itself has several important new elements that call for a discussion. So here is the program in full:

program read_SDS

  use hdf
  use dffunc
  use netcdf

  implicit none

  ! constants

  character(len=7), parameter :: sd_file_name = "SDS.hdf"
  integer, parameter :: sd_set_index = 0
  integer, dimension(1), parameter :: start = (/ 0 /), stride = (/ 1 /)

  ! variables

  integer :: sd_file_id, sd_set_id, sd_read_status, sd_set_status, &
       sd_file_status, n_datasets, n_file_attributes, file_info_status, &
       rank, data_type, n_set_attributes, i, set_info_status
  integer(kind=4), dimension(:), allocatable :: data
  integer, dimension(MAXVDIMS) :: dim_sizes
  integer, dimension(1) :: edges
  character(len=MAXNCNAM) :: sd_set_name

  sd_file_id = sfstart(sd_file_name, DFACC_READ)
     write (*, *) "File ", sd_file_name, " opened"
     write (*, *) "sd_file_id        = ", sd_file_id
  file_info_status = sffinfo(sd_file_id, n_datasets, n_file_attributes)
     write (*, *) "Obtained information about the file"
     write (*, *) "file_info_status  = ", file_info_status
     write (*, *) "n_datasets        = ", n_datasets
     write (*, *) "n_file_attributes = ", n_file_attributes
  sd_set_id = sfselect(sd_file_id, sd_set_index)
     write (*, *) "First scientific data set selected"
     write (*, *) "sd_set_id         = ", sd_set_id
  set_info_status = sfginfo(sd_set_id, sd_set_name, rank, dim_sizes, &
       data_type, n_set_attributes)
     write (*, *) "Obtained information about the data set"
     write (*, *) "sd_set_name       = ", sd_set_name(:10)
     write (*, *) "rank              = ", rank
     write (*, *) "dim_sizes         = ", (/ (dim_sizes(i), i = 1, rank) /)
     write (*, *) "data_type         = ", data_type
     write (*, *) "n_set_attributes  = ", n_set_attributes
  if (rank .eq. 1) then
     allocate (data(dim_sizes(1))); data = 0; edges = dim_sizes(1)
        write (*, *) "data (before)     = ", data
     sd_read_status = sfrdata(sd_set_id, start, stride, edges, data)
        write (*, *) "sd_read_status    = ", sd_read_status
        write (*, *) "data (after)      = ", data
     write (*, *) "rank different from 1, skipping the data reading part"
  end if
  sd_set_status = sfendacc(sd_set_id)
     write (*, *) "sd_set_status     = ", sd_set_status
  sd_file_status = sfend(sd_file_id)
     write (*, *) "sd_file_status    = ", sd_file_status

end program read_SDS
The new elements in this program are as follows. First we drop a definition for a variable number_of_data altogether. It is no longer needed. The number of data is going to be returned by the call to function sfginfo in dim_sizes(1)). edges is no longer a parameter. This time it is a true variable, which can become initialised (to the value returned in dim_sizes(1)) only after function sfginfo returns. But the greatest novelty is in the definition of data:  
integer(kind=4), dimension(:), allocatable :: data
Instead of seeing dimension(10) we now have dimension(:) here. Furthermore amongst the attributes of the array we have the word allocatable. This is much like a pointer in C, but we nevertheless tell Fortran that the object it is going to allocate dynamically is to be treated like an array and that a full set of array semantics must be applicable to it. Fortran compiler can now make various optimisations (if it wants) when it handles that array. ANSI Fortran supports both allocatable arrays and pointers. But allocatable arrays are supposed to be more efficient than pointers.

When the program runs things work as before until we hit the if statement. If the rank of the scientific data set stored on the file is 1 then we allocate space  for reading it in:

allocate (data(dim_sizes(1)))
Otherwise we skip the whole reading part and proceed right into the fragment of the code that disconnects the scientific data set and closes the file.

Once the array data has been allocated it is initialised to zero, using the special array initialisation syntax, which I pointed to you already before:

data = 0
Then the content of the scientific data set is read onto data, and there is nothing new about that, the data is printed on standard output, and$\ldots$, since it is no longer needed, the space is deallocated: 

next up previous index
Next: Annotating an HDF File Up: Working with Scientific Data Previous: Making Enquiries Against a
Zdzislaw Meglicki