From 43aade957ecf9b704044b75635a1c961ac0abd01 Mon Sep 17 00:00:00 2001 From: Kipton Barros Date: Thu, 25 Jul 2024 13:59:08 -0600 Subject: [PATCH] Update to units --- src/Units.jl | 56 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/src/Units.jl b/src/Units.jl index e97364d77..5e957cf97 100644 --- a/src/Units.jl +++ b/src/Units.jl @@ -1,62 +1,82 @@ -# Angstrom in selected length unit const angstrom_in = Base.ImmutableDict( :angstrom => 1.0, # == Å / Å :nm => 0.1, # == Å / nm ) -# meV in selected energy unit const meV_in = Base.ImmutableDict( :meV => 1.0, # meV / meV :K => 801088317/69032450, # meV / kB K :THz => 267029439/1104345025, # meV / h THz + :inverse_cm => 6621486190496429/53405887800000000, # meV / (h c / cm) :T => 17.275985474052367519, # meV / μB T ) +const unit_strs = Base.ImmutableDict( + :angstrom => "Å", + :nm => "nm", + :meV => "meV", + :K => "K", + :THz => "THz", + :inverse_cm => "cm⁻¹", + :T => "μB T", + :vacuum_permeability => "μ0 μB²", +) """ Units(energy, length=:angstrom) Physical constants in units of reference `energy` and `length` scales. Possible -lengths are `[:angstrom, :nm]` and possible energies are `[:meV, :K, :THz]`. -Kelvin is converted to energy via the Boltzmann constant ``k_B``. Similarly, -hertz is converted via the Planck constant ``h``, and tesla (field strength) via -the Bohr magneton ``μ_B``. For a given `Units` system, one can access length -scales (`angstrom`, `nm`) and energy scales (`meV`, `K`, `THz`, `T`). +lengths are `[:angstrom, :nm]` and possible energies are `[:meV, :K, :THz, +:inverse_cm, :T]`. Kelvin is converted to energy via the Boltzmann constant +``k_B``. Similarly, hertz is converted via the Planck constant ``h``, inverse cm +via the speed of light ``c``, and tesla (field strength) via the Bohr magneton +``μ_B``. For a given `Units` system, one can access any of the length and energy +scale symbols listed above. # Examples ```julia -# Create a unit system where energies are measured in meV +# Unit system with [energy] = meV and [length] = Å units = Units(:meV) -# Use the Boltzmann constant ``k_B`` to convert 1 kelvin into meV +# Use the Boltzmann constant kB to convert 1 kelvin into meV @assert units.K ≈ 0.0861733326 -# Use the Planck constant ``h`` to convert 1 THz into meV +# Use the Planck constant h to convert 1 THz into meV @assert units.THz ≈ 4.135667696 -# Use the Bohr magneton ``μ_B`` to convert 1 tesla into meV +# Use the constant h c to convert 1 cm⁻¹ into meV +@assert units.inverse_cm ≈ 0.1239841984 + +# Use the Bohr magneton μB to convert 1 tesla into meV @assert units.T ≈ 0.05788381806 -# The physical constant ``μ_0 μ_B²`` in units of ų meV. +# The physical constant μ0 μB² in units of ų meV. @assert u.vacuum_permeability ≈ 0.6745817653 ``` """ -struct Units{E, L} +struct Units + energy::Symbol + length::Symbol + function Units(energy, length=:angstrom) length in keys(angstrom_in) || error("`length` must be one of $(keys(angstrom_in))") energy in keys(meV_in) || error("`energy` must be one of $(keys(meV_in))") - return new{energy, length}() + return new(energy, length) end end -function Base.getproperty(u::Units{E, L}, name::Symbol) where {E, L} +function Base.getproperty(u::Units, name::Symbol) + if name in (:energy, :length) + return getfield(u, name) + end + if name in (:meV, :K, :THz, :T) - return meV_in[E] / meV_in[name] + return meV_in[u.energy] / meV_in[name] end if name in (:angstrom, :nm) - return angstrom_in[L] / angstrom_in[name] + return angstrom_in[u.length] / angstrom_in[name] end if name == :vacuum_permeability @@ -64,5 +84,5 @@ function Base.getproperty(u::Units{E, L}, name::Symbol) where {E, L} return 0.6745817653324668 * u.angstrom^3 * u.meV end - error("type Units has no constant $name") + error("Unknown unit :$name") end