Skip to content

Commit

Permalink
Update to units
Browse files Browse the repository at this point in the history
  • Loading branch information
kbarros committed Jul 26, 2024
1 parent cf92da3 commit 43aade9
Showing 1 changed file with 38 additions and 18 deletions.
56 changes: 38 additions & 18 deletions src/Units.jl
Original file line number Diff line number Diff line change
@@ -1,68 +1,88 @@
# 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
# 0.6745... = μ0 μB² / ų meV
return 0.6745817653324668 * u.angstrom^3 * u.meV
end

error("type Units has no constant $name")
error("Unknown unit :$name")
end

0 comments on commit 43aade9

Please sign in to comment.