Skip to content

Commit

Permalink
perturbative Compton (#40)
Browse files Browse the repository at this point in the history
This PR adds one photon Compton scattering described in perturbative
QED.

This includes the following variants
* diff. probability and cross section on momenta
* diff. probability and cross section on coordinates (electron restframe
and spherical coordinates)

All implementations are done for arbitrary combinations of spins and
polarizations.

## Todos

- [x] discuss where the spins/polarizations are stored: proc or phase
space point (be aware of dispatch)
- [x] add total cross section
- [x] add unit test for total cross section
- [x] add unit tests for phase space point input

---------

Co-authored-by: Uwe Hernandez Acosta <u.hernandez@hzdr.de>
Co-authored-by: Tom Jungnickel <140055258+tjungni@users.noreply.github.com>
Co-authored-by: Anton Reinhard <anton.reinhard@proton.me>
  • Loading branch information
4 people authored May 16, 2024
1 parent 3db301b commit e84809c
Show file tree
Hide file tree
Showing 18 changed files with 592 additions and 4 deletions.
1 change: 1 addition & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ version = "0.1.0"

[deps]
QEDbase = "10e22c08-3ccb-4172-bfcf-7d7aa3d04d93"
QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"

[compat]
Expand Down
19 changes: 19 additions & 0 deletions src/QEDprocesses.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
module QEDprocesses

# constants
export ALPHA,
ALPHA_SQUARE, ELEMENTARY_CHARGE, ELEMENTARY_CHARGE_SQUARE, ELECTRONMASS, ONE_OVER_FOURPI

# Abstract model interface
export AbstractModelDefinition, fundamental_interaction_type

Expand Down Expand Up @@ -34,16 +38,31 @@ export ParticleStateful, PhaseSpacePoint
export spin, polarization, particle_direction, particle_species, momentum, getindex
export generate_phase_space

# specific compute models
export PerturbativeQED

# specific scattering processes
export Compton, omega_prime

using QEDbase
using StaticArrays
using QuadGK

include("constants.jl")
include("utils.jl")

include("interfaces/model_interface.jl")
include("interfaces/process_interface.jl")
include("interfaces/setup_interface.jl")

include("phase_spaces.jl")
include("momentum_generation.jl")
include("propagators.jl")
include("probabilities.jl")
include("cross_sections.jl")

include("models/models.jl")
include("processes/one_photon_compton/one_photon_compton.jl")

include("patch_QEDbase.jl")
end
7 changes: 7 additions & 0 deletions src/constants.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

const ALPHA = inv(137.035999074)
const ALPHA_SQUARE = ALPHA^2
const ELEMENTARY_CHARGE = sqrt(4 * pi * ALPHA)
const ELEMENTARY_CHARGE_SQUARE = 4 * pi * ALPHA
const ELECTRONMASS = 0.510998928e6 # eV
const ONE_OVER_FOURPI = 1 / (4 * pi)
2 changes: 2 additions & 0 deletions src/models/models.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

include("perturbative_qed.jl")
23 changes: 23 additions & 0 deletions src/models/perturbative_qed.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

struct PerturbativeQED <: AbstractModelDefinition end

fundamental_interaction_type(::PerturbativeQED) = :electromagnetic

"""
in_phase_space_dimension(proc::AbstractProcessDefinition, ::PerturbativeQED)
Return the number of degrees of freedom to determine the incoming phase space for processes in PerturbativeQED.
!!! note "Convention"
The current implementation only supports the case where two of the incoming particles collide head-on.
"""
function in_phase_space_dimension(proc::AbstractProcessDefinition, ::PerturbativeQED)
return 3 * number_incoming_particles(proc) - 4 - 1
end

function out_phase_space_dimension(proc::AbstractProcessDefinition, ::PerturbativeQED)
return 3 * number_outgoing_particles(proc) - 4
end
8 changes: 7 additions & 1 deletion src/patch_QEDbase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
# Patches for `QEDbase.jl`
# remove if this went into `QEDbase.jl`
#
# fix will be provided here: https://github.com/QEDjl-project/QEDbase.jl/pull/62
#############

# fix: https://github.com/QEDjl-project/QEDbase.jl/pull/62
Broadcast.broadcastable(dir::Incoming) = Ref(dir)
Broadcast.broadcastable(dir::Outgoing) = Ref(dir)
Broadcast.broadcastable(part::AbstractParticleType) = Ref(part)
Broadcast.broadcastable(spin_or_pol::AbstractSpinOrPolarization) = Ref(spin_or_pol)

# fix: https://github.com/QEDjl-project/QEDbase.jl/pull/63
number_of_spin_pol(::AbstractDefinitePolarization) = 1
number_of_spin_pol(::AbstractDefiniteSpin) = 1
number_of_spin_pol(::AbstractIndefinitePolarization) = 2
number_of_spin_pol(::AbstractIndefiniteSpin) = 2
11 changes: 11 additions & 0 deletions src/processes/one_photon_compton/one_photon_compton.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#################
# The one-photon Compton process
#
# This file contains the implementation of the abstract process setup for
# Compton
##################

include("process.jl")
include("perturbative/kinematics.jl")
include("perturbative/cross_section.jl")
include("perturbative/total_probability.jl")
173 changes: 173 additions & 0 deletions src/processes/one_photon_compton/perturbative/cross_section.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#####
# Perturbative one-photon Compton scattering
# Implementation of the cross section interface
#####

function _incident_flux(
proc::Compton, model::PerturbativeQED, in_ps::AbstractVector{T}
) where {T<:QEDbase.AbstractFourMomentum}
return @inbounds in_ps[1] * in_ps[2]
end

function _matrix_element(
proc::Compton,
model::PerturbativeQED,
in_ps::AbstractVector{T},
out_ps::AbstractVector{T},
) where {T<:QEDbase.AbstractFourMomentum}
return _pert_compton_matrix_element(proc, in_ps, out_ps)
end

"""
!!! note "Convention"
We average over the initial spins and pols, and sum over final.
"""
function _averaging_norm(proc::Compton)
normalizations = number_of_spin_pol.(_in_spin_and_pol(proc))
return inv(prod(normalizations))
end

function _all_onshell(
proc::Compton, in_ps::AbstractVector{T}, out_ps::AbstractVector{T}
) where {T<:QEDbase.AbstractFourMomentum}
sq_in_moms = getMass2.(in_ps)
sq_out_moms = getMass2.(out_ps)
sq_in_masses = mass.(incoming_particles(proc)) .^ 2
sq_out_masses = mass.(outgoing_particles(proc)) .^ 2
return isapprox(sq_in_moms, SVector(sq_in_masses)) &&
isapprox(sq_out_moms, SVector(sq_out_masses))
end

function _is_in_phasespace(
proc::Compton,
model::PerturbativeQED,
in_ps_def::AbstractPhasespaceDefinition,
in_ps::AbstractVector{T},
out_ps::AbstractVector{T},
) where {T<:QEDbase.AbstractFourMomentum}
return (isapprox(sum(in_ps), sum(out_ps))) ? _all_onshell(proc, in_ps, out_ps) : false
end

@inline function _phase_space_factor(
proc::Compton,
model::PerturbativeQED,
in_ps_def::AbstractPhasespaceDefinition,
in_ps::AbstractVector{T},
out_ps::AbstractVector{T},
) where {T<:QEDbase.AbstractFourMomentum}
return _pert_compton_ps_fac(in_ps_def, in_ps[2], out_ps[2])
end

#######
# Matrix elements
#######

@inline function _pert_compton_matrix_element(
proc::Compton, in_ps::AbstractVector{T}, out_ps::AbstractVector{T}
) where {T<:QEDbase.AbstractFourMomentum}
in_electron_mom = in_ps[1]
in_photon_mom = in_ps[2]
out_electron_mom = out_ps[1]
out_photon_mom = out_ps[2]

in_electron_state = base_state(Electron(), Incoming(), in_electron_mom, proc.in_spin)
in_photon_state = base_state(Photon(), Incoming(), in_photon_mom, proc.in_pol)

out_electron_state = base_state(Electron(), Outgoing(), out_electron_mom, proc.out_spin)

out_photon_state = base_state(Photon(), Outgoing(), out_photon_mom, proc.out_pol)
return _pert_compton_matrix_element(
in_electron_mom,
in_electron_state,
in_photon_mom,
in_photon_state,
out_electron_mom,
out_electron_state,
out_photon_mom,
out_photon_state,
)
end

function _pert_compton_matrix_element(
in_electron_mom::T,
in_electron_state,
in_photon_mom::T,
in_photon_state,
out_electron_mom::T,
out_electron_state,
out_photon_mom::T,
out_photon_state,
) where {T<:QEDbase.AbstractFourMomentum}
base_states_comb = Iterators.product(
QEDbase._as_svec(in_electron_state),
QEDbase._as_svec(in_photon_state),
QEDbase._as_svec(out_electron_state),
QEDbase._as_svec(out_photon_state),
)

matrix_elements = Vector{ComplexF64}()
sizehint!(matrix_elements, length(base_states_comb))
for (in_el, in_ph, out_el, out_ph) in base_states_comb
push!(
matrix_elements,
_pert_compton_matrix_element_single(
in_electron_mom,
in_el,
in_photon_mom,
in_ph,
out_electron_mom,
out_el,
out_photon_mom,
out_ph,
),
)
end

return matrix_elements
end

function _pert_compton_matrix_element_single(
in_electron_mom::T,
in_electron_state::BiSpinor,
in_photon_mom::T,
in_photon_state::SLorentzVector,
out_electron_mom::T,
out_electron_state::AdjointBiSpinor,
out_photon_mom::T,
out_photon_state::SLorentzVector,
) where {T<:QEDbase.AbstractFourMomentum}
in_ph_slashed = slashed(in_photon_state)
out_ph_slashed = slashed(out_photon_state)

prop1 = _fermion_propagator(in_photon_mom + in_electron_mom, mass(Electron()))
prop2 = _fermion_propagator(in_electron_mom - out_photon_mom, mass(Electron()))

# TODO: fermion propagator is not yet in QEDbase
diagram_1 =
out_electron_state *
(out_ph_slashed * (prop1 * (in_ph_slashed * in_electron_state)))
diagram_2 =
out_electron_state *
(in_ph_slashed * (prop2 * (out_ph_slashed * in_electron_state)))

result = diagram_1 + diagram_2

# TODO: find (preferably unitful) global provider for physical constants
# elementary charge
return ELEMENTARY_CHARGE_SQUARE * result
end

#######
# Phase space factors
#######

function _pert_compton_ps_fac(
in_ps_def::PhasespaceDefinition{inCS,ElectronRestFrame}, in_photon_mom, out_photon_mom
) where {inCS}
# TODO
omega = getE(in_photon_mom)
omega_prime = getE(out_photon_mom)
return omega_prime^2 / (16 * pi^2 * omega * mass(Electron()))
end
54 changes: 54 additions & 0 deletions src/processes/one_photon_compton/perturbative/kinematics.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
@inline function _pert_omega_prime(omega, cth; mass=1.0)
return omega / (1 + omega / mass * (1 - cth))
end

function generate_momenta(
proc::Compton,
model::PerturbativeQED,
in_ps_def::PhasespaceDefinition{SphericalCoordinateSystem,ElectronRestFrame},
in_ps::AbstractVector{T},
out_ps::AbstractVector{T},
) where {T<:Real}
return _generate_momenta(proc, model, in_ps_def, in_ps, out_ps)
end

function _generate_incoming_momenta(
proc::Compton,
model::PerturbativeQED,
in_ps_def::PhasespaceDefinition{SphericalCoordinateSystem,ElectronRestFrame},
in_ps::AbstractVector{T},
) where {T<:Real}
om = in_ps[1]

P = SFourMomentum(one(om), zero(om), zero(om), zero(om))
K = SFourMomentum(om, zero(om), zero(om), om)

return [P, K]
end

function _generate_momenta(
proc::Compton,
model::PerturbativeQED,
in_ps_def::PhasespaceDefinition{SphericalCoordinateSystem,ElectronRestFrame},
in_ps::AbstractVector{T},
out_ps::AbstractVector{T},
) where {T<:Real}
omega = in_ps[1]
cth = out_ps[1]
phi = out_ps[2]
P, K, Pp, Kp = _generate_momenta_elab_sph(omega, cth, phi) # TODO: do this coord and frame dependent
in_moms = SVector(P, K)
out_moms = SVector(Pp, Kp)
return in_moms, out_moms
end

function _generate_momenta_elab_sph(om, cth, phi, m=1.0)
P = SFourMomentum(m, zero(m), zero(m), zero(m))
K = SFourMomentum(om, zero(om), zero(om), om)
omp = _pert_omega_prime(om, cth)
sth = sqrt(1 - cth^2)
sphi, cphi = sincos(phi)
Kp = SFourMomentum(omp, omp * sth * cphi, omp * sth * sphi, omp * cth)
Pp = P + K - Kp
return P, K, Pp, Kp
end
20 changes: 20 additions & 0 deletions src/processes/one_photon_compton/perturbative/total_probability.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

function _total_probability(
proc::Compton,
model::PerturbativeQED,
in_phase_space_def::AbstractPhasespaceDefinition,
in_phase_space::AbstractVector{T},
) where {T<:QEDbase.AbstractFourMomentum}
omega = getE(in_phase_space[2])

function func(x)
return _unsafe_differential_probability(
proc, model, in_phase_space_def, [omega], [x, 0.0]
)
end

tot_prob, _ = quadgk(func, -1, 1; rtol=sqrt(eps(omega)))

tot_prob *= 2 * pi # phi integration is trivial
return tot_prob
end
Loading

0 comments on commit e84809c

Please sign in to comment.