CALC_FIELD is an IVE transform subroutine. By modifying CALC_FIELD, you can link your own code to IVE in order to compute diagnostic field variables other than the fields in the original netCDF file. CALC_FIELD is especially useful for calculating fields that will be used frequently or fields that are too complicated to define at the IVE command line (see Diagnostic Computations Using the Command Line).
The CALC_FIELD routine can be programmed in either C or Fortran (To download the default transform package for IVE, refer to Writing Transforms for IVE). In this document, we particularly focus on programming CALC_FIELD in Fortran rather than in C, since Fortran requires the use of pointer variables that allocate memory for field data storage. A number of Fortran-callable IVE subroutines are available for calculating diagnostic variables in CALC_FIELD. Among these subroutines, the most important is GETVAR. GETVAR returns a pointer to the memory location where a specified diagnostic varable is stored. It allows recursion within the CALC_FIELD routine such that the data stored in one memory location may be calculated from data stored in other memory locations. This makes GETVAR a powerful tool. The following code is a sample Fortran version of CALC_FIELD that demonstrates the use of the GETVAR routine:
c pointer function calc_field(name, ndims, dims, stag, min, max, & missing, data_units, data_display_units, dim_names) c c calc_field : This routine is used to calculate user-derived fields. c The return value of the routine is a pointer to the field values. c NULL return => cannot calculate. c c Arguments: c name character The name of the field to derive. c ndims integer Number of dimensions in field (output). c dims integer Number of points in the field in Fortran c order (x, y, z, t) (output). c stag real Grid staggering per dimension (output). c min real Physical space minimum per dimension (output). c max real Physical space maximum per dimension (output). c missing real Missing data value, zero => none (output). c data_units c character Units for field (output). c data_display_units c character Units to use to display field (output). c dim_names character Names of the dimensions in the field (output). c integer ndims, dims(4) real stag(4), min(4), max(4), missing character*(*) name, data_units, data_display_units, dim_names(4) c
There are TWO ways to code the new field variable THETA in the CALC_FIELD routine:
c ibeg = strbeg(name) ! These commands find the beginning and ending iend = strend(name) ! characters in the variable "name". if (name(ibeg:iend) .eq. 'THETA') then c c The following command returns a pointer to the memory location where c the field 'THETA' will be stored. Note that it is necessary to use c IVE syntax in the mathematical expression for THETA. c calc_field = getvar('T*(1000/P)^0.286', ndims, dims, stag, min, & max, missing, data_units, data_display_units, & dim_names, flag) return endif c return end ! CALC_FIELD c
c pointer t, p float pmissing c ibeg = strbeg(name) ! These commands find the beginning and ending iend = strend(name) ! characters in the variable "name". if (name(ibeg:iend) .eq. 'THETA') then p = getvar('P', ndims, dims, stag, min, max, & pmissing, data_units, data_display_units, & dim_names, flag) ! Here, getvar returns a pointer ! to the memory location where ! the field 'P' is stored. c if (p .eq. 0) then ! This 'if' loop flags user when 'P' missing make_help_widget('THETA - cannot get P') calc_field = 0 return endif c c Here, getvar returns a pointer to the memory location where the field c 'T' is stored: t = getvar('T', ndims, dims, stag, min, max, missing, & data_units, data_display_units, dim_names, flag) if (t .eq. 0) then ! This 'if' loop flags user when 'T' missing make_help_widget('THETA - cannot get T') calc_field = 0 return endif c num = dims(1) * dims(2) * dims(3) * dims(4) calc_field = getmem(num) ! This command allocates array memory. if (calc_field .eq. 0) then ! This 'if' loop flags user when ! the memory cannot be allocated. make_help_widget('THETA - cannot allocate memory'); calc_field = 0 return endif c do i = 1, num t1 = r_val(%val(t), i) ! These commands return the i-th p1 = r_val(%val(p), i) ! data value in the arrays p & t if (t1 .eq. missing .or. p1 .eq. missing) then c If the i-th value in either p or t is missing, the c following command stores the value 'missing' in the c i-th value of the array THETA c call s_val(%val(calc_field), i, missing) c else c If the data is not missing, we calculate the i-th value c of the array THETA c call s_val(%val(calc_field), i, t1*(1000/p1)**0.286) endif enddo return endif c return end ! CALC_FIELD c