[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: writing doubles to netcdf



>To: address@hidden
>From: Ben Foster <address@hidden>
>Subject: Re: 20020611: writing doubles to netcdf
>Organization: HAO

Ben,

> Russ: Thanks for the hints. It works now when I compile
> with -r4 (lib r4i4), define the var as NF_DOUBLE, and call 
> nf_put_var_real. Presumably, netcdf is promoting my 4-byte 
> real. However, I guess I could be loosing precision reading
> 8-byte floats from the cray file into 4-byte reals, so
> maybe I should compile with -r8 and call nf_put_var_double.

OK, but if you compile with -r8 that says Fortran reals are 8-bytes,
so in that case you should be calling nf_put_var_real(), linking with
a netCDF library that was also built with -r8.  The TYPE in the
function name nf_put_var_TYPE refers to the native (internal) type of
the array you are writing, not to the external netCDF type of the
variable you are writing into.

> Anyway, I did put together a small test program, see attached.
> I am running this on dataproc with the r4i4 lib, so presumably
> netcdf was compiled with -r4. In the test, I don't understand
> why compiling with -r4 and writing nf_put_var_double does not
> work (whether the var was defined NF_FLOAT or NF_DOUBLE). I guess
> its not kosher to pass a 4-byte real in the put double call.

The problem is with the call

      istat = nf_put_var_double(ncid,id_sigtn,sigtn)  ! wrong (why?)

which says you are providing an array of doubles, but sigtn is an
array of reals.  The (internal) type of the data you are writing must
match the name of the function you array using to write it.  No matter
whether you compile with -r4 and use a library compiled with -r4, or
compile with -r8 and use a library compiled with -r8, when you declare

      real :: sigtn(nsigt)

then sigtn is real and you must use nf_put_var_real() to write it.
The netCDF library will convert the internal type to whatever the
external type of the variable is before writing it on disk, but the
nf_put_var_TYPE function can't figure out the type of the array it was
passed, it can only assume that you have provided the right type.

The fact that

     istat = nf_put_var_double(ncid,id_sigtn,sigtn)  ! works

works when compiled with -r8 even though sigtn is declared real is
because both reals and doubles are 8-bytes under "-r8" (you would
have to include "-d16" to specify 16-byte doubles).  So in this case
it doesn't matter that sigtn is the wrong type, since booth reals and
doubles are the same size.  So this works but isn't right.

--Russ

!
      program nctest
!
! From Makefile for SGI:
! FC = f90
! #FFLAGS= -I/usr/local/include -r4 -64 -mips4  # 4-byte reals
! FFLAGS= -I/usr/local/include -r8 -64 -mips4   # 8-byte reals
! LIBS= -L /usr/local/lib64/r4i4 -lnetcdf
! LDFLAGS = -64
!
! Create netcdf dataset for testing on SGI O2K dataproc.
!
      implicit none
#include "netcdf.inc"
      integer,parameter :: nsigt=6
      real :: sigtn(nsigt)
      real(kind=8) :: sigtn8(nsigt)
      integer :: ncid,istat,id_nsigt,id_sigtn,ids1(1)
      character(len=16) :: filename = 'nctest.nc'
!
      sigtn = (/180.,200.,220.,230.,240.,250./)
      sigtn8 = sigtn ! put 4-byte values in 8-byte real
!
! Create dataset:
      istat = nf_create(filename,NF_CLOBBER,ncid)
!
! Define nsigt dimension:
      istat = nf_def_dim(ncid,"nsigt",nsigt,id_nsigt)
!
! Define sigtn variable (1 dimensional vector):
! Use NF_DOUBLE to write 8-byte reals, or NF_FLOAT to write 4-byte reals
!
      ids1(1) = id_nsigt
      istat = nf_def_var(ncid,"sigtn",NF_DOUBLE,1,ids1,id_sigtn)
!     istat = nf_def_var(ncid,"sigtn",NF_FLOAT,1,ids1,id_sigtn)
!
! Exit define mode:
      istat = nf_enddef(ncid)
!
! Write vector to the file:
!
! When compiled with -r4 and lib r4i4:
      istat = nf_put_var_double(ncid,id_sigtn,sigtn)  ! wrong (why?)
!     istat = nf_put_var_double(ncid,id_sigtn,sigtn8) ! works (8-byte reals)
!     istat = nf_put_var_real(ncid,id_sigtn,sigtn)    ! works (4-byte reals 
promoted)
!
! When compiled with -r8 and lib r4i4:
!     istat = nf_put_var_double(ncid,id_sigtn,sigtn)  ! works
!     istat = nf_put_var_double(ncid,id_sigtn,sigtn8) ! works, but unecessary
!     istat = nf_put_var_real(ncid,id_sigtn,sigtn)    ! wrong (does not demote?)
!
! Close the new netcdf file:
      istat = nf_close(ncid)
      write(6,"('Wrote file ',a)") filename
      end program nctest

--Steam_of_Minnows_287_000
Content-Type: TEXT/x-sun-Makefile; name=Makefile; charset=us-ascii; 
x-unix-mode=0664
Content-Description: Makefile
Content-MD5: S2XaaV0IZO9ZTsKteRhodw==

#
EXEC=nctest
FC = f90
FFLAGS= -I/usr/local/include -r4 -64 -mips4
#FFLAGS= -I/usr/local/include -r8 -64 -mips4
LIBS= -L /usr/local/lib64/r4i4 -lnetcdf
LDFLAGS = -64
#
OBJS = nctest.o
.SUFFIXES: .F
#
$(EXEC):        $(OBJS)
        $(FC) -o $@ $(OBJS) $(LDFLAGS) $(LIBS)
.f.o:
        $(FC) -c $(FFLAGS) $<
.F.o:
        $(FC) -c $(FFLAGS) $<

--Steam_of_Minnows_287_000--