Skip to content

Commit bb8b379

Browse files
authored
feat: add ustripexpand (#162)
* Add `sibasevalue` function * Define uexpand for quantities with Dimensions * Define `sibasevalue(q)=ustrip(uexpand(q)) When obtaining the numerical value of a quantity (e.g. for computations with sparse direct solvers implemented in other languages) via `ustrip`, there is danger of mixing up the right values when quantities with symbolic dimensions come into play. By adding a `uexpand` method for quantities with dimensions, which just passes through the value one can write code consistent for both flavors of quantities. `sibasevalue` shall help to remove a little bit of boilerplate and explicitely hint at the characteristics of the returned value. * Update format in test/unittests.jl Co-authored-by: Miles Cranmer <[email protected]> * remove unintended dependency in docs/Project.toml * sibasevalue -> ustripexpand * fix missing export of ustripexpand * implement suggested changes * define ustripexpand for UnionAbstractQuantity * docs: improve docstring * docs: clean up * style: sort exports * test: tweak tests
1 parent 9625403 commit bb8b379

File tree

5 files changed

+34
-6
lines changed

5 files changed

+34
-6
lines changed

docs/src/symbolic_units.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ To convert a quantity to its regular base SI units, use `uexpand`:
2424

2525
```@docs
2626
uexpand
27+
ustripexpand
2728
```
2829

2930
To convert a quantity in regular base SI units to corresponding symbolic units, use `uconvert`:

src/DynamicQuantities.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ export AbstractDimensions, Dimensions, NoDims
88
export AbstractSymbolicDimensions, SymbolicDimensions, SymbolicDimensionsSingleton
99
export QuantityArray
1010
export DimensionError
11-
export ustrip, dimension
11+
export ustrip, dimension, uexpand, uconvert, ustripexpand
1212
export ulength, umass, utime, ucurrent, utemperature, uluminosity, uamount
13-
export uparse, @u_str, sym_uparse, @us_str, uexpand, uconvert, @register_unit
13+
export uparse, @u_str, sym_uparse, @us_str, @register_unit
1414

1515
# Deprecated:
1616
export expand_units

src/symbolic_dimensions.jl

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ are so many unit symbols).
3434
3535
You can convert a quantity using `SymbolicDimensions` as its dimensions
3636
to one which uses `Dimensions` as its dimensions (i.e., base SI units)
37-
`uexpand`.
37+
with [`uexpand`](@ref).
3838
"""
3939
struct SymbolicDimensions{R} <: AbstractSymbolicDimensions{R}
4040
nzdims::Vector{INDEX_TYPE}
@@ -147,18 +147,23 @@ end
147147

148148

149149
"""
150-
uexpand(q::UnionAbstractQuantity{<:Any,<:AbstractSymbolicDimensions})
150+
uexpand(q::UnionAbstractQuantity)
151+
uexpand(q::QuantityArray)
151152
152-
Expand the symbolic units in a quantity to their base SI form.
153+
Expand the symbolic units in a quantity with symbolic dimensions to their base SI form.
153154
In other words, this converts a quantity with `AbstractSymbolicDimensions`
154155
to one with `Dimensions`. The opposite of this function is `uconvert`,
155156
for converting to specific symbolic units, or, e.g., `convert(Quantity{<:Any,<:AbstractSymbolicDimensions}, q)`,
156157
for assuming SI units as the output symbols.
158+
159+
For quantities with `Dimensions`, this function just passes through the value `q`.
157160
"""
161+
uexpand(q::Q) where {T,R,D<:AbstractDimensions{R},Q<:UnionAbstractQuantity{T,D}} = q
162+
uexpand(q::QuantityArray{T,N,D}) where {T,N,D} = q
158163
function uexpand(q::Q) where {T,R,D<:AbstractSymbolicDimensions{R},Q<:UnionAbstractQuantity{T,D}}
159164
return convert(with_type_parameters(Q, T, Dimensions{R}), q)
160165
end
161-
uexpand(q::QuantityArray) = uexpand.(q)
166+
uexpand(q::QuantityArray{T,N,D}) where {T,N,D<:AbstractSymbolicDimensions} = uexpand.(q)
162167
# TODO: Make the array-based one more efficient
163168

164169
"""
@@ -251,6 +256,15 @@ function Base.:(|>)(
251256
return uconvert(qout, q)
252257
end
253258

259+
"""
260+
ustripexpand(q::AbstractQuantity)
261+
ustripexpand(q::QuantityArray)
262+
263+
Return the value of `q` in SI base units. This is equivalent with `ustrip(uexpand(q))`.
264+
"""
265+
ustripexpand(q::UnionAbstractQuantity) = ustrip(uexpand(q))
266+
ustripexpand(q::QuantityArray) = ustrip(uexpand(q))
267+
254268

255269
Base.copy(d::SymbolicDimensions) = SymbolicDimensions(copy(nzdims(d)), copy(nzvals(d)))
256270
Base.copy(d::SymbolicDimensionsSingleton) = constructorof(typeof(d))(getfield(d, :dim))

src/utils.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,10 @@ Base.copy(q::Q) where {Q<:UnionAbstractQuantity} = new_quantity(Q, copy(ustrip(q
379379
ustrip(q::AbstractGenericQuantity)
380380
381381
Remove the units from a quantity.
382+
383+
!!! note
384+
385+
If using symbolic dimensions, you might also consider using [`ustripexpand`](@ref) to first convert to SI base units before stripping.
382386
"""
383387
@inline ustrip(q::UnionAbstractQuantity) = q.value
384388
ustrip(::AbstractDimensions) = error("Cannot remove units from an `AbstractDimensions` object.")

test/unittests.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,16 @@ end
855855
@test dimension(inv(us"s") * us"km") == dimension(us"km/s")
856856
@test dimension(inv(us"s") * us"m") != dimension(us"km/s")
857857
@test dimension(uexpand(inv(us"s") * us"m")) == dimension(uexpand(us"km/s"))
858+
859+
@test ustripexpand(u"h") == 3600.0
860+
@test ustripexpand(us"h") == 3600.0
861+
# Different behavior than ustrip alone:
862+
@test ustrip(us"h") == 1.0
863+
864+
@test ustripexpand(QuantityArray(fill(1.0,5), u"h")) == fill(3600.0, 5)
865+
@test ustripexpand(QuantityArray(fill(1.0,5), us"h")) == fill(3600.0, 5)
858866

867+
859868
f2(i::Int) = us"s"^i
860869
@inferred f2(5)
861870
@test uexpand(f2(5)) == u"s"^5

0 commit comments

Comments
 (0)