-
Notifications
You must be signed in to change notification settings - Fork 114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Define helpers for unitful interfaces. #698
base: master
Are you sure you want to change the base?
Conversation
This commit adds two simple functions `similar_dims` (and `similar_units`) that return a `Quantity` type with the dimensions (and units) constrained to those of the parameters I found myself trying to write simulation code with strongly typed interfaces, i.e. including information about the units. Initially I wrote my interfaces like so: ```julia const Meters = typeof(1.0m); circumference_of_circle(r::Meters) = pi*r^2 ``` However, when trying to autodiff through this code, I run into a problem, because `Meters` has the numerical type `Float64` baked in, and autodiff evaluates on a type `Quantity{Dual{Float64}}` (roughly). We can instead define `Meters` like so: ```julia const Meters{T<:Real} = Quantity{T, dimension(1.0m), unit(1.0m)} circumference_of_circle(r::Meters{T}) where {T} = pi*r^2 circumference_of_circle(r::Quantity{T, dimension(1.0m), unit(1.0m)}) where {T} = pi*r^2 ``` but I thought a better approach would be to provide some syntactic sugar to this "unit constraint". With this PR, we can write ```julia circumference_of_circle(r::similar_dims(u"m")) where {T} = pi*r^2 circumference_of_circle(r::similar_units(u"m")) where {T} = pi*r^2 ``` The difference is that the first one only constrains the dimension, and the latter constrains both dimension and unit (i.e. doesn't allow e.g. `km`). I'm happy to receive any feedback on the idea and the naming. Other names could be e.g. `quantity_with_dims` (but too long for my taste), or `dims_as` etc., but `similar` is already Julia lingo and feels appropriate in this context.
Instead of
Is there a reason for only allowing |
Rewrite the tests as type-checks only as suggested in the PR review. Co-authored-by: Sebastian Stock <[email protected]>
Thanks for the review. To your points:
That is true for "atomic" dimensions, but becomes much more difficult for any composite dimensions (e.g. energy). julia> kinetic_energy(mass::WithUnits(kg), velocity::WithUnits(m/s))::WithUnits(J) = mass*velocity^2 |> x->uconvert(J, x)
julia> kinetic_energy(1000kg, uconvert(m/s, 100km/hr))
62500000//81 J
import Uniful: Length, Time
kinetic_energy(mass::Mass, velocity::Length/Time) = mass*velocity^2
That is true, and until I read your comment I have also never considered non-real unitful quantities.
|
That is true, I can get to that still. There seems to be |
Using complex numbers for electrical units like voltage, current, or impedance is a very common case in electrical engineering.
Sure. It is "only" a way of concise representation of complex relations. But then, most of the mathematics is "only" a way of concise representation of complex relations.
Complex numbers can be equally used to represent oscillation processes of any nature, be it mechanical or electromagnetic. Both length (displacement) and current can be "complex-valued" in this sense. |
Summary
This commit adds two simple functions
WithDims
(andWithUnits
) that return aQuantity
type with the dimensions (and units) constrained to those of the parametersWith this PR, we can write
The difference between
WithDims
andWithUnits
the two is that the first one only constrains the dimension, and the latter constrains both dimension and unit (i.e. doesn't allow e.g.km
) -- see Units vs Dims.Rationale
I found myself trying to write simulation code with strongly typed interfaces, i.e. including information about the units. Initially I wrote my interfaces like so:
However, when trying to autodiff through this code, I run into a problem, because
Meters
has the numerical typeFloat64
baked in, and autodiff evaluates on a typeQuantity{Dual{Float64}}
(roughly).We can instead define
Meters
like so:but I thought a better approach would be to provide some syntactic sugar to this "unit constraint".
This led to the construction of the syntactic sugar described in the summary.
I'm happy to receive any feedback on the idea and the naming. Other names could be e.g.
quantity_with_dims
(but too long for my taste), ordims_as
etc., butsimilar
is already Julia lingo and feels appropriate in this context.