program calldemo 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. C***The program is dimensioned for time series of up to 70,000 values C***and for a simultaneous read of 7 real*4 time series and 3 integer C***time series. This will handle any record on the CMDAC CD. character filename*11, rname*16(7), iname*16(3), frmt*6 real*4 r4(70000,7), rsp integer i4(70000,3) integer nreals, nints, maxlth, tslth filename = 'rcm01000.nc' ! Put the name of your CM record here maxlth = 70000 ! You supply this C***Bring the time series into the r4 and/or i4 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, maxlth, r4, i4, nreals, nints, tslth, x rname, iname) C***Just to demonstrate that the procedure worked, show a portion of C***the reals (floats in netCDF teminology) that the user requested C***(if any). do j = 1, nreals if (trim(rname(j)) .eq. 'woce_time') then frmt = '5f12.2' else frmt = '5f10.3' end if write (6, 10) trim(rname(j)), (r4(i,j), i = 1,5) 10 format (/ 'The first 5 values of real*4 series ', a, ' are ' x / 5x, 5f12.3) write (6, 20) trim(rname(j)), (r4(i,j), i = tslth - 4,tslth) 20 format ('The last 5 values of real*4 series ', a, ' are ' x / 5x, 5f12.3) end do C***Show a portion of each of the requested integer series, if any. do j = 1, nints write (6, 30) trim(iname(j)), (i4(i,j), i = 1,5) 30 format (/ 'The first 5 values of integer series ', a, ' are ' x / 5x, 5i12) write (6, 40) trim(iname(j)), (i4(i,j), i = tslth - 4,tslth) 40 format ('The last 5 values of integer series ', a, ' are ' x / 5x, 5i12) end do write (6, 50) 50 format (/'Press any key to teminate', $) read (5, '(a1)') rsp stop end C------------------------------------------------------------------------------ subroutine getcdfts (filename, maxlth, r4, i4, nreals, x nints, tsize, rname, iname) C****************************************************************************** C This is the Windows version of getcdfts. It has been tested with Compaq C Visual Fortran and Version 3.5.0 if the UCAR netCDF package. See the note C below for UNIX compatibility. 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), a library (netcdf.lib), and C a DLL (netcdf.dll) from UCAR's netCDF package - you can't build or run the C application without them. C C Time series in the current records are either of type real*4 or integer. C Time and woce_date are integer; all other series are real*4. real*4 C variables are passed back to the calling routine in the array r4(). integer C variables are passed back in i4(). In your calling program YOU MUST MAKE C r4() AND i4() 2-DIMENSIONAL ARRAYS OF THE FORM X(L1,L2) where L1 is the C length of the longest time series you expect to read and L2 is the number C of time series you intend to read into the array. The first real*4 time C series you request will show up in r4(*,1) in your calling program; the 2nd C will be read into in r4(*,2); and so on. Similarly for i4. C C This program can be run from the DOS prompt. It shows the user some C information about the netCDF current record, and asks whether he wants to C read any of the time series and pass them to the 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 r4 and i4 in the C calling program C C Outputs from getcdfts: C C r4 real*4; array of size (maxlth,*) to receive time series C i4 integer; array of size (maxlth,*) to receive time series C nreals integer; the number of real*4 time series you requested C nints integer; the number of integer time series you requested C tsize integer; the length of the time dimension in the netCDF file C rname character*16; array of names of real time series C iname character*16; array of names of integer time series C C When compiling getcdfts you must include the header file netcdf.inc, and C the result must be linked with netcdf.lib, both of which are produced by C building UCAR's netCDF package. C****************************************************************************** C****************************************************************************** C We were able to compile and run this code in a UNIX environment, utilizing C Version 3.4 of the UCAR netCDF package, by making the following changes: C C 1. Link it with libnetcdf.a rather than netcdf.lib. C 2. Remove references to CVF's trim() function. C C****************************************************************************** include 'e:\netcdf\include\netcdf.inc' ! or wherever netcdf.inc is real*4 r4(maxlth,*) integer i4(maxlth,*) integer i, ncid, ndims, nvars, ngatts, recdim, rcode, tid, x tsize, vartype, nvdims, vdims, nvatts, attype, atlth, x atbfrlth, nreals, nints, maxlth, iminvalue, imaxvalue real*4 r4value real*8 r8value, rminvalue, rmaxvalue character dimname*72, varname*16, units*48, longname*48, x atname*24, atbfr*48, filename*11, type*7(2), rname*16(*), X iname*16(*), rsp data type /'integer', 'real*4'/ atbfrlth /48/ nreals = 0 nints = 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. All have character C***values except the null or missing value (-999.9) which is real*8. write (6, 10) 10 format (/"This file's global attributes are"/) call ncinq(ncid, ndims, nvars, ngatts, recdim, rcode) do i = 1, ngatts call ncanam(ncid, NCGLOBAL, i, atname, rcode) call ncainq(ncid, NCGLOBAL, atname, attype, atlth, rcode) if (attype .eq. NCCHAR) then ! All except the missing_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 ! the missing_value call ncagt(ncid, NCGLOBAL, atname, r8value, rcode) write (6, 30) atname(1:20), r8value 30 format (3x, a20, f7.1) end if end do C***To proceed we need the length of the time dimension (tsize). 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. First, the name of the variable: call ncvinq(ncid, i, varname, vartype, nvdims, vdims, nvatts, x rcode) C***vdims > 1 means that we have depth, latitude, or longitude. These are C***dummy variables that are included in the file only to make it compliant C***with the requirements of the WOCE search engine. They are not actual C***time series and we will skip over them here. if (vdims .gt. 1) then write (6, 48) i, varname 48 format (/'Variable ', i2, ' is ', a16 / x ' It is a dummy variable. Skipping it ...') go to 90 end if write (6, 50) i, varname, type(vartype - 3) 50 format (/'Variable ', i2, ' is ', a16 / ' Its type is ', a7) C***Then its long name: longname = '' call ncagtc(ncid, i, 'long_name', longname, atbfrlth, rcode) write (6, 60) longname 60 format (' Its long name is ', a48) C***Units: units = '' call ncagtc(ncid, i, 'units', units, atbfrlth, rcode) write (6, 70) units 70 format (' Its units are ', a48) C***Minimum and maximum values: if (vartype .eq. 4) then call ncagt(ncid, i, 'data_min', iminvalue, rcode) call ncagt(ncid, i, 'data_max', imaxvalue, rcode) write (6, 72) iminvalue, imaxvalue 72 format (' Its min and max are ', i10, ' and ', i10) else call ncagt(ncid, i, 'data_min', rminvalue, rcode) call ncagt(ncid, i, 'data_max', rmaxvalue, rcode) write (6, 74) rminvalue, rmaxvalue 74 format (' Its min and max are ', f12.4, ' and ', f12.4) end if 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 nreals = nreals + 1 call ncvgt(ncid, i, 1, tsize, r4(1,nreals), rcode) rname(nreals) = varname else nints = nints + 1 ! Anything else is integer call ncvgt(ncid, i, 1, tsize, i4(1,nints), rcode) iname(nints) = varname end if end if 90 end do return end