Temperature scales
Temperatures require some care. Temperature scales like K
and Ra
are thermodynamic temperature scales, with zero on the scale corresponding to absolute zero. Unit conversions between thermodynamic or absolute temperatures are done by multiplying conversion factors, as usual. Also in common use are temperature scales like °C
or °F
, which are defined relative to arbitrary offsets. For example, in the case of °C
, zero on the scale is the freezing point of water, not absolute zero. To convert between relative temperature scales, an affine transformation is required. Absolute and relative temperatures can be distinguished by type to avoid ambiguities that could yield erroneous or unexpected results. On relative temperature scales, problems can arise because e.g. 0°C + 0°C
could mean 0°C
or 273.15°C
, depending on whether the operands are variously interpreted as temperature differences or as absolute temperatures. On thermodynamic temperature scales, there is no ambiguity.
Temperatures on absolute scales
Unit conversions between temperatures on absolute scales like Kelvin or Rankine are done in the usual way by multiplication of a scale factor. For example, we have:
julia> uconvert(u"K", 1u"Ra")
5//9 K
We can identify absolute temperatures using the Unitful.AbsoluteScaleTemperature
type alias:
julia> 1u"K" isa Unitful.AbsoluteScaleTemperature
true
Temperatures on relative scales
Unit conversions between temperatures on relative scales like Celsius or Fahrenheit involve an affine transformation, that is, a scaling plus some translation (scale offset). In Unitful, relative scale temperatures are considered to have the same dimension as absolute scale temperatures, as expected. However, temperatures on relative and absolute scales are distinguished by the type of the Unitful.Units
object (and therefore the type of the Unitful.Quantity
object).
julia> uconvert(u"°C", 32u"°F")
0//1 °C
We can identify relative scale temperatures using the Unitful.RelativeScaleTemperature
type alias, e.g.:
julia> 1u"°C" isa Unitful.RelativeScaleTemperature
true
Some operations are not well defined with relative scale temperatures, and therefore throw an Unitful.AffineError
(please report any unexpected behavior on the GitHub issue tracker).
julia> 32u"°F" + 1u"°F"
ERROR: AffineError: an invalid operation was attempted with affine quantities: 32 °F + 1 °F
[...]
julia> 32u"°F" * 2
ERROR: AffineError: an invalid operation was attempted with affine quantities: 32 °F*2
[...]
There is a general mechanism for making units that indicate quantities should unit-convert under some affine transformation. While the usual use case is for relative scale temperatures, nothing in the implementation limits it as such. Accordingly, relative scale temperatures are considered to be Unitful.AffineQuantity
objects with dimensions of temperature. The units on "affine quantities" are Unitful.AffineUnits
objects.
Making your own affine units typically requires two steps. First, define the absolute unit using the Unitful.@unit
macro. Second, use the Unitful.@affineunit
macro to make a corresponding affine unit. As an example, this is how Ra
and °F
are implemented:
@unit Ra "Ra" Rankine (5//9)*K false
@affineunit °F "°F" (45967//100)Ra
The preferred unit for promoting temperatures is usually K
when using Unitful.FreeUnits
.
Unitful.AffineUnits
— TypeAffineUnits{N,D,A} = Units{N,D,A} where A<:Affine
Useful for dispatching on unit objects that indicate a quantity should affine-transform under unit conversion, like absolute temperatures. Not exported.
Unitful.AffineQuantity
— TypeAffineQuantity{T,D,U} = AbstractQuantity{T,D,U} where U<:AffineUnits
Useful for dispatching on quantities that affine-transform under unit conversion, like absolute temperatures. Not exported.
Unitful.ScalarUnits
— TypeScalarUnits{N,D} = Units{N,D,nothing}
Useful for dispatching on unit objects that indicate a quantity should transform in the usual scalar way under unit conversion. Not exported.
Unitful.ScalarQuantity
— TypeScalarQuantity{T,D,U} = AbstractQuantity{T,D,U} where U<:ScalarUnits
Useful for dispatching on quantities that transform in the usual scalar way under unit conversion. Not exported.
Unitful.absoluteunit
— Functionabsoluteunit(::Units)
absoluteunit(::Quantity)
Given a unit or quantity, which may or may not be affine (e.g. °C
), return the corresponding unit on the absolute temperature scale (e.g. K
). Passing a Unitful.ContextUnits
object will return another ContextUnits
object with the same promotion unit, which may be an affine unit, so take care.