program caller C***A simple program to call getcdfts. Its purpose is to show how to C***use the subroutine getcdfts to read time series from a netCDF current C***meter record made by CMDAC. In a real application one would then use C***the series in a calculation. character filename*72 real*4 x4(12000,6) ! Assumes your series length .le. 12000 real*8 x8(12000,2) integer n4, n8, lthts filename = 'testfile.nc' ! Put the name of your CM record here C***Bring the time series into the x4 and/or x8 arrays. Date and time C***of day are real*8 in the current records; all other variables are C***single precision. getcdfts will read each type of variable into the C***proper array. call getcdfts(filename, 12000, x4, x8, n4, n8, lthts) C***Just to demonstrate that the procedure worked, show the single precision C***reals (floats in netCDF teminology) that the user requested (if any). do j = 1, n4 write (6, 10) j, (x4(i,j), i = 1,5) 10 format (/ 'The first 5 values of real*4 series', i2, ' are ' x / 5x, 5f10.3) write (6, 20) j, (x4(i,j), i = lthts-4,lthts) 20 format ('The last 5 values of real*4 series', i2, ' are ' x / 5x, 5f10.3) end do C***Show the double precision reals, if any (doubles in netCDF terminology). do j = 1, n8 write (6, 30) j, (x8(i,j), i = 1,5) 30 format (/ 'The first 5 values of real*8 series', i2, ' are ' x / 5x, 5f12.1) write (6, 40) j, (x8(i,j), i = lthts-4,lthts) 40 format ('The last 5 values of real*8 series', i2, ' are ' x / 5x, 5f12.1) end do stop end C------------------------------------------------------------------------------ subroutine getcdfts (filename, maxlth, x4, x8, n4, n8, tsize) C****************************************************************************** C Opens a current meter record that has CMDAC's netCDF format. Describes C the time series and gives the user an opportunity to request one or more C of them. Utilizes a header file (netcdf.inc) and a library (libnetcdf.a) C from UCAR's netCDF package - you can't build the application without them. C C Time series in the current records are either of type real*4 or real*8. C Date and time of day are real*8; all other series are real*4. real*4 C variables are passed back to the calling routine in the array x4. real*8 C variables are passed back in x8. In your calling program YOU MUST MAKE C x4 AND x8 2-DIMENSIONAL ARRAYS OF THE FORM X(L1,L2) where L1 is the length C of the longest time series you expect to read and L2 is the number of time C series you intend to read into the array. The first real*4 time series C you request will show up in x4(*,1) in your calling program; the 2nd will C show up in x4(*,2); and so on. Similarly for x8. C C This program can be run from the UNIX or Linux prompt, or in a DOS window. C It shows the user some information about the netCDF current record, and C asks whether he wants to read any of the time series and pass them to the C calling routine. C C Inputs to getcdfts: C C filename character; name of the netCDF current record to be read C maxlth integer; length of the longest time series you expect to C read; also the first dimension of x4 and x8 in the C calling program C C Outputs from getcdfts: C C x4 real*4; array of size (maxlth,*) to receive time series C x8 real*8; array of size (maxlth,*) to receive time series C n4 integer; the number of real*4 time series you requested C n8 integer; the number of real*8 time series you requested C tsize integer; the length of the time dimension in the netCDF C file C C When compiling getcdfts you must include the header file netcdf.inc, and C the result must be linked with libnetcdf.a, both of which are produced by C building UCAR's netCDF package. getcdfts has been tested in a UNIX C environment with Version 3.4 of the UCAR package. C****************************************************************************** include '../include/netcdf.inc' ! or wherever netcdf.inc is character filename*(*), atname*24, atbfr*48 real*4 x4(maxlth,*) real*8 x8(maxlth,*), atval integer n4, n8, maxlth, atbfrlth integer i, ncid, ndims, nvars, natts, recdim, rcode, tid, x tsize, vartype, nvdims, vdims, nvatts, attype, atlth character dimname*72, varname*16, units*16, longname*32, x type*6(2), rsp data type /'real*4', 'real*8'/ atbfrlth /48/ n4 = 0 n8 = 0 C***We don't want error messages and don't want errors to be fatal. C***Use "call ncpopt(NCVERBOS)" if you want to see error messages. call ncpopt(0) C***Open the input file. ncid = ncopn(filename, NCNOWRITE, rcode) C***Extract and list the file's global attributes, which are 12 in C***number. All have character values except the null or missing C***value (-999.9) which is real*8. write (6, 10) 10 format (/"This file's global attributes are"/) do i = 1, 12 call ncanam(ncid, NCGLOBAL, i, atname, rcode) call ncainq(ncid, NCGLOBAL, atname, attype, atlth, rcode) if (attype .eq. NCCHAR) then ! All except null_value call ncagtc(ncid, NCGLOBAL, atname, atbfr, atbfrlth, rcode) write (6, 20) atname(1:20), atbfr 20 format (3x, a20, a48) else if (attype .eq. NCDOUBLE) then ! null_value call ncagt(ncid, NCGLOBAL, atname, atval, rcode) write (6, 30) atname(1:20), atval 30 format (3x, a20, f7.2) end if end do C***The following 3 calls return several parameters, but all we need from C***them is the number of time series in the file (nvars) and the length C***of the time dimension (tsize). call ncinq(ncid, ndims, nvars, natts, recdim, rcode) tid = ncdid(ncid, 'time', rcode) call ncdinq(ncid, tid, dimname, tsize, rcode) C***The main loop begins here. On each cycle one variable in the file C***is described and the user has an opportunity to select it for output C***to the calling routine. do i = 1, nvars C***First, get some information about the ith variable, and show it to C***the user. call ncvinq(ncid, i, varname, vartype, nvdims, vdims, nvatts, x rcode) write (6, 50) i, varname, type(vartype - 4) 50 format (/'Variable', i2, ' is ', a16 / ' Its type is ', a6) call ncainq(ncid, i, 'long_name', attype, atlth, rcode) if (rcode .eq. 0) then longname = '' call ncagtc(ncid, i, 'long_name', longname, atlth, rcode) write (6, 60) longname 60 format (' Its long name is ', a32) end if units = '' call ncagtc(ncid, i, 'units', units, atlth, rcode) write (6, 70) units 70 format (' Its units are ', a16) C***Ask the user whether he wants to read the ith variable and pass it C***to the calling program. Note that in a current meter record all C***variables are either Type 5 (real*4) or Type 6 (real*8). write (6, 80) 80 format ('Read this variable? (y/n) ', $) read (5, '(a1)') rsp if (rsp .eq. 'y' .or. rsp .eq. 'Y') then if (vartype .eq. 5) then ! Type 5 is real*4 n4 = n4 + 1 call ncvgt(ncid, i, 1, tsize, x4(1,n4), rcode) else n8 = n8 + 1 ! Anything else is real*8 call ncvgt(ncid, i, 1, tsize, x8(1,n8), rcode) end if end if end do return end