From f40d25f556f8ddfceaa50b0df78da00d93b63d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20A=2E=20Michel=C3=A9n=20Str=C3=B6fer?= Date: Sun, 3 Dec 2023 22:25:08 -0700 Subject: [PATCH] Add support for luminous flux and illuminace (#40) --- docs/src/guide/derived.md | 30 ++++++++++++++++++++++++++++++ src/DimensionfulAngles.jl | 4 ++-- src/convert.jl | 4 ++++ src/defaults.jl | 30 +++++++++++++++++++++--------- src/derived.jl | 26 ++++++++++++++++++++++++++ test/test_core_package.jl | 14 +++++++++++--- 6 files changed, 94 insertions(+), 14 deletions(-) diff --git a/docs/src/guide/derived.md b/docs/src/guide/derived.md index e1e3135..81089a4 100644 --- a/docs/src/guide/derived.md +++ b/docs/src/guide/derived.md @@ -4,6 +4,8 @@ These are: - [`DimensionfulAngles.SolidAngle`](@ref) + - [`DimensionfulAngles.LuminousFlux`](@ref) + - [`DimensionfulAngles.Illuminance`](@ref) - [`DimensionfulAngles.AngularVelocity`](@ref) - [`DimensionfulAngles.AngularAcceleration`](@ref) - [`DimensionfulAngles.AngularWavelength`](@ref) @@ -31,6 +33,20 @@ DimensionfulAngles.SolidAngle DimensionfulAngles.srᡃ ``` +## Luminous flux and illuminance +Luminous flux is a measure of perceived power of light and has dimensions of ``𝐉*𝐀²``. +The SI unit lumen (lm) = candela x steradian is provided as [`DimensionfulAngles.lmᡃ`](@ref). + +Illuminance is luminous flux per unit surface area and has dimensions of ``𝐉*𝐀²*𝐋⁻²``. +The SI unit lux (lx) = lumen / meter^2 is provided as [`DimensionfulAngles.lxᡃ`](@ref). + +```@docs +DimensionfulAngles.LuminousFlux +DimensionfulAngles.Illuminance +DimensionfulAngles.lmᡃ +DimensionfulAngles.lxᡃ +``` + ## Angular velocity and acceleration [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. @@ -111,6 +127,10 @@ DimensionfulAngles.AngularPeriodUnits DimensionfulAngles.AngularPeriodFreeUnits DimensionfulAngles.AngularWavelengthUnits DimensionfulAngles.AngularWavelengthFreeUnits +DimensionfulAngles.LuminousFluxUnits +DimensionfulAngles.LuminousFluxFreeUnits +DimensionfulAngles.IlluminanceUnits +DimensionfulAngles.IlluminanceFreeUnits ``` ### [Prefixed Units](@id derived_prefixed) @@ -119,3 +139,13 @@ DimensionfulAngles.AngularWavelengthFreeUnits Modules = [DimensionfulAngles] Filter = x->_filter_prefixed("sr", x) ``` + +```@autodocs +Modules = [DimensionfulAngles] +Filter = x->_filter_prefixed("lm", x) +``` + +```@autodocs +Modules = [DimensionfulAngles] +Filter = x->_filter_prefixed("lx", x) +``` diff --git a/src/DimensionfulAngles.jl b/src/DimensionfulAngles.jl index 10862a1..2862c26 100644 --- a/src/DimensionfulAngles.jl +++ b/src/DimensionfulAngles.jl @@ -28,9 +28,9 @@ 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: cd as cdα΅€, 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: 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 diff --git a/src/convert.jl b/src/convert.jl index a0149d2..1750d54 100644 --- a/src/convert.jl +++ b/src/convert.jl @@ -47,6 +47,8 @@ function Unitful.uconvert(s::Val{:Unitful}, x::Quantity) x = _convert_units(x, srᡃ, 𝐀^2, sr, NoDims) x = _convert_units(x, rpsᡃ, 𝐀*𝐓^-1, rps, 𝐓^-1) x = _convert_units(x, rpmᡃ, 𝐀*𝐓^-1, rpm, 𝐓^-1) + x = _convert_units(x, lmᡃ, 𝐀^2*𝐉, lm, 𝐉) + x = _convert_units(x, lxᡃ, 𝐀^2*𝐉*𝐋^-2, lx, 𝐉*𝐋^-2) return x end @@ -61,6 +63,8 @@ function Unitful.uconvert(s::Val{:DimensionfulAngles}, x::Quantity) x = _convert_units(x, sr, NoDims, srᡃ, 𝐀^2) x = _convert_units(x, rps, 𝐓^-1, rpsᡃ, 𝐀*𝐓^-1) x = _convert_units(x, rpm, 𝐓^-1, rpmᡃ, 𝐀*𝐓^-1) + x = _convert_units(x, lm, 𝐉, lmᡃ, 𝐀^2*𝐉) + x = _convert_units(x, lx, 𝐉*𝐋^-2, lxᡃ, 𝐀^2*𝐉*𝐋^-2) return x end diff --git a/src/defaults.jl b/src/defaults.jl index 40b20e9..0748fe4 100644 --- a/src/defaults.jl +++ b/src/defaults.jl @@ -21,11 +21,11 @@ will bring the following into the calling namespace: - Base and derived SI units, with SI prefixes - - Candela conflicts with `Base.cd` so it is not brought in (Unitful.jl issue #102) + - Candela conflicts with `Base.cd` so it is brought in as `cdα΅€`. - Degrees: Β° -All angles imported removing the ᡃ superscript. +All angles and derived units imported removing the ᡃ superscript. !!! note "Potential conflict with other packages" @@ -40,7 +40,7 @@ baremodule DefaultSymbols import DimensionfulAngles using Base: filter, ∈, ! - __angle_units = (:rad,:sr) + __angle_units = (:rad, :sr, :lm, :lx) __non_angle_units = filter(u -> !(u ∈ __angle_units), Unitful.si_no_prefix) # Unitful Dimensions @@ -49,10 +49,11 @@ baremodule DefaultSymbols Core.eval(DefaultSymbols, Expr(:export, u)) end - # DimensionfulAngles Dimension + # DimensionfulAngles Dimensions Core.eval(DefaultSymbols, Expr(:import, Expr(:(.), :DimensionfulAngles, :𝐀))) Core.eval(DefaultSymbols, Expr(:export, :𝐀)) + # units for p in Unitful.si_prefixes # Unitful units for u in __non_angle_units @@ -61,18 +62,29 @@ baremodule DefaultSymbols end # DimensionfulAngles units for u in __angle_units - DAname = Symbol(p,u,:ᡃ) - name = Symbol(p,u) - Core.eval(DefaultSymbols, Expr(:import, Expr(:(.), :DimensionfulAngles, DAname))) - Core.eval(DefaultSymbols, Expr(:(=), name, DAname)) - Core.eval(DefaultSymbols, Expr(:export, name)) + Core.eval( + DefaultSymbols, + Expr(:import, Expr(:(.), :DimensionfulAngles, Symbol(p,u,:ᡃ))) + ) + Core.eval(DefaultSymbols, Expr(:(=), Symbol(p,u), Symbol(p,u,:ᡃ))) + Core.eval(DefaultSymbols, Expr(:export, Symbol(p,u))) end end + # degrees Celsius Core.eval(DefaultSymbols, Expr(:import, Expr(:(.), :Unitful, :Β°C))) Core.eval(DefaultSymbols, Expr(:export, :Β°C)) + # DimensionfulAngles degree Core.eval(DefaultSymbols, Expr(:import, Expr(:(.), :DimensionfulAngles, :°ᡃ))) Core.eval(DefaultSymbols, Expr(:(=), :Β°, :°ᡃ)) Core.eval(DefaultSymbols, Expr(:export, :Β°)) + + # candela + u = :cd + for p in Unitful.si_prefixes + Core.eval(DefaultSymbols, Expr(:import, Expr(:(.), :Unitful, Symbol(p,u)))) + Core.eval(DefaultSymbols, Expr(:(=), Symbol(p,u,:α΅€), Symbol(p,u))) + Core.eval(DefaultSymbols, Expr(:export, Symbol(p,u,:α΅€))) + end end diff --git a/src/derived.jl b/src/derived.jl index f8d72cd..71dab3b 100644 --- a/src/derived.jl +++ b/src/derived.jl @@ -18,6 +18,32 @@ Dimension: `𝐀²`." """ @unit srᡃ "sr" Steradianᡃ (1radᡃ*radᡃ) true true +# Luminous flux and illuminance +@derived_dimension LuminousFlux (𝐉*𝐀^2) true +@derived_dimension Illuminance (𝐉*𝐀^2*𝐋^-2) true + +""" + lmᡃ + +The lumen, an SI unit of luminous flux. + +Defined as 1 cd Γ— sr. Accepts SI prefixes. + +Dimension: `𝐉𝐀²`." +""" +@unit lmᡃ "lm" Lumenᡃ 1cdα΅€*srᡃ true true + +""" + lxᡃ + +The lux, an SI unit of illuminance. + +Defined as 1 lm / m^2. Accepts SI prefixes. + +Dimension: `𝐉𝐀²𝐋⁻²`." +""" +@unit lxᡃ "lx" Luxᡃ 1lmᡃ/m^2 true true + # Angular velocity, angular acceleration, and angular frequency. @derived_dimension AngularVelocity (𝐀*𝐓^-1) true @derived_dimension AngularAcceleration (𝐀*𝐓^-2) true diff --git a/test/test_core_package.jl b/test/test_core_package.jl index ea8dbfe..dedc0e3 100644 --- a/test/test_core_package.jl +++ b/test/test_core_package.jl @@ -1,5 +1,5 @@ using Test, DimensionfulAngles, Unitful, UnitfulAngles -using Unitful: 𝐓, 𝐋, ContextUnits, FixedUnits, FreeUnits, Units +using Unitful: 𝐉, 𝐓, 𝐋, ContextUnits, FixedUnits, FreeUnits, Units using DimensionfulAngles: 𝐀 function test_uamacro(unit::Symbol) @@ -245,10 +245,18 @@ end (1//60)^2 * (1//3600)^-1 ) end + # derived units + let x = 1.98u"rpm*rps^2*lm^-1*lx*msr^2" + @test unit(uconvert(:DimensionfulAngles, x)) == ua"rpm*rps^2*lm^-1*lx*msr^2" + @test (uconvert(:DimensionfulAngles, x)).val β‰ˆ 1.98 + end end @testset "DefaultSymbols" begin @test typeof(DimensionfulAngles.DefaultSymbols) == Module - @test dimension(DimensionfulAngles.DefaultSymbols.rad) == DimensionfulAngles.𝐀 - @test dimension(DimensionfulAngles.DefaultSymbols.Β°) == DimensionfulAngles.𝐀 + @test dimension(DimensionfulAngles.DefaultSymbols.rad) == 𝐀 + @test dimension(DimensionfulAngles.DefaultSymbols.Β°) == 𝐀 + @test dimension(DimensionfulAngles.DefaultSymbols.lm) == 𝐉*𝐀^2 + @test dimension(DimensionfulAngles.DefaultSymbols.lx) == 𝐉*𝐀^2*𝐋^-2 + @test DimensionfulAngles.DefaultSymbols.cdα΅€ === Unitful.cd end