Skip to content

Commit

Permalink
implemented dimenionOf methods for AbstractUnit and AbstractQuantity
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Hümmer committed Mar 3, 2021
1 parent 8b892ca commit feecb0c
Show file tree
Hide file tree
Showing 11 changed files with 343 additions and 82 deletions.
2 changes: 2 additions & 0 deletions docs/src/reference/quantities.md
Expand Up @@ -56,6 +56,8 @@ Base.:/(::Any, ::AbstractUnit)
Dimension
Base.:*(::Number, ::Dimension)
Base.:+(::Dimension, ::Dimension)
dimensionOf(::AbstractUnit)
dimensionOf(::AbstractQuantity)
```

## InternalUnits
Expand Down
4 changes: 2 additions & 2 deletions src/Alicorn.jl
Expand Up @@ -41,9 +41,9 @@ export inUnitsOf
export inBasicSIUnits

export Dimension
export InternalUnits
export dimensionOf

export Dimens # TODO
export InternalUnits

include("PrettyPrinting/PrettyPrinting.jl")

Expand Down
4 changes: 2 additions & 2 deletions src/PrettyPrinting/BaseUnitExponents.jl
Expand Up @@ -12,7 +12,7 @@ function _generateLongStringRepresentation(baseUnitExp::BaseUnitExponents)
exponents = _getExponentsAsArray(baseUnitExp)
prettyString = ""
for exp in exponents
prettyString = _addLongPrettyFactor(prettyString, exp)
prettyString = _addLongPrettyFactor_BaseUnitExponents(prettyString, exp)
end
return prettyString
end
Expand All @@ -30,7 +30,7 @@ function _getExponentsAsArray(baseUnitExp::BaseUnitExponents)
return exponents
end

function _addLongPrettyFactor(prettyString::String, exp::Tuple)
function _addLongPrettyFactor_BaseUnitExponents(prettyString::String, exp::Tuple)
(symbol, exponent) = exp

expString = prettyPrintScientificNumber(exponent, sigdigits=2)
Expand Down
40 changes: 40 additions & 0 deletions src/PrettyPrinting/Dimension.jl
@@ -0,0 +1,40 @@
function Base.show(io::IO, dimension::Dimension)
output = _generateLongPrettyPrintingOutput(dimension)
print(io, output)
end

function _generateLongPrettyPrintingOutput(dimension::Dimension)
prettyString = _generateLongStringRepresentation(dimension)
return "Dimension " * prettyString
end

function _generateLongStringRepresentation(dimension::Dimension)
exponents = _getExponentsAsArray(dimension)
prettyString = ""
for exp in exponents
prettyString = _addLongPrettyFactor_Dimension(prettyString, exp)
end
return prettyString
end

function _getExponentsAsArray(dimension::Dimension)
exponents = [
("M", dimension.massExponent),
("L", dimension.lengthExponent),
("T", dimension.timeExponent),
("I", dimension.currentExponent),
("θ", dimension.temperatureExponent),
("N", dimension.amountExponent),
("J", dimension.luminousIntensityExponent)
]
return exponents
end

function _addLongPrettyFactor_Dimension(prettyString::String, exp::Tuple)
(symbol, exponent) = exp

expString = prettyPrintScientificNumber(exponent, sigdigits=2)
addString = "$symbol^$expString"

return _addStringWithWhitespace( prettyString, addString )
end
1 change: 1 addition & 0 deletions src/PrettyPrinting/PrettyPrinting.jl
Expand Up @@ -20,5 +20,6 @@ include("UnitCatalogue.jl")
include("Unit.jl")

include("SimpleQuantity.jl")
include("Dimension.jl")

end # module
180 changes: 153 additions & 27 deletions src/Quantities/Dimension.jl
Expand Up @@ -4,20 +4,34 @@ export Dimension
@doc raw"""
Dimension
The dimension of a physical quantity, expressed as a collection of powers exponentiating each of the seven basic dimensions of the SI system.
The dimension of a physical quantity.
The dimension is expressed as a collection ``(a, b, c, d, e, f, g)``of powers exponentiating each of the seven basic dimensions of the SI system,
```math
\mathrm{M}^a \, \mathrm{L}^b \, \mathrm{T}^c \, \mathrm{I}^d \, \mathrm{\Theta}^e \, \mathrm{N}^f \, \mathrm{J}^g,
```
where
- ``\mathrm{M}``: mass dimension
- ``\mathrm{L}``: length dimension
- ``\mathrm{T}``: time dimension
- ``\mathrm{I}``: electrical current dimension
- ``\mathrm{\Theta}``: temperature dimension
- ``\mathrm{N}``: amount of substance dimension
- ``\mathrm{J}``: luminous intensity dimension
# Fields
- `massExponent::Real`
- `lengthExponent::Real`
- `timeExponent::Real`
- `currentExponent::Real`
- `temperatureExponent::Real`
- `amountExponent::Real`
- `luminousIntensityExponent::Real`
- `massExponent::Real`: exponent ``a`` of the mass dimension
- `lengthExponent::Real`: exponent ``b`` of the length dimension
- `timeExponent::Real`: exponent ``c`` of the time dimension
- `currentExponent::Real`: exponent ``d`` of the electrical current dimension
- `temperatureExponent::Real`: exponent ``e`` of the temperature dimension
- `amountExponent::Real`: exponent ``f`` of the amount of substance dimension
- `luminousIntensityExponent::Real`: exponent ``g`` of the luminous intensity dimension
# Constructor
```
Dimension(; length::Real=0, mass::Real=0, time::Real=0, current::Real=0, temperature::Real=0, amount::Real=0, luminousIntensity::Real=0)
Dimension(; M::Real=0, L::Real=0, T::Real=0, I::Real=0, θ::Real=0, N::Real=0, J::Real=0)
```
# Raises Exceptions
- `Core.DomainError`: if attempting to initialize any field with an infinite number
Expand All @@ -26,7 +40,19 @@ Dimension(; length::Real=0, mass::Real=0, time::Real=0, current::Real=0, tempera
The constructor converts any exponent to `Int` if possible.
# Examples
TODO
Quantities describing an energy are of dimension
```math
\mathrm{M} \, \mathrm{L}^{2} \, \mathrm{T}^{-2}
```
The corresponding `Dimension` object is:
```jldoctest
julia> Dimension(M=1, L=2, T=-2)
Dimension M^1 L^2 T^-2 I^0 θ^0 N^0 J^0
```
Calling the constructor without any keyword arguments returns exponents that correspond to a dimensionless quantity:
```jldoctest
julia> Dimension()
Dimension M^0 L^0 T^0 I^0 θ^0 N^0 J^0
```
"""
struct Dimension
Expand All @@ -38,8 +64,8 @@ struct Dimension
amountExponent::Real
luminousIntensityExponent::Real

function Dimension(; length::Real=0, mass::Real=0, time::Real=0, current::Real=0, temperature::Real=0, amount::Real=0, luminousIntensity::Real=0)
exponents = (mass, length, time, current, temperature, amount, luminousIntensity)
function Dimension(; M::Real=0, L::Real=0, T::Real=0, I::Real=0, θ::Real=0, N::Real=0, J::Real=0)
exponents = (M, L, T, I, θ, N, J)
_assertExponentsAreFinite(exponents)
exponents = _tryCastingExponentsToInt(exponents)
new(exponents...)
Expand All @@ -64,18 +90,30 @@ Base.broadcastable(dimension::Dimension) = Ref(dimension)

"""
Base.:*(number::Number, dimension::Dimension)
Base.:*(dimension::Dimension, number::Number)
TODO
Multiply each exponent in `dimension` by `number`. The result is the dimension
of a quantity of dimension `dimension` when it is raised to the power of
`number`.
# Example
```jldoctest
julia> lengthExps = Dimension(L=1)
Dimension M^0 L^1 T^0 I^0 θ^0 N^0 J^0
julia> lengthSqrdExps = 2 * lengthExps
Dimension M^0 L^2 T^0 I^0 θ^0 N^0 J^0
```
"""
function Base.:*(number::Number, dimension::Dimension)
resultingDimension = Dimension(
mass = number * dimension.massExponent,
length = number * dimension.lengthExponent,
time = number * dimension.timeExponent,
current = number * dimension.currentExponent,
temperature = number * dimension.temperatureExponent,
amount = number * dimension.amountExponent,
luminousIntensity = number * dimension.luminousIntensityExponent
M = number * dimension.massExponent,
L = number * dimension.lengthExponent,
T = number * dimension.timeExponent,
I = number * dimension.currentExponent,
θ = number * dimension.temperatureExponent,
N = number * dimension.amountExponent,
J = number * dimension.luminousIntensityExponent
)
return resultingDimension
end
Expand All @@ -88,17 +126,105 @@ end
"""
Base.:+(dimension1::Dimension, dimension2::Dimension)
Add each exponent in `dimension1` to its counterpart in `dimension2`.
This operation corresponds to multiplying the two corresponding dimensions.
# Example
TODO
"""
function Base.:+(dimension1::Dimension, dimension2::Dimension)
resultingExponents = Dimension(
mass = dimension1.massExponent + dimension2.massExponent,
length = dimension1.lengthExponent + dimension2.lengthExponent,
time = dimension1.timeExponent + dimension2.timeExponent,
current = dimension1.currentExponent + dimension2.currentExponent,
temperature = dimension1.temperatureExponent + dimension2.temperatureExponent,
amount = dimension1.amountExponent + dimension2.amountExponent,
luminousIntensity = dimension1.luminousIntensityExponent + dimension2.luminousIntensityExponent
M = dimension1.massExponent + dimension2.massExponent,
L = dimension1.lengthExponent + dimension2.lengthExponent,
T = dimension1.timeExponent + dimension2.timeExponent,
I = dimension1.currentExponent + dimension2.currentExponent,
θ = dimension1.temperatureExponent + dimension2.temperatureExponent,
N = dimension1.amountExponent + dimension2.amountExponent,
J = dimension1.luminousIntensityExponent + dimension2.luminousIntensityExponent
)
return resultingExponents
end

export dimensionOf
@doc raw"""
dimensionOf(abstractUnit::AbstractUnit)
Returns the dimension of a physical unit of type [`AbstractUnit`](@ref).
# Example
One siemens is defined as ``1\,\mathrm{S} = 1\,\mathrm{kg}^{-1}\,\mathrm{m}^{-2}\,\mathrm{s}^3\,\mathrm{A}^2``. The unit is hence of dimension ``\mathrm{M}^{-1}\,\mathrm{L}^{-2}\,\mathrm{T}^3\,\mathrm{I}^2``:
```jldoctest
julia> ucat = UnitCatalogue() ;
julia> siemens = ucat.siemens
BaseUnit siemens (1 S = 1 kg^-1 m^-2 s^3 A^2)
julia> dimensionOf(siemens)
Dimension M^-1 L^-2 T^3 I^2 θ^0 N^0 J^0
```
"""
function dimensionOf(abstractUnit::AbstractUnit)
unit = convertToUnit(abstractUnit)
return dimensionOf(unit)
end

# documented together with dimensionOf(abstractUnit::AbstractUnit)
function dimensionOf(unit::Unit)
unitFactors = unit.unitFactors

unitFactor_dimensions = map(dimensionOf, unitFactors)
dimension = sum(unitFactor_dimensions)
return dimension
end

# documented together with dimensionOf(abstractUnit::AbstractUnit)
function dimensionOf(unitFactor::UnitFactor)
baseUnit = unitFactor.baseUnit
exponent = unitFactor.exponent

baseUnit_dimension = dimensionOf(baseUnit)
dimension = exponent * baseUnit_dimension
return dimension
end

# documented together with dimensionOf(abstractUnit::AbstractUnit)
function dimensionOf(baseUnit::BaseUnit)
baseUnitExps = baseUnit.exponents

dimension = Dimension(
M = baseUnitExps.kilogramExponent,
L = baseUnitExps.meterExponent,
T = baseUnitExps.secondExponent,
I = baseUnitExps.ampereExponent,
θ = baseUnitExps.kelvinExponent,
N = baseUnitExps.molExponent,
J = baseUnitExps.candelaExponent,
)
return dimension
end

@doc raw"""
dimensionOf(abstractQuantity::AbstractQuantity)
Returns the dimension of a physical quantity of type [`AbstractQuantity`](@ref).
# Example
One henry is defined as ``1\,\mathrm{H} = 1\,\mathrm{kg}^{1}\,\mathrm{m}^{2}\,\mathrm{s}^{-2}\,\mathrm{A}^{-2}`` and is hence of dimension ``\mathrm{M}^{1}\,\mathrm{L}^{2}\,\mathrm{T}^{-2}\,\mathrm{I}^{-2}``:
```jldoctest
julia> ucat = UnitCatalogue() ;
julia> oneHenry = 1 * ucat.henry
1 H
julia> dimensionOf(oneHenry)
Dimension M^1 L^2 T^-2 I^-2 θ^0 N^0 J^0
```
"""
function dimensionOf(abstractQuantity::AbstractQuantity)
simpleQuantity = inBasicSIUnits(abstractQuantity)
return dimensionOf(simpleQuantity)
end

# documented together with dimensionOf(abstractQuantity::AbstractQuantity)
function dimensionOf(simpleQuantity::SimpleQuantity)
unit = simpleQuantity.unit
return dimensionOf(unit)
end
22 changes: 14 additions & 8 deletions src/Units/BaseUnitExponents.jl
Expand Up @@ -4,16 +4,22 @@ export BaseUnitExponents
@doc raw"""
BaseUnitExponents
Collection of powers exponentiating each of the seven SI basic units. The [`BaseUnit`](@ref) type uses `BaseUnitExponents` to define named units in terms of the basic units.
Collection of powers exponentiating each of the seven SI basic units.
The exponents ``(a, b, c, d, e, f, g)`` are interpreted as the powers to which the seven SI basic units are raised:
```math
\mathrm{kg}^a \, \mathrm{m}^b \, \mathrm{s}^c \, \mathrm{A}^d \, \mathrm{K}^e \, \mathrm{mol}^f \, \mathrm{cd}^g.
```
The [`BaseUnit`](@ref) type uses `BaseUnitExponents` to define named units in terms of the basic units.
# Fields
- `kilogramExponent::Real`
- `meterExponent::Real`
- `secondExponent::Real`
- `ampereExponent::Real`
- `kelvinExponent::Real`
- `molExponent::Real`
- `candelaExponent::Real`
- `kilogramExponent::Real`: power ``a`` of kilogram
- `meterExponent::Real`: power ``b`` of meter
- `secondExponent::Real`: power ``c`` of second
- `ampereExponent::Real`: power ``d`` of ampere
- `kelvinExponent::Real`: power ``e`` of kelvin
- `molExponent::Real`: power ``f`` of mol
- `candelaExponent::Real`: power ``g`` of candela
# Constructor
```
Expand Down
24 changes: 23 additions & 1 deletion test/PrettyPrinting/PrettyPrintingTests.jl
Expand Up @@ -16,7 +16,8 @@ function run()
@test unitPrettyPrinting()

