From 6d9678409be673a97079b3ec9b09721be20a0c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20A=2E=20Michel=C3=A9n=20Str=C3=B6fer?= Date: Sun, 10 Dec 2023 17:11:00 -0700 Subject: [PATCH] Dispersion equivalence (#43) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 🚨 Checklist - [x] Read and follow the [Contributing Guidelines](https://github.com/cmichelenstrofer/.github/blob/main/CONTRIBUTING.md). - [x] Provide a more detailed description below, including [referencing or closing the relevant issue(s)](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) 💔 Thanks! ## PR Description - Closes #42. - Adds an equivalence to extend `Periodic` by using a specific, user-supplied, dispersion-relation - This allows converting between temporal and spatial frequencies --- docs/Project.toml | 1 + docs/src/guide/derived.md | 7 +- src/DimensionfulAngles.jl | 32 +++--- src/derived.jl | 62 +----------- src/equivalences.jl | 200 ++++++++++++++++++++++++++++++++++++++ test/Project.toml | 1 + test/test_core_package.jl | 47 +++++++++ 7 files changed, 274 insertions(+), 76 deletions(-) create mode 100644 src/equivalences.jl diff --git a/docs/Project.toml b/docs/Project.toml index 114827e..6257a73 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,6 +1,7 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" DocumenterCitations = "daee34ce-89f3-4625-b898-19384cb65244" +Roots = "f2b01f46-fcfa-551c-844a-d8ac1e96c665" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" UnitfulAngles = "6fb2a4bd-7999-5318-a3b2-8ad61056cd98" diff --git a/docs/src/guide/derived.md b/docs/src/guide/derived.md index 81089a4..ffe5b63 100644 --- a/docs/src/guide/derived.md +++ b/docs/src/guide/derived.md @@ -81,7 +81,7 @@ DimensionfulAngles.AngularPeriod DimensionfulAngles.AngularWavenumber ``` -## Periodic equivalence +## Periodic and Dispersion equivalences 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) @@ -97,10 +97,13 @@ Additionally an angular period and angular wavelength can be defined analogously ![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 , 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. +*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. + +It also provides [`Dispersion`](@ref), which extends [`Periodic`](@ref) to convert between temporal and spatial values using a specific [dispersion relation](https://en.wikipedia.org/wiki/Dispersion_relation) (or equivalently a [phase velocity](https://en.wikipedia.org/wiki/Phase_velocity) as used in the image above)). ```@docs DimensionfulAngles.Periodic +DimensionfulAngles.Dispersion ``` ## [Syntax](@id derived_syntax) diff --git a/src/DimensionfulAngles.jl b/src/DimensionfulAngles.jl index 2862c26..7725986 100644 --- a/src/DimensionfulAngles.jl +++ b/src/DimensionfulAngles.jl @@ -28,13 +28,14 @@ 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: cd as cdᵤ, lm, lx, m, minute, promotion, rad, rpm, rps, s, sr, 𝐉, 𝐋, 𝐓, ° +using Unitful: cd as cdᵤ, Hz, lm, lx, m, minute, promotion, rad, rpm, rps, s, sr, 𝐉, 𝐋, 𝐓, ° 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 UnitfulEquivalences: UnitfulEquivalences # extend: edconvert +using UnitfulEquivalences: dimtype, edconvert, Equivalence, @eqrelation using UnitfulAngles: turn, doubleTurn, halfTurn, quadrant, sextant, octant, clockPosition using UnitfulAngles: hourAngle, compassPoint, hexacontade, brad, diameterPart, grad using UnitfulAngles: arcminute, arcsecond @@ -42,15 +43,19 @@ using UnitfulAngles: mas, μas, pas export @ua_str export θ₀ -export Periodic +export Periodic, Dispersion export sexagesimal, show_sexagesimal -# export 𝐀, Angle, AngleUnits, AngleFreeUnits -# export SolidAngle, SolidAngleUnits, SolidAngleFreeUnits -# export AngularVelocity, AngularVelocityUnits, AngularVelocityFreeUnits -# export AngularAcceleration, AngularAccelerationUnits, AngularAccelerationFreeUnits -# export AngularPeriod, AngularPeriodUnits, AngularPeriodFreeUnits -# export AngularWavenumber, AngularWavenumberUnits, AngularWavenumberFreeUnits -# export AngularWavelength, AngularWavelengthUnits, AngularWavelengthFreeUnits + +# unexported: +# (all angle and derived units, including prefixed units) +# 𝐀, Angle, AngleUnits, AngleFreeUnits +# SolidAngle, SolidAngleUnits, SolidAngleFreeUnits +# AngularVelocity, AngularVelocityUnits, AngularVelocityFreeUnits +# AngularAcceleration, AngularAccelerationUnits, AngularAccelerationFreeUnits +# AngularPeriod, AngularPeriodUnits, AngularPeriodFreeUnits +# AngularWavenumber, AngularWavenumberUnits, AngularWavenumberFreeUnits +# AngularWavelength, AngularWavelengthUnits, AngularWavelengthFreeUnits + # Dimension """ @@ -145,12 +150,13 @@ julia> 2.1ua"rad" / θ₀ const θ₀ = (1 // 1)radᵃ # Other functionalities. -include("units.jl") # Other units of angle. -include("derived.jl") # Units and functionalities for derived dimensions. +include("units.jl") # Define other units of angle. +include("derived.jl") # Define derived units and dimensions. include("convert.jl") # Convert to/from `Unitful` include("uamacro.jl") # String macro for using dimensionful units. include("base.jl") # Extend Base functions to work with angular quantities. -include("defaults.jl") # Submodule to flood workspace with unit types. +include("defaults.jl") # Submodule to flood workspace with unit types. +include("equivalences.jl") # `UnitfulEquivalences` containing angular dimensions # Register new units and dimensions with Unitful.jl. const localpromotion = copy(promotion) diff --git a/src/derived.jl b/src/derived.jl index 71dab3b..2a90b00 100644 --- a/src/derived.jl +++ b/src/derived.jl @@ -1,4 +1,4 @@ -# Units and functionalities for derived dimensions of Angle. +# Derived units and dimensions of Angle. # Solid angle @derived_dimension SolidAngle (𝐀*𝐀) true @@ -80,63 +80,3 @@ See also [`DimensionfulAngles.radᵃ`](@ref). @derived_dimension AngularWavenumber (𝐀*𝐋^-1) true @derived_dimension AngularWavelength (𝐋*𝐀^-1) true @derived_dimension AngularPeriod (𝐓*𝐀^-1) true - -# periodic equivalence for both temporal and spatial frequency -""" - Periodic() - -Equivalence to convert between temporal or spatial period, frequency, and -[angular frequency](https://en.wikipedia.org/wiki/Angular_frequency) -according to the relations ``f = ω/2π = 1/T``, where - - - ``f`` is the (temporal) frequency, - - ``ω`` is the (temporal) angular frequency, - - ``T`` is the (temporal) period, - - ``T̄`` is the (temporal) angular period, - -and ``ν = k/2π = 1/λ = 1/(2πλ̄)``, where - -- ``ν`` is the (spatial) frequency (linear wavenumber), -- ``k`` is the (spatial) angular frequency (angular wavenumber), -- ``λ`` is the (spatial) period (linear wavelength), and -- ``λ̄`` is the (spatial) angular period (angular wavelength). - -# Example - -```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2" -julia> using Unitful - -julia> using DimensionfulAngles - -julia> uconvert(u"s", 10u"Hz", Periodic()) -0.1 s - -julia> uconvert(u"radᵃ/s", 1u"Hz", Periodic()) -6.283185307179586 rad s⁻¹ -``` -""" -struct Periodic <: Equivalence end -# temporal -@eqrelation Periodic (AngularVelocity / Frequency = 2π * radᵃ) -@eqrelation Periodic (Frequency * Time = 1) -@eqrelation Periodic (AngularVelocity * Time = 2π * radᵃ) -@eqrelation Periodic (AngularVelocity * AngularPeriod = 1) -@eqrelation Periodic (Time / AngularPeriod = 2π * radᵃ) -@eqrelation Periodic (AngularPeriod * Frequency = 1/(2π * radᵃ)) -# spatial -@eqrelation Periodic (AngularWavenumber / Wavenumber = 2π * radᵃ) -@eqrelation Periodic (Wavenumber * Length = 1) -@eqrelation Periodic (AngularWavenumber * Length = 2π * radᵃ) -@eqrelation Periodic (AngularWavenumber * AngularWavelength = 1) -@eqrelation Periodic (Length / AngularWavelength = 2π * radᵃ) -@eqrelation Periodic (AngularWavelength * Wavenumber = 1/(2π * radᵃ)) -# default to `uconvert` behavior, temporal -@eqrelation Periodic (Frequency / Frequency = 1) -@eqrelation Periodic (Time / Time = 1) -@eqrelation Periodic (AngularVelocity / AngularVelocity = 1) -@eqrelation Periodic (AngularPeriod / AngularPeriod = 1) -# default to `uconvert` behavior, spatial -@eqrelation Periodic (Wavenumber / Wavenumber = 1) -@eqrelation Periodic (Length / Length = 1) -@eqrelation Periodic (AngularWavenumber / AngularWavenumber = 1) -@eqrelation Periodic (AngularWavelength / AngularWavelength = 1) diff --git a/src/equivalences.jl b/src/equivalences.jl new file mode 100644 index 0000000..89585b6 --- /dev/null +++ b/src/equivalences.jl @@ -0,0 +1,200 @@ +# equivalences containing angular dimensions + +# periodic equivalence for both temporal and spatial frequency +""" + Periodic() + +Equivalence to convert between temporal or spatial period, frequency, +[angular frequency](https://en.wikipedia.org/wiki/Angular_frequency), and angular period. + +These quantities are related by ``f = ω/2π = 1/T = 1/(2πT̅)``, where + + - ``f`` is the (temporal) frequency, + - ``ω`` is the (temporal) angular frequency, + - ``T`` is the (temporal) period, + - ``T̄`` is the (temporal) angular period, + +and ``ν = k/2π = 1/λ = 1/(2πλ̄)``, where + +- ``ν`` is the (spatial) frequency (linear wavenumber), +- ``k`` is the (spatial) angular frequency (angular wavenumber), +- ``λ`` is the (spatial) period (linear wavelength), and +- ``λ̄`` is the (spatial) angular period (angular wavelength). + +See also [`DimensionfulAngles.Dispersion`](@ref) + +# Example + +```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2" +julia> using Unitful + +julia> using DimensionfulAngles + +julia> uconvert(u"s", 10u"Hz", Periodic()) +0.1 s + +julia> uconvert(u"radᵃ/s", 1u"Hz", Periodic()) +6.283185307179586 rad s⁻¹ +``` +""" +struct Periodic <: Equivalence end +# temporal +@eqrelation Periodic (AngularVelocity / Frequency = 2π * radᵃ) +@eqrelation Periodic (Frequency * Time = 1) +@eqrelation Periodic (AngularVelocity * Time = 2π * radᵃ) +@eqrelation Periodic (AngularVelocity * AngularPeriod = 1) +@eqrelation Periodic (Time / AngularPeriod = 2π * radᵃ) +@eqrelation Periodic (AngularPeriod * Frequency = 1/(2π * radᵃ)) +# spatial +@eqrelation Periodic (AngularWavenumber / Wavenumber = 2π * radᵃ) +@eqrelation Periodic (Wavenumber * Length = 1) +@eqrelation Periodic (AngularWavenumber * Length = 2π * radᵃ) +@eqrelation Periodic (AngularWavenumber * AngularWavelength = 1) +@eqrelation Periodic (Length / AngularWavelength = 2π * radᵃ) +@eqrelation Periodic (AngularWavelength * Wavenumber = 1/(2π * radᵃ)) +# default to `uconvert` behavior, temporal +@eqrelation Periodic (Frequency / Frequency = 1) +@eqrelation Periodic (Time / Time = 1) +@eqrelation Periodic (AngularVelocity / AngularVelocity = 1) +@eqrelation Periodic (AngularPeriod / AngularPeriod = 1) +# default to `uconvert` behavior, spatial +@eqrelation Periodic (Wavenumber / Wavenumber = 1) +@eqrelation Periodic (Length / Length = 1) +@eqrelation Periodic (AngularWavenumber / AngularWavenumber = 1) +@eqrelation Periodic (AngularWavelength / AngularWavelength = 1) + + +# periodic equivalence with a specific dispersion relation relating temporal and spatial +# frequencies +""" + Dispersion(; dispersion=nothing, dispersion_inverse=nothing) + +Equivalence to convert between temporal and spatial frequencies using a specific +[dispersion relation](https://en.wikipedia.org/wiki/Dispersion_relation). + +This extends the Periodic() equivalence to convert between spatial and temporal quantities +based on the provided dispersion relation. + +See also [`DimensionfulAngles.Periodic`](@ref). + +# Example + +```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2" +julia> using DimensionfulAngles, Unitful + +julia> g = Unitful.gn # gravitational acceleration +9.80665 m s⁻² + +julia> deepwater = Dispersion( + dispersion = (k -> √(g*k*θ₀)), dispersion_inverse = (ω -> ω^2/(g*θ₀)) + ); + +julia> uconvert(u"radᵃ/mm", 1.0u"Hz", deepwater) +0.004025678249387654 rad mm⁻¹ +``` + +Some dispersion relations do not have an expressible inverse. +In such cases using `Roots.jl` might be beneficial. +For example, here is how we could use the +linear [water wave dispersion](https://en.wikipedia.org/wiki/Dispersion_(water_waves)) +without deep water approximation: + +```jldoctest; filter = r"(\\d*).(\\d{1,10})\\d+" => s"\\1.\\2" +julia> using DimensionfulAngles, Unitful, Roots + +julia> g = Unitful.gn # gravitational acceleration +9.80665 m s⁻² + +julia> k0 = (2π)u"radᵃ/m" # initial guess: 1m wavelength +6.283185307179586 rad m⁻¹ + +julia> h = 0.5u"m" # water depth +0.5 m + +julia> waterwaves = Dispersion( + dispersion = (k -> √(k*θ₀*g*tanh(k*h/θ₀))), + dispersion_inverse = (ω -> solve(ZeroProblem(k -> k - ω^2/(g*tanh(k*h/θ₀))/θ₀, k0))) + ); + +julia> uconvert(u"Hz", 0.004025678249387654u"radᵃ/mm", waterwaves) +0.9823052153509486 Hz + +julia> h = (Inf)u"m" # water depth +Inf m + +julia> waterwaves = Dispersion( + dispersion = ( k -> √(k*θ₀*g*tanh(k*h/θ₀)) ), + dispersion_inverse = (ω -> solve(ZeroProblem(k -> k - ω^2/(g*tanh(k*h/θ₀))/θ₀, k0))) + ); + +julia> uconvert(u"Hz", 0.004025678249387654u"radᵃ/mm", waterwaves) ≈ 1u"Hz" +true +``` +""" +struct Dispersion <: Equivalence + dispersion::Union{Function, Nothing} + dispersion_inverse::Union{Function, Nothing} + + function Dispersion(; + dispersion::Union{Function, Nothing}=nothing, + dispersion_inverse::Union{Function, Nothing}=nothing + ) + return new(dispersion, dispersion_inverse) + end +end + +const _temporal_frequency_dims = [Time, Frequency, AngularPeriod, AngularVelocity] +const _spatial_frequency_dims = [Length, Wavenumber, AngularWavelength, AngularWavenumber] +const _temporal_frequency_units = Dict( + Time => s, Frequency => Hz, AngularPeriod => s/radᵃ, AngularVelocity => radᵃ/s) +const _spatial_frequency_units = Dict( + Length => m, Wavenumber => 1/m, AngularWavelength => m/radᵃ, AngularWavenumber => radᵃ/m +) + +# use all the equivalences in Periodic +for T1 ∈ _temporal_frequency_dims, T2 ∈ _temporal_frequency_dims + @eval begin + function UnitfulEquivalences.edconvert(d::dimtype($T1), x::$T2, ::Dispersion) + return edconvert(d, x, Periodic()) + end + end +end + +for T1 ∈ _spatial_frequency_dims, T2 ∈ _spatial_frequency_dims + @eval begin + function UnitfulEquivalences.edconvert(d::dimtype($T1), x::$T2, ::Dispersion) + return edconvert(d, x, Periodic()) + end + end +end + +# add new equivalences between temporal <-> spatial frequencies +for D_in ∈ _spatial_frequency_dims, D_out ∈ _temporal_frequency_dims + @eval begin + function UnitfulEquivalences.edconvert( + ::dimtype($D_out), x::$D_in, equivalence::Dispersion + ) + isnothing(equivalence.dispersion) && throw(ArgumentError( + "`dispersion` function not defined")) + k = uconvert(radᵃ/m, x, Periodic()) + ω = equivalence.dispersion(k) + u = _temporal_frequency_units[$D_out] + return uconvert(u, ω, Periodic()) + end + end +end + +for D_in ∈ _temporal_frequency_dims, D_out ∈ _spatial_frequency_dims + @eval begin + function UnitfulEquivalences.edconvert( + ::dimtype($D_out), x::$D_in, equivalence::Dispersion + ) + isnothing(equivalence.dispersion_inverse) && throw(ArgumentError( + "`dispersion_inverse` function not defined")) + ω = uconvert(radᵃ/s, x, Periodic()) + k = equivalence.dispersion_inverse(ω) + u = _spatial_frequency_units[$D_out] + return uconvert(u, k, Periodic()) + end + end +end diff --git a/test/Project.toml b/test/Project.toml index 72c0322..60d5888 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,5 +1,6 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +Roots = "f2b01f46-fcfa-551c-844a-d8ac1e96c665" SafeTestsets = "1bc83da4-3b8d-516f-aca4-4fe02f6d838f" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" diff --git a/test/test_core_package.jl b/test/test_core_package.jl index dedc0e3..7de67a6 100644 --- a/test/test_core_package.jl +++ b/test/test_core_package.jl @@ -1,6 +1,7 @@ using Test, DimensionfulAngles, Unitful, UnitfulAngles using Unitful: 𝐉, 𝐓, 𝐋, ContextUnits, FixedUnits, FreeUnits, Units using DimensionfulAngles: 𝐀 +using Roots: ZeroProblem, solve function test_uamacro(unit::Symbol) unitᵃ = Symbol("$unit" * "ᵃ") @@ -138,7 +139,9 @@ end @test typeof(DimensionfulAngles.AngularPeriod) === UnionAll @test DimensionfulAngles.AngularPeriodFreeUnits === FreeUnits{U, 𝐀^-1 * 𝐓} where {U} @test DimensionfulAngles.AngularPeriodUnits === Units{U, 𝐀^-1 * 𝐓} where {U} +end +@testset "Equivalences" begin # periodic: temporal @test uconvert(u"radᵃ/s", 1u"Hz", Periodic()) ≈ (2π)u"radᵃ/s" @test uconvert(u"Hz", 1u"radᵃ/s", Periodic()) ≈ (1 / 2π)u"Hz" @@ -174,6 +177,50 @@ end @test uconvert(u"m", 10u"m", Periodic()) ≈ 10u"m" @test uconvert(u"radᵃ/m", 10u"radᵃ/m", Periodic()) ≈ 10u"radᵃ/m" @test uconvert(u"m/radᵃ", 10u"m/radᵃ", Periodic()) ≈ 10u"m/radᵃ" + + # dispersion: spatial <-> temporal + h, g = (Inf)u"m", Unitful.gn + waterwaves = Dispersion( + dispersion = ( k -> √(k*θ₀*g*tanh(k*h/θ₀)) ), + dispersion_inverse = (ω -> solve(ZeroProblem(k -> k - ω^2/(g*tanh(k*h/θ₀))/θ₀, k0))) + ); + @test uconvert(u"Hz", 0.004025678249387654u"radᵃ/mm", waterwaves) ≈ 1u"Hz" + + # dispersion: temporal + @test uconvert(u"radᵃ/s", 1u"Hz", waterwaves) ≈ (2π)u"radᵃ/s" + @test uconvert(u"Hz", 1u"radᵃ/s", waterwaves) ≈ (1 / 2π)u"Hz" + @test uconvert(u"Hz", 10u"s", waterwaves) ≈ 0.1u"Hz" + @test uconvert(u"s", 10u"Hz", waterwaves) ≈ 0.1u"s" + @test uconvert(u"s", 2u"radᵃ/s", waterwaves) ≈ (π)u"s" + @test uconvert(u"radᵃ/s", (π)u"s", waterwaves) ≈ 2u"radᵃ/s" + @test uconvert(u"s/radᵃ", 10u"radᵃ/s", waterwaves) ≈ 0.1u"s/radᵃ" + @test uconvert(u"radᵃ/s", 10u"s/radᵃ", waterwaves) ≈ 0.1u"radᵃ/s" + @test uconvert(u"s/radᵃ", 1u"s", waterwaves) ≈ (1 / 2π)u"s/radᵃ" + @test uconvert(u"s", 1u"s/radᵃ", waterwaves) ≈ (2π)u"s" + @test uconvert(u"s/radᵃ", 1u"Hz", waterwaves) ≈ (1 / 2π)u"s/radᵃ" + @test uconvert(u"Hz", 1u"s/radᵃ", waterwaves) ≈ (1 / 2π)u"Hz" + @test uconvert(u"Hz", 10u"Hz", waterwaves) ≈ 10u"1/s" + @test uconvert(u"s", 10u"s", waterwaves) ≈ 10u"s" + @test uconvert(u"radᵃ/s", 10u"radᵃ/s", waterwaves) ≈ 10u"radᵃ/s" + @test uconvert(u"s/radᵃ", 10u"s/radᵃ", waterwaves) ≈ 10u"s/radᵃ" + + # dispersion: spatial + @test uconvert(u"radᵃ/m", 1u"1/m", waterwaves) ≈ (2π)u"radᵃ/m" + @test uconvert(u"m^-1", 1u"radᵃ/m", waterwaves) ≈ (1 / 2π)u"1/m" + @test uconvert(u"m^-1", 10u"m", waterwaves) ≈ 0.1u"1/m" + @test uconvert(u"m", 10u"m^-1", waterwaves) ≈ 0.1u"m" + @test uconvert(u"m", 2u"radᵃ/m", waterwaves) ≈ (π)u"m" + @test uconvert(u"radᵃ/m", (π)u"m", waterwaves) ≈ 2u"radᵃ/m" + @test uconvert(u"m/radᵃ", 10u"radᵃ/m", waterwaves) ≈ 0.1u"m/radᵃ" + @test uconvert(u"radᵃ/m", 10u"m/radᵃ", waterwaves) ≈ 0.1u"radᵃ/m" + @test uconvert(u"m/radᵃ", 1u"m", waterwaves) ≈ (1 / 2π)u"m/radᵃ" + @test uconvert(u"m", 1u"m/radᵃ", waterwaves) ≈ (2π)u"m" + @test uconvert(u"m/radᵃ", 1u"m^-1", waterwaves) ≈ (1 / 2π)u"m/radᵃ" + @test uconvert(u"m^-1", 1u"m/radᵃ", waterwaves) ≈ (1 / 2π)u"1/m" + @test uconvert(u"m^-1", 10u"m^-1", waterwaves) ≈ 10u"1/m" + @test uconvert(u"m", 10u"m", waterwaves) ≈ 10u"m" + @test uconvert(u"radᵃ/m", 10u"radᵃ/m", waterwaves) ≈ 10u"radᵃ/m" + @test uconvert(u"m/radᵃ", 10u"m/radᵃ", waterwaves) ≈ 10u"m/radᵃ" end @testset "Convert" begin