Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Computation and process setup interface #14

Merged
merged 19 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/QEDprocesses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export initial_phasespace_dimension, final_phasespace_dimension
export number_incoming_particles, number_outgoing_particles
export differential_cross_section, total_cross_section

# Abstract setup interface
export AbstractComputationSetup, compute
export AbstractProcessSetup, scattering_process, compute_model

# particle types
export AbstractParticleType
export FermionLike, Fermion, AntiFermion, MajoranaFermion
Expand All @@ -26,5 +30,6 @@ include("utils.jl")
include("interfaces/particle_interface.jl")
include("interfaces/model_interface.jl")
include("interfaces/process_interface.jl")
include("interfaces/setup_interface.jl")
include("particle_types.jl")
end
31 changes: 10 additions & 21 deletions src/interfaces/process_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function outgoing_particles end

Return the number of incoming particles of a given process.
"""
@inline function number_incoming_pariticles(proc_def::AbstractProcessDefinition)
@inline function number_incoming_particles(proc_def::AbstractProcessDefinition)
return length(incoming_particles(proc_def))
end

Expand All @@ -57,7 +57,7 @@ end

Return the number of outgoing particles of a given process.
"""
@inline function number_outgoing_pariticles(proc_def::AbstractProcessDefinition)
@inline function number_outgoing_particles(proc_def::AbstractProcessDefinition)
return length(outgoing_particles(proc_def))
end