@test simpleQuantityPrettyPrinting()
end
@test dimensionPrettyPrinting()
end
end

## Numbers
Expand Down Expand Up @@ -215,4 +216,25 @@ function _getSimpleQuantityExamples()
]
end

## Dimension

function dimensionPrettyPrinting()
examples = _getDimensionExamples()
return _verifyPrettyPrintingImplemented(examples)
end

function _getDimensionExamples()
examples = [
( Dimension(), "Dimension M^0 L^0 T^0 I^0 θ^0 N^0 J^0"),
( Dimension(M=1), "Dimension M^1 L^0 T^0 I^0 θ^0 N^0 J^0"),
( Dimension(L=2), "Dimension M^0 L^2 T^0 I^0 θ^0 N^0 J^0"),
( Dimension(L=2, T=1.554), "Dimension M^0 L^2 T^1.6 I^0 θ^0 N^0 J^0"),
( Dimension(T=1.554, I=pi), "Dimension M^0 L^0 T^1.6 I^3.1 θ^0 N^0 J^0"),
( Dimension(T=1.554, I=pi, θ=-1), "Dimension M^0 L^0 T^1.6 I^3.1 θ^-1 N^0 J^0"),
( Dimension(T=1.554, N=pi, θ=-1), "Dimension M^0 L^0 T^1.6 I^0 θ^-1 N^3.1 J^0"),
( Dimension(J=-70), "Dimension M^0 L^0 T^0 I^0 θ^0 N^0 J^-7e+1")
]
return examples
end

end # module

0 comments on commit feecb0c

Please sign in to comment.