API


Scalar API

​ Types

UnitfulTensors.FastQuantities.UnitfulScalarType
UnitfulScalar{TV, TD<:AbstractDimensions} <: AbstractUnitfulScalar{TV, TD}

Concrete type representing a scalar physical quantity with a numerical value of type TV and physical dimensions of type TD.

​ Constants

​ Functions

Base.valuesMethod
values(x::AbstractUnitfulScalar)

Same as value, for consistency with AbstractUnitfulTensor.

See also: dimensions.

UnitfulTensors.FastQuantities.dimexpsFunction
dimexps(x::AbstractDimensions)

Represent x as a product of base dimensions raised to some powers and return a tuple of these powers.

For SIDimensions, the base dimensions are time, length, mass, current, temperature, amount, luminous intensity.

Tensor API

​ Basic types

UnitfulTensors.AbstractUnitfulTensorType
AbstractUnitfulTensor{T<:AbstractUnitfulScalar, N} <: AbstractArray{T, N}

An N-dimensional array of unitful quantities of type T that can be used in linear or multilinear algebra.

This requirement forces its physical dimensions, represented by AbstractAxesDimensions, to factorize into a tensor product of dimensions along each axis, represented by AbstractAxisDimensions. For example, the physical dimensions of an AbstractUnitfulMatrix are the product of its row and column dimensions.

UnitfulTensors.UnitfulTensorType
UnitfulTensor{N, TV, TD<:AbstractDimensions,
                 V <: Union{AbstractArray{TV, N}, AbstractQ{TV}},
                 D <: AbstractAxesDimensions{N, TD}} <:
                 AbstractUnitfulTensor{UnitfulScalar{TV, TD}, N}

An N-dimensional array of unitful quantities that can be used in linear or multilinear algebra.

This requirement forces its physical dimensions, represented by AxesDimensions, to factorize into a tensor product of dimensions along each axis, represented by AxisDimensions. For example, the physical dimensions of a UnitfulMatrix are the product of its row and column dimensions.

UnitfulTensor stores its numerical values as an array of type V and its dimensions as an AbstractAxesDimensions of type D. They can be obtained using values and dimensions.

​ Extra types

​ Type aliases

​ Constructors

UnitfulTensors.UnitfulTensorMethod
UnitfulTensor(A::AbstractArray)

Convert an AbstractArray of UnitfulScalars or Numbers to a UnitfulTensor, which enables efficient operations on the physical dimensions.

The physical dimensions of A must factorize into a tensor product of dimensions along each axis (e. g., row and column dimensions of a matrix). Other arrays cannot be used in linear or multilinear algebra and will throw an error when attempting to convert them to a UnitfulTensor.

Examples:

julia> A = UnitfulTensor([1.0     2.0u"s^-1"
                          3.0u"J" 4.0u"W"   ])
2×2 UnitfulMatrix{Float64, SIDimensions, Matrix{Float64}, AxesDimensions{2, SIDimensions}}:
             1.0         2.0 s^-1
 3.0 kg m^2 s^-2  4.0 kg m^2 s^-3

julia> V = values(A)
2×2 Matrix{Float64}:
 1.0  2.0
 3.0  4.0

julia> D = dimensions(A)
2×2 AxesDimensions{2, SIDimensions}:
     NoDims        𝐓^-1
 𝐋^2 𝐌 𝐓^-2  𝐋^2 𝐌 𝐓^-3

julia> A == UnitfulTensor(V, D)
true

julia> inv(A)
2×2 UnitfulMatrix{Float64, SIDimensions, Matrix{Float64}, AxesDimensions{2, SIDimensions}}:
  -2.0   1.0 s^2 kg^-1 m^-2
 1.5 s  -0.5 s^3 kg^-1 m^-2

julia> inv(V)
2×2 Matrix{Float64}:
 -2.0   1.0
  1.5  -0.5
UnitfulTensors.AxesDimensionsMethod
AxesDimensions(A::AbstractArray{<:AbstractDimensions})

Convert an AbstractArray of physical dimensions to AxesDimensions, which enables efficient operations on the dimensions of unitful arrays.

