Skip to content

Commit

Permalink
keep separate units
Browse files Browse the repository at this point in the history
  • Loading branch information
cmichelenstrofer committed Dec 3, 2023
1 parent 21c9b42 commit 839de91
Show file tree
Hide file tree
Showing 9 changed files with 302 additions and 135 deletions.
4 changes: 2 additions & 2 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
push!(LOAD_PATH,"../src/")
# push!(LOAD_PATH,"../src/")

using Documenter
using DocumenterCitations
Expand Down Expand Up @@ -40,4 +40,4 @@ makedocs(;
plugins = [bib,],
)

# deploydocs(; repo = "github.com/cmichelenstrofer/DimensionfulAngles.jl.git")
deploydocs(; repo="github.com/cmichelenstrofer/DimensionfulAngles.jl.git",)
46 changes: 21 additions & 25 deletions docs/src/guide/derived.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,40 @@ 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)

Expand All @@ -64,33 +76,17 @@ Analogously, spatial period and frequency are [related by](https://en.wikipedia.
``ν = 1/λ = k/2π``

between wavelength `λ` (`𝐋`, `m`), wavenumber `ν` (`1/𝐋`, `1/m`), and angular wavenumber `k` (`𝐀/𝐋`, `rad/m`).
Additionally an angular period and wavelength can be defined analogously as the period or wavelength divided by ````.
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
```

## Angular period, wavenumber, and wavelength
Based on the definitions above the following additional derived dimensions are defined:

- Angular period (`𝐓/𝐀`, `s/rad`)
- Angular wavelength (`𝐋/𝐀`, `m/rad`)
- Angular wavenumber (`𝐀/𝐋`, `rad/m`)

No specific units are added for these dimensions.

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

## [Syntax](@id derived_syntax)

Contents:
Expand Down
24 changes: 22 additions & 2 deletions docs/src/guide/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ julia> what_am_i(angle)
"I am an angle."
```

Finally, we can convert quantities to or from `Unitful` using an extension of `uconvert`
with first argument `:Unitful` or `:DimensionfulAngles`, as:
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"
Expand All @@ -116,6 +116,26 @@ julia> dimension(ω̄)
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
106 changes: 8 additions & 98 deletions src/DimensionfulAngles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,16 @@ module DimensionfulAngles
# using Base: Base # extend: see `base.jl` for full list of functions extended
using Unitful: Unitful # extend: has_unit_spacing, uconvert
using Unitful: minute, promotion, rad, rpm, rps, s, sr, 𝐓, 𝐋, °
using Unitful: Dimension, Dimensions, DimensionlessQuantity, FreeUnits, Frequency
using Unitful: FrequencyFreeUnits, Length, MixedUnits, NoDims, NoUnits, Number, Quantity
using Unitful: Time, Unitlike, Unit, Units, Wavenumber
using Unitful: ContextUnits, Dimension, Dimensions, DimensionlessQuantity, FixedUnits
using Unitful: FreeUnits, Frequency, FrequencyFreeUnits, Length, MixedUnits, NoDims
using Unitful: NoUnits, Number, Quantity, Time, Unitlike, Unit, Units, Wavenumber
using Unitful: @dimension, @refunit, @derived_dimension, @unit
using Unitful: dimension, register, uconvert, unit, ustrip
using UnitfulEquivalences: Equivalence, @eqrelation
using UnitfulAngles: turn, doubleTurn, halfTurn, quadrant, sextant, octant, clockPosition
using UnitfulAngles: hourAngle, compassPoint, hexacontade, brad, diameterPart, grad
using UnitfulAngles: arcminute, arcsecond
# using UnitfulAngles: mas, μas, pas # UnitfulAngles PR #34
using UnitfulAngles: mas, μas, pas

export @ua_str
export θ₀
Expand All @@ -52,6 +52,7 @@ export sexagesimal, show_sexagesimal
# export AngularWavenumber, AngularWavenumberUnits, AngularWavenumberFreeUnits
# export AngularWavelength, AngularWavelengthUnits, AngularWavelengthFreeUnits

# Dimension
"""
𝐀
Expand Down Expand Up @@ -113,7 +114,7 @@ julia> 1ua"°"
@unit °ᵃ "°" Degreeᵃ (1radᵃ * π/180) false
Unitful.has_unit_spacing(u::Units{(Unit{:Degreeᵃ, 𝐀}(0, 1 // 1),), 𝐀}) = false

# Constants
# Constant
"""
θ₀
Expand Down Expand Up @@ -143,103 +144,12 @@ julia> 2.1ua"rad" / θ₀
"""
const θ₀ = (1 // 1)radᵃ

# Convert to/from Unitful (SI)
"""
uconvert(s::Symbol, x::Quantity)
Convert between DimensionfulAngles and Unitful angles (non-dimensional, SI).
The Symbol `s` is either `:Unitful`, to convert to Unitful angles, or `DimensionfulAngles`
to convert to DimensionfulAngles angles.
It converts angle units and the following derived units: `sr`, `rpm`, `rps`).
# Example
```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2"
julia> using Unitful, DimensionfulAngles
julia> ω = 3.2u"radᵃ/s"
3.2 rad s⁻¹
julia> ω̄ = uconvert(:Unitful, ω)
3.2 rad s⁻¹
julia> dimension(ω)
𝐀 𝐓⁻¹
julia> dimension(ω̄)
𝐓⁻¹
julia> dimension(uconvert(:DimensionfulAngles, ω̄))
𝐀 𝐓⁻¹
```
"""
Unitful.uconvert(s::Symbol, x::Quantity) = Unitful.uconvert(Val{s}(), x)

function Unitful.uconvert(s::Val{:Unitful}, x::Quantity)
angle_units = (
radᵃ, °ᵃ, turnᵃ, doubleTurnᵃ, halfTurnᵃ, quadrantᵃ, sextantᵃ, octantᵃ,
clockPositionᵃ, hourAngleᵃ, compassPointᵃ, hexacontadeᵃ, bradᵃ, diameterPartᵃ,
gradᵃ, arcminuteᵃ, arcsecondᵃ, asᵃ, ʰᵃ, ᵐᵃ, ˢᵃ,
)
x = _convert_angles(x, radᵃ, 𝐀, rad, angle_units)
# derived units that contain angles.
x = _convert_angles(x, srᵃ, 𝐀^2, sr, (srᵃ,))
x = _convert_angles(x, rpsᵃ, 𝐀*𝐓^-1, rps, (rpsᵃ,))
x = _convert_angles(x, rpmᵃ, 𝐀*𝐓^-1, rpm, (rpmᵃ,))
return x
end

function Unitful.uconvert(s::Val{:DimensionfulAngles}, x::Quantity)
angle_units = (
rad, °, turn, doubleTurn, halfTurn, quadrant, sextant, octant, clockPosition,
hourAngle, compassPoint, hexacontade, brad, diameterPart, grad, arcminute,
arcsecond,
# TODO: mas, μas, pas # UnitfulAngles PR #34
)
x = _convert_angles(x, rad, NoDims, radᵃ, angle_units)
# derived units that contain angles.
x = _convert_angles(x, sr, NoDims, srᵃ, (sr,))
x = _convert_angles(x, rps, NoDims, rpsᵃ, (rps,))
x = _convert_angles(x, rpm, NoDims, rpmᵃ, (rpm,))
return x
end

function _convert_angles(x::Quantity, input_angle_unit::Units, input_dim::Dimensions,
output_angle_unit::Units, angle_units::NTuple{N, Units} where N,
)
# convert all units in `angle_units` to common `input_angle_unit` unit.
# cannot use `upreferred` because of `FixedUnits` and `ContextUnits`
AngularUnits = [
typeof(typeof(angle_unit).parameters[1][1]) for angle_unit in angle_units
]

power = 0//1
input_units = 1
for iunit in typeof(x).parameters[3].parameters[1]
ipower = iunit.power
if typeof(iunit) AngularUnits
power += ipower
input_units *= uconvert(
input_angle_unit^ipower,
1Unitful.FreeUnits{(iunit,), input_dim^ipower, nothing}()
)
else
input_units *= (
1Unitful.FreeUnits{(iunit,), typeof(iunit).parameters[2]^ipower, nothing}()
)
end
end
input_units = unit(input_units)
x = uconvert(input_units, x)
# convert to output units/dimensions
return x*input_angle_unit^-power*output_angle_unit^power
end

# Other functionalities.
include("units.jl") # Other units of angle.
include("derived.jl") # Units and functionalities for derived dimensions.
include("convert.jl") # Convert to/from `Unitful`
include("uamacro.jl") # String macro for using dimensionful units.
include("base.jl") # Extend Base functions for units of angle.
include("base.jl") # Extend Base functions to work with angular quantities.
include("defaults.jl") # Submodule to flood workspace with unit types.

# Register new units and dimensions with Unitful.jl.
Expand Down
Loading

0 comments on commit 839de91

Please sign in to comment.