ggggggggg / Physical.jl

Units, physical constants, error propagation.
MIT License
7 stars 5 forks source link

Atomic units #9

Open jagot opened 8 years ago

jagot commented 8 years ago

I would like to use this package for atomic units, a unit system where some fundamental quantities are set to unity:

ħ = mₑ = e = 1/(4πε₀) = 1

From these and the fundamental constants, a lot of other units can be derived, such as the unit of length, the Bohr radius a₀ = 4πε₀ħ²/(mₑe²) or the unit of energy, the Hartree Eₕ = α²mₑc² (which incidentally is 2 Rydberg, i.e., twice the binding energy of hydrogen).

It is not too difficult to create something like this:

const Hartree = DerivedUnit("Eₕ", alpha_fine_structure^2*m_electron*c_light^2)
const Tau0 = DerivedUnit("τ₀", hbar_plank/Hartree)
const vB = DerivedUnit("vᴮ", alpha_fine_structure*c_light)
const EField = DerivedUnit("ℰ₀", e_electron/(4π*E0_electric*A_bohr^2))
const I0 = DerivedUnit("I₀", 1/2*E0_electric*c_light*EField^2)

const hartree_eV = Hartree/ElectronVolt
const c_light_au = c_light/vB

export Hartree, Tau0, vB, EField, I0
export hartree_eV, c_light_au

and then use it like this to convert from SI units to atomic units:

λ = 800*(Nano*Meter)/A_bohr
I₀ = 1e13*(Watt/(Centi*Meter)^2)/I0
E₀ = √(I₀)

but I have the feeling there might be a more elegant way to solve this, and furthermore, I am not sure what would be the best names for all the quantities.

I don't think that defining a new unit system, like it is done for CGS is the way to go, since in atomic units, all quantities are somehow "unitless", and I am mostly interested in converting numbers from SI units to atomic units, not doing "unit algebra".

If this can be solved in an elegant fashion, it is trivial to something similar for natural units, where

ħ = c = kᴮ = 1

and all other specialized unit systems that can be thought of.

I am willing to implement this, but I would like to hear how you think it should be done.

ggggggggg commented 8 years ago

This was one of my original interests when I started the package, but I don't actually need it, and just getting the basic functionality took more work than I expected (mostly because I made a few mistakes along the way and it was my first Julia project). So I never came back to it.

What do you think of this?

import Physical: AtomicUnitsOne
λ = 5.2917721092e-11*Meter
as(λ, AtomicUnitsOne) # return 1 AtomicUnits
as(77*AtomicUnitsOne, λ) # convert the Quantity 77 AtomicUnits to have the same units as λ (aka Meters), returns 4.074664524084e-09*Meter
l = 12*AtomicUnitsOne # 12 Atomic Units

It would work for converting to/from atomic units, and the same API could be made to work for natural units. I think it would be easiest to implement if AtomicUnitOne was of a new type AtomicUnitsQuantity. Or maybe if unit system were a type parameter of Quantity. So instead of Quantity{Float64} there would be Quantity{SIUnits, Float64} and Quantity{AtomicUnits, Float64}.

That approach would be a fair amount more work than simply defining the relevant constants. A middle ground would be to define a pair of functions toatomicunits(x::Quantity), fromatomicunits(x::Quantity, dimensions::Quantity) where the value of dimensions is ignored (like as).

jagot commented 8 years ago

Thanks for the input, I'll see what I can do.

jagot commented 8 years ago

I have had a nice proof-of-concept going for some time now, but I think there are some things that could be nicer. See https://github.com/jagot/Physical.jl/blob/natural-units/src/NaturalUnits.jl

It is possible to define a natural unit system like so

@define_natural_unit_system(Hartree, "au",
                            [Hbar_planck,
                             E_electron,
                             M_electron,
                             K_coulomb,
                             K_boltzmann])

and then converting a quantity into Hartree atomic units is a simple matter of

julia> au=get_natural_unity(:Hartree)
Physical.NaturalUnits.HartreeUnitsQuantity{Float64}

julia> au(A_bohr)
Physical.NaturalUnits.HartreeUnitsQuantity{Float64}(1.0000000002679588,1.0 mₑ⁻¹kₑ⁻¹ℏ²e⁻²)

This is nice, I think, but there are some issues:

Do you have any idea on how to go forward?

ggggggggg commented 8 years ago

You state that design AtomicUnitsQuantity is chosen such that "take any unknown quantity in a natural system and automatically get its SI value". However, isn't it the case there a quantity expressed in a natural units system has many possible SI values depending on the dimension of the quantity? For example the quantity 1 expressed in Planck Units can have the value 1.0545717259999999e-31 g s⁻¹m² (hbar), 1.3806488e-20 g s⁻²K⁻¹m² (kb), or other values depending on the dimensions. So I don't understand why you want to keep one specific choice of representation around.

It seems worth hashing that out before working on the details.