diff --git a/.gitignore b/.gitignore index 5a16984..493f309 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ -/Manifest.toml -/docs/Manifest.toml -/docs/build/ +*Manifest.toml +docs/build/ diff --git a/src/QEDcore.jl b/src/QEDcore.jl index c42bed0..782b285 100644 --- a/src/QEDcore.jl +++ b/src/QEDcore.jl @@ -15,6 +15,12 @@ export BiSpinor, AdjointBiSpinor, DiracMatrix # gamma matrices export gamma, GAMMA, DiracGammaRepresentation, slashed +# particle types +export AbstractParticleSpinor +export FermionLike, Fermion, AntiFermion, MajoranaFermion +export BosonLike, Boson, AntiBoson, MajoranaBoson +export Electron, Positron, Photon + # particle spinors export BASE_PARTICLE_SPINOR, BASE_ANTIPARTICLE_SPINOR export IncomingFermionSpinor, @@ -35,5 +41,6 @@ include("algebraic_objects/lorentz_vector.jl") include("algebraic_objects/gamma_matrices.jl") include("particles/spinors.jl") +include("particles/particle_types.jl") end diff --git a/src/algebraic_objects/lorentz_vector.jl b/src/algebraic_objects/lorentz_vector.jl index cff8c75..a0cfcfc 100644 --- a/src/algebraic_objects/lorentz_vector.jl +++ b/src/algebraic_objects/lorentz_vector.jl @@ -98,4 +98,4 @@ end # TODO: this breaks incremental compilation because it's trying to eval permanent changes in a different module #register_LorentzVectorLike(MLorentzVector) @traitimpl QEDbase.IsLorentzVectorLike{MLorentzVector} -@traitimpl QEDbase.IsMutableLorentzVectorLike{MLorentzVector} \ No newline at end of file +@traitimpl QEDbase.IsMutableLorentzVectorLike{MLorentzVector} diff --git a/src/particles/particle_types.jl b/src/particles/particle_types.jl new file mode 100644 index 0000000..2ef3c72 --- /dev/null +++ b/src/particles/particle_types.jl @@ -0,0 +1,202 @@ +############### +# The particle types +# +# In this file, we define the types of particles, their states and directions, and +# implement the abstact particle interface accordingly. +############### + +import QEDbase: is_particle, is_anti_particle, is_boson, is_fermion, mass, charge + +""" + AbstractParticleSpinor + +TBW +""" +abstract type AbstractParticleSpinor end + +""" +Abstract base types for particle species that act like fermions in the sense of particle statistics. + +!!! note "particle interface" + Every concrete subtype of [`FermionLike`](@ref) has `is_fermion(::FermionLike) = true`. +""" +abstract type FermionLike <: QEDbase.AbstractParticleType end + +is_fermion(::FermionLike) = true + +""" +Abstract base type for fermions as distinct from [`AntiFermion`](@ref)s. + +!!! note "particle interface" + All subtypes of `Fermion` have + ```julia + is_fermion(::Fermion) = true + is_particle(::Fermion) = true + is_anti_particle(::Fermion) = false + ``` + +""" +abstract type Fermion <: FermionLike end + +is_particle(::Fermion) = true + +is_anti_particle(::Fermion) = false + +""" +Abstract base type for anti-fermions as distinct from its particle counterpart `Fermion`. + +!!! note "particle interface" + All subtypes of `AntiFermion` have + ```julia + is_fermion(::AntiFermion) = true + is_particle(::AntiFermion) = false + is_anti_particle(::AntiFermion) = true + ``` +""" +abstract type AntiFermion <: FermionLike end + +is_particle(::AntiFermion) = false + +is_anti_particle(::AntiFermion) = true + +""" +Abstract base type for majorana-fermions, i.e. fermions which are their own anti-particles. + +!!! note "particle interface" + All subtypes of `MajoranaFermion` have + ```julia + is_fermion(::MajoranaFermion) = true + is_particle(::MajoranaFermion) = true + is_anti_particle(::MajoranaFermion) = true + ``` + +""" +abstract type MajoranaFermion <: FermionLike end + +is_particle(::MajoranaFermion) = true + +is_anti_particle(::MajoranaFermion) = true + +""" +Concrete type for *electrons* as a particle species. Mostly used for dispatch. + +```jldoctest +julia> using QEDbase + +julia> Electron() +electron +``` + +!!! note "particle interface" + Besides being a subtype of [`Fermion`](@ref), objects of type `Electron` have + + ```julia + mass(::Electron) = 1.0 + charge(::Electron) = -1.0 + ``` +""" +struct Electron <: Fermion end +mass(::Electron) = 1.0 +charge(::Electron) = -1.0 +Base.show(io::IO, ::Electron) = print(io, "electron") + +""" +Concrete type for *positrons* as a particle species. Mostly used for dispatch. + +```jldoctest +julia> using QEDbase + +julia> Positron() +positron +``` + +!!! note "particle interface" + Besides being a subtype of [`AntiFermion`](@ref), objects of type `Positron` have + + ```julia + mass(::Positron) = 1.0 + charge(::Positron) = 1.0 + ``` +""" +struct Positron <: AntiFermion end +mass(::Positron) = 1.0 +charge(::Positron) = 1.0 +Base.show(io::IO, ::Positron) = print(io, "positron") + +""" +Abstract base types for particle species that act like bosons in the sense of particle statistics. + +!!! note "particle interface" + Every concrete subtype of `BosonLike` has `is_boson(::BosonLike) = true`. +""" +abstract type BosonLike <: QEDbase.AbstractParticleType end + +is_boson(::BosonLike) = true + +""" +Abstract base type for bosons as distinct from its anti-particle counterpart [`AntiBoson`](@ref). + +!!! note "particle interface" + All subtypes of `Boson` have + ```julia + is_boson(::Boson) = true + is_particle(::Boson) = true + is_anti_particle(::Boson) = false + ``` +""" +abstract type Boson <: BosonLike end +is_particle(::Boson) = true +is_anti_particle(::Boson) = false + +""" +Abstract base type for anti-bosons as distinct from its particle counterpart [`Boson`](@ref). + +!!! note "particle interface" + All subtypes of `AntiBoson` have + ```julia + is_boson(::AntiBoson) = true + is_particle(::AntiBoson) = false + is_anti_particle(::AntiBoson) = true + ``` +""" +abstract type AntiBoson <: BosonLike end +is_particle(::AntiBoson) = false +is_anti_particle(::AntiBoson) = true + +""" +Abstract base type for majorana-bosons, i.e. bosons which are their own anti-particles. + +!!! note "particle interface" + All subtypes of `MajoranaBoson` have + ```julia + is_boson(::MajoranaBoson) = true + is_particle(::MajoranaBoson) = true + is_anti_particle(::MajoranaBoson) = true + ``` +""" +abstract type MajoranaBoson <: BosonLike end +is_particle(::MajoranaBoson) = true +is_anti_particle(::MajoranaBoson) = true + +""" +Concrete type for the *photons* as a particle species. Mostly used for dispatch. + +```jldoctest +julia> using QEDbase + +julia> Photon() +photon +``` + +!!! note "particle interface" + Besides being a subtype of `MajoranaBoson`, `Photon` has + + ```julia + mass(::Photon) = 0.0 + charge(::Photon) = 0.0 + ``` +""" +struct Photon <: MajoranaBoson end +mass(::Photon) = 0.0 +charge(::Photon) = 0.0 +Base.show(io::IO, ::Photon) = print(io, "photon") diff --git a/src/particles/spinors.jl b/src/particles/spinors.jl index f20b60c..d366807 100644 --- a/src/particles/spinors.jl +++ b/src/particles/spinors.jl @@ -118,6 +118,7 @@ end const SpinorVbar = IncomingAntiFermionSpinor +# TODO: reenable when it's no longer in QEDbase # function getindex(SP::T, idx) where {T<:QEDbase.AbstractParticleSpinor} # return idx in (1, 2) ? SP(idx) : throw(BoundsError()) # end diff --git a/test/particles/types.jl b/test/particles/types.jl new file mode 100644 index 0000000..4766170 --- /dev/null +++ b/test/particles/types.jl @@ -0,0 +1,77 @@ +using QEDbase +using StaticArrays +using Random + +# TODO this can be deleted when QEDbase is released again +# fix for the broadcast tests +Base.broadcastable(part::QEDbase.AbstractParticleType) = Ref(part) + +# test function to test scalar broadcasting +test_broadcast(x::AbstractParticle) = x +test_broadcast(x::ParticleDirection) = x +test_broadcast(x::AbstractSpinOrPolarization) = x + +@testset "fermion likes" begin + @testset "antifermion" begin + struct TestAntiFermion <: AntiFermion end + @test is_fermion(TestAntiFermion()) + @test !is_particle(TestAntiFermion()) + @test is_anti_particle(TestAntiFermion()) + @test test_broadcast.(TestAntiFermion()) == TestAntiFermion() + end + + @testset "majorana fermion" begin + struct TestMajoranaFermion <: MajoranaFermion end + @test is_fermion(TestMajoranaFermion()) + @test is_particle(TestMajoranaFermion()) + @test is_anti_particle(TestMajoranaFermion()) + @test test_broadcast.(TestMajoranaFermion()) == TestMajoranaFermion() + end + + @testset "electron" begin + @test is_fermion(Electron()) + @test is_particle(Electron()) + @test !is_anti_particle(Electron()) + @test mass(Electron()) == 1.0 + @test charge(Electron()) == -1.0 + @test test_broadcast.(Electron()) == Electron() + end + + @testset "positron" begin + @test is_fermion(Positron()) + @test !is_particle(Positron()) + @test is_anti_particle(Positron()) + @test mass(Positron()) == 1.0 + @test charge(Positron()) == 1.0 + @test test_broadcast.(Positron()) == Positron() + end +end + +@testset "boson likes" begin + @testset "boson" begin + struct TestBoson <: Boson end + @test !is_fermion(TestBoson()) + @test is_boson(TestBoson()) + @test is_particle(TestBoson()) + @test !is_anti_particle(TestBoson()) + @test test_broadcast.(TestBoson()) == TestBoson() + end + + @testset "antiboson" begin + struct TestAntiBoson <: AntiBoson end + @test !is_fermion(TestAntiBoson()) + @test is_boson(TestAntiBoson()) + @test !is_particle(TestAntiBoson()) + @test is_anti_particle(TestAntiBoson()) + @test test_broadcast.(TestAntiBoson()) == TestAntiBoson() + end + + @testset "majorana boson" begin + struct TestMajoranaBoson <: MajoranaBoson end + @test !is_fermion(TestMajoranaBoson()) + @test is_boson(TestMajoranaBoson()) + @test is_particle(TestMajoranaBoson()) + @test is_anti_particle(TestMajoranaBoson()) + @test test_broadcast.(TestMajoranaBoson()) == TestMajoranaBoson() + end +end diff --git a/test/runtests.jl b/test/runtests.jl index 0c44d6c..045c44b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -21,6 +21,10 @@ begin end # particles + @time @safetestset "particle types" begin + include("particles/types.jl") + end + @time @safetestset "particle spinors" begin include("particles/spinors.jl") end