Species

A Species is the central data structure of AtomicAndPhysicalConstants.jl. It bundles all intrinsic properties of a particle — mass, charge, spin, magnetic moment, and particle kind — into a single immutable object.

Constructing a species

All species are created with the single-string constructor

Species(speciesname::String)

The string format encodes the particle identity, isotope (for atoms), and charge state in one compact expression.

Subatomic particles

Pass the openPMD particle name exactly as it appears in the table below.

StringParticle
"electron"electron
"positron"positron
"proton"proton
"anti-proton"antiproton
"neutron"neutron
"anti-neutron"antineutron
"muon"muon (μ⁻)
"anti-muon"antimuon (μ⁺)
"pion0"neutral pion
"pion+"positive pion
"pion-"negative pion
"deuteron"deuteron
"anti-deuteron"antideuteron
"triton"triton
"anti-triton"antitriton
"helion"helion
"anti-helion"antihelion
"photon"photon
e  = Species("electron")
mu = Species("muon")
pi0 = Species("pion0")

Atomic species

Atomic symbols from "H" (Z = 1) through "Og" (Z = 118) are supported.

The full format for an atomic species string is:

[mass_number] symbol [charge]

where both mass_number and charge are optional.

Mass number — when given as ASCII digits it must be preceded by #; it may also be written with Unicode superscript digits (no # needed). A bare ASCII mass number such as "4He" is not accepted:

Species("He")    # helium, abundance-averaged mass
Species("#4He")  # helium-4  (# prefix is required for ASCII digits)
Species("⁴He")   # helium-4  (Unicode superscript)

Charge state — appended after the symbol:

SyntaxMeaning
"Li+"+1
"Li++"+2
"Li+++"+3
"Li+3"+3
"K-"−1
"K--"−2
"K-3"−3
"N⁻³"−3 (Unicode superscript magnitude)

Up to three repeated + or - signs are accepted; for larger charges use the +n / -n form.

Species("Li+++") == Species("Li+3")   # true
Species("K---")  == Species("K-3")    # true

Anti-atoms

Prepend "anti-" to any atomic symbol:

Species("anti-H")   # antihydrogen
Species("anti-Fe")  # anti-iron

Null species

A null (placeholder) species is created with no arguments or with the strings "Null", "null", or "":

Species()        # null species
Species("null")  # also null

Use isnullspecies to test for a null species.


Accessing species parameters

A Species is immutable, and its fields are deliberately not reachable with dot syntax. Every property is read through an accessor function instead, which keeps the unit conventions and the special cases below in one place:

p = Species("proton")

p.mass        # ERROR — dot access is disabled
massof(p)     # 9.3827208943e8   eV/c²

Quick reference

Three of the accessors take a keyword argument that switches the unit or sign convention; the signatures below show its default. sp is any Species.

FunctionReturnsUnits / convention
nameof(sp)canonical species nameString, in the #mAS±c form
massof(sp; AMU = false)rest masseV/c², or atomic mass units (daltons) with AMU = true
chargeof(sp; C = false)net chargemultiples of the elementary charge e, or coulombs with C = true, using the active E_CHARGE
spinof(sp)spin; for an atom, the nuclear spinħ
momentof(sp)magnetic dipole momenteV/T
g_spin(sp; signed = false)spin g-factordimensionless |g|, or the signed value with signed = true (negative for the electron, muon, neutron, and helion)
gyromagnetic_anomaly(sp)gyromagnetic anomaly adimensionless
iso_of(sp)mass numberinteger
atomicnumberof(sp)atomic number Zinteger, negative for anti-atoms
kindof(sp)particle classificationKind.T enum value
isnullspecies(sp)whether the species is a placeholderBool

All of the numeric accessors return Float64 except iso_of and atomicnumberof, which return Int.

gyromagnetic_anomaly is built on the unsigned g-factor, so $a = (|g| - 2)/2$ comes out positive for the particles whose stored g-factor is negative. See Physical Constants for why the deuteron, helion, and triton g-factors are renormalized before this formula is applied.

Species that do not carry a given property

Not every property is defined for every kind of particle. Rather than erroring, most accessors return a neutral value:

FunctionOutside its domain
momentof0.0 for atoms and the null species
g_spin0.0 for atomic species (no g-factor is stored)
gyromagnetic_anomalyNaN for photons, atoms, and the null species
spinofNaN for an atom given without a mass number, and for the few isotopes NUBASE leaves unassigned
iso_of0 for subatomic particles; -1 for an atom given without a mass number
atomicnumberofthrows an error for anything that is not an atom

Nuclear spin

For an atomic species, spinof returns the nuclear spin, from the tabulated ground-state values of NUBASE2020. Electron spin is not included, since the total angular momentum of an atom depends on its electronic state, which Species does not model. Two consequences follow: ionising an atom does not change its spin, and an anti-nucleus has the same spin as its mirror.

Nuclear spin is not a function of the mass number. Nucleons pair off with opposite spins, so every even-even nucleus has spin 0 and no closed formula in A reproduces the tabulated values:

julia> using AtomicAndPhysicalConstants

julia> spinof(Species("#4He"))    # even-even: two paired protons, two paired neutrons
0.0

julia> spinof(Species("#3He"))    # one unpaired neutron
0.5

julia> spinof(Species("#12C"))
0.0

julia> spinof(Species("#235U"))
3.5

An atom given without a mass number has no single nuclear spin — the abundance average runs over isotopes with differing spins — so NaN is returned:

julia> spinof(Species("He"))
NaN

Every isotope that occurs naturally has a directly measured spin. For nuclei far from stability the tabulated value may come from NUBASE systematics, and a small number of exotic isotopes carry no unambiguous assignment at all; those also return NaN.

Worked example

julia> using AtomicAndPhysicalConstants

julia> e = Species("electron");

julia> massof(e)            # eV/c²
510998.95069

julia> chargeof(e)          # units of e
-1.0

julia> spinof(e)            # ħ
0.5

julia> g_spin(e)            # absolute value by default
2.00231930436092

julia> g_spin(e, signed = true)
-2.00231930436092

julia> gyromagnetic_anomaly(e)
0.0011596521804599913

julia> momentof(e)          # eV/T
-5.795094307320036e-5

Atomic species carry a mass number and an atomic number, and their mass is often more convenient in daltons:

julia> he3 = Species("#3He");

julia> massof(he3, AMU = true)
3.0160293201

julia> iso_of(he3)
3

julia> atomicnumberof(he3)
2

julia> iso_of(Species("He"))   # abundance-averaged, no specific isotope
-1

julia> nameof(Species("Li+"))
"Li+1"

The full docstring of each accessor is in the API Reference.


The Kind enum

Every species carries a kind field of type Kind.T (provided by EnumX.jl):

ValueMeaning
Kind.LEPTONelectron, positron, muon, anti-muon
Kind.HADRONproton, neutron, pions, deuteron, …
Kind.PHOTONphoton
Kind.ATOMany atomic / ionic species
Kind.NULLnull / placeholder species
kindof(Species("electron")) == Kind.LEPTON   # true
kindof(Species("Fe"))       == Kind.ATOM     # true

Going further

The tables behind the constructor — isotope masses and nuclear spins — are exported as dictionaries, and the sources they are drawn from are described in Internals.