Skip to content

Commit

Permalink
refactor: Add properties module and add ParticleLike type
Browse files Browse the repository at this point in the history
  • Loading branch information
Beforerr committed Nov 14, 2024
1 parent 50124d0 commit b67caab
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 79 deletions.
1 change: 1 addition & 0 deletions src/ChargedParticles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ using Unitful: me, mp
const ELEMENTARY_PARTICLES = (:e, , :n)

include("./types.jl")
include("./properties.jl")
include("./aliases.jl")
include("./utils.jl")
include("./display.jl")
Expand Down
61 changes: 61 additions & 0 deletions src/properties.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""Retrieve the mass of an element isotope."""
function mass(element, mass_number)
for iso in element.isotopes
if iso.mass_number == mass_number
return iso.mass
end
end
throw(ArgumentError("No isotope found with mass number $mass_number for element $element"))
end


# Basic properties
"""Return the mass of the particle in atomic mass units"""
mass(p::AbstractParticle) = p.mass

"""Return the electric charge of the particle in elementary charge units"""
charge(p::AbstractParticle) = p.charge_number * Unitful.q

"""
atomic_number(p::AbstractParticle)
Return the atomic number (number of protons) of the particle.
# Examples
```julia
fe = Particle("Fe")
println(atomic_number(fe)) # 26
e = electron()
println(atomic_number(e)) # 0
"""
function atomic_number(p::AbstractParticle)
e = element(p)
return isnothing(e) ? 0 : e.atomic_number
end

"""
mass_number(p::AbstractParticle)
Return the mass number (total number of nucleons) of the particle.
# Examples
```julia
fe56 = Particle("Fe-56")
println(mass_number(fe56)) # 56
e = electron()
println(mass_number(e)) # 0
```
"""
mass_number(p) = p.mass_number
mass_number(::Nothing) = nothing

function element(p::AbstractParticle)
@match p.symbol begin
x, if x in ELEMENTARY_PARTICLES
end => return nothing
:p => return elements[:H]
_ => return elements[p.symbol]
end
end
98 changes: 19 additions & 79 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ See also: [`ChargedParticleImpl`](@ref)
"""
abstract type AbstractParticle end

# Type for particle-like inputs
const ParticleLike = Union{AbstractParticle,Symbol,AbstractString}

"""
ChargedParticleImpl <: AbstractParticle
Expand Down Expand Up @@ -86,34 +89,22 @@ function Particle(str::AbstractString; mass_numb=nothing, Z=nothing)
throw(ArgumentError("Invalid particle string format: $str"))
end

"""Retrieve the mass of an element isotope."""
function mass(element, mass_number)
for iso in element.isotopes
if iso.mass_number == mass_number
return iso.mass
end
end
throw(ArgumentError("No isotope found with mass number $mass_number for element $element"))
end
"""
Particle(sym::Symbol)
function parse_particle_string(str::AbstractString)
pattern = r"^([A-Za-z]+)(?:-([\d]+))?(?:\s*(\d+)?([+-]))?$"
m = match(pattern, str)
if isnothing(m)
return nothing
else
element_str, mass_str, charge_magnitude, charge_sign = m.captures
symbol = Symbol(element_str)
mass_number = isnothing(mass_str) ? nothing : parse(Int, mass_str)
charge = if isnothing(charge_sign)
nothing
else
magnitude = isnothing(charge_magnitude) ? 1 : parse(Int, charge_magnitude)
charge_sign == "+" ? magnitude : -magnitude
end
return (symbol, charge, mass_number)
end
end
Create a particle from its symbol representation.
# Examples
```jldoctest; output = false
# Elementary particles
electron = Particle(:e)
muon = Particle(:muon)
proton = Particle(:p)
# output
H⁺
```
"""
Particle(sym::Symbol; kwargs...) = Particle(string(sym); kwargs...)

"""
Particle(atomic_number::Int; mass_numb=nothing, Z=0)
Expand Down Expand Up @@ -151,55 +142,4 @@ end
"""Create an electron"""
electron() = ChargedParticleImpl(:e, -1, 0, me)
"""Create a proton"""
proton() = ChargedParticleImpl(:p, 1, 1, mp)

# Basic properties
"""Return the mass of the particle in atomic mass units"""
mass(p::AbstractParticle) = p.mass

"""Return the electric charge of the particle in elementary charge units"""
charge(p::AbstractParticle) = p.charge_number * Unitful.q

"""
atomic_number(p::AbstractParticle)
Return the atomic number (number of protons) of the particle.
# Examples
```julia
fe = Particle("Fe")
println(atomic_number(fe)) # 26
e = electron()
println(atomic_number(e)) # 0
"""
function atomic_number(p::AbstractParticle)
e = element(p)
return isnothing(e) ? 0 : e.atomic_number
end

"""
mass_number(p::AbstractParticle)
Return the mass number (total number of nucleons) of the particle.
# Examples
```julia
fe56 = Particle("Fe-56")
println(mass_number(fe56)) # 56
e = electron()
println(mass_number(e)) # 0
```
"""
mass_number(p) = p.mass_number
mass_number(::Nothing) = nothing

function element(p::AbstractParticle)
@match p.symbol begin
x, if x in ELEMENTARY_PARTICLES
end => return nothing
:p => return elements[:H]
_ => return elements[p.symbol]
end
end
proton() = ChargedParticleImpl(:p, 1, 1, mp)
19 changes: 19 additions & 0 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,23 @@ function determine(x, y; default=nothing)
($nothing, y) => y
(x, y) => x == y ? x : throw(ArgumentError("Inconsistent $x and $y"))
end
end

function parse_particle_string(str::AbstractString)
pattern = r"^([A-Za-z]+)(?:-([\d]+))?(?:\s*(\d+)?([+-]))?$"
m = match(pattern, str)
if isnothing(m)
return nothing
else
element_str, mass_str, charge_magnitude, charge_sign = m.captures
symbol = Symbol(element_str)
mass_number = isnothing(mass_str) ? nothing : parse(Int, mass_str)
charge = if isnothing(charge_sign)
nothing
else
magnitude = isnothing(charge_magnitude) ? 1 : parse(Int, charge_magnitude)
charge_sign == "+" ? magnitude : -magnitude
end
return (symbol, charge, mass_number)
end
end

0 comments on commit b67caab

Please sign in to comment.