Add scheduling, machine info, caching strategies and devices (#9)
Reviewed-on: Rubydragon/MetagraphOptimization.jl#9 Co-authored-by: Anton Reinhard <anton.reinhard@proton.me> Co-committed-by: Anton Reinhard <anton.reinhard@proton.me>
This commit is contained in:
@@ -45,6 +45,12 @@ For valid inputs, both input particles should have the same momenta at this poin
|
||||
12 FLOP.
|
||||
"""
|
||||
function compute(::ComputeTaskS2, data1::ParticleValue, data2::ParticleValue)
|
||||
#=
|
||||
@assert isapprox(abs(data1.p.momentum.E), abs(data2.p.momentum.E), rtol = 0.001, atol = sqrt(eps())) "E: $(data1.p.momentum.E) vs. $(data2.p.momentum.E)"
|
||||
@assert isapprox(data1.p.momentum.px, -data2.p.momentum.px, rtol = 0.001, atol = sqrt(eps())) "px: $(data1.p.momentum.px) vs. $(data2.p.momentum.px)"
|
||||
@assert isapprox(data1.p.momentum.py, -data2.p.momentum.py, rtol = 0.001, atol = sqrt(eps())) "py: $(data1.p.momentum.py) vs. $(data2.p.momentum.py)"
|
||||
@assert isapprox(data1.p.momentum.pz, -data2.p.momentum.pz, rtol = 0.001, atol = sqrt(eps())) "pz: $(data1.p.momentum.pz) vs. $(data2.p.momentum.pz)"
|
||||
=#
|
||||
return data1.v * inner_edge(data1.p) * data2.v
|
||||
end
|
||||
|
||||
@@ -71,186 +77,78 @@ function compute(::ComputeTaskSum, data::Vector{Float64})
|
||||
end
|
||||
|
||||
"""
|
||||
compute(t::FusedComputeTask, data)
|
||||
get_expression(::ComputeTaskP, device::AbstractDevice, inExprs::Vector{Expr}, outExpr::Expr)
|
||||
|
||||
Compute a [`FusedComputeTask`](@ref). This simply asserts false and should not be called. Fused Compute Tasks generate their expressions directly through the other tasks instead.
|
||||
Generate and return code evaluating [`ComputeTaskP`](@ref) on `inSyms`, providing the output on `outSym`.
|
||||
"""
|
||||
function compute(t::FusedComputeTask, data)
|
||||
@assert false "This is not implemented and should never be called"
|
||||
function get_expression(::ComputeTaskP, device::AbstractDevice, inExprs::Vector, outExpr)
|
||||
in = [eval(inExprs[1])]
|
||||
out = eval(outExpr)
|
||||
|
||||
return Meta.parse("$out = compute(ComputeTaskP(), $(in[1]))")
|
||||
end
|
||||
|
||||
"""
|
||||
get_expression(::ComputeTaskP, inSymbol::Symbol, outSymbol::Symbol)
|
||||
get_expression(::ComputeTaskU, device::AbstractDevice, inExprs::Vector{Expr}, outExpr::Expr)
|
||||
|
||||
Generate and return code evaluating [`ComputeTaskP`](@ref) on `inSymbol`, providing the output on `outSymbol`.
|
||||
Generate code evaluating [`ComputeTaskU`](@ref) on `inSyms`, providing the output on `outSym`.
|
||||
`inSyms` should be of type [`ParticleValue`](@ref), `outSym` will be of type [`ParticleValue`](@ref).
|
||||
"""
|
||||
function get_expression(::ComputeTaskP, inSymbol::Symbol, outSymbol::Symbol)
|
||||
return Meta.parse("$outSymbol = compute(ComputeTaskP(), $inSymbol)")
|
||||
function get_expression(::ComputeTaskU, device::AbstractDevice, inExprs::Vector, outExpr)
|
||||
in = [eval(inExprs[1])]
|
||||
out = eval(outExpr)
|
||||
|
||||
return Meta.parse("$out = compute(ComputeTaskU(), $(in[1]))")
|
||||
end
|
||||
|
||||
"""
|
||||
get_expression(::ComputeTaskU, inSymbol::Symbol, outSymbol::Symbol)
|
||||
get_expression(::ComputeTaskV, device::AbstractDevice, inExprs::Vector{Expr}, outExpr::Expr)
|
||||
|
||||
Generate code evaluating [`ComputeTaskU`](@ref) on `inSymbol`, providing the output on `outSymbol`.
|
||||
`inSymbol` should be of type [`ParticleValue`](@ref), `outSymbol` will be of type [`ParticleValue`](@ref).
|
||||
Generate code evaluating [`ComputeTaskV`](@ref) on `inSyms`, providing the output on `outSym`.
|
||||
`inSym[1]` and `inSym[2]` should be of type [`ParticleValue`](@ref), `outSym` will be of type [`ParticleValue`](@ref).
|
||||
"""
|
||||
function get_expression(::ComputeTaskU, inSymbol::Symbol, outSymbol::Symbol)
|
||||
return Meta.parse("$outSymbol = compute(ComputeTaskU(), $inSymbol)")
|
||||
function get_expression(::ComputeTaskV, device::AbstractDevice, inExprs::Vector, outExpr)
|
||||
in = [eval(inExprs[1]), eval(inExprs[2])]
|
||||
out = eval(outExpr)
|
||||
|
||||
return Meta.parse("$out = compute(ComputeTaskV(), $(in[1]), $(in[2]))")
|
||||
end
|
||||
|
||||
"""
|
||||
get_expression(::ComputeTaskV, inSymbol1::Symbol, inSymbol2::Symbol, outSymbol::Symbol)
|
||||
get_expression(::ComputeTaskS2, device::AbstractDevice, inExprs::Vector{Expr}, outExpr::Expr)
|
||||
|
||||
Generate code evaluating [`ComputeTaskV`](@ref) on `inSymbol1` and `inSymbol2`, providing the output on `outSymbol`.
|
||||
`inSymbol1` and `inSymbol2` should be of type [`ParticleValue`](@ref), `outSymbol` will be of type [`ParticleValue`](@ref).
|
||||
Generate code evaluating [`ComputeTaskS2`](@ref) on `inSyms`, providing the output on `outSym`.
|
||||
`inSyms[1]` and `inSyms[2]` should be of type [`ParticleValue`](@ref), `outSym` will be of type `Float64`.
|
||||
"""
|
||||
function get_expression(
|
||||
::ComputeTaskV,
|
||||
inSymbol1::Symbol,
|
||||
inSymbol2::Symbol,
|
||||
outSymbol::Symbol,
|
||||
)
|
||||
return Meta.parse(
|
||||
"$outSymbol = compute(ComputeTaskV(), $inSymbol1, $inSymbol2)",
|
||||
)
|
||||
function get_expression(::ComputeTaskS2, device::AbstractDevice, inExprs::Vector, outExpr)
|
||||
in = [eval(inExprs[1]), eval(inExprs[2])]
|
||||
out = eval(outExpr)
|
||||
|
||||
return Meta.parse("$out = compute(ComputeTaskS2(), $(in[1]), $(in[2]))")
|
||||
end
|
||||
|
||||
"""
|
||||
get_expression(::ComputeTaskS2, inSymbol1::Symbol, inSymbol2::Symbol, outSymbol::Symbol)
|
||||
get_expression(::ComputeTaskS1, device::AbstractDevice, inExprs::Vector{Expr}, outExpr::Expr)
|
||||
|
||||
Generate code evaluating [`ComputeTaskS2`](@ref) on `inSymbol1` and `inSymbol2`, providing the output on `outSymbol`.
|
||||
`inSymbol1` and `inSymbol2` should be of type [`ParticleValue`](@ref), `outSymbol` will be of type `Float64`.
|
||||
Generate code evaluating [`ComputeTaskS1`](@ref) on `inSyms`, providing the output on `outSym`.
|
||||
`inSyms` should be of type [`ParticleValue`](@ref), `outSym` will be of type [`ParticleValue`](@ref).
|
||||
"""
|
||||
function get_expression(
|
||||
::ComputeTaskS2,
|
||||
inSymbol1::Symbol,
|
||||
inSymbol2::Symbol,
|
||||
outSymbol::Symbol,
|
||||
)
|
||||
return Meta.parse(
|
||||
"$outSymbol = compute(ComputeTaskS2(), $inSymbol1, $inSymbol2)",
|
||||
)
|
||||
function get_expression(::ComputeTaskS1, device::AbstractDevice, inExprs::Vector, outExpr)
|
||||
in = [eval(inExprs[1])]
|
||||
out = eval(outExpr)
|
||||
|
||||
return Meta.parse("$out = compute(ComputeTaskS1(), $(in[1]))")
|
||||
end
|
||||
|
||||
"""
|
||||
get_expression(::ComputeTaskS1, inSymbol::Symbol, outSymbol::Symbol)
|
||||
get_expression(::ComputeTaskSum, device::AbstractDevice, inExprs::Vector{Expr}, outExpr::Expr)
|
||||
|
||||
Generate code evaluating [`ComputeTaskS1`](@ref) on `inSymbol`, providing the output on `outSymbol`.
|
||||
`inSymbol` should be of type [`ParticleValue`](@ref), `outSymbol` will be of type [`ParticleValue`](@ref).
|
||||
Generate code evaluating [`ComputeTaskSum`](@ref) on `inSyms`, providing the output on `outSym`.
|
||||
`inSyms` should be of type [`Float64`], `outSym` will be of type [`Float64`].
|
||||
"""
|
||||
function get_expression(::ComputeTaskS1, inSymbol::Symbol, outSymbol::Symbol)
|
||||
return Meta.parse("$outSymbol = compute(ComputeTaskS1(), $inSymbol)")
|
||||
end
|
||||
|
||||
"""
|
||||
get_expression(::ComputeTaskSum, inSymbols::Vector{Symbol}, outSymbol::Symbol)
|
||||
|
||||
Generate code evaluating [`ComputeTaskSum`](@ref) on `inSymbols`, providing the output on `outSymbol`.
|
||||
`inSymbols` should be of type [`Float64`], `outSymbol` will be of type [`Float64`].
|
||||
"""
|
||||
function get_expression(
|
||||
::ComputeTaskSum,
|
||||
inSymbols::Vector{Symbol},
|
||||
outSymbol::Symbol,
|
||||
)
|
||||
return quote
|
||||
$outSymbol = compute(ComputeTaskSum(), [$(inSymbols...)])
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
get_expression(t::FusedComputeTask, inSymbols::Vector{Symbol}, outSymbol::Symbol)
|
||||
|
||||
Generate code evaluating a [`FusedComputeTask`](@ref) on `inSymbols`, providing the output on `outSymbol`.
|
||||
`inSymbols` should be of the correct types and may be heterogeneous. `outSymbol` will be of the type of the output of `T2` of t.
|
||||
"""
|
||||
function get_expression(
|
||||
t::FusedComputeTask,
|
||||
inSymbols::Vector{Symbol},
|
||||
outSymbol::Symbol,
|
||||
)
|
||||
(T1, T2) = get_types(t)
|
||||
c1 = children(T1())
|
||||
c2 = children(T2())
|
||||
|
||||
expr1 = nothing
|
||||
expr2 = nothing
|
||||
|
||||
# TODO need to figure out how to know which inputs belong to which subtask
|
||||
# since we order the vectors with the child nodes we can't just split
|
||||
if (c1 == 1)
|
||||
expr1 = get_expression(T1(), inSymbols[begin], :intermediate)
|
||||
elseif (c1 == 2)
|
||||
expr1 =
|
||||
get_expression(T1(), inSymbols[begin], inSymbols[2], :intermediate)
|
||||
else
|
||||
expr1 = get_expression(T1(), inSymbols[begin:c1], :intermediate)
|
||||
end
|
||||
|
||||
if (c2 == 1)
|
||||
expr2 = get_expression(T2(), :intermediate, outSymbol)
|
||||
elseif c2 == 2
|
||||
expr2 =
|
||||
get_expression(T2(), :intermediate, inSymbols[c1 + 1], outSymbol)
|
||||
else
|
||||
expr2 = get_expression(
|
||||
T2(),
|
||||
:intermediate * inSymbols[(c1 + 1):end],
|
||||
outSymbol,
|
||||
)
|
||||
end
|
||||
|
||||
return Expr(:block, expr1, expr2)
|
||||
end
|
||||
|
||||
"""
|
||||
get_expression(node::ComputeTaskNode)
|
||||
|
||||
Generate and return code for a given [`ComputeTaskNode`](@ref).
|
||||
"""
|
||||
function get_expression(node::ComputeTaskNode)
|
||||
t = typeof(node.task)
|
||||
@assert length(node.children) == children(node.task) || t <: ComputeTaskSum
|
||||
|
||||
if (t <: ComputeTaskU || t <: ComputeTaskP || t <: ComputeTaskS1) # single input
|
||||
symbolIn = Symbol("data_$(to_var_name(node.children[1].id))")
|
||||
symbolOut = Symbol("data_$(to_var_name(node.id))")
|
||||
return get_expression(t(), symbolIn, symbolOut)
|
||||
elseif (t <: ComputeTaskS2 || t <: ComputeTaskV) # double input
|
||||
symbolIn1 = Symbol("data_$(to_var_name(node.children[1].id))")
|
||||
symbolIn2 = Symbol("data_$(to_var_name(node.children[2].id))")
|
||||
symbolOut = Symbol("data_$(to_var_name(node.id))")
|
||||
return get_expression(t(), symbolIn1, symbolIn2, symbolOut)
|
||||
elseif (t <: ComputeTaskSum || t <: FusedComputeTask) # vector input
|
||||
inSymbols = Vector{Symbol}()
|
||||
for child in node.children
|
||||
push!(inSymbols, Symbol("data_$(to_var_name(child.id))"))
|
||||
end
|
||||
outSymbol = Symbol("data_$(to_var_name(node.id))")
|
||||
return get_expression(t(), inSymbols, outSymbol)
|
||||
else
|
||||
error("Unknown compute task")
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
get_expression(node::DataTaskNode)
|
||||
|
||||
Generate and return code for a given [`DataTaskNode`](@ref).
|
||||
"""
|
||||
function get_expression(node::DataTaskNode)
|
||||
# TODO: do things to transport data from/to gpu, between numa nodes, etc.
|
||||
@assert length(node.children) <= 1
|
||||
|
||||
inSymbol = nothing
|
||||
if (length(node.children) == 1)
|
||||
inSymbol = Symbol("data_$(to_var_name(node.children[1].id))")
|
||||
else
|
||||
inSymbol = Symbol("data_$(to_var_name(node.id))_in")
|
||||
end
|
||||
outSymbol = Symbol("data_$(to_var_name(node.id))")
|
||||
|
||||
dataTransportExp = Meta.parse("$outSymbol = $inSymbol")
|
||||
|
||||
return dataTransportExp
|
||||
function get_expression(::ComputeTaskSum, device::AbstractDevice, inExprs::Vector, outExpr)
|
||||
in = eval.(inExprs)
|
||||
out = eval(outExpr)
|
||||
|
||||
return Meta.parse("$out = compute(ComputeTaskSum(), [$(unroll_symbol_vector(in))])")
|
||||
end
|
||||
|
@@ -1,74 +1,198 @@
|
||||
using QEDbase
|
||||
using Random
|
||||
using Roots
|
||||
using ForwardDiff
|
||||
|
||||
ComputeTaskSum() = ComputeTaskSum(0)
|
||||
|
||||
"""
|
||||
Particle(rng)
|
||||
gen_process_input(processDescription::ABCProcessDescription)
|
||||
|
||||
Return a randomly generated particle.
|
||||
Return a ProcessInput of randomly generated [`ABCParticle`](@ref)s from a [`ABCProcessDescription`](@ref). The process description can be created manually or parsed from a string using [`parse_process`](@ref).
|
||||
|
||||
Note: This uses RAMBO to create a valid process with conservation of momentum and energy.
|
||||
"""
|
||||
function Particle(rng, type::ParticleType)
|
||||
function gen_process_input(processDescription::ABCProcessDescription)
|
||||
inParticleTypes = keys(processDescription.inParticles)
|
||||
outParticleTypes = keys(processDescription.outParticles)
|
||||
|
||||
p1 = rand(rng, Float64)
|
||||
p2 = rand(rng, Float64)
|
||||
p3 = rand(rng, Float64)
|
||||
m = mass(type)
|
||||
|
||||
# keep the momenta of the particles on-shell
|
||||
p4 = sqrt(p1^2 + p2^2 + p3^2 + m^2)
|
||||
|
||||
return Particle(p1, p2, p3, p4, type)
|
||||
end
|
||||
|
||||
"""
|
||||
gen_particles(n::Int)
|
||||
|
||||
Return a Vector of `n` randomly generated [`Particle`](@ref)s.
|
||||
|
||||
Note: This does not take into account the preservation of momenta required for an actual valid process!
|
||||
"""
|
||||
function gen_particles(ns::Dict{ParticleType, Int})
|
||||
particles = Dict{ParticleType, Vector{Particle}}()
|
||||
rng = MersenneTwister(0)
|
||||
|
||||
|
||||
if ns == Dict((A => 2), (B => 2))
|
||||
rho = 1.0
|
||||
|
||||
omega = rand(rng, Float64)
|
||||
theta = rand(rng, Float64) * π
|
||||
phi = rand(rng, Float64) * π
|
||||
|
||||
particles[A] = Vector{Particle}()
|
||||
particles[B] = Vector{Particle}()
|
||||
|
||||
push!(particles[A], Particle(omega, 0, 0, omega, A))
|
||||
push!(particles[B], Particle(omega, 0, 0, -omega, B))
|
||||
push!(
|
||||
particles[A],
|
||||
Particle(
|
||||
omega,
|
||||
rho * cos(theta) * cos(phi),
|
||||
rho * cos(theta) * sin(phi),
|
||||
rho * sin(theta),
|
||||
A,
|
||||
),
|
||||
)
|
||||
push!(
|
||||
particles[B],
|
||||
Particle(
|
||||
omega,
|
||||
-rho * cos(theta) * cos(phi),
|
||||
-rho * cos(theta) * sin(phi),
|
||||
-rho * sin(theta),
|
||||
B,
|
||||
),
|
||||
)
|
||||
return particles
|
||||
end
|
||||
|
||||
for (type, n) in ns
|
||||
particles[type] = Vector{Particle}()
|
||||
for i in 1:n
|
||||
push!(particles[type], Particle(rng, type))
|
||||
massSum = 0
|
||||
inputMasses = Vector{Float64}()
|
||||
for (particle, n) in processDescription.inParticles
|
||||
for _ in 1:n
|
||||
massSum += mass(particle)
|
||||
push!(inputMasses, mass(particle))
|
||||
end
|
||||
end
|
||||
return particles
|
||||
outputMasses = Vector{Float64}()
|
||||
for (particle, n) in processDescription.outParticles
|
||||
for _ in 1:n
|
||||
massSum += mass(particle)
|
||||
push!(outputMasses, mass(particle))
|
||||
end
|
||||
end
|
||||
|
||||
# add some extra random mass to allow for some momentum
|
||||
massSum += rand(rng[threadid()]) * (length(inputMasses) + length(outputMasses))
|
||||
|
||||
|
||||
inputParticles = Vector{ABCParticle}()
|
||||
initialMomenta = generate_initial_moms(massSum, inputMasses)
|
||||
index = 1
|
||||
for (particle, n) in processDescription.inParticles
|
||||
for _ in 1:n
|
||||
mom = initialMomenta[index]
|
||||
push!(inputParticles, particle(mom))
|
||||
index += 1
|
||||
end
|
||||
end
|
||||
|
||||
outputParticles = Vector{ABCParticle}()
|
||||
final_momenta = generate_physical_massive_moms(rng[threadid()], massSum, outputMasses)
|
||||
index = 1
|
||||
for (particle, n) in processDescription.outParticles
|
||||
for _ in 1:n
|
||||
mom = final_momenta[index]
|
||||
push!(outputParticles, particle(SFourMomentum(-mom.E, mom.px, mom.py, mom.pz)))
|
||||
index += 1
|
||||
end
|
||||
end
|
||||
|
||||
processInput = ABCProcessInput(processDescription, inputParticles, outputParticles)
|
||||
|
||||
return return processInput
|
||||
end
|
||||
|
||||
####################
|
||||
# CODE FROM HERE BORROWED FROM SOURCE: https://codebase.helmholtz.cloud/qedsandbox/QEDphasespaces.jl/
|
||||
# use qedphasespaces directly once released
|
||||
#
|
||||
# quick and dirty implementation of the RAMBO algorithm
|
||||
#
|
||||
# reference:
|
||||
# * https://cds.cern.ch/record/164736/files/198601282.pdf
|
||||
# * https://www.sciencedirect.com/science/article/pii/0010465586901190
|
||||
####################
|
||||
|
||||
function generate_initial_moms(ss, masses)
|
||||
E1 = (ss^2 + masses[1]^2 - masses[2]^2) / (2 * ss)
|
||||
E2 = (ss^2 + masses[2]^2 - masses[1]^2) / (2 * ss)
|
||||
|
||||
rho1 = sqrt(E1^2 - masses[1]^2)
|
||||
rho2 = sqrt(E2^2 - masses[2]^2)
|
||||
|
||||
return [SFourMomentum(E1, 0, 0, rho1), SFourMomentum(E2, 0, 0, -rho2)]
|
||||
end
|
||||
|
||||
|
||||
Random.rand(rng::AbstractRNG, ::Random.SamplerType{SFourMomentum}) = SFourMomentum(rand(rng, 4))
|
||||
Random.rand(rng::AbstractRNG, ::Random.SamplerType{NTuple{N, Float64}}) where {N} = Tuple(rand(rng, N))
|
||||
|
||||
|
||||
function _transform_uni_to_mom(u1, u2, u3, u4)
|
||||
cth = 2 * u1 - 1
|
||||
sth = sqrt(1 - cth^2)
|
||||
phi = 2 * pi * u2
|
||||
q0 = -log(u3 * u4)
|
||||
qx = q0 * sth * cos(phi)
|
||||
qy = q0 * sth * sin(phi)
|
||||
qz = q0 * cth
|
||||
|
||||
return SFourMomentum(q0, qx, qy, qz)
|
||||
end
|
||||
|
||||
function _transform_uni_to_mom!(uni_mom, dest)
|
||||
u1, u2, u3, u4 = Tuple(uni_mom)
|
||||
cth = 2 * u1 - 1
|
||||
sth = sqrt(1 - cth^2)
|
||||
phi = 2 * pi * u2
|
||||
q0 = -log(u3 * u4)
|
||||
qx = q0 * sth * cos(phi)
|
||||
qy = q0 * sth * sin(phi)
|
||||
qz = q0 * cth
|
||||
|
||||
return dest = SFourMomentum(q0, qx, qy, qz)
|
||||
end
|
||||
|
||||
_transform_uni_to_mom(u1234::Tuple) = _transform_uni_to_mom(u1234...)
|
||||
_transform_uni_to_mom(u1234::SFourMomentum) = _transform_uni_to_mom(Tuple(u1234))
|
||||
|
||||
function generate_massless_moms(rng, n::Int)
|
||||
a = Vector{SFourMomentum}(undef, n)
|
||||
rand!(rng, a)
|
||||
return map(_transform_uni_to_mom, a)
|
||||
end
|
||||
|
||||
function generate_physical_massless_moms(rng, ss, n)
|
||||
r_moms = generate_massless_moms(rng, n)
|
||||
Q = sum(r_moms)
|
||||
M = sqrt(Q * Q)
|
||||
fac = -1 / M
|
||||
Qx = getX(Q)
|
||||
Qy = getY(Q)
|
||||
Qz = getZ(Q)
|
||||
bx = fac * Qx
|
||||
by = fac * Qy
|
||||
bz = fac * Qz
|
||||
gamma = getT(Q) / M
|
||||
a = 1 / (1 + gamma)
|
||||
x = ss / M
|
||||
|
||||
i = 1
|
||||
while i <= n
|
||||
mom = r_moms[i]
|
||||
mom0 = getT(mom)
|
||||
mom1 = getX(mom)
|
||||
mom2 = getY(mom)
|
||||
mom3 = getZ(mom)
|
||||
|
||||
bq = bx * mom1 + by * mom2 + bz * mom3
|
||||
|
||||
p0 = x * (gamma * mom0 + bq)
|
||||
px = x * (mom1 + bx * mom0 + a * bq * bx)
|
||||
py = x * (mom2 + by * mom0 + a * bq * by)
|
||||
pz = x * (mom3 + bz * mom0 + a * bq * bz)
|
||||
|
||||
r_moms[i] = SFourMomentum(p0, px, py, pz)
|
||||
i += 1
|
||||
end
|
||||
return r_moms
|
||||
end
|
||||
|
||||
function _to_be_solved(xi, masses, p0s, ss)
|
||||
sum = 0.0
|
||||
for (i, E) in enumerate(p0s)
|
||||
sum += sqrt(masses[i]^2 + xi^2 * E^2)
|
||||
end
|
||||
return sum - ss
|
||||
end
|
||||
|
||||
function _build_massive_momenta(xi, masses, massless_moms)
|
||||
vec = SFourMomentum[]
|
||||
i = 1
|
||||
while i <= length(massless_moms)
|
||||
massless_mom = massless_moms[i]
|
||||
k0 = sqrt(getT(massless_mom)^2 * xi^2 + masses[i]^2)
|
||||
|
||||
kx = xi * getX(massless_mom)
|
||||
ky = xi * getY(massless_mom)
|
||||
kz = xi * getZ(massless_mom)
|
||||
|
||||
push!(vec, SFourMomentum(k0, kx, ky, kz))
|
||||
|
||||
i += 1
|
||||
end
|
||||
return vec
|
||||
end
|
||||
|
||||
first_derivative(func) = x -> ForwardDiff.derivative(func, float(x))
|
||||
|
||||
|
||||
function generate_physical_massive_moms(rng, ss, masses; x0 = 0.1)
|
||||
n = length(masses)
|
||||
massless_moms = generate_physical_massless_moms(rng, ss, n)
|
||||
energies = getT.(massless_moms)
|
||||
f = x -> _to_be_solved(x, masses, energies, ss)
|
||||
xi = find_zero((f, first_derivative(f)), x0, Roots.Newton())
|
||||
return _build_massive_momenta(xi, masses, massless_moms)
|
||||
end
|
||||
|
@@ -32,13 +32,13 @@ function parse_edges(input::AbstractString)
|
||||
end
|
||||
|
||||
"""
|
||||
parse_abc(filename::String; verbose::Bool = false)
|
||||
parse_dag(filename::String, model::ABCModel; verbose::Bool = false)
|
||||
|
||||
Read an abc-model process from the given file. If `verbose` is set to true, print some progress information to stdout.
|
||||
|
||||
Returns a valid [`DAG`](@ref).
|
||||
"""
|
||||
function parse_abc(filename::String, verbose::Bool = false)
|
||||
function parse_dag(filename::AbstractString, model::ABCModel, verbose::Bool = false)
|
||||
file = open(filename, "r")
|
||||
|
||||
if (verbose)
|
||||
@@ -63,10 +63,9 @@ function parse_abc(filename::String, verbose::Bool = false)
|
||||
end
|
||||
sizehint!(graph.nodes, estimate_no_nodes)
|
||||
|
||||
sum_node = insert_node!(graph, make_node(ComputeTaskSum()), false, false)
|
||||
global_data_out =
|
||||
insert_node!(graph, make_node(DataTask(FLOAT_SIZE)), false, false)
|
||||
insert_edge!(graph, sum_node, global_data_out, false, false)
|
||||
sum_node = insert_node!(graph, make_node(ComputeTaskSum(0)), track = false, invalidate_cache = false)
|
||||
global_data_out = insert_node!(graph, make_node(DataTask(FLOAT_SIZE)), track = false, invalidate_cache = false)
|
||||
insert_edge!(graph, sum_node, global_data_out, track = false, invalidate_cache = false)
|
||||
|
||||
# remember the data out nodes for connection
|
||||
dataOutNodes = Dict()
|
||||
@@ -81,10 +80,7 @@ function parse_abc(filename::String, verbose::Bool = false)
|
||||
noNodes += 1
|
||||
if (noNodes % 100 == 0)
|
||||
if (verbose)
|
||||
percent = string(
|
||||
round(100.0 * noNodes / nodesToRead, digits = 2),
|
||||
"%",
|
||||
)
|
||||
percent = string(round(100.0 * noNodes / nodesToRead, digits = 2), "%")
|
||||
print("\rReading Nodes... $percent")
|
||||
end
|
||||
end
|
||||
@@ -93,30 +89,20 @@ function parse_abc(filename::String, verbose::Bool = false)
|
||||
data_in = insert_node!(
|
||||
graph,
|
||||
make_node(DataTask(PARTICLE_VALUE_SIZE), string(node)),
|
||||
false,
|
||||
false,
|
||||
track = false,
|
||||
invalidate_cache = false,
|
||||
) # read particle data node
|
||||
compute_P =
|
||||
insert_node!(graph, make_node(ComputeTaskP()), false, false) # compute P node
|
||||
data_Pu = insert_node!(
|
||||
graph,
|
||||
make_node(DataTask(PARTICLE_VALUE_SIZE)),
|
||||
false,
|
||||
false,
|
||||
) # transfer data from P to u (one ParticleValue object)
|
||||
compute_u =
|
||||
insert_node!(graph, make_node(ComputeTaskU()), false, false) # compute U node
|
||||
data_out = insert_node!(
|
||||
graph,
|
||||
make_node(DataTask(PARTICLE_VALUE_SIZE)),
|
||||
false,
|
||||
false,
|
||||
) # transfer data out from u (one ParticleValue object)
|
||||
compute_P = insert_node!(graph, make_node(ComputeTaskP()), track = false, invalidate_cache = false) # compute P node
|
||||
data_Pu =
|
||||
insert_node!(graph, make_node(DataTask(PARTICLE_VALUE_SIZE)), track = false, invalidate_cache = false) # transfer data from P to u (one ParticleValue object)
|
||||
compute_u = insert_node!(graph, make_node(ComputeTaskU()), track = false, invalidate_cache = false) # compute U node
|
||||
data_out =
|
||||
insert_node!(graph, make_node(DataTask(PARTICLE_VALUE_SIZE)), track = false, invalidate_cache = false) # transfer data out from u (one ParticleValue object)
|
||||
|
||||
insert_edge!(graph, data_in, compute_P, false, false)
|
||||
insert_edge!(graph, compute_P, data_Pu, false, false)
|
||||
insert_edge!(graph, data_Pu, compute_u, false, false)
|
||||
insert_edge!(graph, compute_u, data_out, false, false)
|
||||
insert_edge!(graph, data_in, compute_P, track = false, invalidate_cache = false)
|
||||
insert_edge!(graph, compute_P, data_Pu, track = false, invalidate_cache = false)
|
||||
insert_edge!(graph, data_Pu, compute_u, track = false, invalidate_cache = false)
|
||||
insert_edge!(graph, compute_u, data_out, track = false, invalidate_cache = false)
|
||||
|
||||
# remember the data_out node for future edges
|
||||
dataOutNodes[node] = data_out
|
||||
@@ -126,63 +112,48 @@ function parse_abc(filename::String, verbose::Bool = false)
|
||||
in1 = capt.captures[1]
|
||||
in2 = capt.captures[2]
|
||||
|
||||
compute_v =
|
||||
insert_node!(graph, make_node(ComputeTaskV()), false, false)
|
||||
data_out = insert_node!(
|
||||
graph,
|
||||
make_node(DataTask(PARTICLE_VALUE_SIZE)),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
compute_v = insert_node!(graph, make_node(ComputeTaskV()), track = false, invalidate_cache = false)
|
||||
data_out =
|
||||
insert_node!(graph, make_node(DataTask(PARTICLE_VALUE_SIZE)), track = false, invalidate_cache = false)
|
||||
|
||||
if (occursin(regex_c, in1))
|
||||
# put an S node after this input
|
||||
compute_S = insert_node!(
|
||||
graph,
|
||||
make_node(ComputeTaskS1()),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
compute_S = insert_node!(graph, make_node(ComputeTaskS1()), track = false, invalidate_cache = false)
|
||||
data_S_v = insert_node!(
|
||||
graph,
|
||||
make_node(DataTask(PARTICLE_VALUE_SIZE)),
|
||||
false,
|
||||
false,
|
||||
track = false,
|
||||
invalidate_cache = false,
|
||||
)
|
||||
|
||||
insert_edge!(graph, dataOutNodes[in1], compute_S, false, false)
|
||||
insert_edge!(graph, compute_S, data_S_v, false, false)
|
||||
insert_edge!(graph, dataOutNodes[in1], compute_S, track = false, invalidate_cache = false)
|
||||
insert_edge!(graph, compute_S, data_S_v, track = false, invalidate_cache = false)
|
||||
|
||||
insert_edge!(graph, data_S_v, compute_v, false, false)
|
||||
insert_edge!(graph, data_S_v, compute_v, track = false, invalidate_cache = false)
|
||||
else
|
||||
insert_edge!(graph, dataOutNodes[in1], compute_v, false, false)
|
||||
insert_edge!(graph, dataOutNodes[in1], compute_v, track = false, invalidate_cache = false)
|
||||
end
|
||||
|
||||
if (occursin(regex_c, in2))
|
||||
# i think the current generator only puts the combined particles in the first space, so this case might never be entered
|
||||
# put an S node after this input
|
||||
compute_S = insert_node!(
|
||||
graph,
|
||||
make_node(ComputeTaskS1()),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
compute_S = insert_node!(graph, make_node(ComputeTaskS1()), track = false, invalidate_cache = false)
|
||||
data_S_v = insert_node!(
|
||||
graph,
|
||||
make_node(DataTask(PARTICLE_VALUE_SIZE)),
|
||||
false,
|
||||
false,
|
||||
track = false,
|
||||
invalidate_cache = false,
|
||||
)
|
||||
|
||||
insert_edge!(graph, dataOutNodes[in2], compute_S, false, false)
|
||||
insert_edge!(graph, compute_S, data_S_v, false, false)
|
||||
insert_edge!(graph, dataOutNodes[in2], compute_S, track = false, invalidate_cache = false)
|
||||
insert_edge!(graph, compute_S, data_S_v, track = false, invalidate_cache = false)
|
||||
|
||||
insert_edge!(graph, data_S_v, compute_v, false, false)
|
||||
insert_edge!(graph, data_S_v, compute_v, track = false, invalidate_cache = false)
|
||||
else
|
||||
insert_edge!(graph, dataOutNodes[in2], compute_v, false, false)
|
||||
insert_edge!(graph, dataOutNodes[in2], compute_v, track = false, invalidate_cache = false)
|
||||
end
|
||||
|
||||
insert_edge!(graph, compute_v, data_out, false, false)
|
||||
insert_edge!(graph, compute_v, data_out, track = false, invalidate_cache = false)
|
||||
dataOutNodes[node] = data_out
|
||||
|
||||
elseif occursin(regex_m, node)
|
||||
@@ -193,43 +164,31 @@ function parse_abc(filename::String, verbose::Bool = false)
|
||||
in3 = capt.captures[3]
|
||||
|
||||
# in2 + in3 with a v
|
||||
compute_v =
|
||||
insert_node!(graph, make_node(ComputeTaskV()), false, false)
|
||||
data_v = insert_node!(
|
||||
graph,
|
||||
make_node(DataTask(PARTICLE_VALUE_SIZE)),
|
||||
false,
|
||||
false,
|
||||
)
|
||||
compute_v = insert_node!(graph, make_node(ComputeTaskV()), track = false, invalidate_cache = false)
|
||||
data_v =
|
||||
insert_node!(graph, make_node(DataTask(PARTICLE_VALUE_SIZE)), track = false, invalidate_cache = false)
|
||||
|
||||
insert_edge!(graph, dataOutNodes[in2], compute_v, false, false)
|
||||
insert_edge!(graph, dataOutNodes[in3], compute_v, false, false)
|
||||
insert_edge!(graph, compute_v, data_v, false, false)
|
||||
insert_edge!(graph, dataOutNodes[in2], compute_v, track = false, invalidate_cache = false)
|
||||
insert_edge!(graph, dataOutNodes[in3], compute_v, track = false, invalidate_cache = false)
|
||||
insert_edge!(graph, compute_v, data_v, track = false, invalidate_cache = false)
|
||||
|
||||
# combine with the v of the combined other input
|
||||
compute_S2 =
|
||||
insert_node!(graph, make_node(ComputeTaskS2()), false, false)
|
||||
data_out = insert_node!(
|
||||
graph,
|
||||
make_node(DataTask(FLOAT_SIZE)),
|
||||
false,
|
||||
false,
|
||||
) # output of a S2 task is only a float
|
||||
compute_S2 = insert_node!(graph, make_node(ComputeTaskS2()), track = false, invalidate_cache = false)
|
||||
data_out = insert_node!(graph, make_node(DataTask(FLOAT_SIZE)), track = false, invalidate_cache = false) # output of a S2 task is only a float
|
||||
|
||||
insert_edge!(graph, data_v, compute_S2, false, false)
|
||||
insert_edge!(graph, dataOutNodes[in1], compute_S2, false, false)
|
||||
insert_edge!(graph, compute_S2, data_out, false, false)
|
||||
insert_edge!(graph, data_v, compute_S2, track = false, invalidate_cache = false)
|
||||
insert_edge!(graph, dataOutNodes[in1], compute_S2, track = false, invalidate_cache = false)
|
||||
insert_edge!(graph, compute_S2, data_out, track = false, invalidate_cache = false)
|
||||
|
||||
insert_edge!(graph, data_out, sum_node, false, false)
|
||||
insert_edge!(graph, data_out, sum_node, track = false, invalidate_cache = false)
|
||||
add_child!(sum_node.task)
|
||||
elseif occursin(regex_plus, node)
|
||||
if (verbose)
|
||||
println("\rReading Nodes Complete ")
|
||||
println("Added ", length(graph.nodes), " nodes")
|
||||
end
|
||||
else
|
||||
@assert false (
|
||||
"Unknown node '$node' while reading from file $filename"
|
||||
)
|
||||
@assert false ("Unknown node '$node' while reading from file $filename")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -244,6 +203,46 @@ function parse_abc(filename::String, verbose::Bool = false)
|
||||
if (verbose)
|
||||
println("Done")
|
||||
end
|
||||
|
||||
# don't actually need to read the edges
|
||||
return graph
|
||||
end
|
||||
|
||||
"""
|
||||
parse_process(string::AbstractString, model::ABCModel)
|
||||
|
||||
Parse a string representation of a process, such as "AB->ABBB" into the corresponding [`ABCProcessDescription`](@ref).
|
||||
"""
|
||||
function parse_process(str::AbstractString, model::ABCModel)
|
||||
inParticles = Dict{Type, Int}()
|
||||
outParticles = Dict{Type, Int}()
|
||||
|
||||
if !(contains(str, "->"))
|
||||
throw("Did not find -> while parsing process \"$str\"")
|
||||
end
|
||||
|
||||
(inStr, outStr) = split(str, "->")
|
||||
|
||||
if (isempty(inStr) || isempty(outStr))
|
||||
throw("Process (\"$str\") input or output part is empty!")
|
||||
end
|
||||
|
||||
for t in types(model)
|
||||
inCount = count(x -> x == String(t)[1], inStr)
|
||||
outCount = count(x -> x == String(t)[1], outStr)
|
||||
if inCount != 0
|
||||
inParticles[t] = inCount
|
||||
end
|
||||
if outCount != 0
|
||||
outParticles[t] = outCount
|
||||
end
|
||||
end
|
||||
|
||||
if length(inStr) != sum(values(inParticles))
|
||||
throw("Encountered unknown characters in the input part of process \"$str\"")
|
||||
elseif length(outStr) != sum(values(outParticles))
|
||||
throw("Encountered unknown characters in the output part of process \"$str\"")
|
||||
end
|
||||
|
||||
return ABCProcessDescription(inParticles, outParticles)
|
||||
end
|
||||
|
@@ -1,99 +1,140 @@
|
||||
"""
|
||||
ParticleType
|
||||
using QEDbase
|
||||
|
||||
A Particle Type in the ABC Model as an enum, with types `A`, `B` and `C`.
|
||||
"""
|
||||
@enum ParticleType A = 1 B = 2 C = 3
|
||||
ABCModel <: AbstractPhysicsModel
|
||||
|
||||
Singleton definition for identification of the ABC-Model.
|
||||
"""
|
||||
struct ABCModel <: AbstractPhysicsModel end
|
||||
|
||||
"""
|
||||
ABCParticle
|
||||
|
||||
Base type for all particles in the [`ABCModel`](@ref).
|
||||
"""
|
||||
abstract type ABCParticle <: AbstractParticle end
|
||||
|
||||
"""
|
||||
ParticleA <: ABCParticle
|
||||
|
||||
An 'A' particle in the ABC Model.
|
||||
"""
|
||||
struct ParticleA <: ABCParticle
|
||||
momentum::SFourMomentum
|
||||
end
|
||||
|
||||
"""
|
||||
ParticleB <: ABCParticle
|
||||
|
||||
A 'B' particle in the ABC Model.
|
||||
"""
|
||||
struct ParticleB <: ABCParticle
|
||||
momentum::SFourMomentum
|
||||
end
|
||||
|
||||
"""
|
||||
ParticleC <: ABCParticle
|
||||
|
||||
A 'C' particle in the ABC Model.
|
||||
"""
|
||||
struct ParticleC <: ABCParticle
|
||||
momentum::SFourMomentum
|
||||
end
|
||||
|
||||
"""
|
||||
ABCProcessDescription <: AbstractProcessDescription
|
||||
|
||||
A description of a process in the ABC-Model. Contains the input and output particles.
|
||||
|
||||
See also: [`in_particles`](@ref), [`out_particles`](@ref), [`parse_process`](@ref)
|
||||
"""
|
||||
struct ABCProcessDescription <: AbstractProcessDescription
|
||||
inParticles::Dict{Type, Int}
|
||||
outParticles::Dict{Type, Int}
|
||||
end
|
||||
|
||||
"""
|
||||
ABCProcessInput <: AbstractProcessInput
|
||||
|
||||
Input for a ABC Process. Contains the [`ABCProcessDescription`](@ref) of the process it is an input for, and the values of the in and out particles.
|
||||
|
||||
See also: [`gen_process_input`](@ref)
|
||||
"""
|
||||
struct ABCProcessInput <: AbstractProcessInput
|
||||
process::ABCProcessDescription
|
||||
inParticles::Vector{ABCParticle}
|
||||
outParticles::Vector{ABCParticle}
|
||||
end
|
||||
|
||||
"""
|
||||
PARTICLE_MASSES
|
||||
|
||||
A constant dictionary containing the masses of the different [`ParticleType`](@ref)s.
|
||||
A constant dictionary containing the masses of the different [`ABCParticle`](@ref)s.
|
||||
"""
|
||||
const PARTICLE_MASSES =
|
||||
Dict{ParticleType, Float64}(A => 1.0, B => 1.0, C => 0.0)
|
||||
const PARTICLE_MASSES = Dict{Type, Float64}(ParticleA => 1.0, ParticleB => 1.0, ParticleC => 0.0)
|
||||
|
||||
"""
|
||||
Particle
|
||||
|
||||
A struct describing a particle of the ABC-Model. It has the 4 momentum parts P0...P3 and a [`ParticleType`](@ref).
|
||||
|
||||
`sizeof(Particle())` = 40 Byte
|
||||
"""
|
||||
struct Particle
|
||||
P0::Float64
|
||||
P1::Float64
|
||||
P2::Float64
|
||||
P3::Float64
|
||||
|
||||
type::ParticleType
|
||||
end
|
||||
|
||||
"""
|
||||
ParticleValue
|
||||
|
||||
A struct describing a particle during a calculation of a Feynman Diagram, together with the value that's being calculated.
|
||||
|
||||
`sizeof(ParticleValue())` = 48 Byte
|
||||
"""
|
||||
struct ParticleValue
|
||||
p::Particle
|
||||
v::Float64
|
||||
end
|
||||
|
||||
"""
|
||||
mass(t::ParticleType)
|
||||
mass(t::Type{T}) where {T <: ABCParticle}
|
||||
|
||||
Return the mass (at rest) of the given particle type.
|
||||
"""
|
||||
mass(t::ParticleType) = PARTICLE_MASSES[t]
|
||||
mass(t::Type{T}) where {T <: ABCParticle} = PARTICLE_MASSES[t]
|
||||
|
||||
"""
|
||||
remaining_type(t1::ParticleType, t2::ParticleType)
|
||||
interaction_result(t1::Type{T1}, t2::Type{T2}) where {T1 <: ABCParticle, T2 <: ABCParticle}
|
||||
|
||||
For 2 given (non-equal) particle types, return the third of ABC.
|
||||
"""
|
||||
function remaining_type(t1::ParticleType, t2::ParticleType)
|
||||
function interaction_result(t1::Type{T1}, t2::Type{T2}) where {T1 <: ABCParticle, T2 <: ABCParticle}
|
||||
@assert t1 != t2
|
||||
if t1 != A && t2 != A
|
||||
return A
|
||||
elseif t1 != B && t2 != B
|
||||
return B
|
||||
if t1 != Type{ParticleA} && t2 != Type{ParticleA}
|
||||
return ParticleA
|
||||
elseif t1 != Type{ParticleB} && t2 != Type{ParticleB}
|
||||
return ParticleB
|
||||
else
|
||||
return C
|
||||
return ParticleC
|
||||
end
|
||||
end
|
||||
|
||||
"""
|
||||
square(p::Particle)
|
||||
types(::ABCModel)
|
||||
|
||||
Return a Vector of the possible types of particle in the [`ABCModel`](@ref).
|
||||
"""
|
||||
function types(::ABCModel)
|
||||
return [ParticleA, ParticleB, ParticleC]
|
||||
end
|
||||
|
||||
"""
|
||||
square(p::ABCParticle)
|
||||
|
||||
Return the square of the particle's momentum as a `Float` value.
|
||||
|
||||
Takes 7 effective FLOP.
|
||||
"""
|
||||
function square(p::Particle)
|
||||
return p.P0 * p.P0 - p.P1 * p.P1 - p.P2 * p.P2 - p.P3 * p.P3
|
||||
function square(p::ABCParticle)
|
||||
return getMass2(p.momentum)
|
||||
end
|
||||
|
||||
"""
|
||||
inner_edge(p::Particle)
|
||||
inner_edge(p::ABCParticle)
|
||||
|
||||
Return the factor of the inner edge with the given (virtual) particle.
|
||||
|
||||
Takes 10 effective FLOP. (3 here + 10 in square(p))
|
||||
Takes 10 effective FLOP. (3 here + 7 in square(p))
|
||||
"""
|
||||
function inner_edge(p::Particle)
|
||||
return 1.0 / (square(p) - mass(p.type) * mass(p.type))
|
||||
function inner_edge(p::ABCParticle)
|
||||
return 1.0 / (square(p) - mass(typeof(p)) * mass(typeof(p)))
|
||||
end
|
||||
|
||||
"""
|
||||
outer_edge(p::Particle)
|
||||
outer_edge(p::ABCParticle)
|
||||
|
||||
Return the factor of the outer edge with the given (real) particle.
|
||||
|
||||
Takes 0 effective FLOP.
|
||||
"""
|
||||
function outer_edge(p::Particle)
|
||||
function outer_edge(p::ABCParticle)
|
||||
return 1.0
|
||||
end
|
||||
|
||||
@@ -111,20 +152,58 @@ function vertex()
|
||||
end
|
||||
|
||||
"""
|
||||
preserve_momentum(p1::Particle, p2::Particle)
|
||||
preserve_momentum(p1::ABCParticle, p2::ABCParticle)
|
||||
|
||||
Calculate and return a new particle from two given interacting ones at a vertex.
|
||||
|
||||
Takes 4 effective FLOP.
|
||||
"""
|
||||
function preserve_momentum(p1::Particle, p2::Particle)
|
||||
p3 = Particle(
|
||||
p1.P0 + p2.P0,
|
||||
p1.P1 + p2.P1,
|
||||
p1.P2 + p2.P2,
|
||||
p1.P3 + p2.P3,
|
||||
remaining_type(p1.type, p2.type),
|
||||
)
|
||||
function preserve_momentum(p1::ABCParticle, p2::ABCParticle)
|
||||
t3 = interaction_result(typeof(p1), typeof(p2))
|
||||
p3 = t3(p1.momentum + p2.momentum)
|
||||
|
||||
return p3
|
||||
end
|
||||
|
||||
"""
|
||||
type_from_name(name::String)
|
||||
|
||||
For a name of a particle, return the particle's [`Type`].
|
||||
"""
|
||||
function type_from_name(name::String)
|
||||
if startswith(name, "A")
|
||||
return ParticleA
|
||||
elseif startswith(name, "B")
|
||||
return ParticleB
|
||||
elseif startswith(name, "C")
|
||||
return ParticleC
|
||||
else
|
||||
throw("Invalid name for a particle in the ABC model")
|
||||
end
|
||||
end
|
||||
|
||||
function String(::Type{ParticleA})
|
||||
return "A"
|
||||
end
|
||||
function String(::Type{ParticleB})
|
||||
return "B"
|
||||
end
|
||||
function String(::Type{ParticleC})
|
||||
return "C"
|
||||
end
|
||||
|
||||
function in_particles(process::ABCProcessDescription)
|
||||
return process.inParticles
|
||||
end
|
||||
|
||||
function in_particles(input::ABCProcessInput)
|
||||
return input.inParticles
|
||||
end
|
||||
|
||||
function out_particles(process::ABCProcessDescription)
|
||||
return process.outParticles
|
||||
end
|
||||
|
||||
function out_particles(input::ABCProcessInput)
|
||||
return input.outParticles
|
||||
end
|
||||
|
58
src/models/abc/print.jl
Normal file
58
src/models/abc/print.jl
Normal file
@@ -0,0 +1,58 @@
|
||||
|
||||
"""
|
||||
show(io::IO, process::ABCProcessDescription)
|
||||
|
||||
Pretty print an [`ABCProcessDescription`](@ref) (no newlines).
|
||||
|
||||
```jldoctest
|
||||
julia> using MetagraphOptimization
|
||||
|
||||
julia> print(parse_process("AB->ABBB", ABCModel()))
|
||||
ABC Process: 'AB->ABBB'
|
||||
```
|
||||
"""
|
||||
function show(io::IO, process::ABCProcessDescription)
|
||||
# types() gives the types in order (ABC) instead of random like keys() would
|
||||
print(io, "ABC Process: \'")
|
||||
for type in types(ABCModel())
|
||||
for _ in 1:get(process.inParticles, type, 0)
|
||||
print(io, String(type))
|
||||
end
|
||||
end
|
||||
print(io, "->")
|
||||
for type in types(ABCModel())
|
||||
for _ in 1:get(process.outParticles, type, 0)
|
||||
print(io, String(type))
|
||||
end
|
||||
end
|
||||
print(io, "'")
|
||||
return nothing
|
||||
end
|
||||
|
||||
"""
|
||||
show(io::IO, processInput::ABCProcessInput)
|
||||
|
||||
Pretty print an [`ABCProcessInput`](@ref) (with newlines).
|
||||
"""
|
||||
function show(io::IO, processInput::ABCProcessInput)
|
||||
println(io, "Input for $(processInput.process):")
|
||||
println(io, " $(length(processInput.inParticles)) Incoming particles:")
|
||||
for particle in processInput.inParticles
|
||||
println(io, " $particle")
|
||||
end
|
||||
println(io, " $(length(processInput.outParticles)) Outgoing Particles:")
|
||||
for particle in processInput.outParticles
|
||||
println(io, " $particle")
|
||||
end
|
||||
return nothing
|
||||
end
|
||||
|
||||
"""
|
||||
show(io::IO, particle::T) where {T <: ABCParticle}
|
||||
|
||||
Pretty print an [`ABCParticle`](@ref) (no newlines).
|
||||
"""
|
||||
function show(io::IO, particle::T) where {T <: ABCParticle}
|
||||
print(io, "$(String(typeof(particle))): $(particle.momentum)")
|
||||
return nothing
|
||||
end
|
@@ -57,42 +57,42 @@ end
|
||||
|
||||
Print the S1 task to io.
|
||||
"""
|
||||
show(io::IO, t::ComputeTaskS1) = print("ComputeS1")
|
||||
show(io::IO, t::ComputeTaskS1) = print(io, "ComputeS1")
|
||||
|
||||
"""
|
||||
show(io::IO, t::ComputeTaskS2)
|
||||
|
||||
Print the S2 task to io.
|
||||
"""
|
||||
show(io::IO, t::ComputeTaskS2) = print("ComputeS2")
|
||||
show(io::IO, t::ComputeTaskS2) = print(io, "ComputeS2")
|
||||
|
||||
"""
|
||||
show(io::IO, t::ComputeTaskP)
|
||||
|
||||
Print the P task to io.
|
||||
"""
|
||||
show(io::IO, t::ComputeTaskP) = print("ComputeP")
|
||||
show(io::IO, t::ComputeTaskP) = print(io, "ComputeP")
|
||||
|
||||
"""
|
||||
show(io::IO, t::ComputeTaskU)
|
||||
|
||||
Print the U task to io.
|
||||
"""
|
||||
show(io::IO, t::ComputeTaskU) = print("ComputeU")
|
||||
show(io::IO, t::ComputeTaskU) = print(io, "ComputeU")
|
||||
|
||||
"""
|
||||
show(io::IO, t::ComputeTaskV)
|
||||
|
||||
Print the V task to io.
|
||||
"""
|
||||
show(io::IO, t::ComputeTaskV) = print("ComputeV")
|
||||
show(io::IO, t::ComputeTaskV) = print(io, "ComputeV")
|
||||
|
||||
"""
|
||||
show(io::IO, t::ComputeTaskSum)
|
||||
|
||||
Print the sum task to io.
|
||||
"""
|
||||
show(io::IO, t::ComputeTaskSum) = print("ComputeSum")
|
||||
show(io::IO, t::ComputeTaskSum) = print(io, "ComputeSum")
|
||||
|
||||
"""
|
||||
copy(t::DataTask)
|
||||
@@ -147,19 +147,20 @@ children(::ComputeTaskV) = 2
|
||||
"""
|
||||
children(::ComputeTaskSum)
|
||||
|
||||
Return the number of children of a ComputeTaskSum, since this is variable and the task doesn't know
|
||||
how many children it will sum over, return a wildcard -1.
|
||||
|
||||
TODO: this is kind of bad because it means we can't fuse with a sum task
|
||||
Return the number of children of a ComputeTaskSum.
|
||||
"""
|
||||
children(::ComputeTaskSum) = -1
|
||||
children(t::ComputeTaskSum) = t.children_number
|
||||
|
||||
"""
|
||||
children(t::FusedComputeTask)
|
||||
|
||||
Return the number of children of a FusedComputeTask. It's the sum of the children of both tasks minus one.
|
||||
Return the number of children of a FusedComputeTask.
|
||||
"""
|
||||
function children(t::FusedComputeTask)
|
||||
(T1, T2) = get_types(t)
|
||||
return children(T1()) + children(T2()) - 1 # one of the inputs is the output of T1 and thus not a child of the node
|
||||
return length(union(Set(t.t1_inputs), Set(t.t2_inputs)))
|
||||
end
|
||||
|
||||
function add_child!(t::ComputeTaskSum)
|
||||
t.children_number += 1
|
||||
return nothing
|
||||
end
|
||||
|
@@ -47,19 +47,13 @@ struct ComputeTaskU <: AbstractComputeTask end
|
||||
|
||||
Task that sums all its inputs, n children.
|
||||
"""
|
||||
struct ComputeTaskSum <: AbstractComputeTask end
|
||||
mutable struct ComputeTaskSum <: AbstractComputeTask
|
||||
children_number::Int
|
||||
end
|
||||
|
||||
"""
|
||||
ABC_TASKS
|
||||
|
||||
Constant vector of all tasks of the ABC-Model.
|
||||
"""
|
||||
ABC_TASKS = [
|
||||
DataTask,
|
||||
ComputeTaskS1,
|
||||
ComputeTaskS2,
|
||||
ComputeTaskP,
|
||||
ComputeTaskV,
|
||||
ComputeTaskU,
|
||||
ComputeTaskSum,
|
||||
]
|
||||
ABC_TASKS = [DataTask, ComputeTaskS1, ComputeTaskS2, ComputeTaskP, ComputeTaskV, ComputeTaskU, ComputeTaskSum]
|
||||
|
109
src/models/interface.jl
Normal file
109
src/models/interface.jl
Normal file
@@ -0,0 +1,109 @@
|
||||
|
||||
"""
|
||||
AbstractPhysicsModel
|
||||
|
||||
Base type for a model, e.g. ABC-Model or QED. This is used to dispatch many functions.
|
||||
"""
|
||||
abstract type AbstractPhysicsModel end
|
||||
|
||||
"""
|
||||
AbstractParticle
|
||||
|
||||
Base type for particles belonging to a certain [`AbstractPhysicsModel`](@ref).
|
||||
"""
|
||||
abstract type AbstractParticle end
|
||||
|
||||
"""
|
||||
ParticleValue{ParticleType <: AbstractParticle}
|
||||
|
||||
A struct describing a particle during a calculation of a Feynman Diagram, together with the value that's being calculated.
|
||||
|
||||
`sizeof(ParticleValue())` = 48 Byte
|
||||
"""
|
||||
struct ParticleValue{ParticleType <: AbstractParticle}
|
||||
p::ParticleType
|
||||
v::Float64
|
||||
end
|
||||
|
||||
"""
|
||||
AbstractProcessDescription
|
||||
|
||||
Base type for process descriptions. An object of this type of a corresponding [`AbstractPhysicsModel`](@ref) should uniquely identify a process in that model.
|
||||
|
||||
See also: [`parse_process`](@ref)
|
||||
"""
|
||||
abstract type AbstractProcessDescription end
|
||||
|
||||
"""
|
||||
AbstractProcessInput
|
||||
|
||||
Base type for process inputs. An object of this type contains the input values (e.g. momenta) of the particles in a process.
|
||||
|
||||
See also: [`gen_process_input`](@ref)
|
||||
"""
|
||||
abstract type AbstractProcessInput end
|
||||
|
||||
"""
|
||||
mass(t::Type{T}) where {T <: AbstractParticle}
|
||||
|
||||
Interface function that must be implemented for every subtype of [`AbstractParticle`](@ref), returning the particles mass at rest.
|
||||
"""
|
||||
function mass end
|
||||
|
||||
"""
|
||||
interaction_result(t1::Type{T1}, t2::Type{T2}) where {T1 <: AbstractParticle, T2 <: AbstractParticle}
|
||||
|
||||
Interface function that must be implemented for every subtype of [`AbstractParticle`](@ref), returning the result particle type when the two given particles interact.
|
||||
"""
|
||||
function interaction_result end
|
||||
|
||||
"""
|
||||
types(::AbstractPhysicsModel)
|
||||
|
||||
Interface function that must be implemented for every subtype of [`AbstractPhysicsModel`](@ref), returning a `Vector` of the available particle types in the model.
|
||||
"""
|
||||
function types end
|
||||
|
||||
"""
|
||||
in_particles(::AbstractProcessDescription)
|
||||
|
||||
Interface function that must be implemented for every subtype of [`AbstractProcessDescription`](@ref).
|
||||
Returns a `<: Dict{Type{AbstractParticle}, Int}` object, representing the number of incoming particles for the process per particle type.
|
||||
|
||||
|
||||
in_particles(::AbstractProcessInput)
|
||||
|
||||
Interface function that must be implemented for every subtype of [`AbstractProcessInput`](@ref).
|
||||
Returns a `<: Vector{AbstractParticle}` object with the values of all incoming particles for the corresponding `ProcessDescription`.
|
||||
"""
|
||||
function in_particles end
|
||||
|
||||
"""
|
||||
out_particles(::AbstractProcessDescription)
|
||||
|
||||
Interface function that must be implemented for every subtype of [`AbstractProcessDescription`](@ref).
|
||||
Returns a `<: Dict{Type{AbstractParticle}, Int}` object, representing the number of outgoing particles for the process per particle type.
|
||||
|
||||
|
||||
out_particles(::AbstractProcessInput)
|
||||
|
||||
Interface function that must be implemented for every subtype of [`AbstractProcessInput`](@ref).
|
||||
Returns a `<: Vector{AbstractParticle}` object with the values of all outgoing particles for the corresponding `ProcessDescription`.
|
||||
"""
|
||||
function out_particles end
|
||||
|
||||
"""
|
||||
parse_process(::AbstractString, ::AbstractPhysicsModel)
|
||||
|
||||
Interface function that must be implemented for every subtype of [`AbstractPhysicsModel`](@ref).
|
||||
Returns a `ProcessDescription` object.
|
||||
"""
|
||||
function parse_process end
|
||||
|
||||
"""
|
||||
gen_process_input(::AbstractProcessDescription)
|
||||
|
||||
Interface function that must be implemented for every specific [`AbstractProcessDescription`](@ref).
|
||||
Returns a randomly generated and valid corresponding `ProcessInput`.
|
||||
"""
|
||||
function gen_process_input end
|
10
src/models/print.jl
Normal file
10
src/models/print.jl
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
"""
|
||||
show(io::IO, particleValue::ParticleValue)
|
||||
|
||||
Pretty print a [`ParticleValue`](@ref), no newlines.
|
||||
"""
|
||||
function show(io::IO, particleValue::ParticleValue)
|
||||
print(io, "($(particleValue.p), value: $(particleValue.v))")
|
||||
return nothing
|
||||
end
|
Reference in New Issue
Block a user