Skip to content

Commit

Permalink
Convert between Unitful and DimensionfulAngles (#34)
Browse files Browse the repository at this point in the history
  • Loading branch information
cmichelenstrofer authored Dec 3, 2023
1 parent fe192af commit 4830351
Show file tree
Hide file tree
Showing 20 changed files with 2,703 additions and 91 deletions.
2 changes: 2 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ version = "0.2.0"

[deps]
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
UnitfulAngles = "6fb2a4bd-7999-5318-a3b2-8ad61056cd98"
UnitfulEquivalences = "da9c4bc3-91c8-4f02-8a40-6b990d2a7e0c"

[compat]
Unitful = "1.10"
UnitfulAngles = "0.7"
UnitfulEquivalences = "0.2"
julia = "1.7"
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ Michelén Ströfer, C. A. (2022). DimensionfulAngles.jl (Version 0.1.0) [Compute

Use *DimensionfulAngles.jl* for units containing angles and *Unitful.jl* for all other units.
The units in *DimensionfulAngles.jl* are differentiated from their dimensionless counterparts with a superscript ``.
Simply add this superscript to any angle units to make it dimensionful.
Simply add this superscript to any angle units to make it dimensionful.
In Julia environments this can be typed as `\^a<tab>`.

```julia
Expand Down Expand Up @@ -125,8 +125,30 @@ julia> using DimensionfulAngles.DefaultSymbols
julia> angular_velocity = 1.2rad / s
```

### Converting to/from `Unitful.jl`
To convert a quantity to or from `Unitful.jl` use the `uconvert` function with first
argument either `:Unitful` or `:DimensionfulAngles`.
For example:

```julia
julia> using Unitful, DimensionfulAngles

julia> ω = 3.2u"radᵃ/s"
3.2 rad s⁻¹

julia> ω̄ = uconvert(:Unitful, ω)
3.2 rad s⁻¹

julia> dimension(ω)
𝐀 𝐓⁻¹

julia> dimension(ω̄)
𝐓⁻¹
```


## Contributing
<!--
<!--
[![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](code_of_conduct.md)
[![ColPrac: Contributor's Guide on Collaborative Practices for Community Packages](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet)](https://github.com/SciML/ColPrac)
[![SciML Code Style](https://img.shields.io/static/v1?label=code%20style&message=SciML&color=9558b2&labelColor=389826)](https://github.com/SciML/SciMLStyle)
Expand Down
6 changes: 4 additions & 2 deletions docs/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
UnitfulAngles = "6fb2a4bd-7999-5318-a3b2-8ad61056cd98"

[compat]
Documenter = "0.27.23"
DocumenterCitations = "0.2.12"
Documenter = "1.2"
DocumenterCitations = "1.3"
Unitful = "1.10"
UnitfulAngles = "0.7"
37 changes: 24 additions & 13 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# push!(LOAD_PATH,"../src/")

using Documenter
using DocumenterCitations
using DimensionfulAngles
using Unitful
using UnitfulAngles

ENV["UNITFUL_FANCY_EXPONENTS"] = true

bib = CitationBibliography(joinpath(@__DIR__, "references.bib"))

Expand All @@ -16,17 +21,23 @@ function _filter_prefixed(base, x; exceptions = [nothing])
return false
end

makedocs(bib;
sitename = "DimensionfulAngles",
format = Documenter.HTML(),
modules = [DimensionfulAngles],
pages = ["Home" => "index.md",
"Angle as a dimension?" => "motivation.md",
"Package Guide" => ["guide/intro.md",
"guide/units.md",
"guide/derived.md",
"guide/base.md"],
"Relationship to proposed SI extensions." => "proposed.md",
"Index" => "syntax.md"])
makedocs(;
sitename = "DimensionfulAngles",
format = Documenter.HTML(
assets=String["assets/citations.css",],
),
modules = [DimensionfulAngles],
pages = [
"Home" => "index.md",
"Angle as a dimension?" => "motivation.md",
"Package Guide" => ["guide/intro.md",
"guide/units.md",
"guide/derived.md",
"guide/base.md"],
"Relationship to proposed SI extensions." => "proposed.md",
"Index" => "syntax.md",
],
plugins = [bib,],
)

deploydocs(; repo = "github.com/cmichelenstrofer/DimensionfulAngles.jl.git")
deploydocs(; repo="github.com/cmichelenstrofer/DimensionfulAngles.jl.git",)
2,213 changes: 2,213 additions & 0 deletions docs/src/assets/Commutative_diagram_of_harmonic_wave_properties.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 18 additions & 0 deletions docs/src/assets/citations.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.citation dl {
display: grid;
grid-template-columns: max-content auto; }
.citation dt {
grid-column-start: 1; }
.citation dd {
grid-column-start: 2;
margin-bottom: 0.75em; }
.citation ul {
padding: 0 0 2.25em 0;
margin: 0;
list-style: none;}
.citation ul li {
text-indent: -2.25em;
margin: 0.33em 0.5em 0.5em 2.25em;}
.citation ol li {
padding-left:0.75em;}

9 changes: 5 additions & 4 deletions docs/src/guide/base.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ The functions in `Base` currently extended to accept dimensionful angle argument
- hyperbolic functions: `sinh`, `cosh`, `tanh`, `coth`, `sech`, `csch`
- exponential functions: `exp`, `expm1`, `cis`, `cispi`
- Sinc functions: `sinc`, `cosc`
- Utilities: `deg2rad`, `rad2deg`, `mod2pi`, `rem2pi`
- conversions: `deg2rad`, `rad2deg`
- divisions: `mod2pi`, `rem2pi`

For example

Expand Down Expand Up @@ -51,7 +52,7 @@ julia> acos(ua"°", 0.9831912354632536)
The functions in `Base` that are currently extended to accept units as their first argument
and return values with those units are:

- inverse trigonometric: `asin`, `acos`, `atan`, `acot`, `asec`, `acsc`, `asind`, `acosd`, `acotd`, `asecd`, `acscd`, `atan(x, y)`
- inverse hyperbolic: `asinh`, `acosh`, `atanh`, `acoth`, `asech`, `acsch`
- logarithmic: `log`, `log1p`
- inverse trigonometric functions: `asin`, `acos`, `atan`, `acot`, `asec`, `acsc`, `asind`, `acosd`, `acotd`, `asecd`, `acscd`, `atan(x, y)`
- inverse hyperbolic functions: `asinh`, `acosh`, `atanh`, `acoth`, `asech`, `acsch`
- logarithmic functions: `log`, `log1p`
- phase angle of a complex number: `angle`
51 changes: 41 additions & 10 deletions docs/src/guide/derived.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ These are:

- [`DimensionfulAngles.SolidAngle`](@ref)
- [`DimensionfulAngles.AngularVelocity`](@ref)
- [`DimensionfulAngles.AngularAcceleration`](@ref).
- [`DimensionfulAngles.AngularAcceleration`](@ref)
- [`DimensionfulAngles.AngularWavelength`](@ref)
- [`DimensionfulAngles.AngularPeriod`](@ref)
- [`DimensionfulAngles.AngularWavenumber`](@ref)

This allows, among other things, dispatching on these derived dimensions.

Expand All @@ -29,34 +32,56 @@ DimensionfulAngles.srᵃ
```

## Angular velocity and acceleration

Content:

- [Angular velocity and acceleration](@ref)

+ [Periodic equivalence](@ref)

[Angular velocity](https://en.wikipedia.org/wiki/Angular_frequency) has dimensions of angle over time `𝐀/𝐓` and can be used to measure different quantities such as rotational velocity, rotational speed, and angular frequency of a phase angle.
Two units of angular velocity are defined: the revolutions per second (RPS) and the revolutions per minute (RPM), provided as [`DimensionfulAngles.rpsᵃ`](@ref) and [`DimensionfulAngles.rpmᵃ`](@ref) respectively.

[Angular acceleration](https://en.wikipedia.org/wiki/Angular_acceleration) is the time rate of change of angular velocity and has dimensions of angle over time squared `𝐀/𝐓²`.
No units are defined specifically for this derived dimension.

See also: [`Periodic`](@ref).

```@docs
DimensionfulAngles.AngularVelocity
DimensionfulAngles.AngularAcceleration
DimensionfulAngles.rpsᵃ
DimensionfulAngles.rpmᵃ
```

### Periodic equivalence
## Angular period, wavenumber, and wavelength
Angular [wavenumber] (https://en.wikipedia.org/wiki/Wavenumber) has dimensions of angle over
length `𝐀/𝐋` and is the spatial analogue of (temporal) angular frequency.
It is used to describe responses that are periodic in space.

The angular period (dimensions of time over angle, `𝐓/𝐀`) and angular wavelength (`𝐋/𝐀`) are define as the reciprocal of angular frequency
and angular wavenumber, respectively.

No units are defined specifically for these derived dimensions.

See also: [`Periodic`](@ref).

```@docs
DimensionfulAngles.AngularWavelength
DimensionfulAngles.AngularPeriod
DimensionfulAngles.AngularWavenumber
```

## Periodic equivalence
For periodic responses there are several analogous ways to measure the repeat period: period `T` (`𝐓`, `s`), frequency `f` (`1/𝐓`, `Hz=1/s`), or angular frequency `ω` (`𝐀/𝐓`, `rad/s`).
These are [related by](https://en.wikipedia.org/wiki/Angular_frequency)

``f = 1/T = ω/2π``.

*DimensionfulAngles.jl* provides [`Periodic`](@ref) a [UnitfulEquivalences.jl](https://sostock.github.io/UnitfulEquivalences.jl/stable/) `Equivalence` to convert between period, frequency, and angular frequency of a periodic response.
Analogously, spatial period and frequency are [related by](https://en.wikipedia.org/wiki/Spatial_frequency)

``ν = 1/λ = k/2π``

between wavelength `λ` (`𝐋`, `m`), wavenumber `ν` (`1/𝐋`, `1/m`), and angular wavenumber `k` (`𝐀/𝐋`, `rad/m`).
Additionally an angular period and angular wavelength can be defined analogously as the reciprocal of angular frequency and angular wavenumber.

![Diagram showing graphically the relationships between the various properties of harmonic waves: frequency, period, wavelength, angular frequency, and wavenumber.](../assets/Commutative_diagram_of_harmonic_wave_properties.svg)
*image-source: Waldir, CC BY-SA 4.0 <https://creativecommons.org/licenses/by-sa/4.0>, via Wikimedia Commons*

*DimensionfulAngles.jl* provides [`Periodic`](@ref) a [UnitfulEquivalences.jl](https://sostock.github.io/UnitfulEquivalences.jl/stable/) `Equivalence` to convert between temporal or spatial period, frequency, angular frequency, and angular period of a periodic response.

```@docs
DimensionfulAngles.Periodic
Expand All @@ -80,6 +105,12 @@ DimensionfulAngles.AngularAccelerationUnits
DimensionfulAngles.AngularAccelerationFreeUnits
DimensionfulAngles.SolidAngleUnits
DimensionfulAngles.SolidAngleFreeUnits
DimensionfulAngles.AngularWavenumberUnits
DimensionfulAngles.AngularWavenumberFreeUnits
DimensionfulAngles.AngularPeriodUnits
DimensionfulAngles.AngularPeriodFreeUnits
DimensionfulAngles.AngularWavelengthUnits
DimensionfulAngles.AngularWavelengthFreeUnits
```

### [Prefixed Units](@id derived_prefixed)
Expand Down
50 changes: 46 additions & 4 deletions docs/src/guide/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ At its core, [`DimensionfulAngles`](@ref) defines:
- the degree [`DimensionfulAngles.°ᵃ`](@ref) (SI-accepted unit of angle)
- the *"defining constant"* [`θ₀`](@ref) equal to one radian.
- the [`@ua_str`](@ref) macro for easily recalling units in the package
- extensions to `uconvert` to convert between `Unitful` and `DimensionfulAngles` quantities.

The unit `radᵃ` is prefixable, and therefore defines many other units, which are documented in [Prefixed units](@ref intro_prefixed).

The units in this package are appended the superscript `` to differentiate them from the units in [Unitful.jl](https://painterqubits.github.io/Unitful.jl/stable/) and [UnitfulAngles.jl](https://github.com/yakir12/UnitfulAngles.jl), which have the same name but are non-dimensional.
The [`@ua_str`](@ref) provides an easier way to access these units without having to type the superscript ``.
For example, both of these are equivalent:

```jldoctest
```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2"
julia> using Unitful
julia> using DimensionfulAngles
Expand All @@ -31,7 +32,7 @@ julia> 1.3ua"rad"

The default `u` string can still be more convenient when defining quantities with mixed units, such as

```jldoctest
```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2"
julia> using Unitful
julia> using DimensionfulAngles
Expand All @@ -43,7 +44,7 @@ julia> 2.1u"radᵃ/s"
Alternatively it might be convenient to import the units you are using directly, renaming units from *DimensionfulAngles* to remove the superscript ``.
For example:

```jldoctest
```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2"
julia> using Unitful
julia> using Unitful: m, s, kg
Expand All @@ -70,7 +71,7 @@ One of the main advantage of defining an angle dimension is to be able to dispat
This behavior and useful aliases are completely inherited from *Unitful.jl*.
The most basic usage uses the automatically defined alias [`DimensionfulAngles.Angle`](@ref):

```jldoctest
```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2"
julia> using Unitful
julia> using DimensionfulAngles
Expand All @@ -94,6 +95,47 @@ julia> what_am_i(angle)
"I am an angle."
```

Finally, we can convert quantities to or from `Unitful` (including `UnitfulAngles`) using an
extension of `uconvert` with first argument `:Unitful` or `:DimensionfulAngles`, as:

```jldoctest; setup = :(using DimensionfulAngles, Unitful), filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2"
julia> ω = 3.2u"radᵃ/s"
3.2 rad s⁻¹
julia> ω̄ = uconvert(:Unitful, ω)
3.2 rad s⁻¹
julia> dimension(ω)
𝐀 𝐓⁻¹
julia> dimension(ω̄)
𝐓⁻¹
```

```@docs
Unitful.uconvert(::Symbol, ::Quantity)
```

Note that astronomical units in `DimensionfulAngles` and `UnitfulAngles` are not equivalent
and quantities containing these units are converted to compatible, non-astronomical, units
first.
Specifically, the `UnitfulAngles` units [`mas`, `μas`, `pas`] are converted to `arcsecond`,
the `DimensionfulAngles` unit `asᵃ` and all its prefixed versions are converted to
`arcsecondᵃ`, and the `DimensionfulAngles` units [`ʰᵃ`, `ᵐᵃ`, `ˢᵃ`] are converted to
`hourAngleᵃ`.
For example:

```jldoctest; setup = :(using DimensionfulAngles, Unitful)
julia> θ = 1u"μas"
1 μas
julia> θ̄ = uconvert(:DimensionfulAngles, θ)
1//1000000″
julia> uconvert(:Unitful, 1u"ᵐᵃ")
1//60 hourAngle
```

## [Syntax](@id intro_syntax)

Contents:
Expand Down
5 changes: 3 additions & 2 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ These include
- A comprehensive list of angular units.
- The `@ua_str` macro for easily accessing these units.
- Derived dimensions and their units, including: solid angles, angular velocity/frequency, and angular acceleration.
- Conversion between `Unitful` and `DimensionfulAngles` quantities.
- A [UnitfulEquivalences.jl](https://sostock.github.io/UnitfulEquivalences.jl/stable/) `Equivalence` to convert between period, frequency, and angular frequency of a periodic response.
- A comprehensive extension of functions in `Base` that take angular quantities as inputs, or output angular quantities.

Expand All @@ -40,8 +41,8 @@ Such proposals do exist, and for completeness these are discussed in [Relation t

These definitions are based on the [SI Brochure](https://www.bipm.org/en/publications/si-brochure).
In particular note the distinction between a quantity (which has a value and a unit), its unit, and its dimension.
A (base or derived) dimension has a unique standard SI unit, but the converse is not true.
E.g. both torque and energy, two distinct quantities, have the same dimension.
Any physical quantity hasa unique standard (coherent) SI unit and dimension, but the converse is not true.
E.g. both torque and energy, two distinct quantities, have the same dimension and units.
Also note the distinction between plane and phase angles as distinct quantities, and angular velocity and angular frequency as distinct quantities.

- **Angle**: Either a plane or phase angle.
Expand Down
11 changes: 8 additions & 3 deletions docs/src/motivation.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ and

> For historical reasons the radian and steradian are treated as derived units
Note that by including *angle* as a dimension we are dropping its definition as a ratio of
lengths.
This is what makes the SI angle dimensionless and would make this 8-dimension system
incoherent (dimensions are not linearly independent).

Point 2 means that we cannot (easily) differentiate between different dimensionless quantities.
In practice this means we have to be very careful when dealing with dimensionless quantities.
Here are some motivating examples using [Unitful.jl](https://painterqubits.github.io/Unitful.jl/).
Expand All @@ -39,7 +44,7 @@ ERROR: DimensionError: 2 m and 5 are not dimensionally compatible.

However this does not work with dimensionless quantities such as angles.

```jldoctest
```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2"
julia> using Unitful
julia> angle = 10u"°"
Expand All @@ -59,7 +64,7 @@ Finally they can be added.

Since angle is not a dimension we cannot differentiate between units of angle and other dimensionless units, which also leads to problems like this:

```jldoctest
```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2"
julia> using Unitful
julia> 1u"°" + 1u"rad"
Expand Down Expand Up @@ -99,7 +104,7 @@ One of the main features of Julia is multiple dispatch.
This ability can **not** be used for angular dimensions, and we have to either (1) dispatch on *no dimension* or (2) dispatch on an union of all angle units.
The former would work for all dimensionless quantities not just angles, and the latter can become cumbersome with a large number of units when considering prefixes and additional units in [UnitfulAngles.jl](https://github.com/yakir12/UnitfulAngles.jl).

```jldoctest
```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2"
julia> using Unitful
julia> what_am_i(::Unitful.Length) = "I am a length."
Expand Down
Loading

0 comments on commit 4830351

Please sign in to comment.