Types

Quantities

FlexUnits.jl has two types of quantity values. FlexQuant, which can contain any object as a value, and Quantity which subtypes to Number (following the convention of most of Julia's unit packages). For convenience, they are often referred to together as QuantUnion. Mathematical operations on a QuantUnion with a Unit will convert to a dimensional quantity (SI by default) having an AbstractDimension instead of a AbstractUnit.

FlexUnits.QuantityType
struct Quantity{T<:Number, U<:AbstractUnitLike} <: Number
    value :: T
    unit  :: U
end

Numeric quantity type (that sutypes to number) with fields value and unit

source
FlexUnits.FlexQuantType
struct FlexQuant{T<:Any, U<:AbstractUnitLike}
    value :: T
    unit  :: U
end

Generic quantity type (that can hold any value) with fields value and unit

source
FlexUnits.QuantUnionType
QuantUnion{T<:Any,U<:AbstractUnitLike}

Convenience union that allows Number and Non-Number types to be considered together

source

Dimensions

Dimensions are the core object used to define units, and Quantity values tend to have some form of AbstractDimension in its unit field after calculations due to computational simplicity.

FlexUnits.AbstractDimensionsType
AbstractDimensions

A class that represents a specific dimensional schema, by default, its only child is Dimensions (SI units), but users can build their own versions (even based on imperial measurements, or where angles are a dimension)

source
FlexUnits.DimensionsType
Dimensions{P}

Basic SI dimensions: length = m, mass = kg, time = s, current = A, temperature = K, luminosity = cd, amount = mol

source
FlexUnits.StaticDimsType
StaticDims{D} <: AbstractDimLike

Static dimensions where the D` is the dimension value. This improves performance when dimensions are statically inferrable.

source

Units

Units contain an AbstractDimensions and an AbstractUnitTransform which represents a conversion formula to convert the Quantity to its pure dimensional form. Typically, the unit transform is called before a calcualtion to convert the quantity to dimensional form, and uconvert applies an invers of that transform to convert the result back to the desired unit. Because dimensions have no transforms, it is most efficient to perform calculations directly on dimensional quantities.

FlexUnits.AbstractUnitsType
AbstractUnits

All units in FlexDims contain two entities: (1) AbstractDimLike (anything that can be interpreted as a dimension) (2) AbstractTransform (contains the formula to convert unit value to dimensions)

source
FlexUnits.UnitsType
@kwdef struct Units{D<:AbstractDimensions, T<:AbstractUnitTransform} <: AbstractUnits{D, T}
    dims   :: D
    todims :: T
    symbol :: Symbol = DEFAULT_USYMBOL
end

A dynamic unit object that contains dimensions (dims) and its conversion formula to said dimensions (todims). The conversion formula determines what kind of unit is referred to. An AffineTransform implies affine units, a NoTransform implies dimensions. Dynamic units can generated through the @ud_str macro.

Constructors

Units{D}(units, todims::T, symbol=DEFAULT_USYMBOL) where {D,T<:AbstractUnitTransform} 
Units(dims::D, todims::AbstractUnitTransform=NoTransform(), symbol=DEFAULT_USYMBOL) where D<:AbstractDimensions 
Units(units::D, todims::AbstractUnitTransform, symbol=DEFAULT_USYMBOL) where D<:AbstractUnits
julia> 1*(5ud"°C") #Operations on units eagerly convert to dimensions
278.15 K

julia> 1*(5du"°C") |> ud"°C" #Converts operation results back to Celsius
5.0 °C

julia> (5ud"°C" + 2ud"°C") |> ud"°C" #Operation adds values in Kelvin, results converted back to Celsius
280.15 °C

julia> (ustrip(5ud"°C") + ustrip(2ud"°C"))*u"°C" #Strips, adds raw quantity values, converts raw number to Celsius
7 °C
source
FlexUnits.StaticUnitsType
@kwdef struct StaticUnits{D, T<:AbstractUnitTransform} <: AbstractUnits{D,T}
    todims :: T
    symbol :: Symbol
end

A static version of units, where the value of dimensions D is a a parameter. Static units can generated through the @u_str macro. This improves performance when dimensions are statically inferrable.

Constructors

StaticUnits(u::Units) = StaticUnits{dimension(u)}(todims(u), usymbol(u))
StaticUnits(d::AbstractDimensions, todims::AbstractUnitTransform, symb=DEFAULT_USYMBOL) = StaticUnits{d}(todims, symb)
StaticUnits(d::StaticDims{D}, todims::AbstractUnitTransform, symb=DEFAULT_USYMBOL) where D = StaticUnits{D}(todims, symb)
source

Unit Transforms

One unique feature to the FlexUnits design is the AbstractUnitTransform object. This is a callable object that contains a conversion formula to convert the unit into its dimensional form. The default transforms are NoTransform (a property of all dimensions) and AffineTransform which can deal with all common linear units. This design could potentially support other transforms like LogTransform for logarithmic units likd dB and pH in the future.

FlexUnits.AbstractUnitTransformType
AbstractUnitTransform

An abstract object representing a unit conversion formula. Any object that subtypes this is made callable.

# Callable form 
utrans = uconvert(u"°C", u"°F")
utrans(0.0)
31.999999999999986

# Shorthand callable form (syntactic sugar)
(u"°C" |> u"°F")(0.0)
31.999999999999986
source
FlexUnits.NoTransformType

NoTransform object, the default transform returned by todims(x::AbstractDimensionLike). Calling it results in an identity.

t = NoTransform()
t("anything")
"anything"
source
FlexUnits.AffineTransformType
@kwdef struct AffineTransform{T<:Real} <: AbstractUnitTransform
    scale  :: T = 1.0
    offset :: T = 0.0
end

A type representing an affine transfomration formula that can be used to convert values from one affine unit to another. This object is callable.

Constructors

AffineTransform(scale::Real, offset::Real)
AffineTransform(; scale, offset)
source

Linear Algebra

Linear algebra functionality is achieved by observing that any matrix of quantities that supports multiplication is a special kind of quantity matrix that functions as a linear mapping. Such matrices have a special structure for units. These special unit structures are unit mappings that contain an input vector of units, and an output vector of units. Accellerated linear algebra operations are achived by keeping numerical matrices and unit mappings separate in a LinmapQuant and performing the linear algebra and unit inference separately (not unlike how a Quantity operates).

Unit Maps

FlexUnits.UnitMapType
struct UnitMap{U<:UnitOrDims, TI<:ScalarOrVec{U}, TO<:ScalarOrVec{U}} <: AbstractUnitMap{U}
    u_in  :: TI
    u_out :: TO
end

Used to represent a unit transformation from input units 'uin' to outpout units 'uout'. Often applied to nonlinear functions.

Constructors

UnitMap{U}(u_in::ScalarOrVec{<:AbstractUnitLike}, u_out::ScalarOrVec{<:AbstractUnitLike}) where U<:AbstractUnitLike
UnitMap(u_in::ScalarOrVec{U1}, u_out::ScalarOrVec{U2}) where {U1<:AbstractUnitLike, U2<:AbstractUnitLike}
source
FlexUnits.DimsMapType
struct DimsMap{D<:AbstractDimLike, TI<:AbstractVector{D}, TO<:AbstractVector{D}} <: AbstractDimsMap{D}
    u_fac :: D
    u_in  :: TI
    u_out :: TO
end

Used to represent a unit transformation from input dimensions 'uin' to outpout dimensions 'uout'. This is like a unit map but focuses on dimensions and has matrix-like behaviour since dimensions support linear algebra, but generic units may not (affine units, logarithmic units etc).

WARNING: The DimsMap constructor on dimensions expects uin and uout to be scaled so that the first element is dimensionless. To prevent excessive allocations, uin and uout may be mutated in-place. If mutating arguments is undesirable, supply immutable arguments or copies; otherwise, ensure that uin and uout have dimensionless values in their first element.

Constructors

DimsMap(u_fac::U, u_in::TI, u_out::TO) where {U<:AbstractUnitLike, TI<:AbstractVector{<:AbstractUnitLike}, TO<:AbstractVector{<:AbstractUnitLike}}
DimsMap(u_fac::Nothing, u_in::TI, u_out::TO) where {TI<:AbstractVector{<:AbstractUnitLike}, TO<:AbstractVector{<:AbstractUnitLike}}
DimsMap(md::AbstractMatrix{<:AbstractDimLike})
DimsMap(mq::AbstractMatrix{<:QuantUnion})
DimsMap(d::AbstractDimsMap)
source

Objects with Unit Maps

FlexUnits.LinmapQuantType
struct LinmapQuant{T, D<:AbstractDimensions, M<:AbstractMatrix{T}, U<:UnitMaps{D}} <: AbstractMatrix{Quantity{T,D}}
    values :: M
    units :: U
end

A linear mapping of quantities. A special kind of matrix that is intended to be used for multiplying vectors of quantities; such matrices must be dimensionally consistent and can be represented by a UnitMap. These constraints lead to much faster unit inference and a smaller memory footprint (O(M+N) instead of O(MNN2) in the case of multiplication).

Constructors

LinmapQuant(m::AbstractMatrix{T}, u::UnitMap) where T
LinmapQuant(m::SMatrix{Nr,Nc,T}, u::UnitMap) where {T, Nr, Nc}
LinmapQuant(m::QuantArrayVals, d::QuantArrayDims)
LinmapQuant(m::AbstractMatrix)
LinmapQuant(m::LinmapQuant)
source
FlexUnits.FunctionQuantType
struct FunctionQuant{F, U<:AbstractUnitMap}
    func  :: F
    units :: U
end

A generic mapping with units. Useful for applying units to unitless functions that assume units for inputs/outputs.

source
FlexUnits.FactorQuantType
struct FactorQuant{T, D<:AbstractDimensions, F<:Factorization{T}, U<:AbstractUnitMap{D}}
    factor :: F
    dims  :: U 
end

A factored linear mapping. A subclass of Factorizations with a unit mapping attached. Calling getproperty is re-routed to the original factor, with the appropriate units calcualted from the mapping.

source