Expand Down Expand Up @@ -119,23 +119,14 @@ function differential_cross_section(
model_def::AbstractModelDefinition,
init_phasespace::Union{AbstractVector{T},AbstractMatrix{T}},
AntonReinhard marked this conversation as resolved.
Show resolved Hide resolved
final_phasespace::Union{AbstractVector{T},AbstractMatrix{T}},
) where {T<:QEDbase.AbstractFourMomentum}
size(init_phasespace, 1) == number_incoming_pariticles(proc_def) || throw(
DimensionMismatch(
"The number of momenta in the initial phasespace <{length(init_phasespace)}> does not match the number of incoming particles of the process <{number_incoming_pariticles(proc_def)}>.",
),
)
size(final_phasespace, 1) == number_outgoing_pariticles(proc_def) || throw(
DimensionMismatch(
"The number of momenta in the final phasespace <{length(final_phasespace)}> does not match the number of outgoing particles of the process <{number_outgoing_pariticles(proc_def)}>.",
),
) where {T<:QEDbase.AbstractFourMomentum}
size(init_phasespace, 1) == number_incoming_particles(proc_def) || throw(
DimensionMismatch("The number of momenta in the initial phasespace <{length(init_phasespace)}> does not match the number of incoming particles of the process <{number_incoming_particles(proc_def)}>."),
)
return _differential_cross_section(
proc_def,
model_def,
init_phasespace,
final_phasespace,
size(final_phasespace, 1) == number_outgoing_particles(proc_def) || throw(
DimensionMismatch("The number of momenta in the final phasespace <{length(final_phasespace)}> does not match the number of outgoing particles of the process <{number_outgoing_particles(proc_def)}>."),
)
return _differential_cross_section(proc_def, model_def, init_phasespace, final_phasespace)
end

# returns diffCS for single `initPS` and several `finalPS` points without input-check
Expand Down Expand Up @@ -265,10 +256,8 @@ function total_cross_section(
model_def::AbstractModelDefinition,
init_phasespace::Union{AbstractVector{T},AbstractMatrix{T}},
) where {T<:QEDbase.AbstractFourMomentum}
size(init_phasespace, 1) == number_incoming_pariticles(proc_def) || throw(
DimensionMismatch(
"The number of momenta in the initial phasespace <{length(init_phasespace)}> does not match the number of incoming particles of the process <{number_incoming_pariticles(proc_def)}>.",
),
size(init_phasespace, 1) == number_incoming_particles(proc_def) || throw(
DimensionMismatch("The number of momenta in the initial phasespace <{length(init_phasespace)}> does not match the number of incoming particles of the process <{number_incoming_particles(proc_def)}>."),
)
return _total_cross_section(proc_def, model_def, init_phasespace)
end
171 changes: 171 additions & 0 deletions src/interfaces/setup_interface.jl
AntonReinhard marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
###############
# The process setup
#
# In this file, we define the interface for general computation and process setups.
#
# This file is part of `QEDprocesses.jl` which is by itself part of the `QED.jl`
# ecosystem.
AntonReinhard marked this conversation as resolved.
Show resolved Hide resolved
#
###############

"""
Abstract base type for computation setups. A *setup* means
a collection of setup data needed to evaluate a dedicated quantity of given
running data. Therefore, each setup is associated with a single quantity, which one may compute using the setup data and the running data.
Despite that, the decomposition into setup and running data is
arbitrary, and this can be used for cases where a subset of the variables a
quantity depends on is kept constant.

!!! note "Computation setup interface"

The computation performed using a computation setup is separated into three steps:

1. input validation
2. actual computation
3. post processing

where every step has its own interface function (see [`compute`](@ref) for details).

## Input validation

Every subtype of `AbstractComputationSetup` should implement the interface function

```Julia
_input_validation(stp::AbstractComputationSetup, input) # default: true
```

which should return true iff the `input` is valid for the computation of the associated quantity (see [`_input_validation`](@ref) for more details).
The default implementation always returns `true`. Provide a custom implementation if a different behavior is required.

## Actual computation

Every subtype of `AbstractComputationSetup` must at least implement the required interface function

```Julia
_compute(stp::AbstractComputationSetup, input)
```

which computes the value of the associated quantity for a given `input` (see [`_compute`](@ref) for more details).


## Post computation

Every subtype of `AbstractComputationSetup` should implement the interface function

```Julia
_post_computation(stp::AbstractComputationSetup, input)
```

which performs *computations* after the actual computation, e.g. conversions or normalisations (see [`_post_computation`](@ref) for more details).
szabo137 marked this conversation as resolved.
Show resolved Hide resolved



"""
abstract type AbstractComputationSetup end

# convenience function to check if an object is a computation setup
_is_computation_setup(::AbstractComputationSetup) = true

"""

_is_valid_input(stp::AbstractComputationSetup, input::Any)
AntonReinhard marked this conversation as resolved.
Show resolved Hide resolved

Interface function, which returns true if the constraints of the `input` associated with the quantity of `stp` are met.
This function is called to validate the input of [`compute`](@ref) before calling [`_compute`](@ref).

!!! note "Default implementation"

Since no input validation is equivalent to every input being valid, this function returns `true` by default.
This behavior can be overwritten if actual validation is necessary.
AntonReinhard marked this conversation as resolved.
Show resolved Hide resolved

"""
@inline function _input_validation(stp::AbstractComputationSetup, input)
return true
end

"""

function _post_computation(stp::AbstractComputationSetup, input::Any, result::Any)
tjungni marked this conversation as resolved.
Show resolved Hide resolved

Interface function, which is called in [`compute`](@ref) after [`_compute`](@ref) has been called. This function is dedicated to
finalize the result of a computation.

!!! note "default implementation"

Since in the case of no post computation the result of [`_compute`](@ref) is unchanged, this function returns `result` by default.

"""
@inline function _post_computation(stp::AbstractComputationSetup, input, result)
return result
end

"""

_compute(stp::AbstractComputationSetup, input::Any)

Interface function that returns the value of the associated quantity evaluated on `input`, which can be anything the associated quantity is defined to be feasible for.

!!! note "unsafe implementation"

This function must be implemented for any subtype of [`AbstractComputationSetup`]. It should not do any input validation or post processing (see [`_input_validation`](@ref) and [`_post_computation`](@ref)), as those two are performed while calling
the safe version of this function [`compute`](@ref).

"""
function _compute end
AntonReinhard marked this conversation as resolved.
Show resolved Hide resolved

"""

compute(stp::AbstractComputationSetup, input::Any)

Return the value of the quantity associated with `stp` for a given `input`.
In addition to the actual call of the associated unsafe version [`_compute`](@ref),
input validation (using [`_input_validation`](@ref)) and post computation
(using [`_post_computation`](@ref)) are wrapped around the calculation (see [`AbstractComputationSetup`](@ref) for details).
"""
function compute(stp::AbstractComputationSetup, input)
_input_validation(stp,input) || error("InvalidInputError: there is something wrong with the input!\n setup:$stp \n input:$input")
AntonReinhard marked this conversation as resolved.
Show resolved Hide resolved
raw_result = _compute(stp,input)
return _post_computation(stp, input,raw_result)
end

"""
Abstract base type for setups related to combining scattering processes and compute models.
Every subtype of `AbstractProcessSetup` must implement at least the following
interface functions:

```Julia
scattering_process(::AbstractProcessSetup)
compute_model(::AbstractProcessSetup)
```

Derived from these interface functions, the following delegations are provided:

```Julia
number_incoming_particles(::AbstractProcessSetup)
number_outgoing_particles(::AbstractProcessSetup)
```

"""
abstract type AbstractProcessSetup <: AbstractComputationSetup end

"""

scattering_process(stp::AbstractProcessSetup)

Interface function that returns the scattering process associated with `stp`,
i.e. an object which is a subtype of `AbstractProcessDefinition`.
"""
function scattering_process end
AntonReinhard marked this conversation as resolved.
Show resolved Hide resolved

"""

compute_model(stp::AbstractProcessSetup)

Interface function that returns the compute model associated with `stp`, i.e.
an object which is a subtype of `AbstractModelDefinition`.
"""
function compute_model end
AntonReinhard marked this conversation as resolved.
Show resolved Hide resolved

@inline number_incoming_particles(stp::AbstractProcessSetup) = number_incoming_particles(scattering_process(stp))
@inline number_outgoing_particles(stp::AbstractProcessSetup) = number_outgoing_particles(scattering_process(stp))

5 changes: 5 additions & 0 deletions test/interfaces/process_interface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ end
@test outgoing_particles(TestProcess()) == OUTGOING_PARTICLES
end

@testset "delegated functions" begin
@test number_incoming_particles(TestProcess()) == N_INCOMING
@test number_outgoing_particles(TestProcess()) == N_OUTGOING
end


@testset "cross section" begin

Expand Down
Loading
Loading