# DynamicQuantities.jl v0.7.0: efficient and type-stable physical quantities

**URL:** <https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709>\
**Category:** Package Announcements\
**Tags:** package, physics, unitful\
**Created:** [September 9, 2023, 11:48pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709 "2023-09-09T23:48:08Z")\
**Posts on this page:** 20\
**Page:** 2

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [March 11, 2024, 6:55pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/21 "2024-03-11T18:55:01Z")

</div>

> [@MilesCranmer](#):
>
> I mean, `W/arcmin^2` is by definition equivalent dimension to `W` in SI. I guess here you just mean it’s not convenient for astronomy (which is very fair!).

It’s completely orthogonal to astronomy, these are just fundamentally very different units. For example, in SI, lumen and candela aren’t the same unit – they are `1 lm = 1 cd·sr`. And if one ignores angular units in conversions, they end up with `1 lm = 1 cd` instead.

> [@MilesCranmer](#):
>
> I guess you could try to do something like this if you want?

Sounds similar to what DimensionfulAngles.jl does. It would resolve the issue if everyone used these units instead of regular `u"arcmin"`. Otherwise, you have some library function that returns `W/arcmin^2`, but downstream conversions cannot distinguish it from `W`.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [March 11, 2024, 6:57pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/22 "2024-03-11T18:57:04Z")

</div>

The `|>` docstring says

> |\>(x, f)
> 
> Infix operator which applies function f to the argument x. This allows f(g(x)) to be  
> written x |\> g |\> f.

Does this mean units are now callable, or is this introducing a special case?

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 11, 2024, 6:58pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/23 "2024-03-11T18:58:11Z")

</div>

It’s just not really practical to start adding another field for all the dimensions people may care about. If you need another dimension that is not part of the SI base units, it’s easy enough to declare a custom struct. I don’t want to violate SI in the main package though.

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 11, 2024, 6:59pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/24 "2024-03-11T18:59:59Z")

</div>

