Hi John,
I think that using f90 generic functions as wrappers to the type specific
netCDF routines addresses the problem you have presented. Here is an
example of using a generic function for writing a 1D array of real data:
module mod1
implicit none
save
private
public :: writenc_var_real
interface writenc_var_real
module procedure writenc_var_sp, writenc_var_dp
end interface
contains
integer function writenc_var_sp( ncid, varid, vals )
! Write single precision data to a netCDF file.
implicit none
include 'netcdf.inc'
integer, intent(in) :: ncid, varid
real, intent(in), dimension(:) :: vals
writenc_var_sp = NF_PUT_VAR_REAL( ncid, varid, vals )
end function writenc_var_sp
integer function writenc_var_dp( ncid, varid, vals )
! Write double precision data to a netCDF file.
implicit none
include 'netcdf.inc'
integer, intent(in) :: ncid, varid
double precision, intent(in), dimension(:) :: vals
writenc_var_dp = NF_PUT_VAR_DOUBLE( ncid, varid, vals )
end function writenc_var_dp
end module mod1
program main
! Write single or double precision data to a netCDF file.
use mod1
implicit none
include 'netcdf.inc'
integer, parameter :: len = 4
real :: arr(len) = (/ 1., 2., 3., 4. /)
integer :: ret, ncid, ndims = 1, dimid, varid
! Create file.
ret = NF_CREATE( 'zzz.nc', NF_CLOBBER, ncid )
! Define dimensions.
ret = NF_DEF_DIM( ncid, 'len', len, dimid )
! Define variables.
ret = NF_DEF_VAR( ncid, 'arr', NF_FLOAT, ndims, dimid, varid )
! End definition mode.
ret = NF_ENDDEF( ncid )
! Write the data.
ret = writenc_var_real( ncid, varid, arr )
! Close file.
ret = NF_CLOSE( ncid )
end program main
Notes:
1. The module should be compiled separately, and it can't be compiled with
a -r8 flag because then the specific funtions have identical interfaces
and the generic function is ambiguous.
2. The main program can be compiled with or without a -r8 flag and the
generic function writenc_var_real calls the correct netCDF function.
Alternatively the main program can declare different real types using
real*4, real*8, or parameterized real types as in f90. I did manage to
break the code on a Cray J90 using a real(selected_real_kind(p=6))
declaration of arr. This is because the J90 returned a kind value of 4
even though there are no 4-byte floating point representations on that
machine.
3. Since generic functions identify the correct specific functions based on
both type and rank of array arguments, additional specific functions
need to be added to writenc_var_real to generalize this example to
arrays of dimension other than one.
4. This should work on Crays in general (with the specific exception
described in note 2.). On the older PVP type machines using Cray
floating point the specific function for writing double precision data
(16-byte) is of course broken, but under normal circumstances that
function would not be called. The newer Crays use IEEE floating point
and things should work the same there as on non-Cray platforms.
Regards,
Brian
Brian Eaton | email: eaton@xxxxxxxx
Climate Modeling Section |
National Center for Atmospheric Research |
P.O. Box 3000, Boulder, CO 80307 |