Some units conversions of interest are nonlinear; for example, temperature conversions between the Fahrenheit and Celsius scales cannot be done by simply multiplying by conversions factors.
When you give a linear unit definition such as inch 2.54 cm you
are providing information that units
uses to convert values in
inches into primitive units of meters. For nonlinear units, you give
a functional definition that provides the same information.
Nonlinear units are represented using a functional notation. It is best to regard this notation not as a function call but as a way of adding units to a number, much the same way that writing a linear unit name after a number adds units to that number. Internally, nonlinear units are defined by a pair of functions which convert to and from linear units in the data file, so that an eventual conversion to primitive units is possible.
Here is an example nonlinear unit definition:
tempF(x) [1;K] (x+(-32)) degF + stdtemp ; (tempF+(-stdtemp))/degF + 32
A nonlinear unit definition comprises a unit name, a dummy parameter
name, two functions, and two corresponding units. The functions tell
units
how to convert to and from the new unit. In order to
produce valid results, the arguments of these functions need to have
the correct dimensions. To facilitate error checking, you may specify
the dimensions.
The definition begins with the unit name followed immediately (with no
spaces) by a ( character. In parentheses is the name of the
parameter. Next is an optional specification of the units required by
the functions in this definition. In the example above, the
tempF function requires an input argument conformable with
1. For normal nonlinear units definitions the forward
function will always take a dimensionless argument.
The inverse function requires an input argument conformable
with K. In general the inverse function will need units
that match the quantity measured by your nonlinear unit.
The sole purpose of the expression in brackets to enable
units
to perform error checking on function arguments.
Next the function definitions appear. In the example above, the tempF function is defined by
tempF(x) = (x+(-32)) degF + stdtemp
This gives a rule for converting x in the units tempF to linear units of absolute temperature, which makes it possible to convert from tempF to other units.
In order to make conversions to Fahrenheit possible, you must give a rule for the inverse conversions. The inverse will be x(tempF) and its definition appears after a ; character. In our example, the inverse is
x(tempF) = (tempF+(-stdtemp))/degF + 32
This inverse definition takes an absolute temperature as its argument and converts it to the Fahrenheit temperature. The inverse can be omitted by leaving out the ; character, but then conversions to the unit will be impossible. If the inverse is omitted then the --check option will display a warning. It is up to you to calculate and enter the correct inverse function to obtain proper conversions. The --check option tests the inverse at one point and print an error if it is not valid there, but this is not a guarantee that your inverse is correct.
If you wish to make synonyms for nonlinear units, you still need to define both the forward and inverse functions. Inverse functions can be obtained using the ~ operator. So to create a synonym for tempF you could write
fahrenheit(x) [1;K] tempF(x); ~tempF(fahrenheit)
You may occasionally wish to define a function that operates on units. This can be done using a nonlinear unit definition. For example, the definition below provides conversion between radius and the area of a circle. Note that this definition requires a length as input and produces an area as output, as indicated by the specification in brackets.
circlearea(r) [m;m^2] pi r^2 ; sqrt(circlearea/pi)
Sometimes you may be interested in a piecewise linear unit such as many wire gauges. Piecewise linear units can be defined by specifying conversions to linear units on a list of points. Conversion at other points will be done by linear interpolation. A partial definition of zinc gauge is
zincgauge[in] 1 0.002, 10 0.02, 15 0.04, 19 0.06, 23 0.1
In this example, zincgauge is the name of the piecewise linear unit. The definition of such a unit is indicated by the embedded [ character. After the bracket, you should indicate the units to be attached to the numbers in the table. No spaces can appear before the ] character, so a definition like foo[kg meters] is illegal; instead write foo[kg*meters]. The definition of the unit consists of a list of pairs optionally separated by commas. This list defines a function for converting from the piecewise linear unit to linear units. The first item in each pair is the function argument; the second item is the value of the function at that argument (in the units specified in brackets). In this example, we define zincgauge at five points. For example, we set zincgauge(1) equal to 0.002 in. Definitions like this may be more readable if written using continuation characters as
zincgauge[in] \ 1 0.002 \ 10 0.02 \ 15 0.04 \ 19 0.06 \ 23 0.1
With the preceeding definition, the following conversion can be performed:
You have: zincgauge(10) You want: in * 0.02 / 50 You have: .01 inch You want: zincgauge 5
If you define a piecewise linear unit that is not strictly
monotonic, then the inverse will not be well defined. If the inverse is
requested for such a unit, units
will return the smallest
inverse. The --check option will print a warning if a
non-monotonic piecewise linear unit is encountered.