> [@jar1](#):
>
> Does this mean units are now callable, or is this introducing a special case?

Only `|>` is defined, rather than making quantities themselves callable (which we thought would introduce a bunch of potential bugs)

> <https://github.com/SymbolicML/DynamicQuantities.jl/blob/1f996f3b26d1532d6f90916402ec6efb20d97e43/src/symbolic_dimensions.jl#L241-L252>

---

<div class="post-metadata">

**Author:** ![aplavin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/aplavin/32/222056_2.png) [@aplavin](https://discourse.julialang.org/u/aplavin)\
**Post date:** [March 11, 2024, 7:01pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/25 "2024-03-11T19:01:49Z")

</div>

> [@MilesCranmer](#):
>
> I don’t want to violate SI in the main package though.

Don’t see how disallowing conversion between lumen and candela would be a SI violation. That seems a pretty strong take IMO.  
They are defined in SI as different units, used for different dimensions.

Anyway, I’ll stop here. I think I kinda explained my PoV and how this “ignore angular units” approach is fundamentally more error-prone by allowing conversion between incompatible units. Meanwhile, “distinguish angular units by default” covers strictly more usecases.

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 11, 2024, 7:06pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/26 "2024-03-11T19:06:49Z")

</div>

> [@aplavin](#):
>
> Don’t see how disallowing conversion between lumen and candela would be a SI violation. That seems a pretty strong take IMO.

> **[International System of Units | Derived units](https://en.wikipedia.org/wiki/International_System_of_Units#Derived_units)**
>
> The system allows for an unlimited number of additional units, called derived units, which can always be represented as products of powers of the base units, possibly with a nontrivial numeric multiplier. When that multiplier is one, the unit is called a coherent derived unit. For example, the coherent derived SI unit of velocity is the metre per second, with the symbol m/s.: 139  The base and coherent derived units of the SI together form a coherent system of units (the set of coherent SI uni Tw...

My only opinion here is that the package should respect the SI unit system. If `1 rad = 1` in SI that’s what the package does. Like you, I would also prefer to track angles in the base units, but I think standards are more important than my subjective view, so this is what I went with.

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [March 11, 2024, 9:23pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/27 "2024-03-11T21:23:44Z")

</div>

The way I read that table of “derived units” in the “Derived units” section of that wiki article is that radian and steradian are official SI derived units. They are _dimensionless_, but they are not _unitless_.

Typical dimensions include length `[L]`, mass `[M]`, and time `[T]`. A radian has dimensions `[L]/[L] = 1`, so it is dimensionless. But it is still a unit!

In other words, the SI system _requires_ keeping track of dimensionless units like radian and steradian.

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 11, 2024, 9:31pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/28 "2024-03-11T21:31:03Z")

</div>

In DynamicQuantities.jl, `SymbolicDimensions` (with `us"..."`) are how you can represent derived SI units (and whatever other symbols you want). But a `Dimensions` (with `u"..."`) exclusively stores SI base units.

```julia
julia> x = us"rad" # Derived SI units
1.0 rad

julia> dimension(x).rad
1

julia> uexpand(x) # Base SI units
1.0

julia> y = us"J"
1.0 J

julia> dimension(y).J
1

julia> uexpand(y)
1.0 m² kg s⁻²

```

Does that help?

---

<div class="post-metadata">

**Author:** ![CameronBieganek](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cameronbieganek/32/6915_2.png) [@CameronBieganek](https://discourse.julialang.org/u/CameronBieganek)\
**Post date:** [March 11, 2024, 9:45pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/29 "2024-03-11T21:45:13Z")

</div>

I haven’t used DynamicQuantities before, and I’ve barely used Unitful. So I don’t understand the output of `dimension(y).J`. Shouldn’t that be something like `m² kg s⁻²` or `[L]² [M] [T]⁻²`?

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 11, 2024, 9:57pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/30 "2024-03-11T21:57:18Z")

</div>

I suggest reviewing the DynamicQuantities documentation [here](https://symbolicml.org/DynamicQuantities.jl/dev/) for clarity on the key functions and unit handling. Happy to discuss further if needed.

---

<div class="post-metadata">

**Author:** ![ggggggggg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ggggggggg/32/265_2.png) [@ggggggggg](https://discourse.julialang.org/u/ggggggggg)\
**Post date:** [March 12, 2024, 3:23pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/31 "2024-03-12T15:23:23Z")

</div>

`1 rad = 1` is what the SI system defines, but it is not useful. It’s confusing. If someone is using a unit tracking system to track the `rad` they asking for some useful behavior.

I agree with aplavin’s argument that it’s much more error prone to ignore angular units by default than it is to prevent “SI allowed” conversions by default. I suggest either not including angular units (no loss of functionality, just multiply by `1` if you want a `rad` or an `sr`) or having separate angular unit (`rad_si`) to express the SI behavior. OR (and this is the best choice IMHO) requiring an explicit request to allow conversions that rely on `rad=1`. It doesn’t violate the SI to require this request, it just requires a bit of ceremony to engage with the single most confusing part of the SI.

I think you may be heartened to know that it’s not just random internet people who are arguing for unitful radians. Many scientists including those from national metrology institutes that are responsible for providing standards to “realize” the SI units also argue for unitful radians. Many physicists argue that only the minimum set of fundamental base units should be included in the, which would exclude the `mol` (just a number, 10 isn’t a unit so why is the `mol`?) and the `candela` (which is about human perception of light rather than light itself). so why are you only seeing complaints about `rad` when the `candela` and `mol` is also controversial in the SI? Because we don’t actually want a super principled unit implementation, they want something useful, and despite their flaws, the `mol` and `candela` are useful, while the unitless `rad` is not. Below are some papers criticizing the SI, 4 on topic of unitful radians and one on the `candela`.

1. [Proposal for the dimensionally consistent treatment of angle and solid angle by the International System of Units (SI)](https://iopscience.iop.org/article/10.1088/1681-7575/abe0fc/meta) This author is from BIPM, which until the redefinition of the SI had the artifact standards which defined the meter and the kilogram for the entire world. He argues for a angle base unit.
2. [Physiological Units in the SI](https://iopscience.iop.org/article/10.1088/0026-1394/30/2/001/meta) argues for a new concept of “physiological derived unit” so that the candela would no longer be a base unit.
3. [Angles in the SI: treating the radian as an independent, unhidden unit does not require the redefinition of the term ‘frequency’ or the unit hertz](https://iopscience.iop.org/article/10.1088/1681-7575/ab931e/meta#metab931ebib6) Also arguing for an angle base unit.
4. [A proposal to classify the radian as a base unit in the SI](https://arxiv.org/pdf/1604.06774.pdf) Nobel prize winner William Phillips from NIST, the US institute of Standards and Technology argues that the radian should be a base unit.
5. [Proposal for the dimensionally consistent treatment of angle and solid angle by the International System of Units](https://iopscience.iop.org/article/10.1088/1681-7575/ab3fbf/met)

I strongly encourage you to reconsider that “doing exactly what the SI says” is the best choice, instead do what is useful to your users.

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 12, 2024, 4:04pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/32 "2024-03-12T16:04:51Z")

</div>

@ggggggggg why did you delete your post? It looked like you had some good references. I think having concrete papers to point to (like you had) on modifications to SI is very good and makes me want to reconsider my opinion 🙂 Especially if someone has worked out all the issues and found it can be made robust.

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 12, 2024, 4:07pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/33 "2024-03-12T16:07:41Z")

</div>

p.s., another alternative is to have the `AngleDimensions` I suggested above as a built-in

```julia
julia> struct AngleDimensions{R} <: AbstractDimensions{R}
           length::R
           mass::R
           time::R
           current::R
           temperature::R
           luminosity::R
           amount::R
           angle::R
       end

```

and set up promotion rules so that if it collides with any regular `Dimensions` object, it converts it into the `AngleDimensions`. It’s a lot of work though so I won’t work on this myself. But if someone cares enough about this to actually contribute it, I’d welcome it.

---

<div class="post-metadata">

**Author:** ![Jake](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jake/32/46007_2.png) [@Jake](https://discourse.julialang.org/u/Jake)\
**Post date:** [March 12, 2024, 4:17pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/34 "2024-03-12T16:17:24Z")

</div>

I have not reviewed the Wikipedia article, but my favourite source for information on SI is [NIST](https://physics.nist.gov/cuu/pdf/sp811.pdf). I assume that Wikipedia is heavily based on this document.

Strain is similar to angle in that it is determined as ΔL/L which is also unitless but often given as μm/m.

Another is that the units of energy (work) and torque are the same in base units. Both are N \* m, but are fundamentally different.

My favourite is fuel consumption. Since I am from Canada we use liter/(100 km) which becomes L^3/L or L^2. So I can give my car’s fuel economy in hectares , or acres if you prefer.

Units are fun, I like the idea of using SI as a reference and NIST is a good place to go for this reference.

---

<div class="post-metadata">

**Author:** ![ggggggggg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ggggggggg/32/265_2.png) [@ggggggggg](https://discourse.julialang.org/u/ggggggggg)\
**Post date:** [March 12, 2024, 4:36pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/35 "2024-03-12T16:36:08Z")

</div>

I undeleted it since you seem happy about it. The reason I deleted it was that I was about to write a follow up post, and it felt like I was going to pile on and it might be overall discouraging. If you’re into it, then I do have more input I’d like to share

The suggestion to use symbolic units to “avoid” `1 rad = 1` feels worse than not having it to me, since it dissapears as soon as you interact with normal units. I haven’t wrapped my head around your goals with symbolic units fully, and I find their behavior quite surprising. For example I can’t add `m` and `mm` when they’re symbolic which gives this very odd error message  
`1us"m"+1us"mm" = DimensionError: 1.0 m and 1.0 mm have incompatible dimensions`  
nor can I add `rad` and `sr` which is something the docs suggest is a plus  
`1us"rad" +1us"sr"=DimensionError: 1.0 rad and 1.0 sr have incompatible dimensions`  
but I can easily add them if I change just one character  
`1us"rad"+1u"sr"=2.0`  
and that ease of changing behavior feels very footgunny to me, though I haven’t come up with any examples outside of `rad` where it is really problematic.

Do you have any plans to support displaying the working units. Eg `1u"nm"*1u"eV"=1 eV nm` until at some point it’s requested to be reduced to base or unified with another compatible unit?

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 12, 2024, 4:45pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/36 "2024-03-12T16:45:25Z")

</div>

I wouldn’t say I am necessarily ‘happy’ with it; more I just feel like the safest thing to do is go with the international standard. But I am very happy to be proven wrong – I just want the proof to be in the form of studies/papers rather than strong opinions and small code examples. My worry is that if I were to adopt some non-standard mixed SI system, it would introduce inconsistencies we haven’t thought of yet (but that SI has thought of – which is why they’ve made the choice of choosing slightly inconvenient unit system).

SI has put much more thought into units than any of us so I am basically just looking for a very strong evidence to switch (but I do not have any reason to prefer one over the other; I don’t really care either way).

> [@ggggggggg](#):
>
> Do you have any plans to support displaying the working units. Eg `1u"nm"*1u"eV"=1 eV nm` until at some point it’s requested to be reduced to base or unified with another compatible unit?

This is the purpose of the symbolic units with `us"..."`

```julia
julia> using DynamicQuantities

julia> 1us"nm"*1us"Constants.eV"
1.0 nm eV

julia> ans |> uexpand
1.602176634e-28 m³ kg s⁻²

```

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 12, 2024, 4:51pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/37 "2024-03-12T16:51:01Z")

</div>

> [@ggggggggg](#):
>
> For example I can’t add `m` and `mm` when they’re symbolic which gives this very odd error message  
> `1us"m"+1us"mm" = DimensionError: 1.0 m and 1.0 mm have incompatible dimensions`  
> nor can I add `rad` and `sr` which is something the docs suggest is a plus

This is the intended behavior. It makes it clear to the user that they are adding units of different scale. (Also happy to reconsider this. I added it as @odow wanted it for JuMP).

If you want to get around this, you can just do:

1. `1.5us"m" + (3us"mm" |> us"m")`, or
2. `1.5us"m" + (3us"mm" |> uexpand)` which will convert to `Dimensions`, or
3. just work in the base SI units with `1.5u"m" + 3u"mm"`.

Working in the base SI units is always faster in DynamicQuantities.jl because it only needs to track 7 numbers in an immutable struct, rather than two sparse arrays as in SymbolicDimensions

---

<div class="post-metadata">

**Author:** ![MilesCranmer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/milescranmer/32/21070_2.png) [@MilesCranmer](https://discourse.julialang.org/u/MilesCranmer)\
**Post date:** [March 12, 2024, 5:00pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/38 "2024-03-12T17:00:58Z")

</div>

Here’s a full implementation of `AngleDimensions`. This is probably good to add as an example to the documentation for extending DynamicQuantities:

```julia
using DynamicQuantities
import DynamicQuantities: DynamicQuantities as DQ

struct AngleDimensions{R} <: AbstractDimensions{R}
    length::R
    mass::R
    time::R
    current::R
    temperature::R
    luminosity::R
    amount::R
    angle::R
end

# field -> string mapping
function DQ.dimension_name(::AngleDimensions, k::Symbol)
    default_dimensions = (
        length = "m",
        mass = "kg",
        time = "s",
        current = "A",
        temperature = "K",
        luminosity = "cd",
        amount = "mol",
        angle = "rad",
    )
    return get(default_dimensions, k, string(k))
end

function Base.promote_rule(::Type{AngleDimensions{R1}}, ::Type{Dimensions{R2}}) where {R1,R2}
    return AngleDimensions{promote_type(R1, R2)}
end
function (::Type{AngleDimensions{R}})(d::Dimensions) where {R}
    return AngleDimensions{R}(
        d.length, d.mass, d.time, d.current, d.temperature, d.luminosity, d.amount, zero(R),
    )
end

const rad = Quantity(1.0, AngleDimensions(angle = 1))

```

Then, we can do operations with `rad` as follows:

```julia
julia> θ = 0.02rad # AngleDimensions-based
0.02 rad

julia> distance = 10u"km" # Dimensions
10000.0 m

julia> θ * distance # Promotes to AngleDimensions
200.0 m rad

```

---

<div class="post-metadata">

**Author:** ![ggggggggg](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ggggggggg/32/265_2.png) [@ggggggggg](https://discourse.julialang.org/u/ggggggggg)\
**Post date:** [March 12, 2024, 7:33pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/39 "2024-03-12T19:33:18Z")

</div>

One more comment. I was re-reading some of the references, and many of them call out software specifically as being an area where rigorous treatment of radians is needed. For example from Ref 1 above:

“These seemingly ad hoc ‘rules’ for getting the ‘appropriate’ answer are at the core of the widespread confusion about angle (and solid angle), in general, and about the radian (and steradian), in particular. Since these ‘rules’ require human experience and ‘insight’ to apply, they do not translate easily into programing algorithms for computer-aided physics and engineering calculation software.”

---

<div class="post-metadata">

**Author:** ![juliohm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/juliohm/32/215266_2.png) [@juliohm](https://discourse.julialang.org/u/juliohm)\
**Post date:** [March 12, 2024, 7:43pm UTC](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709/40 "2024-03-12T19:43:07Z")

</div>

I sympathize with the issue of angles. It is one of our pain points with Unitful.jl

Many other people also dislike the way Unitful.jl handles angles, precisely because of the SI rules. Examples include UnitfulAngles.jl and DimensionfulAngles.jl

It would be really nice to treat angles with a more practical set of rules, ideally allowing to differentiate between angles and raw unitless numbers.

The lack of explicit treatment of angles leads to our inability to represent things like `34° 24' 16''` with Unitful.jl or any other package. These are angles expressed as Degree Minute Second (DMS), yet another popular alternative to Radians or Degrees.

[Previous page](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709.md?page=1)

[Next page](https://discourse.julialang.org/t/dynamicquantities-jl-v0-7-0-efficient-and-type-stable-physical-quantities/103709.md?page=3)
