Compare commits

..

No commits in common. "00a1252c9ae3f4fdf69ede8806c4d7895c2b7b80" and "a647801f12e95cb0e5a10f20da117fb8569f2962" have entirely different histories.

6 changed files with 80 additions and 558 deletions

View File

@ -9,9 +9,7 @@
"name": "stderr", "name": "stderr",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"WARNING: Method definition (::Type{QEDcore.ParticleStateful{DIR, SPECIES, ELEMENT} where ELEMENT<:QEDbase.AbstractFourMomentum})(QEDbase.AbstractFourMomentum) where {DIR<:QEDbase.ParticleDirection, SPECIES<:QEDbase.AbstractParticleType} in module QEDcore at /home/antonr/.julia/packages/QEDcore/uVldP/src/phase_spaces/create.jl:7 overwritten in module MetagraphOptimization at /home/antonr/.julia/packages/MetagraphOptimization/0iydf/src/QEDprocesses_patch.jl:15.\n", "WARNING: Method definition (::Type{QEDcore.ParticleStateful{DIR, SPECIES, ELEMENT} where ELEMENT<:QEDbase.AbstractFourMomentum})(QEDbase.AbstractFourMomentum) where {DIR<:QEDbase.ParticleDirection, SPECIES<:QEDbase.AbstractParticleType} in module QEDcore at /home/antonr/.julia/packages/QEDcore/uVldP/src/phase_spaces/create.jl:7 overwritten in module MetagraphOptimization at /home/antonr/.julia/packages/MetagraphOptimization/mvCVq/src/QEDprocesses_patch.jl:15.\n",
"ERROR: Method overwriting is not permitted during Module precompilation. Use `__precompile__(false)` to opt-out of precompilation.\n",
"WARNING: Method definition (::Type{QEDcore.ParticleStateful{DIR, SPECIES, ELEMENT} where ELEMENT<:QEDbase.AbstractFourMomentum})(QEDbase.AbstractFourMomentum) where {DIR<:QEDbase.ParticleDirection, SPECIES<:QEDbase.AbstractParticleType} in module QEDcore at /home/antonr/.julia/packages/QEDcore/uVldP/src/phase_spaces/create.jl:7 overwritten in module MetagraphOptimization at /home/antonr/.julia/packages/MetagraphOptimization/0iydf/src/QEDprocesses_patch.jl:15.\n",
"ERROR: Method overwriting is not permitted during Module precompilation. Use `__precompile__(false)` to opt-out of precompilation.\n" "ERROR: Method overwriting is not permitted during Module precompilation. Use `__precompile__(false)` to opt-out of precompilation.\n"
] ]
} }
@ -23,34 +21,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [],
{
"data": {
"text/plain": [
"6-element Vector{VirtualParticle{QEDProcess{Tuple{Photon, Photon, Electron}, Tuple{Photon, Electron}, Tuple{AllPolarization, AllPolarization, AllSpin}, Tuple{AllPolarization, AllSpin}}, PT, 3, 2} where PT<:AbstractParticleType}:\n",
" positron: \t000 | 11\n",
" electron: \t001 | 10\n",
" positron: \t010 | 01\n",
" electron: \t011 | 00\n",
" positron: \t100 | 01\n",
" electron: \t101 | 00"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"WARNING: both QEDcore and QEDbase export \"mul\"; uses of it in module FeynmanDiagramGenerator must be qualified\n"
]
}
],
"source": [ "source": [
"proc = QEDProcess(2, 1, 1, 1, 0, 0)\n", "proc = GenericQEDProcess(3, 1, 1, 1, 0, 0)\n",
"all_particles = Set()\n", "all_particles = Set()\n",
"for fd in feynman_diagrams(proc)\n", "for fd in feynman_diagrams(proc)\n",
" push!(all_particles, virtual_particles(proc, fd)...)\n", " push!(all_particles, virtual_particles(proc, fd)...)\n",
@ -61,83 +36,27 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [],
{
"data": {
"text/plain": [
"OrderedCollections.OrderedDict{VirtualParticle, Vector{Tuple{VirtualParticle, VirtualParticle}}} with 6 entries:\n",
" positron: \t000 | 11 => [(positron: \t000 | 01, photon: \t000 | 10)]\n",
" electron: \t001 | 10 => [(photon: \t000 | 10, electron: \t001 | 00)]\n",
" positron: \t010 | 01 => [(positron: \t000 | 01, photon: \t010 | 00)]\n",
" electron: \t011 | 00 => [(electron: \t001 | 00, photon: \t010 | 00)]\n",
" positron: \t100 | 01 => [(positron: \t000 | 01, photon: \t100 | 00)]\n",
" electron: \t101 | 00 => [(electron: \t001 | 00, photon: \t100 | 00)]"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"pairs = sort(FeynmanDiagramGenerator.particle_pairs(all_particles))" "pairs = FeynmanDiagramGenerator.particle_pairs(all_particles)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [],
{
"data": {
"text/plain": [
"6-element Vector{Tuple{VirtualParticle, VirtualParticle, VirtualParticle}}:\n",
" (photon: \t000 | 10, electron: \t011 | 00, positron: \t100 | 01)\n",
" (photon: \t000 | 10, electron: \t101 | 00, positron: \t010 | 01)\n",
" (photon: \t010 | 00, electron: \t101 | 00, positron: \t000 | 11)\n",
" (photon: \t010 | 00, electron: \t001 | 10, positron: \t100 | 01)\n",
" (photon: \t100 | 00, electron: \t011 | 00, positron: \t000 | 11)\n",
" (photon: \t100 | 00, electron: \t001 | 10, positron: \t010 | 01)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"triples = FeynmanDiagramGenerator.total_particle_triples(all_particles)" "triples = FeynmanDiagramGenerator.total_particle_triples(all_particles)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [],
{
"name": "stdout",
"output_type": "stream",
"text": [
"s: 6, should be: 6\n",
"number of triples: 6\n"
]
},
{
"data": {
"text/plain": [
"6-element Vector{Tuple{VirtualParticle, VirtualParticle, VirtualParticle}}:\n",
" (photon: \t000 | 10, electron: \t011 | 00, positron: \t100 | 01)\n",
" (photon: \t000 | 10, electron: \t101 | 00, positron: \t010 | 01)\n",
" (photon: \t010 | 00, electron: \t001 | 10, positron: \t100 | 01)\n",
" (photon: \t010 | 00, electron: \t101 | 00, positron: \t000 | 11)\n",
" (photon: \t100 | 00, electron: \t001 | 10, positron: \t010 | 01)\n",
" (photon: \t100 | 00, electron: \t011 | 00, positron: \t000 | 11)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"function n(vp::VirtualParticle)\n", "function n(vp::VirtualParticle)\n",
" if !haskey(pairs, vp)\n", " if !haskey(pairs, vp)\n",
@ -163,110 +82,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [],
{
"data": {
"text/plain": [
"Graph:\n",
" Nodes: Total: 642, FeynmanDiagramGenerator.ComputeTask_PropagatePairs: 24, FeynmanDiagramGenerator.ComputeTask_CollectPairs: 24, \n",
" FeynmanDiagramGenerator.ComputeTask_Triple: 192, FeynmanDiagramGenerator.ComputeTask_SpinPolCumulation: 1, MetagraphOptimization.DataTask: 329, \n",
" FeynmanDiagramGenerator.ComputeTask_BaseState: 10, FeynmanDiagramGenerator.ComputeTask_Pair: 24, FeynmanDiagramGenerator.ComputeTask_Propagator: 6, \n",
" FeynmanDiagramGenerator.ComputeTask_CollectTriples: 32\n",
" Edges: 1249\n",
" Total Compute Effort: 0.0\n",
" Total Data Transfer: 0.0\n",
" Total Compute Intensity: 0.0\n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"graph = generate_DAG(proc)" "generate_DAG(proc)"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"mock_machine (generic function with 1 method)"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"using MetagraphOptimization\n",
"using UUIDs\n",
"\n",
"function mock_machine()\n",
" return Machine(\n",
" [\n",
" MetagraphOptimization.NumaNode(\n",
" 0,\n",
" 1,\n",
" MetagraphOptimization.default_strategy(MetagraphOptimization.NumaNode),\n",
" -1.0,\n",
" UUIDs.uuid1(),\n",
" ),\n",
" ],\n",
" [-1.0;;],\n",
" )\n",
"end"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"PhaseSpacePoint{QEDProcess{Tuple{Photon, Photon, Electron}, Tuple{Photon, Electron}, Tuple{AllPolarization, AllPolarization, AllSpin}, Tuple{AllPolarization, AllSpin}}, PerturbativeQED, PhasespaceDefinition{SphericalCoordinateSystem, ElectronRestFrame}, Tuple{ParticleStateful{Incoming, Photon, SFourMomentum}, ParticleStateful{Incoming, Photon, SFourMomentum}, ParticleStateful{Incoming, Electron, SFourMomentum}}, Tuple{ParticleStateful{Outgoing, Photon, SFourMomentum}, ParticleStateful{Outgoing, Electron, SFourMomentum}}, SFourMomentum}"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"psp = PhaseSpacePoint(\n",
" proc, \n",
" PerturbativeQED(), \n",
" PhasespaceDefinition(SphericalCoordinateSystem(), ElectronRestFrame()), \n",
" tuple((rand(SFourMomentum) for _ in 1:number_incoming_particles(proc))...),\n",
" tuple((rand(SFourMomentum) for _ in 1:number_outgoing_particles(proc))...)\n",
")\n",
"typeof(psp)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"ename": "Base.Meta.ParseError",
"evalue": "Error trying to display an error.",
"output_type": "error",
"traceback": [
"Error trying to display an error."
]
}
],
"source": [
"func = eval(get_compute_function(graph, proc, mock_machine()))\n",
"\n",
"func(psp)"
] ]
} }
], ],

View File

@ -14,7 +14,7 @@ import QEDbase.process
export FlatMatrix export FlatMatrix
export QEDProcess, isphysical export GenericQEDProcess, isphysical
export AbstractTreeLevelFeynmanDiagram, FeynmanVertex, FeynmanDiagram export AbstractTreeLevelFeynmanDiagram, FeynmanVertex, FeynmanDiagram
export external_particles, virtual_particles, process, generate_DAG export external_particles, virtual_particles, process, generate_DAG

View File

@ -682,7 +682,7 @@ function Base.iterate(iter::FeynmanDiagramIterator{E,U,T,M}, ::Nothing) where {E
return (f, nothing) return (f, nothing)
end end
function feynman_diagrams(proc::PROC) where {PROC<:QEDProcess} function feynman_diagrams(proc::PROC) where {PROC<:GenericQEDProcess}
return feynman_diagrams(incoming_particles(proc), outgoing_particles(proc)) return feynman_diagrams(incoming_particles(proc), outgoing_particles(proc))
end end
@ -727,7 +727,7 @@ function feynman_diagrams(in_particles::Tuple, out_particles::Tuple)
) )
end end
function virtual_particles(proc::QEDProcess) function virtual_particles(proc::GenericQEDProcess)
if !isempty(proc.virtual_particles_cache) if !isempty(proc.virtual_particles_cache)
return proc.virtual_particles_cache return proc.virtual_particles_cache
end end

View File

@ -5,12 +5,12 @@ end
function _assert_particle_type_tuple(t::Any) function _assert_particle_type_tuple(t::Any)
throw( throw(
InvalidInputError( InvalidInputError(
"invalid input, provide a tuple of AbstractParticleTypes to construct a QEDProcess", "invalid input, provide a tuple of AbstractParticleTypes to construct a GenericQEDProcess",
), ),
) )
end end
mutable struct QEDProcess{INT,OUTT,INSP,OUTSP} <: AbstractProcessDefinition where { mutable struct GenericQEDProcess{INT,OUTT,INSP,OUTSP} <: AbstractProcessDefinition where {
INT<:Tuple,OUTT<:Tuple,INSP<:Tuple,OUTSP<:Tuple INT<:Tuple,OUTT<:Tuple,INSP<:Tuple,OUTSP<:Tuple
} }
incoming_particles::INT incoming_particles::INT
@ -21,7 +21,7 @@ mutable struct QEDProcess{INT,OUTT,INSP,OUTSP} <: AbstractProcessDefinition wher
virtual_particles_cache::Vector virtual_particles_cache::Vector
function QEDProcess( function GenericQEDProcess(
in_particles::INT, out_particles::OUTT, in_sp::INSP, out_sp::OUTSP in_particles::INT, out_particles::OUTT, in_sp::INSP, out_sp::OUTSP
) where {INT<:Tuple,OUTT<:Tuple,INSP<:Tuple,OUTSP<:Tuple} ) where {INT<:Tuple,OUTT<:Tuple,INSP<:Tuple,OUTSP<:Tuple}
_assert_particle_type_tuple(in_particles) _assert_particle_type_tuple(in_particles)
@ -31,12 +31,12 @@ mutable struct QEDProcess{INT,OUTT,INSP,OUTSP} <: AbstractProcessDefinition wher
end end
""" """
QEDProcess(in_ph::Int, out_ph::Int, in_el::Int, out_el::Int, in_po::Int, out_po::Int) GenericQEDProcess(in_ph::Int, out_ph::Int, in_el::Int, out_el::Int, in_po::Int, out_po::Int)
Convenience constructor from numbers of input/output photons, electrons and positrons. Convenience constructor from numbers of input/output photons, electrons and positrons.
Uses `AllSpin()` and `AllPol()` for every particle's spin/pol by default. Uses `AllSpin()` and `AllPol()` for every particle's spin/pol by default.
""" """
function QEDProcess( function GenericQEDProcess(
in_ph::Int, out_ph::Int, in_el::Int, out_el::Int, in_po::Int, out_po::Int in_ph::Int, out_ph::Int, in_el::Int, out_el::Int, in_po::Int, out_po::Int
) )
in_p = ntuple(i -> if i <= in_ph in_p = ntuple(i -> if i <= in_ph
@ -55,12 +55,15 @@ mutable struct QEDProcess{INT,OUTT,INSP,OUTSP} <: AbstractProcessDefinition wher
end, out_ph + out_el + out_po) end, out_ph + out_el + out_po)
in_sp = tuple([i <= in_ph ? AllPol() : AllSpin() for i in 1:length(in_p)]...) in_sp = tuple([i <= in_ph ? AllPol() : AllSpin() for i in 1:length(in_p)]...)
out_sp = tuple([i <= out_ph ? AllPol() : AllSpin() for i in 1:length(out_p)]...) out_sp = tuple([i <= out_ph ? AllPol() : AllSpin() for i in 1:length(out_p)]...)
return QEDProcess(in_p, out_p, in_sp, out_sp) return GenericQEDProcess(in_p, out_p, in_sp, out_sp)
end end
end end
function spin_or_pol( function spin_or_pol(
process::QEDProcess, dir::ParticleDirection, species::AbstractParticleType, n::Int process::GenericQEDProcess,
dir::ParticleDirection,
species::AbstractParticleType,
n::Int,
) )
i = 0 i = 0
c = n c = n
@ -91,14 +94,14 @@ function spin_or_pol(
end end
end end
function QEDprocesses.incoming_particles(proc::QEDProcess{INT,OUTT}) where {INT,OUTT} function QEDprocesses.incoming_particles(proc::GenericQEDProcess{INT,OUTT}) where {INT,OUTT}
return proc.incoming_particles return proc.incoming_particles
end end
function QEDprocesses.outgoing_particles(proc::QEDProcess{INT,OUTT}) where {INT,OUTT} function QEDprocesses.outgoing_particles(proc::GenericQEDProcess{INT,OUTT}) where {INT,OUTT}
return proc.outgoing_particles return proc.outgoing_particles
end end
function isphysical(proc::QEDProcess) function isphysical(proc::GenericQEDProcess)
return ( return (
number_particles(proc, Incoming(), Electron()) + number_particles(proc, Incoming(), Electron()) +
number_particles(proc, Outgoing(), Positron()) == number_particles(proc, Outgoing(), Positron()) ==
@ -107,6 +110,6 @@ function isphysical(proc::QEDProcess)
) && number_particles(proc, Incoming()) + number_particles(proc, Outgoing()) >= 2 ) && number_particles(proc, Incoming()) + number_particles(proc, Outgoing()) >= 2
end end
function matrix_element(proc::QEDProcess, psp::PhaseSpacePoint) function matrix_element(proc::GenericQEDProcess, psp::PhaseSpacePoint)
return nothing return nothing
end end

View File

@ -1,23 +1,13 @@
struct ComputeTask_BaseState <: AbstractComputeTask end # calculate the base state of an external particle struct ComputeTask_BaseState <: AbstractComputeTask end # calculate the base state of an external particle
struct ComputeTask_Propagator <: AbstractComputeTask end # calculate the propagator term of a virtual particle struct ComputeTask_Propagator <: AbstractComputeTask end # calculate the propagator term of a virtual particle
struct ComputeTask_Pair <: AbstractComputeTask end # from a pair of virtual particle currents, calculate the product struct ComputeTask_Pair <: AbstractComputeTask end # from a pair of virtual particle currents, calculate the product
struct ComputeTask_CollectPairs <: AbstractComputeTask # for a list of virtual particle current pair products, sum struct ComputeTask_CollectPairs <: AbstractComputeTask end # for a list of virtual particle current pair products, sum
children::Int struct ComputeTask_PropagatePairs <: AbstractComputeTask end # for the result of a CollectPairs compute task and a propagator, propagate the sum
end struct ComputeTask_Triple <: AbstractComputeTask end # from a triple of virtual particle currents, calculate the diagram result
struct ComputeTask_PropagatePairs <: AbstractComputeTask end # for the result of a CollectPairs compute task and a propagator, propagate the sum struct ComputeTask_CollectTriples <: AbstractComputeTask end # sum over triples results and
struct ComputeTask_Triple <: AbstractComputeTask end # from a triple of virtual particle currents, calculate the diagram result
struct ComputeTask_CollectTriples <: AbstractComputeTask # sum over triples results and
children::Int
end
struct ComputeTask_SpinPolCumulation <: AbstractComputeTask # abs2 sum over all spin/pol configs
children::Int
end
# import compute so we don't have to repeat it all the time # import compute so we don't have to repeat it all the time
import MetagraphOptimization: compute, compute_effort, children import MetagraphOptimization: compute, compute_effort
const e = sqrt(4π / 137)
_vertex() = -1im * e * gamma()
compute_effort(::ComputeTask_BaseState) = 0 compute_effort(::ComputeTask_BaseState) = 0
compute_effort(::ComputeTask_Propagator) = 0 compute_effort(::ComputeTask_Propagator) = 0
@ -26,16 +16,6 @@ compute_effort(::ComputeTask_CollectPairs) = 0
compute_effort(::ComputeTask_PropagatePairs) = 0 compute_effort(::ComputeTask_PropagatePairs) = 0
compute_effort(::ComputeTask_Triple) = 0 compute_effort(::ComputeTask_Triple) = 0
compute_effort(::ComputeTask_CollectTriples) = 0 compute_effort(::ComputeTask_CollectTriples) = 0
compute_effort(::ComputeTask_SpinPolCumulation) = 0
children(::ComputeTask_BaseState) = 1
children(::ComputeTask_Propagator) = 1
children(::ComputeTask_Pair) = 2
children(t::ComputeTask_CollectPairs) = t.children
children(::ComputeTask_PropagatePairs) = 2
children(::ComputeTask_Triple) = 3
children(t::ComputeTask_CollectTriples) = t.children
children(t::ComputeTask_SpinPolCumulation) = t.children
struct BaseStateInput{PS_T<:AbstractParticleStateful,SPIN_POL_T<:AbstractSpinOrPolarization} struct BaseStateInput{PS_T<:AbstractParticleStateful,SPIN_POL_T<:AbstractSpinOrPolarization}
particle::PS_T particle::PS_T
@ -45,12 +25,8 @@ end
@inline function compute( @inline function compute(
::ComputeTask_BaseState, input::BaseStateInput{PS,SPIN_POL} ::ComputeTask_BaseState, input::BaseStateInput{PS,SPIN_POL}
) where {PS,SPIN_POL} ) where {PS,SPIN_POL}
species = particle_species(input.particle)
if is_outgoing(input.particle)
species = invert(species)
end
return Propagated( # "propagated" because it goes directly into the next pair return Propagated( # "propagated" because it goes directly into the next pair
species, input.particle,
QEDbase.base_state( QEDbase.base_state(
particle_species(input.particle), particle_species(input.particle),
particle_direction(input.particle), particle_direction(input.particle),
@ -91,11 +67,6 @@ struct Unpropagated{PARTICLE_T<:AbstractParticleType,VALUE_T}
value::VALUE_T value::VALUE_T
end end
import Base.+
function +(a::Unpropagated{P,V}, b::Unpropagated{P,V}) where {P,V}
return Unpropagated(a.particle, a.value + b.value)
end
struct Propagated{PARTICLE_T<:AbstractParticleType,VALUE_T} struct Propagated{PARTICLE_T<:AbstractParticleType,VALUE_T}
particle::PARTICLE_T particle::PARTICLE_T
value::VALUE_T value::VALUE_T
@ -105,33 +76,33 @@ end
@inline function compute( @inline function compute(
::ComputeTask_Pair, electron::Propagated{Electron,V1}, positron::Propagated{Positron,V2} ::ComputeTask_Pair, electron::Propagated{Electron,V1}, positron::Propagated{Positron,V2}
) where {V1,V2} ) where {V1,V2}
return Unpropagated(Photon(), positron.value * _vertex() * electron.value) # fermion - antifermion -> photon return Unpropagated(Photon(), positron.value * electron.value) # fermion - antifermion -> photon
end end
@inline function compute( @inline function compute(
::ComputeTask_Pair, positron::Propagated{Positron,V1}, electron::Propagated{Electron,V2} ::ComputeTask_Pair, positron::Propagated{Positron,V1}, electron::Propagated{Electron,V2}
) where {V1,V2} ) where {V1,V2}
return Unpropagated(Photon(), positron.value * _vertex() * electron.value) # antifermion - fermion -> photon return Unpropagated(Photon(), positron.value * electron.value) # antifermion - fermion -> photon
end end
@inline function compute( @inline function compute(
::ComputeTask_Pair, photon::Propagated{Photon,V1}, fermion::Propagated{F,V2} ::ComputeTask_Pair, photon::Propagated{Photon,V1}, fermion::Propagated{F,V2}
) where {F<:FermionLike,V1,V2} ) where {F<:FermionLike,V1,V2}
return Unpropagated(fermion.particle, photon.value * _vertex() * fermion.value) # (anti-)fermion - photon -> (anti-)fermion return Unpropagated(invert(fermion.particle), fermion.value * photon.value) # (anti-)fermion - photon -> (anti-)fermion
end end
@inline function compute( @inline function compute(
::ComputeTask_Pair, fermion::Propagated{F,V2}, photon::Propagated{Photon,V1} ::ComputeTask_Pair, fermion::Propagated{F,V2}, photon::Propagated{Photon,V1}
) where {F<:FermionLike,V1,V2} ) where {F<:FermionLike,V1,V2}
return Unpropagated(fermion.particle, photon.value * _vertex() * fermion.value) # photon - (anti-)fermion -> (anti-)fermion return Unpropagated(invert(fermion.particle), fermion.value * photon.value) # photon - (anti-)fermion -> (anti-)fermion
end end
@inline function compute( @inline function compute(
::ComputeTask_PropagatePairs, left::PROP_V, right::Unpropagated{P,VAL} ::ComputeTask_PropagatePairs, left::PROP_V, right::Unpropagated{P,VAL}
) where {PROP_V,P<:AbstractParticleType,VAL} ) where {PROP_V,P<:AbstractParticleType,VAL}
return Propagated(right.particle, left * right.value) return Propagated(right.particle, right.value * left.value)
end end
@inline function compute( @inline function compute(
::ComputeTask_PropagatePairs, left::Unpropagated{P,VAL}, right::PROP_V ::ComputeTask_PropagatePairs, left::Unpropagated{P,VAL}, right::PROP_V
) where {PROP_V,P<:AbstractParticleType,VAL} ) where {PROP_V,P<:AbstractParticleType,VAL}
return Propagated(left.particle, right * left.value) return Propagated(left.particle, left.value * right.value)
end end
@inline function compute( @inline function compute(
@ -140,7 +111,7 @@ end
electron::Propagated{Electron,V2}, electron::Propagated{Electron,V2},
positron::Propagated{Positron,V3}, positron::Propagated{Positron,V3},
) where {V1,V2,V3} ) where {V1,V2,V3}
return positron.value * _vertex() * photon.value * electron.value return positron.value * photon.value * electron.input
end end
@inline function compute( @inline function compute(
c::ComputeTask_Triple, c::ComputeTask_Triple,
@ -171,10 +142,3 @@ end
# use a summation algorithm with more accuracy and/or parallelization # use a summation algorithm with more accuracy and/or parallelization
@inline compute(::ComputeTask_CollectPairs, args::Vararg{N,T}) where {N,T} = sum(args) @inline compute(::ComputeTask_CollectPairs, args::Vararg{N,T}) where {N,T} = sum(args)
@inline compute(::ComputeTask_CollectTriples, args::Vararg{N,T}) where {N,T} = sum(args) @inline compute(::ComputeTask_CollectTriples, args::Vararg{N,T}) where {N,T} = sum(args)
@inline function compute(::ComputeTask_SpinPolCumulation, args::Vararg{N,T}) where {N,T}
sum = 0.0
for arg in args
sum += abs2(arg)
end
return sum
end

View File

@ -22,7 +22,7 @@ function _parse_particle(name::String)
throw(InvalidInputError("failed to parse particle direction from \"$name\"")) throw(InvalidInputError("failed to parse particle direction from \"$name\""))
end end
name = name[5:end] name = name[4:end]
local species local species
if startswith(name, "el") if startswith(name, "el")
@ -35,7 +35,7 @@ function _parse_particle(name::String)
throw(InvalidInputError("failed to parse particle species from name \"$name\"")) throw(InvalidInputError("failed to parse particle species from name \"$name\""))
end end
name = name[4:end] name = name[3:end]
local spin_pol local spin_pol
if startswith(name, "su") if startswith(name, "su")
@ -54,15 +54,13 @@ function _parse_particle(name::String)
) )
end end
name = name[4:end] name = name[3:end]
index = parse(Int, name) index = parse(Int, name)
return (dir, species, spin_pol, index) return (dir, species, spin_pol, index)
end end
function MetagraphOptimization.input_expr( function input_expr(instance::GenericQEDProcess, name::String, psp_symbol::Symbol)
proc::AbstractProcessDefinition, name::String, psp_symbol::Symbol
)
if startswith(name, "bs_") if startswith(name, "bs_")
(dir, species, spin_pol, index) = _parse_particle(name[4:end]) (dir, species, spin_pol, index) = _parse_particle(name[4:end])
dir_str = _construction_string(dir) dir_str = _construction_string(dir)
@ -70,7 +68,7 @@ function MetagraphOptimization.input_expr(
sp_str = _construction_string(spin_pol) sp_str = _construction_string(spin_pol)
return Meta.parse( return Meta.parse(
"FeynmanDiagramGenerator.BaseStateInput( "BaseStateInput(
ParticleStateful($dir_str, $species_str, momentum($psp_symbol, $dir_str, $species_str, $index)), ParticleStateful($dir_str, $species_str, momentum($psp_symbol, $dir_str, $species_str, $index)),
$sp_str, $sp_str,
)", )",
@ -80,10 +78,10 @@ function MetagraphOptimization.input_expr(
index = parse(Int, name[4:end]) # get index of the virtual particle in the process index = parse(Int, name[4:end]) # get index of the virtual particle in the process
vp = virtual_particles(proc)[index] vp = virtual_particles(proc)[index]
return Meta.parse("FeynmanDiagramGenerator.PropagatorInput( return Meta.parse("PropagatorInput(
FeynmanDiagramGenerator.VirtualParticle( VirtualParticle(
process($psp_symbol), process($psp_symbol),
$(_construction_string(particle_species(vp))), $species_str,
$(vp.in_particle_contributions), $(vp.in_particle_contributions),
$(vp.out_particle_contributions) $(vp.out_particle_contributions)
), ),
@ -94,20 +92,6 @@ function MetagraphOptimization.input_expr(
end end
end end
function MetagraphOptimization.input_type(p::AbstractProcessDefinition)
return Any
in_t = QEDcore._assemble_tuple_type(incoming_particles(p), Incoming(), SFourMomentum)
out_t = QEDcore._assemble_tuple_type(outgoing_particles(p), Outgoing(), SFourMomentum)
return PhaseSpacePoint{
typeof(p),
PerturbativeQED,
PhasespaceDefinition{SphericalCoordinateSystem,ElectronRestFrame},
Tuple{in_t...},
Tuple{out_t...},
SFourMomentum,
}
end
_species_str(::Photon) = "ph" _species_str(::Photon) = "ph"
_species_str(::Electron) = "el" _species_str(::Electron) = "el"
_species_str(::Positron) = "po" _species_str(::Positron) = "po"
@ -117,22 +101,6 @@ _spin_pol_str(::SpinDown) = "sd"
_spin_pol_str(::PolX) = "px" _spin_pol_str(::PolX) = "px"
_spin_pol_str(::PolY) = "py" _spin_pol_str(::PolY) = "py"
function Base.parse(::Type{AbstractSpinOrPolarization}, s::AbstractString)
if s == "su"
return SpinUp()
end
if s == "sd"
return SpinDown()
end
if s == "px"
return PolX()
end
if s == "py"
return PolY()
end
throw(InvalidInputError("invalid string \"$s\" to parse to AbstractSpinOrPolarization"))
end
_dir_str(::Incoming) = "inc" _dir_str(::Incoming) = "inc"
_dir_str(::Outgoing) = "out" _dir_str(::Outgoing) = "out"
@ -145,49 +113,6 @@ _spin_pols(::PolY) = (PolY(),)
_is_external(p::VirtualParticle) = number_contributions(p) == 1 _is_external(p::VirtualParticle) = number_contributions(p) == 1
function _total_index(
proc::AbstractProcessDefinition,
dir::ParticleDirection,
species::AbstractParticleType,
n::Int,
)
# find particle index of all particles given n-th particle of dir and species (inverse of _species_index)
total_index = 0
species_count = 0
for p in particles(proc, dir)
total_index += 1
if species == p
species_count += 1
end
if species_count == n
return if dir == Incoming()
total_index
else
number_incoming_particles(proc) + total_index
end
end
end
throw("did not find $n-th $dir $species")
end
function _species_index(
proc::AbstractProcessDefinition,
dir::ParticleDirection,
species::AbstractParticleType,
n::Int,
)
# find particle index of n-th particle of *this species and dir*
species_index = 0
for i in 1:n
if particles(proc, dir)[i] == species
species_index += 1
end
end
return species_index
end
function _base_state_name(p::VirtualParticle) function _base_state_name(p::VirtualParticle)
proc = process(p) proc = process(p)
@ -205,7 +130,13 @@ function _base_state_name(p::VirtualParticle)
species = particles(proc, dir)[index] species = particles(proc, dir)[index]
species_index = _species_index(proc, dir, species, index) # find particle index of *this species*
species_index = 0
for i in 1:index
if particles(proc, dir)[i] == species
species_index += 1
end
end
spin_pol = spin_or_pol(proc, dir, species, species_index) spin_pol = spin_or_pol(proc, dir, species, species_index)
@ -216,70 +147,11 @@ function _base_state_name(p::VirtualParticle)
) )
end end
# from two or three node names like "1_su-2-px"... return a single tuple of the indices and spin/pols in sorted function generate_DAG(proc::GenericQEDProcess)
function _parse_node_names(name1::String, name2::String)
split_strings_1 = split.(split(name1, "-"), "_")
split_strings_2 = split.(split(name2, "-"), "_")
return tuple(
# TODO: could use merge sort since the sub lists are sorted already
sort([
tuple.(
parse.(Int, getindex.(split_strings_1, 1)),
parse.(AbstractSpinOrPolarization, getindex.(split_strings_1, 2)),
)...,
tuple.(
parse.(Int, getindex.(split_strings_2, 1)),
parse.(AbstractSpinOrPolarization, getindex.(split_strings_2, 2)),
)...,
])...,
)
end
function _parse_node_names(name1::String, name2::String, name3::String)
split_strings_1 = split.(split(name1, "-"), "_")
split_strings_2 = split.(split(name2, "-"), "_")
split_strings_3 = split.(split(name3, "-"), "_")
return tuple(
# TODO: could use merge sort since the sub lists are sorted already
sort([
tuple.(
parse.(Int, getindex.(split_strings_1, 1)),
parse.(AbstractSpinOrPolarization, getindex.(split_strings_1, 2)),
)...,
tuple.(
parse.(Int, getindex.(split_strings_2, 1)),
parse.(AbstractSpinOrPolarization, getindex.(split_strings_2, 2)),
)...,
tuple.(
parse.(Int, getindex.(split_strings_3, 1)),
parse.(AbstractSpinOrPolarization, getindex.(split_strings_3, 2)),
)...,
])...,
)
end
function _make_node_name(
spin_pols::NTuple{N,Tuple{Int,AbstractSpinOrPolarization}}
) where {N}
node_name = ""
first = true
for spin_pol_tuple in spin_pols
if !first
node_name *= "-"
else
first = false
end
node_name *= "$(spin_pol_tuple[1])_$(_spin_pol_str(spin_pol_tuple[2]))"
end
return node_name
end
function generate_DAG(proc::QEDProcess)
external_particles = _pseudo_virtual_particles(proc) # external particles that will be input to base_state tasks external_particles = _pseudo_virtual_particles(proc) # external particles that will be input to base_state tasks
particles = virtual_particles(proc) # virtual particles that will be input to propagator tasks particles = virtual_particles(proc) # virtual particles that will be input to propagator tasks
pairs = sort(particle_pairs(particles)) # pairs to generate the pair tasks pairs = particle_pairs(particles) # pairs to generate the pair tasks
triples = sort(total_particle_triples(particles)) # triples to generate the triple tasks triples = total_particle_triples(particles) # triples to generate the triple tasks
graph = DAG() graph = DAG()
@ -309,13 +181,7 @@ function generate_DAG(proc::QEDProcess)
) )
data_out = insert_node!( data_out = insert_node!(
graph, graph, make_node(DataTask(0)); track=false, invalidate_cache=false
make_node(
DataTask(0),
"$(_total_index(proc, dir, species, index))_$(_spin_pol_str(spin_pol))",
);
track=false,
invalidate_cache=false,
) )
insert_edge!(graph, data_in, compute_base_state) insert_edge!(graph, data_in, compute_base_state)
@ -336,10 +202,7 @@ function generate_DAG(proc::QEDProcess)
data_node_name = "pr_$vp_index" data_node_name = "pr_$vp_index"
data_in = insert_node!( data_in = insert_node!(
graph, graph, make_node(DataTask(0)); track=false, invalidate_cache=false
make_node(DataTask(0), data_node_name);
track=false,
invalidate_cache=false,
) )
compute_vp_propagator = insert_node!( compute_vp_propagator = insert_node!(
graph, make_node(ComputeTask_Propagator()); track=false, invalidate_cache=false graph, make_node(ComputeTask_Propagator()); track=false, invalidate_cache=false
@ -351,19 +214,15 @@ function generate_DAG(proc::QEDProcess)
insert_edge!(graph, data_in, compute_vp_propagator) insert_edge!(graph, data_in, compute_vp_propagator)
insert_edge!(graph, compute_vp_propagator, data_out) insert_edge!(graph, compute_vp_propagator, data_out)
propagator_task_outputs[vp] = data_out propagator_task_outputs[data_node_name] = data_out
end end
# -- Pair Tasks -- # -- Pair Tasks --
pair_task_outputs = Dict{VirtualParticle,Vector{Node}}() pair_task_outputs = Dict()
for (product_particle, input_particle_vector) in pairs for (product_particle, input_particle_vector) in pairs
pair_task_outputs[product_particle] = Vector{Node}() # for all spins/pols of particles in product_particles do ...
# make a dictionary of vectors to collect the outputs depending on spin/pol configs of the input particles pair_task_outputs[product_particle] = Vector()
N = number_contributions(product_particle)
pair_output_nodes_by_spin_pol = Dict{
NTuple{N,Tuple{Int,AbstractSpinOrPolarization}},Vector{DataTaskNode}
}()
for input_particles in input_particle_vector for input_particles in input_particle_vector
particles_data_out_nodes = (Vector(), Vector()) particles_data_out_nodes = (Vector(), Vector())
@ -378,152 +237,28 @@ function generate_DAG(proc::QEDProcess)
) )
else else
# grab from propagated particles # grab from propagated particles
append!(particles_data_out_nodes[c], pair_task_outputs[p]) push!(particles_date_out_nodes[c], pair_task_outputs[p])
end end
end end
for in_nodes in Iterators.product(particles_data_out_nodes...) for in_nodes in Iterators.product(input_particles...)
# make the compute pair nodes for every combination of the found input_particle_nodes to get all spin/pol combinations # make the compute pair nodes for every combination of the found input_particle_nodes to get all spin/pol combinations
compute_pair = insert_node!(
graph,
make_node(ComputeTask_Pair());
track=false,
invalidate_cache=false,
)
pair_data_out = insert_node!(
graph, make_node(DataTask(0)); track=false, invalidate_cache=false
)
insert_edge!(graph, in_nodes[1], compute_pair) #insert_node!(graph, )
insert_edge!(graph, in_nodes[2], compute_pair)
insert_edge!(graph, compute_pair, pair_data_out)
# get the spin/pol config of the input particles from the data_out names
index = _parse_node_names(in_nodes[1].name, in_nodes[2].name)
if !haskey(pair_output_nodes_by_spin_pol, index)
pair_output_nodes_by_spin_pol[index] = Vector()
end
push!(pair_output_nodes_by_spin_pol[index], pair_data_out)
end end
# make the collect pair and propagate nodes
end end
propagator_node = propagator_task_outputs[product_particle] data_out_propagated = insert_node!(
graph, make_node(DataTask(0)); track=false, invalidate_caches=false
for (index, nodes_to_sum) in pair_output_nodes_by_spin_pol
compute_pairs_sum = insert_node!(
graph,
make_node(ComputeTask_CollectPairs(length(nodes_to_sum)));
track=false,
invalidate_cache=false,
)
data_pairs_sum = insert_node!(
graph, make_node(DataTask(0)); track=false, invalidate_cache=false
)
compute_propagated = insert_node!(
graph,
make_node(ComputeTask_PropagatePairs());
track=false,
invalidate_cache=false,
)
# give this out node the correct name
data_out_propagated = insert_node!(
graph,
make_node(DataTask(0), _make_node_name(index));
track=false,
invalidate_cache=false,
)
for node in nodes_to_sum
insert_edge!(graph, node, compute_pairs_sum)
end
insert_edge!(graph, compute_pairs_sum, data_pairs_sum)
insert_edge!(graph, propagator_node, compute_propagated)
insert_edge!(graph, data_pairs_sum, compute_propagated)
insert_edge!(graph, compute_propagated, data_out_propagated)
push!(pair_task_outputs[product_particle], data_out_propagated)
end
end
# -- Triples --
triples_results = Dict()
for (ph, el, po) in triples # for each triple (each "diagram")
photons = if is_external(ph)
getindex.(Ref(base_state_task_outputs), _base_state_name(ph))
else
pair_task_outputs[ph]
end
electrons = if is_external(el)
getindex.(Ref(base_state_task_outputs), _base_state_name(el))
else
pair_task_outputs[el]
end
positrons = if is_external(po)
getindex.(Ref(base_state_task_outputs), _base_state_name(po))
else
pair_task_outputs[po]
end
for (a, b, c) in Iterators.product(photons, electrons, positrons) # for each spin/pol config of each part
compute_triples = insert_node!(
graph, make_node(ComputeTask_Triple()); track=false, invalidate_cache=false
)
data_triples = insert_node!(
graph, make_node(DataTask(0)); track=false, invalidate_cache=false
)
insert_edge!(graph, a, compute_triples)
insert_edge!(graph, b, compute_triples)
insert_edge!(graph, c, compute_triples)
insert_edge!(graph, compute_triples, data_triples)
index = _parse_node_names(a.name, b.name, c.name)
if !haskey(triples_results, index)
triples_results[index] = Vector{DataTaskNode}()
end
push!(triples_results[index], data_triples)
end
end
# -- Collect Triples --
collected_triples = Vector{DataTaskNode}()
for (index, results) in triples_results
compute_collect_triples = insert_node!(
graph,
make_node(ComputeTask_CollectTriples(length(results)));
track=false,
invalidate_cache=false,
)
data_collect_triples = insert_node!(
graph, make_node(DataTask(0)); track=false, invalidate_cache=false
) )
for triple in results pair_task_outputs[p] = data_out_propagated
insert_edge!(graph, triple, compute_collect_triples)
end
insert_edge!(graph, compute_collect_triples, data_collect_triples)
push!(collected_triples, data_collect_triples) # ... end do
end end
# Finally, abs2 sum over spin/pol configurations
compute_total_result = insert_node!(
graph,
make_node(ComputeTask_SpinPolCumulation(length(collected_triples)));
track=false,
invalidate_cache=false,
)
for finished_triple in collected_triples
insert_edge!(graph, finished_triple, compute_total_result)
end
final_data_out = insert_node!(
graph, make_node(DataTask(0)); track=false, invalidate_cache=false
)
insert_edge!(graph, compute_total_result, final_data_out)
return graph return graph
end end