Writing Output from FORTRAN Code

All data loaded into IVE must be in netCDF (network Common Data Form) format. Sample netCDF files for use with the default IVE transforms are described on the help page IVE Data Format. The following will describe two ways of generating the netCDF file described in the third example of "IVE Data Format."

Creating Output Using CDL files and `ncgen'

A CDL (network Common data form Description Language) file is an ASCII descripton of the binary data in a netCDF file that is designed to be easily read by humans. CDL files can be generated from netCDF files via the `ncdump', command. For example,

ncdump -c sample.nc

generates the file `sample.cdl' that contains the file name, the dimensions, the specification of the variables, any attributes and the data for any "coordinate variables." A CDL file of this type is shown below. (This is the same CDL file shown in the third example of IVE Data Format.) Note that the double slash indicates a comment in the CDL file.

netcdf implicit_grid{

dimensions:
lon = 101;
lat = 101;
level = 5;
time = UNLIMITED ; //(7 currently)

variables:

float A(time,level,lat,lon);
A:units = "meters/second";

float level(level);

level:units = "millibars";

float time(time);

time:units = "hours";

//global attributes:

:x_min = -180.f;
:x_max = 180.f;
:x_units = "degrees_east";
:x_label = "longitude";

:y_min = -90.f;
:y_max = 90.f;
:y_units = "degrees_north";
:y_label = "latitude";

:z_label = "level";
:t_label = "time";

data:
level = 1000, 850, 700, 500, 300 ;
time = 0, 2, 4, 6, 8, 10, 12 ;

The command `ncgen' is the inverse of `ncdump'; it converts an ASCII CDL file to a binary netCDF file. For example

ncgen -o sample.nc sample.cdl

converts the CDL file `sample.cdl' to the netCDF file `sample.nc'. The easiest way to create a netCDF file is to (1) write all the header data (the name, dimensions, variable and attribute specifications, and the values of any coordinate variables) to a CDL file, (2) convert the CDL file to a netCDF file using ncgen, and (3) continue writing the main data arrays to this netCDF file.

The following example shows how this approach can be implemented in a FORTRAN program. The data set created is the one associated with the preceding CDL file. Everything except the data for the variables `A' and `time' are written to the original CDL file. This file is then converted to a netCDF file by `ncgen' and opened for further data input with `ncopn'. The data for `A' and `time' are subsequently written directly to the open netCDF file in a manner similar to that which would occur if output was periodically generated during a numerical simulation. The data written to `A' in this example are, however, completely artifical. Note how the use of the "UNLIMITED" option for the time dimension allows data to be written at an arbitrary number of output times.

     program netCDF_example1
c
c     -----------------------------------------------------------------
c    Declare and set constants, parameters and scratch variables
c     -----------------------------------------------------------------
c
      implicit none
c
c       UNIX include statement to include standard netCDF parameter
c   names, such as NCWRITE. (path is for UW Unix machines)
c
      include '/usr/local/include/netcdf.inc'
c
c   Netcdf file declaration
c
      integer cdfid     ! ID for the netCDF file to be created
      character *(*) cdf_out    ! Name of the netCDF output file
      parameter(cdf_out='example.nc')
c
c       Declare and set integer values for the netCDF dimensions 
c
      integer 
     &    nlon          ! number of points in the 1st dimension;
     &   ,nlat          ! number of points in the 2nd dimension;
     &   ,nlevel        ! number of points in the 3rd dimension;
      parameter(nlon = 101, nlat = 101, nlevel = 5)

      real
     &    level(nlevel),    ! values of the z-coordinate;
     &    A(nlon, nlat, nlevel) ! 3D data array;
      data level/1000, 850, 700, 500, 300/

      integer 
     &    start(4)      ! for indexing the netCDF data array;
     &   ,count(4)      ! for indexing the netCDF data array;
      real actual_time
      data
     &    start /1, 1, 1, 1/, count /nlon, nlat, nlevel, 1/
c      
c       NetCDF IDs for variable that written out every time step
c
      integer 
     &    idtime        ! ID for the time coordinate variable;
     &   ,idA           ! ID for main data array, `A';
c
c       Declare scratch variables
c
      integer i, j, k, time_index, ierr
      character*80 command
c
c     -----------------------------------------------------------------
c   Create the CDL file that matches the preceding example,
c       writing the result to file `my.cdl'
c     -----------------------------------------------------------------
c
      open(unit=7, name='my.cdl')
c
c       Write the netCDF file name
c
      write(7,*) 'netcdf mine{'
c
c       Write the dimensions
c
      write(7,*) 'dimensions:'
      write(7,*) 'lon=', nlon, ';'
      write(7,*) 'lat=', nlat, ';'
      write(7,*) 'level=', nlevel, ';'
      write(7,*) 'time=UNLIMITED;'
c
c       Write the variable declarations along with
c       their attributes
c
      write(7,*) 'variables:'
      write(7,*) 'float A(time,level,lat,lon);'
      write(7,*) 'A:units="meters/second";'
      write(7,*) 'float level(level);'
      write(7,*) 'level:units="millibars";'
      write(7,*) 'float time(time);'
      write(7,*) 'time:units="hours";'
c
c       Write the global attributes
c
      write(7,*) ':x_min=-180.f;'
      write(7,*) ':x_max=180.f;'
      write(7,*) ':x_units="degrees_east";'
      write(7,*) ':x_label="longitude";'
      write(7,*) ':y_min=-90.f;'
      write(7,*) ':y_max=90.f;'
      write(7,*) ':y_units="degrees_north";'
      write(7,*) ':y_label="latitude";'
      write(7,*) ':z_label="level";'
      write(7,*) ':t_label="time";'
c
c       Begin writing the data
c
      write(7,*) 'data:'
      write(7,*) 'level='
      do i = 1, nlevel-1
         write(7, *) level(i), ','
      enddo
      write(7, *) level(nlevel), ';'
      write(7,*) '}'
c
      close (unit=7)
c
c     -----------------------------------------------------------------
c   Convert the CDL file `my.cdl' to a netCDF file using ncgen
c     -----------------------------------------------------------------
c
      write(command, *) 'ncgen -o ', cdf_out, ' my.cdl'
      call system(command)
c
c     -----------------------------------------------------------------
c       Write the remaining data, which consists of the values of 
c       the variables `A' and `time' at seven different times
c     -----------------------------------------------------------------
c
c       Open the new netcdf file 
c
      cdfid=ncopn(cdf_out, NCWRITE, ierr)
c
c     Get the variable ID's for A and time
c
      idtime=ncvid(cdfid, 'time'  , ierr)
      idA=ncvid(cdfid, 'A'  , ierr)
c
c     -----------------------------------------------------------------
c       Generate dummy data for 'time' and `A'. Write out this
c       data to the netCDF file each time step.
c     -----------------------------------------------------------------
c
c       This loop is executed for each time.
c
      do time_index = 1, 7

         actual_time = (time_index-1)*2.
         call ncvpt1(cdfid, idtime, time_index, actual_time, ierr)
c
c       Compute the variable A
c
         do k = 1, nlevel
            do j = 1, nlat
               do i = 1, nlon
                  A(i, j, k) = float(time_index*((i+k))/float(j))
               enddo
            enddo
         enddo
         start(4) = time_index
c
c          Write data tp `A'
c
         call ncvpt(cdfid, idA , start, count, A , ierr)
      enddo
c
c     -----------------------------------------------------------------
c       Close the netCDF file
c     -----------------------------------------------------------------
c
      call ncclos(cdfid, ierr)
c
      stop
      end


back to index