-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
38 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |