Particles and Phase Space Points
There are three layers of abstraction from particles to phase space points in the QEDjl project:
- QEDbase.AbstractParticleType: Base type for singleton particle type definitions. We also call these species.
- QEDbase.AbstractParticleStateful: Base type for particles with a direction and carrying a momentum.
- QEDbase.AbstractPhaseSpacePoint: Representation of a point in the phase space for a combination of an- QEDbase.AbstractProcessDefinition,- QEDbase.AbstractModelDefinition, and- QEDbase.AbstractPhaseSpaceLayout.
This manual is intended to showcase the basic usage of these types and their implementations in QEDcore.
using QEDcoreTo use concrete process definitions, models and phase-space layouts, we use the QEDbase.Mocks module
using QEDbase.MocksParticle Types
QEDcore currently defines the three basic particle types of QED, Electron, Positron, and Photon, and a type hierarchy for them:
@assert Photon <: MajoranaBoson
@assert Electron <: Fermion
@assert Positron <: AntiFermionAll of these are subtypes of QEDbase.AbstractParticleType. There are also convenience functions in Julia convention:
@assert is_boson(Photon())
@assert is_particle(Electron())
@assert is_anti_particle(Positron())
@assert !is_boson(Electron())
@assert !is_anti_particle(Electron())
@assert !is_fermion(Photon())These functions are part of QEDbase.jl's particle interface.
ParticleStateful
ParticleStateful is the implementation of QEDbase's QEDbase.AbstractParticleStateful interface. It represents a particle with a direction (as used in the context of scattering processes, QEDbase.Incoming, QEDbase.Outgoing, or QEDbase.UnknownDirection), a particle species (Electron, Positron, Photon, ...), and a 4-momentum vector.
ps = ParticleStateful(Incoming(), Electron(), rand(SFourMomentum))ParticleStateful: incoming electron
    momentum: [0.5698072906362056, 0.6878020445643898, 0.19772488248571862, 0.8132211886481635]
The relevant accessor functions for the interface are implemented:
particle_direction(ps)incomingparticle_species(ps)electronmomentum(ps)4-element SFourMomentum{Float64} with indices SOneTo(4):
 0.5698072906362056
 0.6878020445643898
 0.19772488248571862
 0.8132211886481635Phase Space Points
A PhaseSpacePoint is the combination of incoming and outgoing ParticleStatefuls. It also contains information about the scattering process, model, and phase space that it is created for.
Constructors
psp = PhaseSpacePoint(
    MockProcess(                    # scattering process
        (MockFermion(), MockBoson()),
        (MockFermion(), MockBoson()),
    ),
    MockModel(),                    # physics model
    MockOutPhaseSpaceLayout(        # layout for outgoing phase space
        MockInPhaseSpaceLayout{     # layout for incoming phase space
            MockMomentum,            # momentum type
        }(),
    ),
    (   # momenta of the incoming particles
        rand(MockMomentum),
        rand(MockMomentum),
    ),
    (   # momenta of the outgoing particles
        rand(MockMomentum),
        rand(MockMomentum),
    ),
)PhaseSpacePoint:
    process: mock process (2 -> 2)
    model: mock model
    phase space layout: mock out phase space layout
    incoming particles:
     -> incoming mock fermion: [0.591747091511917, 0.25185151796704863, 0.10906240910376086, 0.4054933952514248]
     -> incoming mock boson: [0.008383828240797864, 0.4151627322193159, 0.79446199633816, 0.3237313193704221]
    outgoing particles:
     -> outgoing mock fermion: [0.31685794570035486, 0.5005316537329544, 0.41100993005109576, 0.11774546949056452]
     -> outgoing mock boson: [0.2092619500718781, 0.2216334747184603, 0.05586480516495107, 0.5078222176494706]
This version of the constructor automatically creates ParticleStateful obejcts from the momenta, matching the particles of the process. In the case of our example process, this is means an incoming mock fermion and mock boson, and outgoing mock fermion and mock boson.
Automatic checks make sure that the number of 4-momenta given matches the necessary number of 4-momenta for the process (this adds 0 overhead at runtime because it is inferred from type information alone).
    PhaseSpacePoint(
        MockProcess((MockFermion(), MockBoson()), (MockFermion(), MockBoson())),
        MockModel(),
        MockOutPhaseSpaceLayout(MockInPhaseSpaceLayout{MockMomentum}()),
        (rand(MockMomentum),), # incorrect number of incoming momenta, should be 2
        (rand(MockMomentum), rand(MockMomentum)),
    )┌ Error: InvalidInputError("expected 2 incoming particles for the process but got 1")
└ @ Main particles.md:131Alternatively, a PhaseSpacePoint can also be constructed from already existing ParticleStateful objects.
psp = PhaseSpacePoint(
    MockProcess((MockFermion(), MockBoson()), (MockFermion(), MockBoson())),
    MockModel(),
    MockOutPhaseSpaceLayout(MockInPhaseSpaceLayout{MockMomentum}()),
    (   # incoming particles
        ParticleStateful(Incoming(), MockFermion(), rand(MockMomentum)),
        ParticleStateful(Incoming(), MockBoson(), rand(MockMomentum)),
    ),
    (   # outgoing particles
        ParticleStateful(Outgoing(), MockFermion(), rand(MockMomentum)),
        ParticleStateful(Outgoing(), MockBoson(), rand(MockMomentum)),
    ),
)PhaseSpacePoint:
    process: mock process (2 -> 2)
    model: mock model
    phase space layout: mock out phase space layout
    incoming particles:
     -> incoming mock fermion: [0.034260637872777666, 0.10068700330144664, 0.9135269851765709, 0.5443504766782558]
     -> incoming mock boson: [0.31744676843526454, 0.5924380513850407, 0.995792351210102, 0.1588161207355785]
    outgoing particles:
     -> outgoing mock fermion: [0.889743867966127, 0.621209514736792, 0.24882858275045538, 0.528560284571596]
     -> outgoing mock boson: [0.2689260088379115, 0.30128743997567686, 0.03556943141398017, 0.034228075872263286]
Similar to the constructor from momenta, this checks that the given ParticleStatefuls fit to the given process and throws otherwise. Again, since this can be infered from type information alone, it adds no overhead.
    PhaseSpacePoint(
        MockProcess((MockFermion(), MockBoson()), (MockFermion(), MockBoson())),
        MockModel(),
        MockOutPhaseSpaceLayout(MockInPhaseSpaceLayout{MockMomentum}()),
        (   # incoming particles
            ParticleStateful(Incoming(), MockBoson(), rand(MockMomentum)), # wrong particle type
            ParticleStateful(Incoming(), MockBoson(), rand(MockMomentum)),
        ),
        (   # outgoing particles
            ParticleStateful(Outgoing(), MockFermion(), rand(MockMomentum)),
            ParticleStateful(Outgoing(), MockBoson(), rand(MockMomentum)),
        ),
    )┌ Error: InvalidInputError("expected incoming mock fermion but got incoming mock boson")
└ @ Main particles.md:178While these constructors check that the given types make sense and work together, they do not check whether the given momenta make a physical phase space point or that the incoming or outgoing particles have on-shell 4-momenta.
Accessors
The phase space point provides some convenient accessors to the stateful particles within:
psp[Incoming(), 1]  # the first incoming particleParticleStateful: incoming mock fermion
    momentum: [0.034260637872777666, 0.10068700330144664, 0.9135269851765709, 0.5443504766782558]
psp[Outgoing(), 2]  # the second outgoing particleParticleStateful: outgoing mock boson
    momentum: [0.2689260088379115, 0.30128743997567686, 0.03556943141398017, 0.034228075872263286]
particles(psp, Incoming()) # all incoming particles as a tuple(incoming mock fermion: [0.034260637872777666, 0.10068700330144664, 0.9135269851765709, 0.5443504766782558], incoming mock boson: [0.31744676843526454, 0.5924380513850407, 0.995792351210102, 0.1588161207355785])Momentum accessors:
momentum(psp, Incoming(), MockFermion(), 1) # the momentum of the first incoming electron4-element QEDbase.Mocks.MockMomentum{Float64} with indices SOneTo(4):
 0.034260637872777666
 0.10068700330144664
 0.9135269851765709
 0.5443504766782558When only one particle of the species exists in the particle set, the 1 can be omitted for convenience.
@assert ans == momentum(psp, Incoming(), MockFermion())This method throws when multiple (or zero) particles of the given direction and species exist in the phase space point.
When the index of the required momentum is known at compile time, a Val(N) can be used instead of N. This performs bounds checks at compile time and removes loops from the runtime execution
using BenchmarkTools
judge(
    median(@benchmark momentum($psp, Incoming(), MockBoson(), Val(1))),
    median(@benchmark momentum($psp, Incoming(), MockBoson(), 1)),
)BenchmarkTools.TrialJudgement: 
  time:   -89.57% => improvement (5.00% tolerance)
  memory: -100.00% => improvement (1.00% tolerance)
This is only faster when N is actually known at compile time, for example when it is a literal integer or a function's type parameter. For dynamic values of N, prefer the Int variant or in case of loops, directly loop over the tuple of momenta.
Some more overloads for the momentum function exist, for a complete list please refer to its documentation: QEDbase.momentum, QEDbase.momenta.
Finally, process, model, and phase_space_layout can be used to request the object in question:
process(psp)mock process (2 -> 2)model(psp)mock modelphase_space_layout(psp)mock out phase space layoutIn/Out Phase Space Points
As a special case, phase space points are allowed to only contain the incoming or outgoing particle momenta. These types can be helpful for overloading some functions that don't require the entire phase space point to exist.
function in_sum(in_psp::AbstractInPhaseSpacePoint)
    return sum(momenta(in_psp, Incoming()))
end
psp = InPhaseSpacePoint(
    MockProcess((MockFermion(), MockBoson()), (MockFermion(), MockBoson())),
    MockModel(),
    MockOutPhaseSpaceLayout(MockInPhaseSpaceLayout{MockMomentum}()),
    (rand(MockMomentum), rand(MockMomentum)),
)
in_sum(psp)4-element QEDbase.Mocks.MockMomentum{Float64} with indices SOneTo(4):
 1.0190877293923433
 0.3392967994941083
 0.6602644753325908
 1.6591983350949475Every full PhaseSpacePoint is both an InPhaseSpacePoint and an OutPhaseSpacePoint, too. For example, the in_sum function defined above still works with a full PhaseSpacePoint:
psp = PhaseSpacePoint(
    MockProcess((MockFermion(), MockBoson()), (MockFermion(), MockBoson())),
    MockModel(),
    MockOutPhaseSpaceLayout(MockInPhaseSpaceLayout{MockMomentum}()),
    (rand(MockMomentum), rand(MockMomentum)),
    (rand(MockMomentum), rand(MockMomentum)),
)
in_sum(psp)4-element QEDbase.Mocks.MockMomentum{Float64} with indices SOneTo(4):
 0.8271991863706079
 1.4509065268493786
 1.9046362960588326
 1.4977347885303973But an InPhaseSpacePoint is not an OutPhaseSpacePoint and vice versa. We cannot call in_sum on an OutPhaseSpacePoint:
psp = OutPhaseSpacePoint(
    MockProcess((MockFermion(), MockBoson()), (MockFermion(), MockBoson())),
    MockModel(),
    MockOutPhaseSpaceLayout(MockInPhaseSpaceLayout{MockMomentum}()),
    (rand(MockMomentum), rand(MockMomentum)),
)
    in_sum(psp)┌ Error: MethodError(Main.in_sum, (PhaseSpacePoint of mock process (2 -> 2),), 0x0000000000007b7a)
└ @ Main particles.md:307This page was generated using Literate.jl.