Defining new equivalences
Each equivalence must be of a type that is a subtype of Equivalence. To define a new equivalence, one creates a new such type and extends the UnitfulEquivalences.edconvert function to enable conversion between the desired dimensions.
As an example, let us implement our own version of the MassEnergy() equivalence.
struct MyMassEnergy <: Equivalence endFor this equivalence, a singleton struct is sufficient. In general, Equivalence types may also have fields and/or type parameters. To enable our MassEnergy type to convert between Unitful.Mass (of dimension π) and Unitful.Energy (of dimension π^2*π*π^-2), we need to define two edconvert methods (one for the mass-to-energy and one for the energy-to-mass conversion). The edconvert function converts a quantity (its second argument) to an equivalent quantity of the dimension specified by its first argument (the ed in edconvert stands for βequivalent dimensionβ). The third argument is the MyMassEnergy equivalence.
using Unitful: π, π, π, Energy, Mass, c0
UnitfulEquivalence.edconvert(::typeof(π^2*π*π^-2), x::Mass, ::MyMassEnergy) = x * c0^2
UnitfulEquivalence.edconvert(::typeof(π), x::Energy, ::MyMassEnergy) = x / c0^2This particular example implementation does not work correctly on 32-bit systems, since c0 is based on an Int and c0^2 therefore overflows on these systems ($299792458^2 > 2^{31}-1$).
When defining edconvert methods for DimensionlessQuantity arguments, the equivalence will also work with plain numbers (like Float64s or Ints), even though those are not subtypes of DimensionlessQuantity. Furthermore, uconvert and ustrip convert affine quantities (like Β°C) to absolute quantities before calling edconvert, so edconvert only needs to work on ScalarQuantitys.
After defining the two edconvert methods, MyMassEnergy() can be used to convert between mass and energy:
julia> uconvert(u"J", 1u"kg", MyMassEnergy())
89875517873681764 JAn equivalence can have an arbitrary number of edconvert methods defined for it. For example, the Spectral equivalence can convert between energy, frequency, wavelength, and wavenumber. For each pair of these quantities, there is one pair of edconvert methods defined that handles the conversion between them.
Convenience functions
The definition of the edconvert methods above could be simplified in two ways:
The
UnitfulEquivalences.dimtypefunction extracts theDimensionstype from a quantity type likeUnitful.Length. It can be used to simplify the declaration of the firstedconvertargument:using Unitful: Energy, Mass, c0 using UnitfulEquivalences: dimtype UnitfulEquivalence.edconvert(::dimtype(Energy), x::Mass, ::MyMassEnergy) = x * c0^2 UnitfulEquivalence.edconvert(::dimtype(Mass), x::Energy, ::MyMassEnergy) = x / c0^2In many cases, including this one, equivalences are simple proportional or antiproportional relations where the quotient or the product of the two equivalent quantities is a constant value (like a physical constant). In these cases, the
@eqrelationmacro can be used to define bothedconvertmethods at once. In the case of theMyMassEnergyequivalence, it would be used as follows:using Unitful: Energy, Mass, c0 @eqrelation MyMassEnergy Energy/Mass = c0^2This defines the two
edconvertmethods as shown above.
API
UnitfulEquivalences.dimtype β Functiondimtype(x)For a quantity type alias as created by Unitful.@dimension or Unitful.@derived_dimension (e.g., Unitful.Energy), return its Dimensions type. (not exported)
Example
julia> using UnitfulEquivalences: dimtype
julia> dimtype(Unitful.Length)
Unitful.Dimensions{(Unitful.Dimension{:Length}(1//1),)}UnitfulEquivalences.edconvert β Functionedconvert(d::Dimensions, x::AbstractQuantity, e::Equivalence)Convert x to the equivalent dimension d using the equivalence e. (not exported)
Example
julia> using UnitfulEquivalences: edconvert
julia> edconvert(dimension(u"J"), 1u"kg", MassEnergy()) # E = m*c^2
89875517873681764 kg m^2 s^-2UnitfulEquivalences.@eqrelation β Macro@eqrelation Name a/b = c
@eqrelation Name a*b = cAdd a proportional or antiproportional relation between dimensions a and b to an existing equivalence type Name <: Equivalence. The dimensions a and b must be specified as quantity type aliases like Unitful.Energy.
Example
using Unitful: Energy, Mass, c0
struct MassEnergy <: Equivalence end
@eqrelation MassEnergy Energy/Mass = c0^2In the rest frame of a particle, its energy is proportional to its mass. Defining the MassEnergy equivalence like above allows conversion between energies and masses via uconvert(massunit, energy, MassEnergy()) and uconvert(energyunit, massunit, MassEnergy()).