UnitfulTensors.AxesDimensionsMethod
AxesDimensions(dims, scale; normalize = true)
AxesDimensions(dims; normalize = true)

Assemble AxesDimensions from the physical dimensions along each axis (dims) and an overall scalar factor (scale).

The inverse operation of factorizing AxesDimensions into dims and scale can be performed via normdims and dimscale.

dims can be a tuple of AxisDimensions or a tuple of Vectors of AbstractDimensions. If scale == NoDims, it can be omitted.

By default, dims are scaled by a scalar factor so that their first element is NoDims. If you are absolutely sure that dims already satisfy this condition, you may set normalize = false for performance.

UnitfulTensors.AxisDimensionsMethod
AxisDimensions(dims::AbstractVector; normalize = true)
AxisDimensions(dims::AbstractVector{<:AbstractDimensions}; normalize = true)

Convert an AbstractVector of AbstractDimensions to AxisDimensions.

By default, the dimensions are scaled by a scalar factor so that the first element of AxisDimensions is NoDims. If you are absolutely sure that dims already satisfy this condition, you may set normalize = false for performance.

​ Functions

UnitfulTensors.normdimsFunction
normdims(x::AbstractAxesDimensions)
normdims(x::AbstractAxisDimensions)
normdims(x::AbstractDimensions)
normdims(x::AbstractUnitfulTensor)

Get a tuple of AbstractAxisDimensions representing the physical dimensions of x along each axis.

AbstractAxisDimensions are normalized so that their first element is NoDims. The scalar normalization factor can be retrieved via dimscale(x).

For example, if x isa AbstractMatrixDimensions, normdims returns its row and column dimensions, and the elements of x satisfy x[i, j] == dimscale(x) * normdims(x)[1][i] * normdims(x)[2][j].

AbstractAxisDimensions and AbstractDimensions are treated as 1- and 0-dimensional AbstractAxesDimensions, respectively.

UnitfulTensors.dimscaleFunction
dimscale(x::AbstractAxesDimensions)
dimscale(x::AbstractAxisDimensions)
dimscale(x::AbstractDimensions)
dimscale(x::AbstractUnitfulTensor)

Get the first element of x.

AbstractAxesDimensions are factorized into an overall scalar factor, retrieved by dimscale, and zero or more AbstractAxisDimensions, which represent the physical dimensions along each axis. AbstractAxisDimensions are normalized so that their first element is NoDims and can be retrieved via normdims(x). Normalization ensures that the factorization is unique.

For example, if x isa AbstractMatrixDimensions, the elements of x satisfy x[i, j] == dimscale(x) * normdims(x)[1][i] * normdims(x)[2][j].

AbstractAxisDimensions and AbstractDimensions are treated as 1- and 0-dimensional AbstractAxesDimensions, respectively.

UnitfulTensors.nodimsFunction
nodims(size...)

Create AxesDimensions representing the physical dimensions of a dimensionless array of size size.

Examples

julia> nodims(2, 3)
2×3 AxesDimensions{2, SIDimensions}:
 NoDims  NoDims  NoDims
 NoDims  NoDims  NoDims

julia> UnitfulTensor([1 2 3; 4 5 6], 𝐍 * nodims(2, 3))
2×3 UnitfulMatrix{Int64, SIDimensions, Matrix{Int64}, AxesDimensions{2, SIDimensions}}:
 1 mol  2 mol  3 mol
 4 mol  5 mol  6 mol
UnitfulTensors.tensor_productFunction
tensor_product(xs::AbstractAxesDimensionsLike...; init = NoDims)

Compute the tensor product of AbstractAxesDimensions, AbstractAxisDimensions, or AbstractDimensions.

If the argument list may be empty, the init keyword must be supplied (NoDims if one works with SIDimensions). can be used as a shorthand.

Examples:

julia> 𝐋 ⊗ AxisDimensions([NoDims, 𝐌]) ⊗ AxisDimensions([NoDims, 𝐓])
2×2 AxesDimensions{2, SIDimensions}:
   𝐋    𝐋 𝐓
 𝐋 𝐌  𝐋 𝐌 𝐓
