### 14.4 Defining Piecewise Linear Units ¶

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 invalid; 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 preceding 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.

After adding nonlinear units definitions, you should normally run ‘`units --check`’ to check for errors. If the ‘`units`’ keyword is not given, the `--check` option checks a nonlinear unit definition using a dimensionless argument, and then checks using an arbitrary combination of units, as well as the square and cube of that combination; a warning is given if any of these tests fail. For example,

    Warning: function 'squirt(x)' defined as 'sqrt(x)'
             failed for some test inputs:
             squirt(7(kg K)^1): Unit not a root
             squirt(7(kg K)^3): Unit not a root

Running ‘`units --check`’ will print a warning if a non-monotonic piecewise linear unit is encountered. For example, the relationship between ANSI coated abrasive designation and mean particle size is non-monotonic in the vicinity of 800 grit:

    ansicoated[micron] \
         . . .
        600 10.55 \
        800 11.5 \
        1000 9.5 \

Running ‘`units --check`’ would give the error message

    Table 'ansicoated' lacks unique inverse around entry 800

Although the inverse is not well defined in this region, it’s not really an error. Viewing such error messages can be tedious, and if there are enough of them, they can distract from true errors. Error checking for nonlinear unit definitions can be suppressed by giving the ‘`noerror`’ keyword; for the examples above, this could be done as

    squirt(x) noerror domain=[0,) range=[0,) sqrt(x); squirt^2
    ansicoated[micron] noerror \
         . . .

Use the ‘`noerror`’ keyword with caution. The safest approach after adding a nonlinear unit definition is to run ‘`units --check`’ and confirm that there are no actual errors before adding the ‘`noerror`’ keyword.