NetCDF

Unidata Network Common Data Form (NetCDF) is a set of libraries and machine-independent data formats that support the creation, access, and sharing of array-oriented scientific data from C, C++, FORTRAN 77, Fortran 90, and Java. For several other programming languages, interface bindings are available (e. g., Python, Octave, Perl).

Installation

The Fortran 90 version of NetCDF 4 can be installed as a package on most Unix-like operating system. On FreeBSD, run:

# pkg install science/netcdf-fortran

The NetCDF shared library is linked with -lnetcdff. Note the additional f at the end, indicating the Fortran version.

Example

The following example program in Fortran 90 fills an integer array and writes the data to the NetCDF file data.nc. The data is then read back into the array from the very same NetCDF file.

! example.f90
program main
    use :: netcdf
    implicit none
    character(len=*), parameter :: FILE_NAME = 'data.nc'    ! Export/import file.
    integer,          parameter :: NX        = 12           ! Number of columns.
    integer,          parameter :: NY        = 6            ! Number of rows.

    integer :: array(NX, NY)
    integer :: x, y

    ! Create and output sample data.
    print '(a)', 'Data to be written to NetCDF file:'
    print '(a)', repeat('-', 64)

    do y = 1, NY
        do x = 1, NX
            array(x, y) = (y - 1) * NY + (x - 1)
            write (*, '(i4)', advance='no') array(x, y)
        end do
        write (*, *)
    end do

    print '(a)', repeat('-', 64)

    ! Write data to NetCDF file (into variable `data`).
    call export_int_array(FILE_NAME, array, 'data')

    array = 0

    ! Read data back in from the same NetCDF file (from variable `data`).
    call import_int_array(FILE_NAME, array, 'data')

    ! Print read data to stdout.
    print '(/, a)', 'Data read from NetCDF file:'
    print '(a)', repeat('-', 64)

    do y = 1, NY
        do x = 1, NX
            write (*, '(i4)', advance='no') array(x, y)
        end do
        write (*, *)
    end do

    print '(a)', repeat('-', 64)
contains
    subroutine check(stat)
        integer, intent(in) :: stat

        if (stat /= nf90_noerr) then
            print '(a)', trim(nf90_strerror(stat))
            stop
        end if
    end subroutine check

    subroutine export_int_array(file_name, array, var_name)
        character(len=*), intent(in)    :: file_name
        integer,          intent(inout) :: array(:, :)
        character(len=*), intent(in)    :: var_name
        integer                         :: ncid, varid
        integer                         :: x_dimid, y_dimid

        ! Create the NetCDF file. Override file, if it already exists.
        call check(nf90_create(file_name, NF90_CLOBBER, ncid))

        ! Define the dimensions. NetCDF returns the IDs `x_dimid` and `y_dimid`.
        call check(nf90_def_dim(ncid, 'x', size(array, 1), x_dimid))
        call check(nf90_def_dim(ncid, 'y', size(array, 2), y_dimid))

        ! Define the variable type (NF90_INT: 4-byte integer).
        call check(nf90_def_var(ncid, var_name, NF90_INT, [ x_dimid, y_dimid ], varid))

        ! End define mode.
        call check(nf90_enddef(ncid))

        ! Write the data to the file.
        call check(nf90_put_var(ncid, varid, array))

        ! Close the file.
        call check(nf90_close(ncid))
    end subroutine export_int_array

    subroutine import_int_array(file_name, array, var_name)
        character(len=*), intent(in)    :: file_name
        integer,          intent(inout) :: array(:, :)
        character(len=*), intent(in)    :: var_name
        integer                         :: ncid, varid

        ! Open the NetCDF file read-only.
        call check(nf90_open(file_name, NF90_NOWRITE, ncid))

        ! Get the `varid` of the data variable, based on its name.
        call check(nf90_inq_varid(ncid, var_name, varid))

        ! Read the data.
        call check(nf90_get_var(ncid, varid, array))

        ! Close the file.
        call check(nf90_close(ncid))
    end subroutine import_int_array
end program main

Compile, link, and run the program with:

$ gfortran10 -I/usr/local/include/ -L/usr/local/lib/ -o example example.f90 -lnetcdff
$ ./example
Data to be written to NetCDF file:
----------------------------------------------------------------
   0   1   2   3   4   5   6   7   8   9  10  11
  12  13  14  15  16  17  18  19  20  21  22  23
  24  25  26  27  28  29  30  31  32  33  34  35
  36  37  38  39  40  41  42  43  44  45  46  47
  48  49  50  51  52  53  54  55  56  57  58  59
  60  61  62  63  64  65  66  67  68  69  70  71
----------------------------------------------------------------

Data read from NetCDF file:
----------------------------------------------------------------
   0   1   2   3   4   5   6   7   8   9  10  11
  12  13  14  15  16  17  18  19  20  21  22  23
  24  25  26  27  28  29  30  31  32  33  34  35
  36  37  38  39  40  41  42  43  44  45  46  47
  48  49  50  51  52  53  54  55  56  57  58  59
  60  61  62  63  64  65  66  67  68  69  70  71
----------------------------------------------------------------

References