UnitfulTensors.tensor_factorizeFunction
tensor_factorize(A::AbstractAxesDimensions, factor_ndims::Tuple{Vararg{Int}})

Represent A as dimscale(A) ⊗ factors[1] ⊗ factors[2] ⊗ ..., where dimscale(factors[i]) == NoDims and ndims.(factors) == factor_ndims.

Returns (factors, dimscale(A)).

UnitfulTensors.ishomogeneousFunction
ishomogeneous(A::AbstractUnitfulTensor[, d::Integer]) -> Bool
ishomogeneous(A::AbstractAxesDimensions[, d::Integer]) -> Bool
ishomogeneous(A::AbstractArray{<:Number}[, d::Integer]) -> Bool
ishomogeneous(A::AbstractAxisDimensions) -> Bool

Test whether an array is dimensionally homogeneous (all of its elements have the same physical dimensions).

d can be provided to test homogeneity along a specific (mathematical) dimension.

Most of linear algebra can be applied to dimensionally homogeneous matrices. Notable functions that require homogeneity include svd and norm. Least-squares solution of an overdetermined system with \ or pinv requires homogeneity along the first dimension; otherwise the sum of squares is undefined.

UnitfulTensors.issquareableFunction
issquareable(A::AbstractUnitfulMatrix) -> Bool
issquareable(A::AbstractMatrixDimensions) -> Bool
issquareable(A::AbstractMatrix{<:Number}) -> Bool

Test whether a matrix can be squared.

Certain functions, such as eigen and tr, are defined only for squareable matrices.

UnitfulTensors.isendomorphicFunction
isendomorphic(A::AbstractUnitfulMatrix) -> Bool
isendomorphic(A::AbstractMatrixDimensions) -> Bool
isendomorphic(A::AbstractMatrix{<:Number}) -> Bool

Test whether a matrix is endomorphic (can represent a linear map from a vector space to itself).

Transcendental functions, such as exp and log, are defined only for endomorphic matrices.

UnitfulTensors.units_offFunction
units_off()

Switch from UnitfulScalars and UnitfulTensors to plain numbers and arrays of numbers, as if this package was not loaded.

If you are concerned with the overhead of using unitful quantities:

  • Run your code on a small-scale problem to check the units
  • Call units_off() immediately after using UnitfulTensors
  • Run your code on the actual large-scale problem

If you used UnitfulScalar(...), UnitfulTensor(...), and the number * u"unit" syntax for constructing unitful quantities, units_off() should eliminate all runtime overhead. Quantities are still converted to the default units (SI) upon construction, but then the units are stripped and the rest of the execution proceeds with plain numbers.

However, inner constructors like UnitfulScalar{Float64, SIDimensions}(1., 𝐓) will still produce unitful quantities, so don't use them.

There is no units_on switch at present. You will have to restart Julia if you need units again.

Examples

using UnitfulTensors, BenchmarkTools

13u"cm" |> println
typeof(13u"cm") |> println
u = UnitfulTensor([1u"eV", 2u"ns", 3u"μF"])
v = [1.602176634e-19, 1e-9, 3e-6]
@btime $v * $v'
@btime $u * $u'

units_off()
println()

13u"cm" |> println
typeof(13u"cm") |> println
u = UnitfulTensor([1u"eV", 2u"ns", 3u"μF"])
v = [1.602176634e-19, 1e-9, 3e-6]
@btime $v * $v'
@btime $u * $u'

# output

0.13 m
UnitfulScalar{Float64, SIDimensions}
  73.610 ns (1 allocation: 128 bytes)
  80.519 ns (1 allocation: 128 bytes)

0.13
Float64
  73.561 ns (1 allocation: 128 bytes)
  73.077 ns (1 allocation: 128 bytes)

3×3 Matrix{Float64}:
 2.56697e-38  3.20435e-28  4.80653e-25
 3.20435e-28  4.0e-18      6.0e-15
 4.80653e-25  6.0e-15      9.0e-12