WIP on DAG generation

This commit is contained in:
Rubydragon 2024-07-16 18:51:09 +02:00
parent 9859c3b928
commit a647801f12
6 changed files with 541 additions and 222 deletions

View File

@ -9,52 +9,23 @@
"name": "stderr", "name": "stderr",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"WARNING: Method definition number_particles(QEDbase.AbstractProcessDefinition, DIR, PT) where {DIR<:QEDbase.ParticleDirection, PT<:QEDbase.AbstractParticleType} in module QEDbase at /home/antonr/.julia/packages/QEDbase/gWHxL/src/interfaces/process.jl:208 overwritten in module FeynmanDiagramGenerator at /home/antonr/repos/FeynmanDiagramGenerator/src/QEDprocesses_patch.jl:23.\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" "ERROR: Method overwriting is not permitted during Module precompilation. Use `__precompile__(false)` to opt-out of precompilation.\n"
] ]
} }
], ],
"source": [ "source": [
"using Revise\n",
"using FeynmanDiagramGenerator" "using FeynmanDiagramGenerator"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 6, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [],
{
"data": {
"text/plain": [
"254-element Vector{VirtualParticle{GenericQEDProcess{Tuple{Photon, Photon, Photon, Photon, Photon, Photon, Photon, Electron}, Tuple{Photon, Electron}}, PT, 8, 2} where PT<:AbstractParticleType}:\n",
" positron: \t00000000 | 11\n",
" electron: \t00000001 | 10\n",
" positron: \t00000010 | 01\n",
" electron: \t00000011 | 00\n",
" positron: \t00000100 | 01\n",
" electron: \t00000101 | 00\n",
" positron: \t00001000 | 01\n",
" electron: \t00001001 | 00\n",
" positron: \t00010000 | 01\n",
" electron: \t00010001 | 00\n",
" ⋮\n",
" electron: \t11100001 | 10\n",
" positron: \t11100010 | 01\n",
" electron: \t11100011 | 00\n",
" positron: \t11100100 | 01\n",
" electron: \t11100101 | 00\n",
" positron: \t11101000 | 01\n",
" electron: \t11101001 | 00\n",
" positron: \t11110000 | 01\n",
" electron: \t11110001 | 00"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"proc = GenericQEDProcess(7, 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",
@ -65,125 +36,27 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 7, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [],
{
"data": {
"text/plain": [
"Dict{VirtualParticle, Vector{Tuple{VirtualParticle, VirtualParticle}}} with 254 entries:\n",
" positron: \t01000010 | 11 => [(photon: \t00000000 | 10, positron: \t01000010 | 01),…\n",
" positron: \t11010000 | 11 => [(photon: \t00000000 | 10, positron: \t11010000 | 01),…\n",
" electron: \t10100011 | 00 => [(photon: \t00000010 | 00, electron: \t10100001 | 00),…\n",
" positron: \t11000000 | 11 => [(photon: \t00000000 | 10, positron: \t11000000 | 01),…\n",
" positron: \t00010100 | 01 => [(photon: \t00000100 | 00, positron: \t00010000 | 01),…\n",
" positron: \t01001000 | 11 => [(photon: \t00000000 | 10, positron: \t01001000 | 01),…\n",
" positron: \t11000110 | 01 => [(photon: \t00000010 | 00, positron: \t11000100 | 01),…\n",
" electron: \t10001011 | 10 => [(photon: \t00000000 | 10, electron: \t10001011 | 00),…\n",
" positron: \t00100000 | 11 => [(photon: \t00000000 | 10, positron: \t00100000 | 01),…\n",
" positron: \t01010000 | 11 => [(photon: \t00000000 | 10, positron: \t01010000 | 01),…\n",
" electron: \t11101001 | 00 => [(photon: \t00001000 | 00, electron: \t11100001 | 00),…\n",
" electron: \t00100101 | 10 => [(photon: \t00000000 | 10, electron: \t00100101 | 00),…\n",
" electron: \t11000101 | 00 => [(photon: \t00000100 | 00, electron: \t11000001 | 00),…\n",
" electron: \t01101001 | 00 => [(photon: \t00001000 | 00, electron: \t01100001 | 00),…\n",
" positron: \t00101000 | 01 => [(photon: \t00001000 | 00, positron: \t00100000 | 01),…\n",
" positron: \t00011000 | 11 => [(photon: \t00000000 | 10, positron: \t00011000 | 01),…\n",
" positron: \t00011010 | 01 => [(photon: \t00000010 | 00, positron: \t00011000 | 01),…\n",
" electron: \t10000101 | 10 => [(photon: \t00000000 | 10, electron: \t10000101 | 00),…\n",
" electron: \t10000111 | 00 => [(photon: \t00000010 | 00, electron: \t10000101 | 00),…\n",
" ⋮ => ⋮"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [ "source": [
"pairs = FeynmanDiagramGenerator.particle_pairs(all_particles)" "pairs = FeynmanDiagramGenerator.particle_pairs(all_particles)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 8, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [],
{
"data": {
"text/plain": [
"280-element Vector{Tuple{VirtualParticle, VirtualParticle, VirtualParticle}}:\n",
" (photon: \t00000000 | 10, electron: \t01001011 | 00, positron: \t10110100 | 01)\n",
" (photon: \t00000000 | 10, electron: \t00010111 | 00, positron: \t11101000 | 01)\n",
" (photon: \t00000000 | 10, electron: \t00110011 | 00, positron: \t11001100 | 01)\n",
" (photon: \t00000000 | 10, electron: \t10111001 | 00, positron: \t01000110 | 01)\n",
" (photon: \t00000000 | 10, electron: \t10110101 | 00, positron: \t01001010 | 01)\n",
" (photon: \t00000000 | 10, electron: \t11110001 | 00, positron: \t00001110 | 01)\n",
" (photon: \t00000000 | 10, electron: \t11010011 | 00, positron: \t00101100 | 01)\n",
" (photon: \t00000000 | 10, electron: \t01001101 | 00, positron: \t10110010 | 01)\n",
" (photon: \t00000000 | 10, electron: \t11101001 | 00, positron: \t00010110 | 01)\n",
" (photon: \t00000000 | 10, electron: \t10011011 | 00, positron: \t01100100 | 01)\n",
" ⋮\n",
" (photon: \t01000000 | 00, electron: \t00111001 | 00, positron: \t10000110 | 11)\n",
" (photon: \t01000000 | 00, electron: \t00000111 | 10, positron: \t10111000 | 01)\n",
" (photon: \t01000000 | 00, electron: \t00011011 | 00, positron: \t10100100 | 11)\n",
" (photon: \t01000000 | 00, electron: \t10101011 | 00, positron: \t00010100 | 11)\n",
" (photon: \t01000000 | 00, electron: \t10000111 | 10, positron: \t00111000 | 01)\n",
" (photon: \t01000000 | 00, electron: \t10100101 | 10, positron: \t00011010 | 01)\n",
" (photon: \t01000000 | 00, electron: \t00100111 | 00, positron: \t10011000 | 11)\n",
" (photon: \t01000000 | 00, electron: \t10001101 | 10, positron: \t00110010 | 01)\n",
" (photon: \t01000000 | 00, electron: \t10011101 | 00, positron: \t00100010 | 11)"
]
},
"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": 9, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [],
{
"name": "stdout",
"output_type": "stream",
"text": [
"s: 40320, should be: 40320\n",
"number of triples: 280\n"
]
},
{
"data": {
"text/plain": [
"280-element Vector{Tuple{VirtualParticle, VirtualParticle, VirtualParticle}}:\n",
" (photon: \t00000000 | 10, electron: \t00001111 | 00, positron: \t11110000 | 01)\n",
" (photon: \t00000000 | 10, electron: \t00010111 | 00, positron: \t11101000 | 01)\n",
" (photon: \t00000000 | 10, electron: \t00011011 | 00, positron: \t11100100 | 01)\n",
" (photon: \t00000000 | 10, electron: \t00011101 | 00, positron: \t11100010 | 01)\n",
" (photon: \t00000000 | 10, electron: \t00100111 | 00, positron: \t11011000 | 01)\n",
" (photon: \t00000000 | 10, electron: \t00101011 | 00, positron: \t11010100 | 01)\n",
" (photon: \t00000000 | 10, electron: \t00101101 | 00, positron: \t11010010 | 01)\n",
" (photon: \t00000000 | 10, electron: \t00110011 | 00, positron: \t11001100 | 01)\n",
" (photon: \t00000000 | 10, electron: \t00110101 | 00, positron: \t11001010 | 01)\n",
" (photon: \t00000000 | 10, electron: \t00111001 | 00, positron: \t11000110 | 01)\n",
" ⋮\n",
" (photon: \t01000000 | 00, electron: \t10100101 | 10, positron: \t00011010 | 01)\n",
" (photon: \t01000000 | 00, electron: \t10100111 | 00, positron: \t00011000 | 11)\n",
" (photon: \t01000000 | 00, electron: \t10101001 | 10, positron: \t00010110 | 01)\n",
" (photon: \t01000000 | 00, electron: \t10101011 | 00, positron: \t00010100 | 11)\n",
" (photon: \t01000000 | 00, electron: \t10101101 | 00, positron: \t00010010 | 11)\n",
" (photon: \t01000000 | 00, electron: \t10110001 | 10, positron: \t00001110 | 01)\n",
" (photon: \t01000000 | 00, electron: \t10110011 | 00, positron: \t00001100 | 11)\n",
" (photon: \t01000000 | 00, electron: \t10110101 | 00, positron: \t00001010 | 11)\n",
" (photon: \t01000000 | 00, electron: \t10111001 | 00, positron: \t00000110 | 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",
@ -206,6 +79,15 @@
"\n", "\n",
"sort(triples)" "sort(triples)"
] ]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"generate_DAG(proc)"
]
} }
], ],
"metadata": { "metadata": {

View File

@ -17,7 +17,7 @@ export FlatMatrix
export GenericQEDProcess, isphysical export GenericQEDProcess, isphysical
export AbstractTreeLevelFeynmanDiagram, FeynmanVertex, FeynmanDiagram export AbstractTreeLevelFeynmanDiagram, FeynmanVertex, FeynmanDiagram
export external_particles, virtual_particles, process export external_particles, virtual_particles, process, generate_DAG
export VirtualParticle, number_contributions export VirtualParticle, number_contributions
export contributions, in_contributions, out_contributions export contributions, in_contributions, out_contributions

View File

@ -39,12 +39,12 @@ function leaves(partition::TopologyPartition)
return partition.leaves1 + partition.leaves2 + partition.leaves3 return partition.leaves1 + partition.leaves2 + partition.leaves3
end end
# #
# Feynman Diagram, tree-level, QED # Feynman Diagram, tree-level, QED
# #
struct FeynmanDiagram{N,E,U,T,M,FM} <: AbstractTreeLevelFeynmanDiagram where {N,E,U,T,M,FM<:FlatMatrix} struct FeynmanDiagram{N,E,U,T,M,FM} <:
AbstractTreeLevelFeynmanDiagram where {N,E,U,T,M,FM<:FlatMatrix}
diagram_structure::FM diagram_structure::FM
electron_permutation::NTuple{E,Int} electron_permutation::NTuple{E,Int}
@ -59,19 +59,26 @@ struct FeynmanDiagram{N,E,U,T,M,FM} <: AbstractTreeLevelFeynmanDiagram where {N,
::Val{E}, ::Val{E},
::Val{U}, ::Val{U},
::Val{T}, ::Val{T},
::Val{M} ::Val{M},
) where {E,U,T,M} ) where {E,U,T,M}
@assert E == length(elec_perm) @assert E == length(elec_perm)
@assert U == length(muon_perm) @assert U == length(muon_perm)
@assert T == length(tauon_perm) @assert T == length(tauon_perm)
N = E + U + T N = E + U + T
return new{N,E,U,T,M,FlatMatrix{Int64,2 * N - 2 + M,N}}(FlatMatrix(structure), NTuple{E,Int}(elec_perm), NTuple{U,Int}(muon_perm), NTuple{T,Int}(tauon_perm)) return new{N,E,U,T,M,FlatMatrix{Int64,2 * N - 2 + M,N}}(
FlatMatrix(structure),
NTuple{E,Int}(elec_perm),
NTuple{U,Int}(muon_perm),
NTuple{T,Int}(tauon_perm),
)
end end
end end
# representation of a virtual particle and the return type of the virtual_particles function # representation of a virtual particle and the return type of the virtual_particles function
struct VirtualParticle{PROC<:QEDbase.AbstractProcessDefinition,PT<:QEDbase.AbstractParticleType,I,O} struct VirtualParticle{
PROC<:QEDbase.AbstractProcessDefinition,PT<:QEDbase.AbstractParticleType,I,O
}
proc::PROC proc::PROC
species::PT species::PT
in_particle_contributions::NTuple{I,Bool} in_particle_contributions::NTuple{I,Bool}
@ -80,7 +87,10 @@ end
function Base.show(io::IO, vp::VirtualParticle) function Base.show(io::IO, vp::VirtualParticle)
pr = x -> x ? "1" : "0" pr = x -> x ? "1" : "0"
print(io, "$(vp.species): \t$(*(pr.(vp.in_particle_contributions)...)) | $(*(pr.(vp.out_particle_contributions)...))") return print(
io,
"$(vp.species): \t$(*(pr.(vp.in_particle_contributions)...)) | $(*(pr.(vp.out_particle_contributions)...))",
)
end end
function QEDbase.process(vp::VirtualParticle) function QEDbase.process(vp::VirtualParticle)
@ -96,11 +106,14 @@ out_contributions(vp::VirtualParticle) = vp.out_particle_contributions
contributions(vp::VirtualParticle) = ((in_contributions(vp), out_contributions(vp))) contributions(vp::VirtualParticle) = ((in_contributions(vp), out_contributions(vp)))
is_virtual(vp::VirtualParticle) = number_contributions(vp) > 1 is_virtual(vp::VirtualParticle) = number_contributions(vp) > 1
is_external(vp::VirtualParticle) = number_contributions(vp) == 1
import Base: + import Base: +
# "addition" of the bool tuples # "addition" of the bool tuples
function +(a::Tuple{NTuple{I,Bool},NTuple{O,Bool}}, b::Tuple{NTuple{I,Bool},NTuple{O,Bool}}) where {I,O} function +(
a::Tuple{NTuple{I,Bool},NTuple{O,Bool}}, b::Tuple{NTuple{I,Bool},NTuple{O,Bool}}
) where {I,O}
# realistically, there should never be "colliding" 1s. if there are there is probably an error and this should be asserted # realistically, there should never be "colliding" 1s. if there are there is probably an error and this should be asserted
#= for (i, j) in zip(a[1], b[1]) @assert !(i && j) end #= for (i, j) in zip(a[1], b[1]) @assert !(i && j) end
for (i, j) in zip(a[2], b[2]) @assert !(i && j) end =# for (i, j) in zip(a[2], b[2]) @assert !(i && j) end =#
@ -111,7 +124,9 @@ end
invert(::Electron) = Positron() invert(::Electron) = Positron()
invert(::Positron) = Electron() invert(::Positron) = Electron()
invert(::Photon) = Photon() invert(::Photon) = Photon()
invert(::AbstractParticleType) = throw(InvalidInputError("unimplemented for this particle type")) function invert(::AbstractParticleType)
throw(InvalidInputError("unimplemented for this particle type"))
end
function invert(virtual_particle::VirtualParticle) function invert(virtual_particle::VirtualParticle)
I = length(virtual_particle.in_particle_contributions) I = length(virtual_particle.in_particle_contributions)
@ -120,7 +135,8 @@ function invert(virtual_particle::VirtualParticle)
virtual_particle.proc, virtual_particle.proc,
invert(virtual_particle.species), invert(virtual_particle.species),
ntuple(x -> !virtual_particle.in_particle_contributions[x], I), ntuple(x -> !virtual_particle.in_particle_contributions[x], I),
ntuple(x -> !virtual_particle.out_particle_contributions[x], O)) ntuple(x -> !virtual_particle.out_particle_contributions[x], O),
)
end end
# normalize the representation # normalize the representation
@ -138,7 +154,12 @@ function normalize(virtual_particle::VirtualParticle)
end end
end end
function _momentum_contribution(proc::AbstractProcessDefinition, dir::ParticleDirection, species::AbstractParticleType, index::Int) function _momentum_contribution(
proc::AbstractProcessDefinition,
dir::ParticleDirection,
species::AbstractParticleType,
index::Int,
)
I = number_incoming_particles(proc) I = number_incoming_particles(proc)
O = number_outgoing_particles(proc) O = number_outgoing_particles(proc)
@ -151,7 +172,10 @@ function _momentum_contribution(proc::AbstractProcessDefinition, dir::ParticleDi
particles_seen += 1 particles_seen += 1
end end
if particles_seen == index if particles_seen == index
return (((is_incoming(dir) && x == c for x in 1:I)...,), ((is_outgoing(dir) && x == c for x in 1:O)...,)) return (
((is_incoming(dir) && x == c for x in 1:I)...,),
((is_outgoing(dir) && x == c for x in 1:O)...,),
)
end end
end end
@ -159,17 +183,25 @@ function _momentum_contribution(proc::AbstractProcessDefinition, dir::ParticleDi
end end
function _fermion_type(proc::AbstractProcessDefinition, n::Int) function _fermion_type(proc::AbstractProcessDefinition, n::Int)
E = number_particles(proc, Incoming(), Electron()) + number_particles(proc, Outgoing(), Positron()) E =
number_particles(proc, Incoming(), Electron()) +
number_particles(proc, Outgoing(), Positron())
U = 0 # TODO add muons U = 0 # TODO add muons
T = 0 # TODO add tauons T = 0 # TODO add tauons
M = number_particles(proc, Incoming(), Photon()) + number_particles(proc, Outgoing(), Photon()) M =
number_particles(proc, Incoming(), Photon()) +
number_particles(proc, Outgoing(), Photon())
N = E + U + T N = E + U + T
# from the fermion index, get (Direction, Species, n) tuple, where n means it's the nth particle of that dir and species # from the fermion index, get (Direction, Species, n) tuple, where n means it's the nth particle of that dir and species
if (n > 0 && n <= E) if (n > 0 && n <= E)
electron_n = n electron_n = n
if electron_n > number_particles(proc, Incoming(), Electron()) if electron_n > number_particles(proc, Incoming(), Electron())
return (Outgoing(), Positron(), electron_n - number_particles(proc, Incoming(), Electron())) return (
Outgoing(),
Positron(),
electron_n - number_particles(proc, Incoming(), Electron()),
)
else else
return (Incoming(), Electron(), electron_n) return (Incoming(), Electron(), electron_n)
end end
@ -185,7 +217,11 @@ function _fermion_type(proc::AbstractProcessDefinition, n::Int)
# photon # photon
photon_n = n - N photon_n = n - N
if photon_n > number_particles(proc, Incoming(), Photon()) if photon_n > number_particles(proc, Incoming(), Photon())
return (Outgoing(), Photon(), photon_n - number_particles(proc, Incoming(), Photon())) return (
Outgoing(),
Photon(),
photon_n - number_particles(proc, Incoming(), Photon()),
)
else else
return (Incoming(), Photon(), photon_n) return (Incoming(), Photon(), photon_n)
end end
@ -194,7 +230,11 @@ function _fermion_type(proc::AbstractProcessDefinition, n::Int)
electron_n = n - N - M electron_n = n - N - M
if electron_n > number_particles(proc, Outgoing(), Electron()) if electron_n > number_particles(proc, Outgoing(), Electron())
# incoming positron # incoming positron
return (Incoming(), Positron(), electron_n - number_particles(proc, Outgoing(), Electron())) return (
Incoming(),
Positron(),
electron_n - number_particles(proc, Outgoing(), Electron()),
)
else else
# outgoing electron # outgoing electron
return (Outgoing(), Electron(), electron_n) return (Outgoing(), Electron(), electron_n)
@ -245,7 +285,8 @@ end
Return true if the momenta contributions of `a` and `b` are disjunct. Return true if the momenta contributions of `a` and `b` are disjunct.
""" """
function disjunct(a::VirtualParticle, b::VirtualParticle) function disjunct(a::VirtualParticle, b::VirtualParticle)
for (a_contrib, b_contrib) in Iterators.zip(Iterators.flatten.(contributions.((a, b)))...) for (a_contrib, b_contrib) in
Iterators.zip(Iterators.flatten.(contributions.((a, b)))...)
if b_contrib && a_contrib if b_contrib && a_contrib
return false return false
end end
@ -260,7 +301,8 @@ end
Returns true if the set of particles contributing to `a` are contains the set of particles contributing to `b`. Returns true if the set of particles contributing to `a` are contains the set of particles contributing to `b`.
""" """
function contains(a::VirtualParticle, b::VirtualParticle) function contains(a::VirtualParticle, b::VirtualParticle)
for (a_contrib, b_contrib) in Iterators.zip(Iterators.flatten.(contributions.((a, b)))...) for (a_contrib, b_contrib) in
Iterators.zip(Iterators.flatten.(contributions.((a, b)))...)
if b_contrib && !a_contrib if b_contrib && !a_contrib
return false return false
end end
@ -279,7 +321,8 @@ function make_up(a::VirtualParticle, b::VirtualParticle, c::VirtualParticle)
return false return false
end end
# it should be unnecessary to check here that a and b can actually react. if a + b = c they must be able to if a, b and c all exist in the diagram. # it should be unnecessary to check here that a and b can actually react. if a + b = c they must be able to if a, b and c all exist in the diagram.
for (a_contrib, b_contrib, c_contrib) in Iterators.zip(Iterators.flatten.(contributions.((a, b, c)))...) for (a_contrib, b_contrib, c_contrib) in
Iterators.zip(Iterators.flatten.(contributions.((a, b, c)))...)
if c_contrib != a_contrib + b_contrib if c_contrib != a_contrib + b_contrib
return false return false
end end
@ -294,7 +337,8 @@ end
Return true if a, b and c combined contain all external particles exactly once. Return true if a, b and c combined contain all external particles exactly once.
""" """
function are_total(a::VirtualParticle, b::VirtualParticle, c::VirtualParticle) function are_total(a::VirtualParticle, b::VirtualParticle, c::VirtualParticle)
for (a_contrib, b_contrib, c_contrib) in Iterators.zip(Iterators.flatten.(contributions.((a, b, c)))...) for (a_contrib, b_contrib, c_contrib) in
Iterators.zip(Iterators.flatten.(contributions.((a, b, c)))...)
if a_contrib + b_contrib + c_contrib != 1 if a_contrib + b_contrib + c_contrib != 1
return false return false
end end
@ -311,14 +355,17 @@ function particle_pairs(particles::Vector)
all_particles = sort([_pseudo_virtual_particles(proc)..., particles...]) all_particles = sort([_pseudo_virtual_particles(proc)..., particles...])
# find pairs for every particle after the external ones (those can't have pairs) # find pairs for every particle after the external ones (those can't have pairs)
for p_i in number_incoming_particles(proc)+number_outgoing_particles(proc)+1:length(all_particles) for p_i in
(number_incoming_particles(proc) + number_outgoing_particles(proc) + 1):length(
all_particles
)
p = all_particles[p_i] p = all_particles[p_i]
pairs[p] = Vector{Tuple{VirtualParticle,VirtualParticle}}() pairs[p] = Vector{Tuple{VirtualParticle,VirtualParticle}}()
# only need to consider external particles and virtual particles that come before p_i # only need to consider external particles and virtual particles that come before p_i
for p_a_i in 1:p_i-2 for p_a_i in 1:(p_i - 2)
# and only partners between a and p_i # and only partners between a and p_i
for p_b_i in p_a_i+1:p_i-1 for p_b_i in (p_a_i + 1):(p_i - 1)
p_a = all_particles[p_a_i] p_a = all_particles[p_a_i]
p_b = all_particles[p_b_i] p_b = all_particles[p_b_i]
@ -343,11 +390,20 @@ function total_particle_triples(particles::Vector)
photons = filter(p -> is_boson(particle_species(p)), working_set) photons = filter(p -> is_boson(particle_species(p)), working_set)
# make electrons a set for fast deletion # make electrons a set for fast deletion
electrons = Set(filter(p -> is_fermion(particle_species(p)) && is_particle(particle_species(p)), working_set)) electrons = Set(
filter(
p -> is_fermion(particle_species(p)) && is_particle(particle_species(p)),
working_set,
),
)
# make positrons a set for fast lookup # make positrons a set for fast lookup
positrons = Set(filter(p -> is_fermion(particle_species(p)) && is_anti_particle(particle_species(p)), working_set)) positrons = Set(
filter(
p -> is_fermion(particle_species(p)) && is_anti_particle(particle_species(p)),
working_set,
),
)
# no participant can have more than half the external particles, so every possible particle is contained here # no participant can have more than half the external particles, so every possible particle is contained here
# every photon has exactly one electron and positron partner # every photon has exactly one electron and positron partner
@ -358,7 +414,11 @@ function total_particle_triples(particles::Vector)
end end
# create the only partner the ph and e could have together, then look for it in the actual positrons # create the only partner the ph and e could have together, then look for it in the actual positrons
expected_p = invert(VirtualParticle(proc, particle_species(e), (contributions(ph) + contributions(e))...)) expected_p = invert(
VirtualParticle(
proc, particle_species(e), (contributions(ph) + contributions(e))...
),
)
if expected_p in positrons if expected_p in positrons
@assert are_total(ph, e, expected_p) @assert are_total(ph, e, expected_p)
@ -376,10 +436,16 @@ end
Return a vector of `VirtualParticle` for each external particle. These are not actually virtual particles, but can be helpful as entry points. Return a vector of `VirtualParticle` for each external particle. These are not actually virtual particles, but can be helpful as entry points.
""" """
function _pseudo_virtual_particles(proc::AbstractProcessDefinition) function _pseudo_virtual_particles(proc::AbstractProcessDefinition)
return sort(_external_particle.(proc, [1:number_incoming_particles(proc)+number_outgoing_particles(proc);])) return sort(
_external_particle.(
proc, [1:(number_incoming_particles(proc) + number_outgoing_particles(proc));]
),
)
end end
function virtual_particles(proc::AbstractProcessDefinition, diagram::FeynmanDiagram{N,E,U,T,M,FM}) where {N,E,U,T,M,FM} function virtual_particles(
proc::AbstractProcessDefinition, diagram::FeynmanDiagram{N,E,U,T,M,FM}
) where {N,E,U,T,M,FM}
fermion_lines = PriorityQueue{Int64,Int64}() fermion_lines = PriorityQueue{Int64,Int64}()
# count number of internal photons in each fermion line and make a priority queue for fermion line => number of internal photons # count number of internal photons in each fermion line and make a priority queue for fermion line => number of internal photons
@ -452,11 +518,17 @@ function virtual_particles(proc::AbstractProcessDefinition, diagram::FeynmanDiag
else # if the binding particle is unknown else # if the binding particle is unknown
# we have arrived at the "middle" of the line # we have arrived at the "middle" of the line
# this line will be the unknown particle for the other lines # this line will be the unknown particle for the other lines
internal_photon_contributions[current_line] = cumulative_mom + unknown_photon_momentum internal_photon_contributions[current_line] =
cumulative_mom + unknown_photon_momentum
# now we know that the fermion line that binding_particle binds to on the other end has one fewer unknown internal photons # now we know that the fermion line that binding_particle binds to on the other end has one fewer unknown internal photons
fermion_lines[binding_particle] -= 1 fermion_lines[binding_particle] -= 1
# add the internal photon virtual particle # add the internal photon virtual particle
push!(result, VirtualParticle(proc, Photon(), (cumulative_mom + unknown_photon_momentum)...)) push!(
result,
VirtualParticle(
proc, Photon(), (cumulative_mom + unknown_photon_momentum)...
),
)
break break
end end
else # binding_particle is an external photon else # binding_particle is an external photon
@ -466,7 +538,7 @@ function virtual_particles(proc::AbstractProcessDefinition, diagram::FeynmanDiag
end end
end end
return normalize.(result)[1:end-1] return normalize.(result)[1:(end - 1)]
end end
# #
@ -484,14 +556,7 @@ end
function _feynman_structures(n::Int, m::Int) function _feynman_structures(n::Int, m::Int)
f = labelled_plane_trees(n) f = labelled_plane_trees(n)
return ExternalPhotonIterator( return ExternalPhotonIterator(n, m, f, 1, _external_photon_multiplicity(f[1], n, m), 1)
n,
m,
f,
1,
_external_photon_multiplicity(f[1], n, m),
1
)
end end
function Base.length(it::ExternalPhotonIterator) function Base.length(it::ExternalPhotonIterator)
@ -510,7 +575,9 @@ function Base.iterate(iter::ExternalPhotonIterator, n::Nothing)
iter.fermion_structure_index += 1 iter.fermion_structure_index += 1
iter.photon_structure_index = 1 iter.photon_structure_index = 1
iter.photon_structures = _external_photon_multiplicity(iter.fermion_structures[iter.fermion_structure_index], iter.N, iter.M) iter.photon_structures = _external_photon_multiplicity(
iter.fermion_structures[iter.fermion_structure_index], iter.N, iter.M
)
else else
iter.photon_structure_index += 1 iter.photon_structure_index += 1
end end
@ -518,7 +585,9 @@ function Base.iterate(iter::ExternalPhotonIterator, n::Nothing)
return (iter.photon_structures[iter.photon_structure_index], nothing) return (iter.photon_structures[iter.photon_structure_index], nothing)
end end
function _external_photon_multiplicity(fermion_structure::Vector{Vector{Int}}, n::Int, m::Int) function _external_photon_multiplicity(
fermion_structure::Vector{Vector{Int}}, n::Int, m::Int
)
if m == 0 if m == 0
return [fermion_structure] return [fermion_structure]
end end
@ -529,7 +598,7 @@ function _external_photon_multiplicity(fermion_structure::Vector{Vector{Int}}, n
for line_index in eachindex(fermion_structure) for line_index in eachindex(fermion_structure)
# go through indices start to end # go through indices start to end
for index in 1:length(fermion_structure[line_index])+1 for index in 1:(length(fermion_structure[line_index]) + 1)
# copy to prevent muting # copy to prevent muting
new_photon_structure = deepcopy(fermion_structure) new_photon_structure = deepcopy(fermion_structure)
# add new photon # add new photon
@ -564,11 +633,17 @@ end
function Base.iterate(iter::FeynmanDiagramIterator{E,U,T,M}) where {E,U,T,M} function Base.iterate(iter::FeynmanDiagramIterator{E,U,T,M}) where {E,U,T,M}
N = E + U + T N = E + U + T
f = FeynmanDiagram(iter.photon_structure, iter.e_perms[iter.e_index], iter.u_perms[iter.u_index], iter.t_perms[iter.t_index], iter.e, iter.u, iter.t, iter.m) f = FeynmanDiagram(
return ( iter.photon_structure,
f, iter.e_perms[iter.e_index],
nothing iter.u_perms[iter.u_index],
iter.t_perms[iter.t_index],
iter.e,
iter.u,
iter.t,
iter.m,
) )
return (f, nothing)
end end
function Base.iterate(iter::FeynmanDiagramIterator{E,U,T,M}, ::Nothing) where {E,U,T,M} function Base.iterate(iter::FeynmanDiagramIterator{E,U,T,M}, ::Nothing) where {E,U,T,M}
@ -594,11 +669,17 @@ function Base.iterate(iter::FeynmanDiagramIterator{E,U,T,M}, ::Nothing) where {E
end end
N = E + U + T N = E + U + T
f = FeynmanDiagram(iter.photon_structure, iter.e_perms[iter.e_index], iter.u_perms[iter.u_index], iter.t_perms[iter.t_index], iter.e, iter.u, iter.t, iter.m) f = FeynmanDiagram(
return ( iter.photon_structure,
f, iter.e_perms[iter.e_index],
nothing iter.u_perms[iter.u_index],
iter.t_perms[iter.t_index],
iter.e,
iter.u,
iter.t,
iter.m,
) )
return (f, nothing)
end end
function feynman_diagrams(proc::PROC) where {PROC<:GenericQEDProcess} function feynman_diagrams(proc::PROC) where {PROC<:GenericQEDProcess}
@ -625,10 +706,39 @@ function feynman_diagrams(in_particles::Tuple, out_particles::Tuple)
# left electrons -> left muons -> left tauons -> left photons -> right photons -> right electrons -> right muons -> right tauons # left electrons -> left muons -> left tauons -> left photons -> right photons -> right electrons -> right muons -> right tauons
# a "left" fermion is simply an incoming fermion or outgoing antifermion of the type, while a "left" photon is an incoming photon, and the reverse for the right ones # a "left" fermion is simply an incoming fermion or outgoing antifermion of the type, while a "left" photon is an incoming photon, and the reverse for the right ones
f_iter = _feynman_structures(e + u + t, m) f_iter = _feynman_structures(e + u + t, m)
e_perms = collect(permutations(Int[n+m+1:n+m+e;])) e_perms = collect(permutations(Int[(n + m + 1):(n + m + e);]))
u_perms = collect(permutations(Int[n+m+e+1:n+m+e+u;])) u_perms = collect(permutations(Int[(n + m + e + 1):(n + m + e + u);]))
t_perms = collect(permutations(Int[n+m+e+u+1:n+m+e+u+t;])) t_perms = collect(permutations(Int[(n + m + e + u + 1):(n + m + e + u + t);]))
first_photon_structure, _ = iterate(f_iter) first_photon_structure, _ = iterate(f_iter)
return FeynmanDiagramIterator(Val(e), e_perms, 1, Val(u), u_perms, 1, Val(t), t_perms, 1, Val(m), f_iter, first_photon_structure) return FeynmanDiagramIterator(
Val(e),
e_perms,
1,
Val(u),
u_perms,
1,
Val(t),
t_perms,
1,
Val(m),
f_iter,
first_photon_structure,
)
end
function virtual_particles(proc::GenericQEDProcess)
if !isempty(proc.virtual_particles_cache)
return proc.virtual_particles_cache
end
# use a set for deduplication
particles = Set{VirtualParticle}()
for fd in feynman_diagrams(proc)
push!(particles, virtual_particles(proc, fd)...)
end
# convert to vector
proc.virtual_particles_cache = [particles...]
return return proc.virtual_particles_cache
end end

View File

@ -1,41 +1,115 @@
_assert_particle_type_tuple(::Tuple{}) = nothing _assert_particle_type_tuple(::Tuple{}) = nothing
_assert_particle_type_tuple(t::Tuple{AbstractParticleType,Vararg}) = _assert_particle_type_tuple(t[2:end]) function _assert_particle_type_tuple(t::Tuple{AbstractParticleType,Vararg})
_assert_particle_type_tuple(t::Any) = throw(InvalidInputError("invalid input, provide a tuple of AbstractParticleTypes to construct a GenericQEDProcess")) return _assert_particle_type_tuple(t[2:end])
end
function _assert_particle_type_tuple(t::Any)
throw(
InvalidInputError(
"invalid input, provide a tuple of AbstractParticleTypes to construct a GenericQEDProcess",
),
)
end
struct GenericQEDProcess{INT,OUTT} <: QEDbase.AbstractProcessDefinition where {INT<:Tuple,OUTT<:Tuple} mutable struct GenericQEDProcess{INT,OUTT,INSP,OUTSP} <: AbstractProcessDefinition where {
INT<:Tuple,OUTT<:Tuple,INSP<:Tuple,OUTSP<:Tuple
}
incoming_particles::INT incoming_particles::INT
outgoing_particles::OUTT outgoing_particles::OUTT
function GenericQEDProcess(in_particles::INT, out_particles::OUTT) where {INT<:Tuple,OUTT<:Tuple} incoming_spins_pols::INSP
outgoing_spins_pols::OUTSP
virtual_particles_cache::Vector
function GenericQEDProcess(
in_particles::INT, out_particles::OUTT, in_sp::INSP, out_sp::OUTSP
) where {INT<:Tuple,OUTT<:Tuple,INSP<:Tuple,OUTSP<:Tuple}
_assert_particle_type_tuple(in_particles) _assert_particle_type_tuple(in_particles)
_assert_particle_type_tuple(out_particles) _assert_particle_type_tuple(out_particles)
return new{INT,OUTT}(in_particles, out_particles) return new{INT,OUTT,INSP,OUTSP}(in_particles, out_particles, in_sp, out_sp, [])
end end
""" """
GenericQEDProcess(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.
""" """
function GenericQEDProcess(in_ph::Int, out_ph::Int, in_el::Int, out_el::Int, in_po::Int, out_po::Int) function GenericQEDProcess(
in_p = ntuple(i -> i <= in_ph ? Photon() : i <= in_ph + in_el ? Electron() : Positron(), in_ph + in_el + in_po) in_ph::Int, out_ph::Int, in_el::Int, out_el::Int, in_po::Int, out_po::Int
out_p = ntuple(i -> i <= out_ph ? Photon() : i <= out_ph + out_el ? Electron() : Positron(), out_ph + out_el + out_po) )
return GenericQEDProcess(in_p, out_p) in_p = ntuple(i -> if i <= in_ph
Photon()
elseif i <= in_ph + in_el
Electron()
else
Positron()
end, in_ph + in_el + in_po)
out_p = ntuple(i -> if i <= out_ph
Photon()
elseif i <= out_ph + out_el
Electron()
else
Positron()
end, out_ph + out_el + out_po)
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)]...)
return GenericQEDProcess(in_p, out_p, in_sp, out_sp)
end end
end end
QEDprocesses.incoming_particles(proc::GenericQEDProcess{INT,OUTT}) where {INT,OUTT} = proc.incoming_particles function spin_or_pol(
QEDprocesses.outgoing_particles(proc::GenericQEDProcess{INT,OUTT}) where {INT,OUTT} = proc.outgoing_particles process::GenericQEDProcess,
dir::ParticleDirection,
species::AbstractParticleType,
n::Int,
)
i = 0
c = n
for p in particles(process, dir)
i += 1
if p == species
c -= 1
end
if c == 0
break
end
end
if c != 0 || n <= 0
throw(
InvalidInputError(
"could not get $n-th spin/pol of $dir $species, does not exist"
),
)
end
if is_incoming(dir)
return process.incoming_spins_pols[i]
elseif is_outgoing(dir)
return process.outgoing_spins_pols[i]
else
throw(InvalidInputError("unknown direction $(dir) given"))
end
end
function QEDprocesses.incoming_particles(proc::GenericQEDProcess{INT,OUTT}) where {INT,OUTT}
return proc.incoming_particles
end
function QEDprocesses.outgoing_particles(proc::GenericQEDProcess{INT,OUTT}) where {INT,OUTT}
return proc.outgoing_particles
end
function isphysical(proc::GenericQEDProcess) function isphysical(proc::GenericQEDProcess)
return (number_particles(proc, Incoming(), Electron()) + number_particles(proc, Outgoing(), Positron()) == return (
number_particles(proc, Incoming(), Positron()) + number_particles(proc, Outgoing(), Electron())) && number_particles(proc, Incoming(), Electron()) +
number_particles(proc, Incoming()) + number_particles(proc, Outgoing()) >= 2 number_particles(proc, Outgoing(), Positron()) ==
number_particles(proc, Incoming(), Positron()) +
number_particles(proc, Outgoing(), Electron())
) && number_particles(proc, Incoming()) + number_particles(proc, Outgoing()) >= 2
end end
function matrix_element(proc::GenericQEDProcess, psp::PhaseSpacePoint) function matrix_element(proc::GenericQEDProcess, psp::PhaseSpacePoint)
return nothing return nothing
end end

View File

@ -7,7 +7,15 @@ struct ComputeTask_Triple <: AbstractComputeTask end # from a triple
struct ComputeTask_CollectTriples <: AbstractComputeTask end # sum over triples results and struct ComputeTask_CollectTriples <: AbstractComputeTask end # sum over triples results and
# 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 import MetagraphOptimization: compute, compute_effort
compute_effort(::ComputeTask_BaseState) = 0
compute_effort(::ComputeTask_Propagator) = 0
compute_effort(::ComputeTask_Pair) = 0
compute_effort(::ComputeTask_CollectPairs) = 0
compute_effort(::ComputeTask_PropagatePairs) = 0
compute_effort(::ComputeTask_Triple) = 0
compute_effort(::ComputeTask_CollectTriples) = 0
struct BaseStateInput{PS_T<:AbstractParticleStateful,SPIN_POL_T<:AbstractSpinOrPolarization} struct BaseStateInput{PS_T<:AbstractParticleStateful,SPIN_POL_T<:AbstractSpinOrPolarization}
particle::PS_T particle::PS_T

View File

@ -1,19 +1,264 @@
using MetagraphOptimization: insert_node!, insert_edge!, make_node, make_edge
function generate_DAG(proc::GenericQEDProcess) _construction_string(::Incoming) = "Incoming()"
# use a set for deduplication _construction_string(::Outgoing) = "Outgoing()"
particles = Set()
for fd in feynman_diagrams(proc) _construction_string(::Electron) = "Electron()"
push!(all_particles, virtual_particles(proc, fd)...) _construction_string(::Positron) = "Positron()"
_construction_string(::Photon) = "Photon()"
_construction_string(::PolX) = "PolX()"
_construction_string(::PolY) = "PolY()"
_construction_string(::SpinUp) = "SpinUp()"
_construction_string(::SpinDown) = "SpinDown()"
function _parse_particle(name::String)
local dir
if startswith(name, "inc_")
dir = Incoming()
elseif startswith(name, "out_")
dir = Outgoing()
else
throw(InvalidInputError("failed to parse particle direction from \"$name\""))
end end
# convert to vector name = name[4:end]
particles = [particles...]
external_particles = _pseudo_virtual_particles(proc) local species
pairs = particle_pairs(particles) if startswith(name, "el")
triples = total_particle_triples(particles) species = Electron()
elseif startswith(name, "ph")
species = Photon()
elseif startswith(name, "po")
species = Positron()
else
throw(InvalidInputError("failed to parse particle species from name \"$name\""))
end
name = name[3:end]
local spin_pol
if startswith(name, "su")
spin_pol = SpinUp()
elseif startswith(name, "sd")
spin_pol = SpinDown()
elseif startswith(name, "px")
spin_pol = PolX()
elseif startswith(name, "py")
spin_pol = PolY()
else
throw(
InvalidInputError(
"failed to parse particle spin or polarization from \"$name\""
),
)
end
name = name[3:end]
index = parse(Int, name)
return (dir, species, spin_pol, index)
end
function input_expr(instance::GenericQEDProcess, name::String, psp_symbol::Symbol)
if startswith(name, "bs_")
(dir, species, spin_pol, index) = _parse_particle(name[4:end])
dir_str = _construction_string(dir)
species_str = _construction_string(species)
sp_str = _construction_string(spin_pol)
return Meta.parse(
"BaseStateInput(
ParticleStateful($dir_str, $species_str, momentum($psp_symbol, $dir_str, $species_str, $index)),
$sp_str,
)",
)
elseif startswith(name, "pr_")
index = parse(Int, name[4:end]) # get index of the virtual particle in the process
vp = virtual_particles(proc)[index]
return Meta.parse("PropagatorInput(
VirtualParticle(
process($psp_symbol),
$species_str,
$(vp.in_particle_contributions),
$(vp.out_particle_contributions)
),
$psp_symbol
)")
else
throw(InvalidInputError("failed to parse node name \"$name\""))
end
end
_species_str(::Photon) = "ph"
_species_str(::Electron) = "el"
_species_str(::Positron) = "po"
_spin_pol_str(::SpinUp) = "su"
_spin_pol_str(::SpinDown) = "sd"
_spin_pol_str(::PolX) = "px"
_spin_pol_str(::PolY) = "py"
_dir_str(::Incoming) = "inc"
_dir_str(::Outgoing) = "out"
_spin_pols(::AllSpin) = (SpinUp(), SpinDown())
_spin_pols(::SpinUp) = (SpinUp(),)
_spin_pols(::SpinDown) = (SpinDown(),)
_spin_pols(::AllPol) = (PolX(), PolY())
_spin_pols(::PolX) = (PolX(),)
_spin_pols(::PolY) = (PolY(),)
_is_external(p::VirtualParticle) = number_contributions(p) == 1
function _base_state_name(p::VirtualParticle)
proc = process(p)
dir = sum(in_contributions(p)) == 1 ? Incoming() : Outgoing()
# find particle in the contributions
index = 0
contribs = is_incoming(dir) ? in_contributions(p) : out_contributions(p)
for p in particles(proc, dir)
index += 1
if contribs[index]
break
end
end
species = particles(proc, dir)[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)
return string.(
"bs_$(_dir_str(dir))_$(_species_str(species))_",
_spin_pol_str.(_spin_pols(spin_pol)),
"_$(species_index)",
)
end
function generate_DAG(proc::GenericQEDProcess)
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
pairs = particle_pairs(particles) # pairs to generate the pair tasks
triples = total_particle_triples(particles) # triples to generate the triple tasks
graph = DAG() graph = DAG()
# -- Base State Tasks --
base_state_task_outputs = Dict()
for dir in (Incoming(), Outgoing())
for species in (Electron(), Positron(), Photon())
for index in 1:number_particles(proc, dir, species)
for spin_pol in _spin_pols(spin_or_pol(proc, dir, species, index))
# gen entry nodes
# names are "bs_<dir>_<species>_<spin/pol>_<index>"
data_node_name = "bs_$(_dir_str(dir))_$(_species_str(species))_$(_spin_pol_str(spin_pol))_$(index)"
data_in = insert_node!(
graph,
make_node(DataTask(0), data_node_name);
track=false,
invalidate_cache=false,
)
# generate initial base_state tasks
compute_base_state = insert_node!(
graph,
make_node(ComputeTask_BaseState());
track=false,
invalidate_cache=false,
)
data_out = insert_node!(
graph, make_node(DataTask(0)); track=false, invalidate_cache=false
)
insert_edge!(graph, data_in, compute_base_state)
insert_edge!(graph, compute_base_state, data_out)
base_state_task_outputs[data_node_name] = data_out
end
end
end
end
# -- Propagator Tasks --
propagator_task_outputs = Dict()
vp_index = 0
for vp in virtual_particles(proc)
vp_index += 1
data_node_name = "pr_$vp_index"
data_in = insert_node!(
graph, make_node(DataTask(0)); track=false, invalidate_cache=false
)
compute_vp_propagator = insert_node!(
graph, make_node(ComputeTask_Propagator()); track=false, invalidate_cache=false
)
data_out = insert_node!(
graph, make_node(DataTask(0)); track=false, invalidate_cache=false
)
insert_edge!(graph, data_in, compute_vp_propagator)
insert_edge!(graph, compute_vp_propagator, data_out)
propagator_task_outputs[data_node_name] = data_out
end
# -- Pair Tasks --
pair_task_outputs = Dict()
for (product_particle, input_particle_vector) in pairs
# for all spins/pols of particles in product_particles do ...
pair_task_outputs[product_particle] = Vector()
for input_particles in input_particle_vector
particles_data_out_nodes = (Vector(), Vector())
c = 0
for p in input_particles
c += 1
if (is_external(p))
# grab from base_states (broadcast over _base_state_name because it is a tuple for different spin_pols)
push!.(
Ref(particles_data_out_nodes[c]),
getindex.(Ref(base_state_task_outputs), _base_state_name(p)),
)
else
# grab from propagated particles
push!(particles_date_out_nodes[c], pair_task_outputs[p])
end
end
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
#insert_node!(graph, )
end end
# make the collect pair and propagate nodes
end
data_out_propagated = insert_node!(
graph, make_node(DataTask(0)); track=false, invalidate_caches=false
)
pair_task_outputs[p] = data_out_propagated
# ... end do
end
return graph
end