." $Id: udunits.3fi,v 1.7 2003/08/29 18:30:33 steve Exp $ .TH UDUNITS 3f "$Date: 2003/08/29 18:30:33 $" "Printed: \n(yr.\n(mo.\n(dy" "UNIDATA LIBRARY FUNCTIONS" .SH NAME udunits, utopen, utmake, uttime, utorigin, utclr, utcpy, utorig, utscal, utmult, utinv, utdiv, utexp, utdec, utcaltime, uticaltime, utenc, utcvt, utfree, utcls \- Unidata units library .SH SYNOPSIS .nf .ft B f77 -I\fIunidata_inc\fP -L\fIunidata_lib\fP -ludunits ... .sp include udunits.inc .sp .ta \w'integer function 'u +\w'uticaltime 'u +\w'('u integer function utopen (character*(*) path) .sp PTR function utmake () .sp integer function uttime (PTR unit) .sp integer function utorigin (PTR unit) .sp subroutine utclr (PTR unit) .sp subroutine utcpy (PTR source, PTR dest) .sp subroutine utorig (PTR source, doubleprecision amount, PTR result) .sp subroutine utscal (PTR source, doubleprecision factor, PTR result) .sp subroutine utmult (PTR term1, PTR term2, PTR result) .sp subroutine utinv (PTR source, PTR result) .sp subroutine utdiv (PTR numer, PTR denom, PTR result) .sp subroutine utexp (PTR source, integer power, PTR result) .sp integer function utdec (character*(*) spec, PTR unit) .sp integer function utcaltime (doubleprecision value, PTR unit, integer year, integer month, integer day, integer hour, integer minute, real second) .sp integer function uticaltime (integer year, integer month, integer day, integer hour, integer minute, real second PTR unit, doubleprecision value) .sp integer function utenc (PTR unit, character*(*) spec) .sp integer function utcvt (PTR from, PTR to, doubleprecision slope, doubleprecision intercept) .sp subroutine utfree (PTR unit) .sp subroutine utcls () .ft .fi .SH DESCRIPTION .LP The Unidata units library, \fBudunits\fP, supports conversion of unit specifications between formatted and binary forms, arithmetic manipulation of unit specifications, and conversion of values between compatible scales of measurement. .LP A unit is the amount by which a physical quantity is measured. For example: .sp .TS center tab(|); c c c c. Phisical Quantity|Possible Unit \_|\_ time|weeks distance|centimeters power|watts .TE .sp A unit can have an origin associated with it \-\- in which case the unit and origin together define a scale. For example, the phrase "the temperature is 25 degrees Celsius" specifies a particular point on a measurement scale; whereas the phrase "the temperature difference is 25 degrees Celsius" specifies a unit with no origin and, hence, no associated scale. If not remembered, this subtle distinction can cause problems when handling units. .LP Because the units library passes pointers to units structures and FORTRAN 77 has no pointer type, the word PTR in the above synopsis stands for whatever FORTRAN type is appropriate for holding a pointer to a C structure on the given platform. This is necessarily platform-dependent and, consequently, \fBIT IS UP TO THE USER TO DECLARE AND USE THE CORRECT FORTRAN DATA TYPE\fR. .LP .B utopen() initializes the units package. If \fIpath\fP is not empty, then it specifies a units file containing initializing unit definitions; otherwise, the environment variable \fBUDUNITS_PATH\fR is checked and, if it exits and is not empty, then it is assumed to contain the pathname of the units file; otherwise, a compile-time default pathname is used. .sp The definitions in the units file are read into memory. This function returns 0 on success, UT_ENOFILE if the units file doesn't exist, UT_ESYNTAX if the units file contains a syntax error, UT_EUNKNOWN if the units file contains an unknown specification, UT_EIO if an I/O error occurred while accessing the units file, and UT_EALLOC if a memory allocation failure occurred. .LP .B utdec() decodes the formatted unit specification \fIspec\fP into a binary unit representation and stores the result in \fIunit\fP. The binary representation is used for algebraic manipulation. This function returns 0 on success, UT_ENOINIT if the package hasn't been initialized, UT_EUNKNOWN if the specification contains an unknown unit, and UT_ESYNTAX if the specification contains a syntax error. .LP .B utcaltime() converts the amount, \fIvalue\fP, of the temporal unit, \fIunit\fP, into a UTC-referenced date and time (see, however, the section on HANDLING TIME). The reference unit shall be a time unit and have an origin. This function returns 0 on success, UT_ENOINIT if the package hasn't been initialized and UT_EINVALID if the unit structure is not a temporal one. .LP .B uticaltime() converts a UTC-referenced date and time into the amount, \fIvalue\fP, of the temporal unit, \fIunit\fP (see, however, the section on HANDLING TIME). The reference unit shall be a time unit and have an origin. This function returns 0 on success, UT_ENOINIT if the package hasn't been initialized and UT_EINVALID if the unit structure is not a temporal one. .LP .B utcvt() returns the coefficients of the Galilean transformation (i.e. y = a*x + b) necessary to convert the \fIfrom\fP unit into the \fIto\fP unit. The units must be compatible (i.e., their quotient must be dimensionless). On successful return, \fIslope\fP and \fIintercept\fP will contain the values for the slope and intercept coefficients, respectively. This function returns 0 on success, UT_ENOINIT if the package hasn't been initialized, UT_EINVALID if one of the unit variables is invalid, and UT_ECONVERT if the units are not convertable. .LP .B utenc() encodes the binary unit variable \fIunit\fP into a formatted unit specification and stores the string in \fIspec\fP. This function returns 0 on success, UT_ENOINIT if the package hasn't been initialized, UT_EINVALID if the unit variable is invalid, and UT_ENOROOM if the supplied character buffer is too small. .LP .B utclr() clears a unit variable by setting it to the dimensionless scalar 1. .LP .B uttime() returns 1 if the given unit variable refers to a time unit; 0 otherwise. This function ignores whether or not the unit has an origin. .LP .B utorigin() returns 1 if the given unit variable has an origin (i.e. defines a scale) and 0 otherwise. .LP .B utcpy() copies the unit variable \fIsource\fP to the unit variable \fIdest\fP. This function correctly handles the case where the same unit variable is referenced by the source and destination units. .LP .B utscal() scales the unit variable \fIsource\fP by the multiplicative scalar \fIfactor\fP, storing the result in the unit variable \fIresult\fP. This function correctly handles the case where the same unit variable is referenced by the source and result units. .LP .B utinv() inverts the unit variable \fIsource\fP, storing the result in unit variable \fIresult\fP. Multiplying a unit by its reciprocal yields the dimensionless scalar 1. This function correctly handles the case where the source and result unit refer to the same variable. .LP .B utdiv() divides unit variable \fInumer\fP by unit variable \fIdenom\fP and stores the result in unit variable \fIresult\fP. This function correctly handles the case where the same unit variable is referenced by two or more arguments. .LP .B utmult() multiplies unit variable \fIterm1\fP by unit variable \fIterm2\fP and stores the result in unit variable \fIresult\fP. This function correctly handles the case where the same unit variable is referenced by two or more arguments. .LP .B utexp() raises the unit variable \fIsource\fP by the power \fPpower\fP, storing the result in the unit variable \fIresult\fP. This function correctly handles the case where the same unit variable is referenced by the source and result units. .LP .B utcls() terminates usage of this package. In particular, it frees all allocated memory. It should be called when the library is no longer needed. .LP .B utmake() Creates a new unit variable. The value returned by this function may be used in subsequent calls. The unit variable is cleared by a call to utclr. .LP .B utfree() Frees the unit variable \fIunit\fP which was returned by a previous call to \fButmake()\fP. .SH "HANDLING TIME" .LP The \fBudunits\fP(3) package uses a mixed Gregorian/Julian calendar system. Dates prior to 1582-10-15 are assumed to use the Julian calendar, which was introduced by Julius Caesar in 46 BCE and is based on a year that is exactly 365.25 days long. Dates on and after 1582-10-15 are assumed to use the Gregorian calendar, which was introduced on that date and is based on a year that is exactly 365.2425 days long. (A year is actually approximately 365.242198781 days long.) Seemingly strange behavior of the \fBudunits\fP(3) package can result if a user-given time interval includes the changeover date. For example, \fButCalendar\fP() and \fButInvCalendar\fP() can be used to show that 1582-10-15 *preceeded* 1582-10-14 by 9 days. .SH "EXAMPLES" .LP In the following, it is assumed that a FORTRAN INTEGER data type is appropriate for storing a pointer to a C structure. This assumption is valid for most 32-bit architectures but is invalid for most 64-bit architectures that have 32-bit INTEGERs (e.g. a DEC Alpha). .LP Convert two data sets to a common unit, subtract one from the other, then save the result in a (different) output unit: .sp .RS +4 .nf INTEGER UTOPEN ... IF (UTOPEN('') .NE. 0) THEN C Handle initialization error ELSE CHARACTER*80 UNITSTRING1, UNITSTRING2 CHARACTER*80 OUTPUTUNITSTRING INTEGER UNIT1, UNIT2, OUTPUTUNIT INTEGER UTMAKE, UTDEC ... UNIT1 = UTMAKE() UNIT2 = UTMAKE() OUTPUTUNIT = UTMAKE() IF (UTDEC(UNITSTRING1, UNIT1) .NE. 0 .OR. * UTDEC(UNITSTRING2, UNIT2) .NE. 0 .OR. * UTDEC(OUTPUTUNITSTRING2, OUTPUTUNIT) .ne. 0) THEN C C Handle decode error C ELSE DOUBLEPRECISION INSLOPE, ININTERCEPT DOUBLEPRECISION OUTSLOPE, OUTINTERCEPT IF (UTCVT(UNIT2, UNIT1, INSLOPE, ININTERCEPT) .NE. 0 * .OR. UTCVT(UNIT1, OUTPUTUNIT, OUTSLOPE, * OUTINTERCEPT) .NE. 0) THEN C C Handle data-incompatibility C ELSE C Process data using: C OUTPUTVALUE = OUTSLOPE*(DATA1VALUE C - (INSLOPE*DATA2VALUE * + ININTERCEPT)) C + OUTINTERCEPT ENDIF CALL UTFREE(UNIT1) CALL UTFREE(UNIT2) CALL UTFREE(OUTPUTUNIT) CALL UTCLS ENDIF ENDIF .fi .RE .LP the above example could be made more efficient by testing the returned conversion factors for nearness to 1 and 0 and using appropriately streamlined processing expressions. .sp .LP Compute a threshold value corresponding to an input data value plus a user-specified delta (the units of the input data value and delta can differ): .sp .RS +4 .nf INTEGER INPUT_UNIT, DELTA_UNIT INTEGER UTOPEN, UTMAKE, UTDEC CHARACTER*(80) INPUT_UNIT_STRING, DELTA_UNIT_STRING ... INPUT_UNIT = UTMAKE() DELTA_UNIT = UTMAKE() CALL UTOPEN('udunits.dat') IF (UTDEC(INPUT_UNIT_STRING, INPUT_UNIT) .NE. 0 .OR. UTDEC(DELTA_UNIT_STRING, DELTA_UNIT) .NE. 0) THEN C C Handle decode error C ELSE DOUBLEPRECISION SLOPE, INTERCEPT REAL DELTA_VALUE ... IF (UTCVT(DELTA_UNIT, INPUT_UNIT, SLOPE, INTERCEPT) * .NE. 0) THEN C C Handle units incompatibility C ELSE REAL INPUT_VALUE REAL THRESHOLD ... THRESHOLD = INPUT_VALUE + SLOPE*DELTA_VALUE + INTERCEPT ENDIF ENDIF CALL UTCLS .fi .RE .sp .LP Compute the number of time intervals from a start time to a reference time. \fIPTR is a placeholder for the FORTRAN data type equivalent to a memory address. .sp .RS +4 .nf .so testcal2.f .sp .fi .RE .SH "FORMATTED UNIT SPECIFICATIONS" .LP The following are examples of formatted unit specifications that can be interpreted by the .B utScan() function: .sp .RS +4 .nf 10 kilogram.meters/seconds2 10 kg-m/sec2 10 kg\ m/s^2 (PI\ radian)2 degF 100rpm geopotential meters 33 feet water .fi .RE .LP A unit is specified as an arbitrary product of constants and unit names raised to arbitrary integral powers. Division is indicated by a slash `/'. Multiplication is indicated by whitespace, a period `.', or a hyphen `-'. Exponentiation is indicated by an integer suffix or by the exponentiation operators `^' and `**'. Parentheses may be used for grouping and disambiguation. .LP Arbitrary Galilean transformations (i.e. y = ax + b) are supported. In particular, temperature and time conversions are correctly handled. The specification: .sp .RS degF @ 32 .RE .sp indicates a Fahrenheit scale with the origin shifted to thirty-two degrees Fahrenheit (i.e. to zero degrees Celsius). The Celsius scale is equivalent to the following unit: .sp .RS .nf 1.8 degR @ 273.15 .fi .RE .sp Besides the character `\fB@\fP', the words `\fBafter\fP', `\fBfrom\fP', `\fBref\fP', and `\fBsince\fP' may also be used. Note that multiplication takes precedence over origin-shift. In order of increasing precedence, the operations are origin-shift, division, multiplication, and exponentiation. .LP Units of time are similarly handled. The specification: .sp .RS .nf seconds since 1992-10-8 15:15:42.5 -6:00 .fi .RE .sp indicates seconds since October 8th, 1992 at 3 hours, 15 minutes and 42.5 seconds in the afternoon in the time zone which is six hours to the west of Coordinated Universal Time (i.e. Mountain Daylight Time). The time zone specification can also be written without a colon using one or two-digits (indicating hours) or three or four digits (indicating hours and minutes). .LP .B utScan() understands most conventional prefixes and abbreviations: .sp .TS center tab(|); c c c l l c. Factor|Prefix|Abbreviation \_|\_|\_ 1e24|yotta|Y 1e21|zetta|Z 1e18|exa|E 1e15|peta|P 1e12|tera|T 1e9|giga|G 1e6|mega|M 1e3|kilo|k 1e2|hecto|h 1e1|deca, deka|da 1e-1|deci|d 1e-2|centi|c 1e-3|milli|m 1e-6|micro|u 1e-9|nano|n 1e-12|pico|p 1e-15|femto|f 1e-18|atto|a 1e-21|zepto|z 1e-24|yocto|y .TE .LP The function .B utPrint() always encodes a unit specification one way. To reduce misunderstandings, it is recommended that this encoding style be used as the default. In general, a unit is printed in terms of basic units, factors, and exponents. Basic units are separated by spaces; and any exponent directly appends its associated unit. The above examples would be printed as follows: .sp .RS +4 .nf 10 kilogram meter second-2 9.8696044 radian2 0.555556 kelvin @ 255.372 10.471976 radian second-1 9.80665 meter2 second-2 98636.5 kilogram meter-1 second-2 .fi .RE .sp Note that the Fahrenheit unit is encoded as a deviation, in fractional kelvins, from an origin at 255.372 kelvin. .SH "UNITS FILE" .LP The units file is a formatted file containing unit definitions and is used to initialize this package. It is the first place to look to discover the set of valid names and symbols (of which there are many \-\- On October 9, 1992, it contained 446 entries). .LP The format for the units file is documented internally and the file may be modified by the user as necessary. In particular, additional units and constants may be easily added (including variant spellings of existing units or constants). .SH ENVIRONMENT .IP UDUNITS_PATH 17 If \fButInit()\fP is called without a pathname argument, and if this environment variable is non-empty, then its value overrides the default pathname for the units file. .SH DIAGNOSTICS .LP This package prints (hopefully) self-explanatory error-messages to standard error. .SH "SEE ALSO" .LP .BR udunits (1). .SH "BUGS AND RESTRICTIONS" .LP .B utScan() is case-sensitive. If this causes difficulties, you might try making appropriate additional entries to the units file. .LP Some unit abbreviations in the default units file might seem counter-intuitive. In particular, note the following: .sp .RS 4 .nf .ta \w'Celsius 'u +\w'`newton\' or `N\' 'u +\w'`rad\' 'u For Use Not Which Instead Means .sp Celsius `Celsius' `C' coulomb gram `gram' `g' gallon `gallon' `gal' radian `radian' `rad' Newton `newton' or `N' `nt' nit (unit of photometry) .fi .RE .SH REFERENCES .LP NIST Special Publication 811, 1995 Edition: "Guide for the Use of the International System of Units (SI)" by Barry N. Taylor. URL . .LP ANSI/IEEE Std 260-1978: "IEEE Standard Letter Symbols for Units of Measurement". .LP ASTM Designation: E 380 \- 85: "Standard for METRIC PRACTICE". .LP International Standard (ISO) 2955: "Information processing \-\- Representation of SI and other units in systems with limited character sets", Ref. No. ISO 2955-1983 (E).