Page MenuHomeHEPForge

No OneTemporary

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4a7bde1..ae387d6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,435 +1,443 @@
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project("HEJ" VERSION 2.0.5 LANGUAGES C CXX)
# Set a default build type if none was specified
set(default_build_type "RelWithDebInfo")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
## Flags for the compiler. No warning allowed.
if (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
elseif (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /WX /EHsc")
endif()
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 14)
## Create Version
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
# Get the latest abbreviated commit hash of the working branch
execute_process(
COMMAND git rev-parse HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE PROJECT_GIT_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Get the current working branch
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE PROJECT_GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
## target directories for install
set(INSTALL_INCLUDE_DIR_BASE include)
set(INSTALL_INCLUDE_DIR ${INSTALL_INCLUDE_DIR_BASE}/HEJ)
set(INSTALL_BIN_DIR bin)
set(INSTALL_LIB_DIR lib)
set(INSTALL_CONFIG_DIR lib/cmake/HEJ)
## Template files
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Templates/Version.hh.in
${PROJECT_BINARY_DIR}/include/HEJ/Version.hh @ONLY )
configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Templates/HEJ-config.cc.in
${PROJECT_BINARY_DIR}/src/bin/HEJ-config.cc @ONLY )
# Generate CMake config file
include(CMakePackageConfigHelpers)
configure_package_config_file(
cmake/Templates/hej-config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/${INSTALL_CONFIG_DIR}/hej-config.cmake
INSTALL_DESTINATION ${INSTALL_CONFIG_DIR}
PATH_VARS INSTALL_INCLUDE_DIR_BASE INSTALL_LIB_DIR
)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/${INSTALL_CONFIG_DIR}/hej-config-version.cmake
COMPATIBILITY SameMajorVersion
)
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/${INSTALL_CONFIG_DIR}/hej-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${INSTALL_CONFIG_DIR}/hej-config-version.cmake
DESTINATION ${INSTALL_CONFIG_DIR})
## Add directories and find dependences
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include)
find_package(fastjet REQUIRED)
include_directories(${fastjet_INCLUDE_DIRS})
find_package(CLHEP 2.3 REQUIRED)
include_directories(${CLHEP_INCLUDE_DIRS})
find_package(LHAPDF REQUIRED)
include_directories(${LHAPDF_INCLUDE_DIRS})
## Amend unintuitive behaviour of FindBoost.cmake
## Priority of BOOST_ROOT over BOOSTROOT matches FindBoost.cmake
## at least for cmake 3.12
if(DEFINED BOOST_ROOT)
message("BOOST_ROOT set - only looking for Boost in ${BOOST_ROOT}")
set(Boost_NO_BOOST_CMAKE ON)
elseif(DEFINED BOOSTROOT)
message("BOOSTROOT set - only looking for Boost in ${BOOSTROOT}")
set(Boost_NO_BOOST_CMAKE ON)
endif()
find_package(Boost REQUIRED COMPONENTS iostreams)
include_directories(${Boost_INCLUDE_DIRS})
find_package(yaml-cpp) # requiring yaml does not work with fedora
include_directories(${YAML_CPP_INCLUDE_DIR})
if(${EXCLUDE_HepMC})
message(STATUS "Skipping HepMC")
# avoid "unused variable" warning if EXCLUDE_rivet is set by user
set(EXCLUDE_rivet TRUE)
else()
find_package(HepMC 2 EXACT)
endif()
if(${HepMC_FOUND})
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -DHEJ_BUILD_WITH_HepMC2"
)
include_directories(${HepMC_INCLUDE_DIRS})
if(${EXCLUDE_rivet})
message(STATUS "Skipping rivet")
else()
find_package(rivet)
endif()
if(${rivet_FOUND})
include_directories(${rivet_INCLUDE_DIRS})
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -DHEJ_BUILD_WITH_RIVET"
)
endif()
endif()
if(${EXCLUDE_HepMC3})
message(STATUS "Skipping HepMC3")
else()
## version 3.1: Finding version not possible in 3.1.1, see HepMC3 git 29e7a6c3
find_package(HepMC3)
## print standard message
find_package_handle_standard_args( HepMC3
FOUND_VAR
HepMC3_FOUND
REQUIRED_VARS
HEPMC3_INCLUDE_DIR
HEPMC3_LIBRARIES
# VERSION_VAR
# HEPMC3_VERSION
)
if(${HepMC3_FOUND})
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -DHEJ_BUILD_WITH_HepMC3"
)
include_directories(${HEPMC3_INCLUDE_DIR})
endif()
endif()
if(${EXCLUDE_QCDloop})
message(STATUS "Skipping QCDloop")
else()
find_package(QCDloop 2)
endif()
if(${QCDloop_FOUND})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHEJ_BUILD_WITH_QCDLOOP")
include_directories(SYSTEM ${QCDloop_INCLUDE_DIRS})
endif()
if(${EXCLUDE_HighFive})
message(STATUS "Skipping HighFive")
else()
find_package(HighFive QUIET)
find_package_handle_standard_args( HighFive CONFIG_MODE )
endif()
if(${HighFive_FOUND})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DHEJ_BUILD_WITH_HDF5")
include_directories($<TARGET_PROPERTY:HighFive,INTERFACE_INCLUDE_DIRECTORIES>)
endif()
add_subdirectory(src)
## define executable
add_executable(HEJ src/bin/HEJ.cc)
## link libraries
target_link_libraries(HEJ hejlib)
add_executable(HEJ-config src/bin/HEJ-config.cc)
file(GLOB hej_headers
${CMAKE_CURRENT_SOURCE_DIR}/include/HEJ/*.hh
${PROJECT_BINARY_DIR}/include/HEJ/*.hh
)
file(GLOB hej_detail_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/HEJ/detail/*.hh)
file(GLOB lhef_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/LHEF/*.h)
install(FILES ${hej_headers} DESTINATION ${INSTALL_INCLUDE_DIR})
install(FILES ${hej_detail_headers} DESTINATION ${INSTALL_INCLUDE_DIR}/detail/)
install(FILES ${lhef_headers} DESTINATION ${INSTALL_INCLUDE_DIR_BASE}/LHEF/)
install(TARGETS HEJ HEJ-config DESTINATION ${INSTALL_BIN_DIR})
## tests
enable_testing()
set(tst_dir "${CMAKE_CURRENT_SOURCE_DIR}/t")
set(tst_ME_data_dir "${tst_dir}/ME_data")
# test event classification
add_executable(test_classify ${tst_dir}/test_classify.cc)
target_link_libraries(test_classify hejlib)
add_test(
NAME t_classify
COMMAND test_classify
)
add_executable(test_classify_ref ${tst_dir}/test_classify_ref.cc)
target_link_libraries(test_classify_ref hejlib)
add_test(
NAME t_classify_ref
COMMAND test_classify_ref ${tst_dir}/classify_ref ${tst_dir}/classify.lhe.gz
)
add_test(
NAME t_classify_ref_4j
COMMAND test_classify_ref ${tst_dir}/classify_ref_4j ${tst_dir}/4j.lhe.gz
)
# test phase space point
add_executable(test_psp ${tst_dir}/test_psp.cc)
target_link_libraries(test_psp hejlib)
add_test(
NAME t_psp
COMMAND test_psp ${tst_dir}/psp_gen.lhe.gz
)
# test importing scales
add_library(scales SHARED ${tst_dir}/scales.cc)
add_executable(test_scale_import ${tst_dir}/test_scale_import)
target_link_libraries(test_scale_import hejlib)
add_test(
NAME t_scale_import
COMMAND test_scale_import ${tst_dir}/jet_config_with_import.yml
)
# test scale arithmetic (e.g. 2*H_T/4)
add_executable(test_scale_arithmetics ${tst_dir}/test_scale_arithmetics)
target_link_libraries(test_scale_arithmetics hejlib)
add_test(
NAME t_scale_arithmetics
COMMAND test_scale_arithmetics ${tst_dir}/jet_config.yml ${tst_dir}/2j.lhe.gz
)
# test "ParameterDescription"
add_executable(test_descriptions ${tst_dir}/test_descriptions)
target_link_libraries(test_descriptions hejlib)
add_test(
NAME t_descriptions
COMMAND test_descriptions
)
# test "EventParameters*Weight"
add_executable(test_parameters ${tst_dir}/test_parameters)
target_link_libraries(test_parameters hejlib)
add_test(
NAME test_parameters
COMMAND test_parameters
)
# test colour generation
add_executable(test_colours ${tst_dir}/test_colours)
target_link_libraries(test_colours hejlib)
add_test(
NAME t_colour_flow
COMMAND test_colours
)
# test matrix elements
add_executable(test_ME_generic ${tst_dir}/test_ME_generic.cc)
target_link_libraries(test_ME_generic hejlib)
add_test(
NAME t_ME_j
COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml ${tst_ME_data_dir}/ME_jets_tree.dat ${tst_ME_data_dir}/PSP_jets.lhe.gz
)
add_test(
NAME t_ME_h
COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml ${tst_ME_data_dir}/ME_h_mtinf_tree.dat ${tst_ME_data_dir}/PSP_h.lhe.gz
)
if(${QCDloop_FOUND})
add_test(
NAME t_ME_h_mt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_mt.yml ${tst_ME_data_dir}/ME_h_mt_tree.dat ${tst_ME_data_dir}/PSP_h.lhe.gz
)
add_test(
NAME t_ME_h_mtmb
COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtmb.yml ${tst_ME_data_dir}/ME_h_mtmb_tree.dat ${tst_ME_data_dir}/PSP_h.lhe.gz
)
endif()
add_test(
NAME t_ME_w_FKL
COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml ${tst_ME_data_dir}/ME_w_FKL_tree.dat ${tst_ME_data_dir}/PSP_w_FKL.lhe.gz
)
add_test(
NAME t_ME_w_FKL_virt
COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml ${tst_ME_data_dir}/ME_w_FKL_virt.dat ${tst_ME_data_dir}/PSP_w_FKL.lhe.gz
)
add_test(
NAME t_ME_Wp
COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml ${tst_ME_data_dir}/ME_Wp.dat ${tst_ME_data_dir}/PSP_Wp.lhe.gz
)
add_test(
NAME t_ME_Wm
COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml ${tst_ME_data_dir}/ME_Wm.dat ${tst_ME_data_dir}/PSP_Wm.lhe.gz
)
# test main executable
file(COPY "${tst_dir}/jet_config.yml" DESTINATION "${CMAKE_BINARY_DIR}")
set(test_config "${CMAKE_BINARY_DIR}/jet_config.yml")
if(${HepMC3_FOUND})
file(READ ${test_config} config)
file(WRITE ${test_config} "${config} - tst.hepmc\n")
endif()
if(${HepMC_FOUND})
file(READ ${test_config} config)
file(WRITE ${test_config} "${config} - tst.hepmc2\n")
if(${rivet_FOUND})
file(READ ${test_config} config)
file(WRITE ${test_config} "${config}\nanalysis:\n rivet: MC_XS\n output: tst\n")
endif()
endif()
set(test_cmd_main "$<TARGET_FILE:HEJ>\\\;${test_config}\\\;${tst_dir}/2j.lhe.gz")
# check that HepMC3 output is correct
if(${HepMC3_FOUND})
add_executable(check_hepmc ${tst_dir}/check_hepmc.cc)
target_link_libraries(check_hepmc hejlib)
set(test_cmd_hepmc "$<TARGET_FILE:check_hepmc>\\\;tst.hepmc")
else()
set(test_cmd_hepmc "")
endif()
# check that LHEF output is correct
add_executable(check_lhe ${tst_dir}/check_lhe.cc)
target_link_libraries(check_lhe hejlib)
set(tes_cmd_lhe "$<TARGET_FILE:check_lhe>\\\;tst.lhe")
# Run dependent tests in one command to ensure correct execution order
# Note: The commands are concatenated with "\;" to escape CMake lists.
# Thus arguments have to be escaped twice "\\\;".
# e.g. "cmd1\;cmd2\\\;arg1\\\;arg2" is executed like "cmd1 && cmd2 arg1 arg2"
add_test(
NAME t_main
COMMAND ${CMAKE_COMMAND}
-DCMDS=${test_cmd_main}\;${test_cmd_hepmc}\;${test_cmd_lhe}
-P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/run_multiple_tests.cmake
)
# check HDF5 reader
if(${HighFive_FOUND})
add_executable(test_hdf5 ${tst_dir}/test_hdf5.cc)
target_link_libraries(test_hdf5 hejlib)
add_test(
NAME t_hdf5
COMMAND test_hdf5 ${tst_dir}/Wm9-g4-repack.hdf5
)
endif()
# check rivet interface
if(${RIVET_FOUND})
add_executable(check_rivet ${tst_dir}/check_rivet.cc)
target_link_libraries(check_rivet hejlib)
add_test(
NAME t_rivet
COMMAND check_rivet
)
endif()
# test boson reconstruction
add_executable(cmp_events ${tst_dir}/cmp_events.cc)
target_link_libraries(cmp_events hejlib)
add_test(
NAME t_epnu_2j_noW
COMMAND cmp_events ${tst_dir}/epnu2jLOFKL_unweight.lhe.tar.gz ${tst_dir}/epnu2jLOFKL_unweight_noW.lhe.gz
)
# test resummed result
add_executable(check_res ${tst_dir}/check_res.cc)
target_link_libraries(check_res hejlib)
if(${TEST_ALL}) # deactivate long tests by default
add_test(
NAME t_2j
COMMAND check_res ${tst_dir}/2j.lhe.gz 3.49391e+07 419684
)
add_test(
NAME t_3j
COMMAND check_res ${tst_dir}/3j.lhe.gz 2.37902e+06 25746.6
)
add_test(
+ NAME t_3j_unof
+ COMMAND check_res ${tst_dir}/3j.lhe.gz 133399 4688.83 unof
+ )
+ add_test(
+ NAME t_3j_unob
+ COMMAND check_res ${tst_dir}/3j.lhe.gz 105247 3449.45 unob
+ )
+ add_test(
NAME t_4j
COMMAND check_res ${tst_dir}/4j.lhe.gz 603713 72822.6
)
add_test(
NAME t_h_3j
COMMAND check_res ${tst_dir}/h_3j.lhe.gz 0.821622 0.0220334
)
add_test(
NAME t_h_3j_unof
COMMAND check_res ${tst_dir}/h_3j_uno.lhe.gz 0.0127362 0.000271555 unof
)
add_test(
NAME t_h_3j_unob
COMMAND check_res ${tst_dir}/h_3j_uno.lhe.gz 0.0130615 0.000224793 unob
)
add_test(
NAME t_epnu_2j
COMMAND check_res ${tst_dir}/epnu2jLOFKL_unweight.lhe.tar.gz 262.7 3
)
add_test(
NAME t_MGepnu_3j
COMMAND check_res ${tst_dir}/MGepnu3j_unweighted.tar.gz 38.9512 1
)
add_test(
NAME t_MGemnubar_3j
COMMAND check_res ${tst_dir}/MGemnubar3j_unweighted.tar.gz 24.1575 1
)
add_test(
NAME t_MGepnu_3j_unof
COMMAND check_res ${tst_dir}/MGepnu3j_unweighted.tar.gz 9.63702 0.128355 unof
)
add_test(
NAME t_MGepnu_3j_unob
COMMAND check_res ${tst_dir}/MGepnu3j_unweighted.tar.gz 9.70119 0.108436 unob
)
add_test(
NAME t_MGepnu_3j_splitf
COMMAND check_res ${tst_dir}/MGepnu3j_unweighted.tar.gz 2.91995 0.0463182 splitf
)
add_test(
NAME t_MGepnu_3j_splitb
COMMAND check_res ${tst_dir}/MGepnu3j_unweighted.tar.gz 3.40708 0.0550975 splitb
)
add_test(
NAME t_MGepnu_4j
COMMAND check_res ${tst_dir}/MGepnu4j_unweighted.tar.gz 10.2542 0.135106
)
add_test(
NAME t_MGemnubar_4j
COMMAND check_res ${tst_dir}/MGemnubar4j_unweighted.tar.gz 5.57909 0.0300496
)
add_test(
NAME t_MGepnu_4j_qqxmid
COMMAND check_res ${tst_dir}/MGepnu4j_unweighted.tar.gz 0.732084 0.005 qqxmid
)
endif()
diff --git a/Changes.md b/Changes.md
index 712d775..ed7de34 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,58 +1,60 @@
# Changelog
This is the log for changes to the HEJ program. Further changes to the HEJ API
are documented in `Changes-API.md`. If you are using HEJ as a library, please
also read the changes there.
## Version 2.X
### 2.X.0
* Resummation for W bosons with jets
- New subleading processes `extremal qqx` & `central qqx` for a quark and
anti-quark in the final state, e.g. `g g => u d_bar Wm g` (the other
subleading processes also work with W's)
- `HEJFOG` can generate mutliple jets together with a (off-shell) W bosons
decaying into lepton & neutrino
+* Resummation can now be performed on `unordered` subleading processes
+ in pure jets.
* Allow multiplication and division of multiple scale functions e.g.
`H_T/2*m_j1j2`
* Print cross sections at end of run
* Follow HepMC convention for particle Status codes: incoming = 11,
decaying = 2, outgoing = 1 (unchanged)
* Partons now have a Colour charge
- Colours are read from and written to LHE files
- For reweighted events the colours are created according to leading colour in
the FKL limit
* Allow changing the regulator lambda in input (`regulator parameter`, only for
advanced users)
* Use `git-lfs` for raw data in test (`make test` now requires `git-lfs`)
* Added support to read `hdf5` event files suggested in
[arXiv:1905.05120](https://arxiv.org/abs/1905.05120) (needs
[HighFive](https://github.com/BlueBrain/HighFive))
* Support input with avarage weight equal to the cross section (`IDWTUP=1 or 4`)
* Rename `non-HEJ` Processes to `non-resummable`
* Dropped support for HepMC 3.0.0, either HepMC version 2 or >3.1 is required
- It is now possible to write out both HepMC 2 and HepMC 3 events at the same
time
## 2.0.5
* Fixed event classification for input not ordered in rapidity
### 2.0.4
* Fixed wrong path of `HEJ_INCLUDE_DIR` in `hej-config.cmake`
### 2.0.3
* Fixed parsing of (numerical factor) * (base scale) in configuration
* Don't change scale names, but sanitise Rivet output file names instead
### 2.0.2
* Changed scale names to `"_over_"` and `"_times_"` for proper file names (was
`"/"` and `"*"` before)
### 2.0.1
* Fixed name of fixed-order generator in error message.
diff --git a/FixedOrderGen/include/Subleading.hh b/FixedOrderGen/include/Subleading.hh
index c209b2d..36f2976 100644
--- a/FixedOrderGen/include/Subleading.hh
+++ b/FixedOrderGen/include/Subleading.hh
@@ -1,20 +1,24 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019
* \copyright GPLv2 or later
*/
#pragma once
namespace HEJFOG{
- /**
- * Bit position of different subleading channels
- * e.g. (unsigned int) 1 => only unordered
- */
- enum Subleading: unsigned {
- none = 0u,
- all = ~0u,
- uno = 1u,
- unordered = uno,
- qqx = 2u
- };
+ namespace channels{
+ /**
+ * Bit position of different subleading channels
+ * e.g. (unsigned int) 1 => only unordered
+ */
+ enum Subleading: unsigned {
+ none = 0u,
+ all = ~0u,
+ uno = 1u,
+ unordered = uno,
+ qqx = 2u
+ };
+ }
+
+ using Subleading = channels::Subleading;
}
diff --git a/FixedOrderGen/src/config.cc b/FixedOrderGen/src/config.cc
index 2a87eb6..48aeaff 100644
--- a/FixedOrderGen/src/config.cc
+++ b/FixedOrderGen/src/config.cc
@@ -1,411 +1,409 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019
* \copyright GPLv2 or later
*/
#include "config.hh"
#include <cctype>
#include "Subleading.hh"
#include "HEJ/config.hh"
#include "HEJ/YAMLreader.hh"
namespace HEJFOG{
using HEJ::set_from_yaml;
using HEJ::set_from_yaml_if_defined;
using HEJ::pid::ParticleID;
namespace{
//! Get YAML tree of supported options
/**
* The configuration file is checked against this tree of options
* in assert_all_options_known.
*/
YAML::Node const & get_supported_options(){
const static YAML::Node supported = [](){
YAML::Node supported;
static const auto opts = {
"process", "events", "subleading fraction","subleading channels",
"scales", "scale factors", "max scale ratio", "pdf",
"event output", "analysis", "import scales"
};
// add subnodes to "supported" - the assigned value is irrelevant
for(auto && opt: opts) supported[opt] = "";
for(auto && jet_opt: {"min pt", "peak pt", "algorithm", "R", "max rapidity"}){
supported["jets"][jet_opt] = "";
}
for(auto && particle_type: {"Higgs", "Wp", "W+", "Wm", "W-", "Z"}){
for(auto && particle_opt: {"mass", "width"}){
supported["particle properties"][particle_type][particle_opt] = "";
}
supported["particle properties"][particle_type]["decays"]["into"] = "";
supported["particle properties"][particle_type]["decays"]["branching ratio"] = "";
}
for(auto && opt: {"mt", "use impact factors", "include bottom", "mb"}){
supported["Higgs coupling"][opt] = "";
}
for(auto && beam_opt: {"energy", "particles"}){
supported["beam"][beam_opt] = "";
}
for(auto && unweight_opt: {"sample size", "max deviation"}){
supported["unweight"][unweight_opt] = "";
}
for(auto && opt: {"name", "seed"}){
supported["random generator"][opt] = "";
}
return supported;
}();
return supported;
}
JetParameters get_jet_parameters(
YAML::Node const & node, std::string const & entry
){
const auto p = HEJ::get_jet_parameters(node, entry);
JetParameters result;
result.def = p.def;
result.min_pt = p.min_pt;
set_from_yaml(result.max_y, node, entry, "max rapidity");
set_from_yaml_if_defined(result.peak_pt, node, entry, "peak pt");
if(result.peak_pt && *result.peak_pt <= result.min_pt)
throw std::invalid_argument{
"Value of option 'peak pt' has to be larger than 'min pt'."
};
return result;
}
Beam get_Beam(
YAML::Node const & node, std::string const & entry
){
Beam beam;
std::vector<HEJ::ParticleID> particles;
set_from_yaml(beam.energy, node, entry, "energy");
set_from_yaml_if_defined(particles, node, entry, "particles");
if(! particles.empty()){
for(HEJ::ParticleID particle: particles){
if(particle != HEJ::pid::p && particle != HEJ::pid::p_bar){
throw std::invalid_argument{
"Unsupported value in option " + entry + ": particles:"
" only proton ('p') and antiproton ('p_bar') beams are supported"
};
}
}
if(particles.size() != 2){
throw std::invalid_argument{"Not exactly two beam particles"};
}
beam.particles.front() = particles.front();
beam.particles.back() = particles.back();
}
return beam;
}
std::vector<std::string> split(
std::string const & str, std::string const & delims
){
std::vector<std::string> result;
for(size_t begin, end = 0; end != str.npos;){
begin = str.find_first_not_of(delims, end);
if(begin == str.npos) break;
end = str.find_first_of(delims, begin + 1);
result.emplace_back(str.substr(begin, end - begin));
}
return result;
}
std::invalid_argument invalid_incoming(std::string const & what){
return std::invalid_argument{
"Incoming particle type " + what + " not supported,"
" incoming particles have to be 'p', 'p_bar' or partons"
};
}
std::invalid_argument invalid_outgoing(std::string const & what){
return std::invalid_argument{
"Outgoing particle type " + what + " not supported,"
" outgoing particles have to be 'j', 'photon', 'H', 'Wm', 'Wp', 'e-', 'e+', 'nu_e', 'nu_e_bar'"
};
}
HEJ::ParticleID reconstruct_boson_id(
std::vector<HEJ::ParticleID> const & ids
){
assert(ids.size()==2);
const int pidsum = ids[0] + ids[1];
if(pidsum == +1) {
assert(HEJ::is_antilepton(ids[0]));
if(HEJ::is_antineutrino(ids[0])) {
throw HEJ::not_implemented{"lepton-flavour violating final state"};
}
assert(HEJ::is_neutrino(ids[1]));
// charged antilepton + neutrino means we had a W+
return HEJ::pid::Wp;
}
if(pidsum == -1) {
assert(HEJ::is_antilepton(ids[0]));
if(HEJ::is_neutrino(ids[1])) {
throw HEJ::not_implemented{"lepton-flavour violating final state"};
}
assert(HEJ::is_antineutrino(ids[0]));
// charged lepton + antineutrino means we had a W-
return HEJ::pid::Wm;
}
throw HEJ::not_implemented{
"final state with leptons "+HEJ::name(ids[0])+" and "+HEJ::name(ids[1])
+" not supported"
};
}
Process get_process(
YAML::Node const & node, std::string const & entry
){
Process result;
std::string process_string;
set_from_yaml(process_string, node, entry);
assert(! process_string.empty());
const auto particles = split(process_string, " \n\t\v=>");
if(particles.size() < 3){
throw std::invalid_argument{
"Bad format in option process: '" + process_string
+ "', expected format is 'in1 in2 => out1 ...'"
};
}
result.incoming.front() = HEJ::to_ParticleID(particles[0]);
result.incoming.back() = HEJ::to_ParticleID(particles[1]);
for(size_t i = 0; i < result.incoming.size(); ++i){
const HEJ::ParticleID in = result.incoming[i];
if(
in != HEJ::pid::proton && in != HEJ::pid::p_bar
&& !HEJ::is_parton(in)
){
throw invalid_incoming(particles[i]);
}
}
result.njets = 0;
for(size_t i = result.incoming.size(); i < particles.size(); ++i){
assert(! particles[i].empty());
if(particles[i] == "j") ++result.njets;
else if(std::isdigit(particles[i].front())
&& particles[i].back() == 'j')
result.njets += std::stoi(particles[i]);
else{
const auto pid = HEJ::to_ParticleID(particles[i]);
if(pid==HEJ::pid::Higgs || pid==HEJ::pid::Wp || pid==HEJ::pid::Wm){
if(result.boson)
throw std::invalid_argument{
"More than one outgoing boson is not supported"
};
if(!result.boson_decay.empty())
throw std::invalid_argument{
"Production of a boson together with a lepton is not supported"
};
result.boson = pid;
} else if (HEJ::is_anylepton(pid)){
// Do not accept more leptons, if two leptons are already mentioned
if( result.boson_decay.size()>=2 )
throw std::invalid_argument{"Too many leptons provided"};
if(result.boson)
throw std::invalid_argument{
"Production of a lepton together with a boson is not supported"
};
result.boson_decay.emplace_back(pid);
} else {
throw invalid_outgoing(particles[i]);
}
}
}
if(result.njets < 2){
throw std::invalid_argument{
"Process has to include at least two jets ('j')"
};
}
if(!result.boson_decay.empty()){
std::sort(begin(result.boson_decay),end(result.boson_decay));
assert(!result.boson);
result.boson = reconstruct_boson_id(result.boson_decay);
}
return result;
}
HEJFOG::Subleading to_subleading_channel(YAML::Node const & yaml){
std::string name;
- using HEJFOG::Subleading;
+ using namespace HEJFOG::channels;
set_from_yaml(name, yaml);
if(name == "none")
return none;
if(name == "all")
return all;
if(name == "unordered" || name == "uno")
return uno;
if(name == "qqx")
return qqx;
throw HEJ::unknown_option("Unknown subleading channel '"+name+"'");
}
unsigned int get_subleading_channels(YAML::Node const & node){
using YAML::NodeType;
- using HEJFOG::Subleading;
+ using namespace HEJFOG::channels;
// all channels allowed by default
if(!node) return all;
switch(node.Type()){
case NodeType::Undefined:
return all;
case NodeType::Null:
return none;
case NodeType::Scalar:
return to_subleading_channel(node);
case NodeType::Map:
throw HEJ::invalid_type{"map is not a valid option for subleading channels"};
case NodeType::Sequence:
unsigned int channels = HEJFOG::Subleading::none;
for(auto && channel_node: node){
channels |= get_subleading_channels(channel_node);
}
return channels;
}
throw std::logic_error{"unreachable"};
}
Decay get_decay(YAML::Node const & node){
Decay decay;
set_from_yaml(decay.products, node, "into");
decay.branching_ratio=1;
set_from_yaml_if_defined(decay.branching_ratio, node, "branching ratio");
return decay;
}
std::vector<Decay> get_decays(YAML::Node const & node){
using YAML::NodeType;
if(!node) return {};
switch(node.Type()){
case NodeType::Null:
case NodeType::Undefined:
return {};
case NodeType::Scalar:
throw HEJ::invalid_type{"value is not a list of decays"};
case NodeType::Map:
return {get_decay(node)};
case NodeType::Sequence:
std::vector<Decay> result;
for(auto && decay_str: node){
result.emplace_back(get_decay(decay_str));
}
return result;
}
throw std::logic_error{"unreachable"};
}
ParticleProperties get_particle_properties(
YAML::Node const & node, std::string const & entry
){
ParticleProperties result;
set_from_yaml(result.mass, node, entry, "mass");
set_from_yaml(result.width, node, entry, "width");
try{
result.decays = get_decays(node[entry]["decays"]);
}
catch(HEJ::missing_option const & ex){
throw HEJ::missing_option{entry + ": decays: " + ex.what()};
}
catch(HEJ::invalid_type const & ex){
throw HEJ::invalid_type{entry + ": decays: " + ex.what()};
}
return result;
}
ParticlesPropMap get_all_particles_properties(YAML::Node const & node){
ParticlesPropMap result;
for(auto const & entry: node) {
const auto name = entry.first.as<std::string>();
const auto id = HEJ::to_ParticleID(name);
result.emplace(id, get_particle_properties(node,name));
}
return result;
}
UnweightSettings get_unweight(
YAML::Node const & node, std::string const & entry
){
UnweightSettings result;
set_from_yaml(result.sample_size, node, entry, "sample size");
if(result.sample_size <= 0){
throw std::invalid_argument{
"negative sample size " + std::to_string(result.sample_size)
};
}
set_from_yaml(result.max_dev, node, entry, "max deviation");
return result;
}
Config to_Config(YAML::Node const & yaml){
try{
HEJ::assert_all_options_known(yaml, get_supported_options());
}
catch(HEJ::unknown_option const & ex){
throw HEJ::unknown_option{std::string{"Unknown option '"} + ex.what() + "'"};
}
Config config;
config.process = get_process(yaml, "process");
set_from_yaml(config.events, yaml, "events");
config.jets = get_jet_parameters(yaml, "jets");
config.beam = get_Beam(yaml, "beam");
for(size_t i = 0; i < config.process.incoming.size(); ++i){
const auto & in = config.process.incoming[i];
using namespace HEJ::pid;
if( (in == p || in == p_bar) && in != config.beam.particles[i]){
throw std::invalid_argument{
"Particle type of beam " + std::to_string(i+1) + " incompatible"
+ " with type of incoming particle " + std::to_string(i+1)
};
}
}
set_from_yaml(config.pdf_id, yaml, "pdf");
set_from_yaml(config.subleading_fraction, yaml, "subleading fraction");
if(config.subleading_fraction < 0 || config.subleading_fraction > 1){
throw std::invalid_argument{
"subleading fraction has to be between 0 and 1"
};
}
if(config.subleading_fraction == 0)
config.subleading_channels = Subleading::none;
else
config.subleading_channels = get_subleading_channels(yaml["subleading channels"]);
- if(!config.process.boson && config.subleading_channels != Subleading::none)
- throw HEJ::not_implemented("Subleading processes for pure Jet production not implemented yet");
if(yaml["particle properties"]){
config.particles_properties = get_all_particles_properties(
yaml["particle properties"]);
}
if(config.process.boson
&& config.particles_properties.find(*(config.process.boson))
== config.particles_properties.end())
throw HEJ::missing_option("Process wants to generate boson "
+std::to_string(*(config.process.boson))+", but particle properties are missing");
set_from_yaml_if_defined(config.analysis_parameters, yaml, "analysis");
config.scales = HEJ::to_ScaleConfig(yaml);
set_from_yaml_if_defined(config.output, yaml, "event output");
config.rng = HEJ::to_RNGConfig(yaml, "random generator");
config.Higgs_coupling = HEJ::get_Higgs_coupling(yaml, "Higgs coupling");
if(yaml["unweight"]) config.unweight = get_unweight(yaml, "unweight");
return config;
}
} // namespace anonymous
Config load_config(std::string const & config_file){
try{
return to_Config(YAML::LoadFile(config_file));
}
catch(...){
std::cerr << "Error reading " << config_file << ":\n ";
throw;
}
}
}
diff --git a/doc/developer_manual/currents.tex b/doc/developer_manual/currents.tex
index 8892772..16e795c 100644
--- a/doc/developer_manual/currents.tex
+++ b/doc/developer_manual/currents.tex
@@ -1,592 +1,592 @@
\section{Currents}
\label{sec:currents_impl}
The following section contains a list of all the currents implemented
in \HEJ. Clean up of the code structure is ongoing. All $W$+Jet currents
are located in \texttt{src/Wjets.cc}, all Higgs+Jets currents are
defined in \texttt{src/Hjets.cc}, and pure jet currents are defined in
in \texttt{src/jets.cc}. All of these have their own separate header
files: \texttt{include/HEJ/Wjets.hh}, \texttt{include/HEJ/Hjets.hh} and
\texttt{include/HEJ/jets.hh} respectively.
The naming convention for the current contraction $\left\|S_{f_1 f_2\to f_1
f_2}\right\|^2$ is \lstinline!ME_[Boson]_[subleading-type]_[incoming]!. For
example \lstinline!ME_W_unob_qq! corresponds to the contraction $j_W^\mu
j_{\text{uno}, \mu}$ ($qQ\to \bar{q}WQg$). For bosons on the same side as the
subleading we drop the connecting underscore, e.g. \lstinline!ME_Wuno_qq!
gives $j_{W,\text{uno}}^\mu j_\mu$ ($qQ\to g\bar{q}WQ$).
\subsection{Pure Jets}
\subsubsection{Quark}
\label{sec:current_quark}
\begin{align}
j_\mu(p_i,p_j)=\bar{u}(p_i)\gamma_\mu u(p_j)
\end{align}
The exact for depends on the helicity and direction (forward/backwards) for the quarks. Currently all different contractions of incoming and outgoing states are defined in \lstinline!joi!, \lstinline!jio! and \lstinline!joo!.
\subsubsection{Gluon}
In \HEJ the currents for gluons and quarks are the same, up to a colour factor $K_g/C_F$, where
\begin{align}
K_g(p_1^-, p_a^-) = \frac{1}{2}\left(\frac{p_1^-}{p_a^-} + \frac{p_a^-}{p_1^-}\right)\left(C_A -
\frac{1}{C_A}\right)+\frac{1}{C_A}.
\end{align}
Thus we can just reuse the results from sec.~\ref{sec:current_quark}.
\subsubsection{Single unordered gluon}
Configuration $q(p_a) \to g(p_1) q(p_2) g^*(\tilde{q}_2)$~\cite{Andersen:2017kfc}
\begin{align}
\label{eq:juno}
\begin{split}
&j^{{\rm uno}\; \mu\ cd}(p_2,p_1,p_a) = i \varepsilon_{1\nu} \left( T_{2i}^{c}T_{ia}^d\
\left(U_1^{\mu\nu}-L^{\mu\nu} \right) + T_{2i}^{d}T_{ia}^c\ \left(U_2^{\mu\nu} +
L^{\mu\nu} \right) \right). \\
U_1^{\mu\nu} &= \frac1{s_{21}} \left( j_{21}^\nu j_{1a}^\mu + 2 p_2^\nu
j_{2a}^\mu \right) \qquad \qquad U_2^{\mu\nu} = \frac1{t_{a1}} \left( 2
j_{2a}^\mu p_a^\nu - j_{21}^\mu j_{1a}^\nu \right) \\
L^{\mu\nu} &= \frac1{t_{a2}} \left(-2p_1^\mu j_{2a}^\nu+2p_1.j_{2a}
g^{\mu\nu} + (\tilde{q}_1+\tilde{q}_2)^\nu j_{2a}^\mu + \frac{t_{b2}}{2} j_{2a}^\mu \left(
\frac{p_2^\nu}{p_1.p_2} + \frac{p_b^\nu}{p_1.p_b} \right) \right) ,
\end{split}
\end{align}
-$j^{{\rm uno}\; \mu}$ is currently not calculated as a separate current, but always as needed for the ME (i.e. in \lstinline!jM2unoXXX!).
+$j^{{\rm uno}\; \mu}$ is currently not calculated as a separate current, but always as needed for the ME (i.e. in \lstinline!ME_unob_XX!).
\subsection{Higgs}
Different rapidity orderings \todo{give name of functions}
\begin{enumerate}
\item $qQ\to HqQ/qHQ/qQH$ (any rapidity order, full LO ME) $\Rightarrow$ see~\ref{sec:V_H}
\item $qg\to Hqg$ (Higgs outside quark) $\Rightarrow$ see~\ref{sec:V_H}
\item $qg\to qHg$ (central Higgs) $\Rightarrow$ see~\ref{sec:V_H}
\item $qg\to qgH$ (Higgs outside gluon) $\Rightarrow$ see~\ref{sec:jH_mt}
\item $gg\to gHg$ (central Higgs) $\Rightarrow$ see~\ref{sec:V_H}
\item $gg\to ggH$ (Higgs outside gluon) $\Rightarrow$ see~\ref{sec:jH_mt}
\end{enumerate}
\subsubsection{Higgs gluon vertex}
\label{sec:V_H}
The coupling of the Higgs boson to gluons via a virtual quark loop can be written as
\begin{align}
\label{eq:VH}
V^{\mu\nu}_H(q_1, q_2) = \mathgraphics{build/figures/V_H.pdf} &=
\frac{\alpha_s m^2}{\pi v}\big[
g^{\mu\nu} T_1(q_1, q_2) - q_2^\mu q_1^\nu T_2(q_1, q_2)
\big]\, \\
&\xrightarrow{m \to \infty} \frac{\alpha_s}{3\pi
v} \left(g^{\mu\nu} q_1\cdot q_2 - q_2^\mu q_1^\nu\right).
\end{align}
The outgoing momentum of the Higgs boson is $p_H = q_1 - q_2$.
As a contraction with two currents this by implemented in \lstinline!cHdot! inside \texttt{src/Hjets.cc}.
The form factors $T_1$ and $T_2$ are then given by~\cite{DelDuca:2003ba}
\begin{align}
\label{eq:T_1}
T_1(q_1, q_2) ={}& -C_0(q_1, q_2)\*\left[2\*m^2+\frac{1}{2}\*\left(q_1^2+q_2^2-p_H^2\right)+\frac{2\*q_1^2\*q_2^2\*p_H^2}{\lambda}\right]\notag\\
&-\left[B_0(q_2)-B_0(p_H)\right]\*\frac{q_2^2}{\lambda}\*\left(q_2^2-q_1^2-p_H^2\right)\notag\\
&-\left[B_0(q_1)-B_0(p_H)\right]\*\frac{q_1^2}{\lambda}\*\left(q_1^2-q_2^2-p_H^2\right)-1\,,\displaybreak[0]\\
\label{eq:T_2}
T_2(q_1, q_2) ={}& C_0(q_1,
q_2)\*\left[\frac{4\*m^2}{\lambda}\*\left(p_H^2-q_1^2-q_2^2\right)-1-\frac{4\*q_1^2\*q_2^2}{\lambda}
-
\frac{12\*q_1^2\*q_2^2\*p_H^2}{\lambda^2}\*\left(q_1^2+q_2^2-p_H^2\right)\right]\notag\\
&-\left[B_0(q_2)-B_0(p_H)\right]\*\left[\frac{2\*q_2^2}{\lambda}+\frac{12\*q_1^2\*q_2^2}{\lambda^2}\*\left(q_2^2-q_1^2+p_H^2\right)\right]\notag\\
&-\left[B_0(q_1)-B_0(p_H)\right]\*\left[\frac{2\*q_1^2}{\lambda}+\frac{12\*q_1^2\*q_2^2}{\lambda^2}\*\left(q_1^2-q_2^2+p_H^2\right)\right]\notag\\
&-\frac{2}{\lambda}\*\left(q_1^2+q_2^2-p_H^2\right)\,,
\end{align}
where we have used the scalar bubble and triangle integrals
\begin{align}
\label{eq:B0}
B_0\left(p\right) ={}& \int \frac{d^dl}{i\pi^{\frac{d}{2}}}
\frac{1}{\left(l^2-m^2\right)\left((l+p)^2-m^2\right)}\,,\\
\label{eq:C0}
C_0\left(p,q\right) ={}& \int \frac{d^dl}{i\pi^{\frac{d}{2}}} \frac{1}{\left(l^2-m^2\right)\left((l+p)^2-m^2\right)\left((l+p-q)^2-m^2\right)}\,,
\end{align}
and the K\"{a}ll\'{e}n function
\begin{equation}
\label{eq:lambda}
\lambda = q_1^4 + q_2^4 + p_H^4 - 2\*q_1^2\*q_2^2 - 2\*q_1^2\*p_H^2- 2\*q_2^2\*p_H^2\,.
\end{equation}
The Integrals as such are provided by \QCDloop{} (see wrapper functions \lstinline!B0DD! and \lstinline!C0DD! in \texttt{src/Hjets.cc}).
In the code we are sticking to the convention of~\cite{DelDuca:2003ba}, thus instead of the $T_{1/2}$ we implement (in the functions \lstinline!A1! and \lstinline!A2!)
\begin{align}
\label{eq:A_1}
A_1(q_1, q_2) ={}& \frac{i}{16\pi^2}\*T_2(-q_1, q_2)\,,\\
\label{eq:A_2}
A_2(q_1, q_2) ={}& -\frac{i}{16\pi^2}\*T_1(-q_1, q_2)\,.
\end{align}
\subsubsection{Peripheral Higgs emission - Finite quark mass}
\label{sec:jH_mt}
We describe the emission of a peripheral Higgs boson close to a
scattering gluon with an effective current. In the following we consider
a lightcone decomposition of the gluon momenta, i.e. $p^\pm = E \pm p_z$
and $p_\perp = p_x + i p_y$. The incoming gluon momentum $p_a$ defines
the $-$ direction, so that $p_a^+ = p_{a\perp} = 0$. The outgoing
momenta are $p_1$ for the gluon and $p_H$ for the Higgs boson. We choose
the following polarisation vectors:
\begin{equation}
\label{eq:pol_vectors}
\epsilon_\mu^\pm(p_a) = \frac{j_\mu^\pm(p_1, p_a)}{\sqrt{2}
\bar{u}^\pm(p_a)u^\mp(p_1)}\,, \quad \epsilon_\mu^{\pm,*}(p_1) = -\frac{j_\mu^\pm(p_1, p_a)}{\sqrt{2}
\bar{u}^\mp(p_1)u^\pm(p_a)}\,.
\end{equation}
Following~\cite{DelDuca:2001fn}, we introduce effective polarisation
vectors to describe the contraction with the Higgs-boson production
vertex eq.~\eqref{eq:VH}:
\begin{align}
\label{eq:eps_H}
\epsilon_{H,\mu}(p_a) = \frac{T_2(p_a, p_a-p_H)}{(p_a-p_H)^2}\big[p_a\cdot
p_H\epsilon_\mu(p_a) - p_H\cdot\epsilon(p_a) p_{a,\mu}\big]\,,\\
\epsilon_{H,\mu}^*(p_1) = -\frac{T_2(p_1+p_H, p_1)}{(p_1+p_H)^2}\big[p_1\cdot
p_H\epsilon_\mu^*(p_1) - p_H\cdot\epsilon^*(p_1) p_{1,\mu}\big]\,,
\end{align}
We also employ the usual short-hand notation
\begin{equation}
\label{eq:spinor_helicity}
\spa i.j = \bar{u}^-(p_i)u^+(p_j)\,,\qquad \spb i.j =
\bar{u}^+(p_i)u^-(p_j)\,, \qquad[ i | H | j\rangle = j_\mu^+(p_i, p_j)p_H^\mu\,.
\end{equation}
Without loss of generality, we consider only the case where the incoming
gluon has positive helicity. The remaining helicity configurations can
be obtained through parity transformation.
Labelling the effective current by the helicities of the gluons we obtain
for the same-helicity case
\begin{equation}
\label{eq:jH_same_helicity}
\begin{split}
j_{H,\mu}^{++}{}&(p_1,p_a,p_H) =
\frac{m^2}{\pi v}\bigg[\\
&-\sqrt{\frac{2p_1^-}{p_a^-}}\frac{p_{1\perp}^*}{|p_{1\perp}|}\frac{t_2}{\spb a.1}\epsilon^{+,*}_{H,\mu}(p_1)
+\sqrt{\frac{2p_a^-}{p_1^-}}\frac{p_{1\perp}^*}{|p_{1\perp}|}\frac{t_2}{\spa 1.a}\epsilon^{+}_{H,\mu}(p_a)\\
&+ [1|H|a\rangle \bigg(
\frac{\sqrt{2}}{\spa 1.a}\epsilon^{+}_{H,\mu}(p_a)
+ \frac{\sqrt{2}}{\spb a.1}\epsilon^{+,*}_{H,\mu}(p_1)-\frac{\spa 1.a T_2(p_a, p_a-p_H)}{\sqrt{2}(p_a-p_H)^2}\epsilon^{+,*}_{\mu}(p_1)\\
&
\qquad
-\frac{\spb a.1 T_2(p_1+p_H,
p_1)}{\sqrt{2}(p_1+p_H)^2}\epsilon^{+}_{\mu}(p_a)-\frac{RH_4}{\sqrt{2}\spb a.1}\epsilon^{+,*}_{\mu}(p_1)+\frac{RH_5}{\sqrt{2}\spa 1.a}\epsilon^{+}_{\mu}(p_a)
\bigg)\\
&
- \frac{[1|H|a\rangle^2}{2 t_1}(p_{a,\mu} RH_{10} - p_{1,\mu} RH_{12})\bigg]
\end{split}
\end{equation}
with $t_1 = (p_a-p_1)^2$, $t_2 = (p_a-p_1-p_H)^2$ and $R = 8 \pi^2$. Eq.~\eqref{eq:jH_same_helicity}
is implemented by \lstinline!g_gH_HC! in \texttt{src/Hjets.cc}
\footnote{\lstinline!g_gH_HC! and \lstinline!g_gH_HNC! includes an additional
$1/t_2$ factor, which should be in the Matrix element instead.}.
The currents with a helicity flip is given through
\begin{equation}
\label{eq:jH_helicity_flip}
\begin{split}
j_{H,\mu}^{+-}{}&(p_1,p_a,p_H) =
\frac{m^2}{\pi v}\bigg[\\
&-\sqrt{\frac{2p_1^-}{p_a^-}}\frac{p_{1\perp}^*}{|p_{1\perp}|}\frac{t_2}{\spb
a.1}\epsilon^{-,*}_{H,\mu}(p_1)
+\sqrt{\frac{2p_a^-}{p_1^-}}\frac{p_{1\perp}}{|p_{1\perp}|}\frac{t_2}{\spb a.1}\epsilon^{+}_{H,\mu}(p_a)\\
&+ [1|H|a\rangle \left(
\frac{\sqrt{2}}{\spb a.1} \epsilon^{-,*}_{H,\mu}(p_1)
-\frac{\spa 1.a T_2(p_a, p_a-p_H)}{\sqrt{2}(p_a-p_H)^2}\epsilon^{-,*}_{\mu}(p_1)
- \frac{RH_4}{\sqrt{2}\spb a.1}\epsilon^{-,*}_{\mu}(p_1)\right)
\\
&+ [a|H|1\rangle \left(
\frac{\sqrt{2}}{\spb a.1}\epsilon^{+}_{H,\mu}(p_a)
-\frac{\spa 1.a
T_2(p_1+p_H,p_1)}{\sqrt{2}(p_1+p_H)^2}\epsilon^{+}_{\mu}(p_a)
+\frac{RH_5}{\sqrt{2}\spb a.1}\epsilon^{+}_{\mu}(p_a)
\right)\\
& - \frac{[1|H|a\rangle [a|H|1\rangle}{2 \spb a.1 ^2}(p_{a,\mu} RH_{10} - p_{1,\mu}
RH_{12})\\
&+ \frac{\spa 1.a}{\spb a.1}\bigg(RH_1p_{1,\mu}-RH_2p_{a,\mu}+2
p_1\cdot p_H \frac{T_2(p_1+p_H, p_1)}{(p_1+p_H)^2} p_{a,\mu}
\\
&
\qquad- 2p_a \cdot p_H \frac{T_2(p_a, p_a-p_H)}{(p_a-p_H)^2} p_{1,\mu}+ T_1(p_a-p_1, p_a-p_1-p_H)\frac{(p_1 + p_a)_\mu}{t_1}\\
&\qquad-\frac{(p_1+p_a)\cdot p_H}{t_1} T_2(p_a-p_1, p_a-p_1-p_H)(p_1 - p_a)_\mu
\bigg)
\bigg]\,,
\end{split}
\end{equation}
and implemented by \lstinline!g_gH_HNC! again in \texttt{src/Hjets.cc}.
If we instead choose the gluon momentum in the $+$ direction, so that
$p_a^- = p_{a\perp} = 0$, the corresponding currents are obtained by
replacing $p_1^- \to p_1^+, p_a^- \to p_a^+,
\frac{p_{1\perp}}{|p_{1\perp}|} \to -1$ in the second line of
eq.~\eqref{eq:jH_same_helicity} and eq.~\eqref{eq:jH_helicity_flip} (see variables \lstinline!ang1a! and \lstinline!sqa1! in the implementation).
The form factors $H_1,H_2,H_4,H_5, H_{10}, H_{12}$ are given in~\cite{DelDuca:2003ba}, and are implemented under their name in \texttt{src/Hjets.cc}. They reduce down to fundamental QCD integrals, which are again provided by \QCDloop.
\subsubsection{Peripheral Higgs emission - Infinite top mass}
\label{sec:jH_eff}
To get the result with infinite top mass we could either take the limit $m_t\to \infty$ in~\eqref{eq:jH_helicity_flip} and~\eqref{eq:jH_same_helicity}, or use the \textit{impact factors} as given in~\cite{DelDuca:2003ba}. Both methods are equivalent, and lead to the same result. For the first one would find
\begin{align}
\lim_{m_t\to\infty} m_t^2 H_1 &= i \frac{1}{24 \pi^2}\\
\lim_{m_t\to\infty} m_t^2 H_2 &=-i \frac{1}{24 \pi^2}\\
\lim_{m_t\to\infty} m_t^2 H_4 &= i \frac{1}{24 \pi^2}\\
\lim_{m_t\to\infty} m_t^2 H_5 &=-i \frac{1}{24 \pi^2}\\
\lim_{m_t\to\infty} m_t^2 H_{10} &= 0 \\
\lim_{m_t\to\infty} m_t^2 H_{12} &= 0.
\end{align}
\todo{double check this, see James thesis eq. 4.33}
However only the second method is implemented in the code through \lstinline!C2gHgp!
and \lstinline!C2gHgm! inside \texttt{src/Hjets.cc}, each function
calculates the square of eq. (4.23) and (4.22) from~\cite{DelDuca:2003ba} respectively.
\subsection{$W$+Jets}
\label{sec:currents_W}
\subsubsection{Quark+$W$}
\begin{figure}
\centering
\begin{minipage}[b]{0.2\textwidth}
\includegraphics[width=\textwidth]{figures/Wbits.pdf}
\end{minipage}
\begin{minipage}[b]{0.1\textwidth}
\centering{=}
\vspace{0.7cm}
\end{minipage}
\begin{minipage}[b]{0.2\textwidth}
\includegraphics[width=\textwidth]{figures/Wbits2.pdf}
\end{minipage}
\begin{minipage}[b]{0.1\textwidth}
\centering{+}
\vspace{0.7cm}
\end{minipage}
\begin{minipage}[b]{0.2\textwidth}
\includegraphics[width=\textwidth]{figures/Wbits3.pdf}
\end{minipage}
\caption{The $j_W$ current is constructed from the two diagrams which
contribute to the emission of a $W$-boson from a given quark line.}
\label{fig:jW}
\end{figure}
For a $W$ emission we require a fermion. The $j_W$ current is actually a sum of
two separate contributions, see figure~\ref{fig:jW}, one with a $W$-emission
from the initial state, and one with the $W$-emission from the final state.
Mathematically this can be seen as the following two
terms~\cite{Andersen:2012gk}\todo{cite W subleading paper}:
\begin{align}
\label{eq:Weffcur1}
j_W^\mu(p_a,p_{\ell},p_{\bar{\ell}}, p_1) =&\ \frac{g_W^2}{2}\
\frac1{p_W^2-M_W^2+i\ \Gamma_W M_W}\ \bar{u}^-(p_\ell) \gamma_\alpha
v^-(p_{\bar\ell})\nonumber \\
& \cdot \left( \frac{ \bar{u}^-(p_1) \gamma^\alpha (\slashed{p}_W +
\slashed{p}_1)\gamma^\mu u^-(p_a)}{(p_W+p_1)^2} +
\frac{ \bar{u}^-(p_1)\gamma^\mu (\slashed{p}_a + \slashed{p}_W)\gamma^\alpha u^-(p_a)}{(p_a-p_W)^2} \right).
\end{align}
There are a couple of subtleties here. There is a minus sign
distinction between the quark-anti-quark cases due to the fermion flow
of the propagator in the current. Note that the type of $W$ emission
(+ or -) will depend on the quark flavour, and that the handedness of
the quark-line is given by whether its a quark or anti-quark.
\subsubsection{$W$+uno}
\begin{figure}
\centering
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{figures/wuno1}
\caption{}
\label{fig:U1diags}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{figures/wuno2}
\caption{}
\label{fig:U2diags}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{figures/wuno3}
\caption{}
\label{fig:Cdiags}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{figures/wuno4}
\caption{}
\label{fig:Ddiags}
\end{subfigure}
\vspace{0.4cm}
\caption{Examples of each of the four categories of Feynman diagram which
contribute to at leading-order; there are twelve in total. (a) is an example where the gluon and $W$
boson are emitted from the same quark line and the gluon comes after the
$t$-channel propagator. In (b), the gluon and $W$ boson are emitted from
the same quark line and the gluon comes before the $t$-channel proagator.
In (c) the gluon is emitted from the $t$-channel gluon and in (d) the gluon
is emitted from the $b$--$3$ quark line.}
\label{fig:Wunodiags}
\end{figure}
It is necessary to include subleading processes in $W$+Jets also. All of
these currents have been built for the \lstinline!Tensor! Class detailed in
section~\ref{sec:tensor}. Similarly to the pure jet case, the uno currents are
not calculated separately, and only in the ME functions when required
in the \texttt{src/Wjets.cc} file. For unordered emissions a new
current is required, $j_{W,{\rm uno}}$, it is only non-zero for
$h_a=h_1=-$ and hence we have suppressed its helicity indices. It is
derived from the 12 leading-order Feynman diagrams in the QMRK
limit (see figure~\ref{fig:Wunodiags}). Using $T^m_{ij}$ represent fundamental
colour matrices between quark state $i$ and $j$ with adjoint index $m$ we find
\begin{align}\label{eq:wunocurrent}
\begin{split}
j^{d\,\mu}_{\rm W,uno}(p_a,p_1,p_2,p_\ell,p_{\bar{\ell}}) =& \ i \varepsilon_{\nu}(p_1)\
\bar{u}^-(p_\ell) \gamma_\rho v^-(p_{\bar \ell}) \\ & \quad \times\
\left(T^1_{2i} T^d_{ia} (\tilde U_1^{\nu\mu\rho}-\tilde L^{\nu\mu\rho}) +
T^d_{2i} T^1_{ia} (\tilde U_2^{\nu\mu\rho}+\tilde L^{\nu\mu\rho}) \right),
\end{split}
\end{align}
where expressions for $\tilde U_{1,2}^{\nu\mu\rho}$ and $\tilde L^{\nu\mu\rho}$
are given as:
\begin{align}
\label{eq:U1tensor}
\begin{split}
\tilde U_1^{\nu\mu\rho} =&\frac{\langle 2|\nu (\slashed{p}_2+ \slashed{p}_1)\mu (\slashed{p}_a - \slashed{p}_W)\rho P_L |a\rangle }{s_{12}t_{aW}} + \frac{\langle 2|\nu (\slashed{p}_2+ \slashed{p}_1)\rho P_L (\slashed{p}_2+\slashed{p}_1 + \slashed{p}_W)\mu |a\rangle }{s_{12}s_{12W}} \\
&+ \frac{\langle 2|\rho P_L (\slashed{p}_2+ \slashed{p}_W) \nu
(\slashed{p}_1 + \slashed{p}_2+\slashed{p}_W)\mu |a\rangle}{s_{2W}s_{12W}}.
\end{split}
\end{align}
\begin{align}
\label{eq:U2tensor}
\begin{split}
\tilde U_2^{\nu\mu\rho} =&\frac{\langle 2|\mu (\slashed{p}_a-\slashed{p}_W-\slashed{p}_1)\nu (\slashed{p}_a - \slashed{p}_W)\rho P_L |a\rangle }{t_{aW1}t_{aW}} + \frac{\langle 2|\mu (\slashed{p}_a-\slashed{p}_W- \slashed{p}_1)\rho P_L (\slashed{p}_a-\slashed{p}_1) \nu |a\rangle }{t_{a1W}t_{a1}} \\
&+ \frac{\langle 2|\rho P_L (\slashed{p}_2+ \slashed{p}_W) \mu
(\slashed{p}_a-\slashed{p}_1)\nu |a\rangle}{s_{2W}t_{a1}}.
\end{split}
\end{align}
\begin{align}
\label{eq:Ltensor}
\tilde L^{\nu\mu\rho} &= \frac{q_2^2}{2t_{aW2}} \left[\frac{\langle 2 |\mu (\slashed{p}_a - \slashed{p}_W) \rho P_L | a\rangle}{t_{aW}} + \frac{\langle 2 |\rho P_L (\slashed{p}_2 + \slashed{p}_W) \mu | a\rangle }{s_{2W}} \right]
\cdot \left( \frac{p_b^{\nu}}{p_b\cdot p_1} + \frac{p_3^{\nu}}{p_3\cdot p_1} \right) \nonumber \\
&\quad+\frac{1}{t_{aW2}}\left[\frac{\langle 2 |\sigma (\slashed{p}_a - \slashed{p}_W) \rho P_L | a\rangle}{t_{aW}} + \frac{\langle 2 |\rho P_L (\slashed{p}_2 + \slashed{p}_W) \sigma | a\rangle }{s_{2W}} \right] \nonumber \\
&\vphantom{+\frac{1}{t_{aW2}}}\quad\cdot \left( g^{\sigma \mu} (q_1 +q_2)^\nu + g^{\mu \nu}(-q_2 +p_1)^\sigma+ g^{\nu \sigma}(-p_1 -q_1)^\mu \right).
\end{align}
\subsubsection{$W$+Extremal $\mathbf{q\bar{q}}$}
The $W$+Jet sub-leading processes containing an extremal $q\bar{q}$ are
related by crossing symmetry to the $W$+Jet unordered processes. This
means that one can simply perform a crossing symmetry argument on
eq.~\ref{eq:wunocurrent} to arrive at the extremal $q\bar{q}$ current
required.We show the basic structure of the extremal $q\bar{q}$
current in figure~\ref{fig:qgimp}, neglecting the $W$-emission for
simplicity.
\begin{figure}
\centering
\includegraphics[width=0.3\textwidth]{{qqbarex_schem}}
\caption{Schematic structure of the $gq \to \bar{Q}Qq$ amplitude in the limit
$y_1 \sim y_2 \ll y_3$}
\label{fig:qgimp}
\end{figure}
\begin{figure}
\centering
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarex1}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarex2}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarex4}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarex5}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{qqbarex3}
\end{subfigure}
\caption{The five tree-level graphs which contribute to the process $gq \to \bar{Q}Qq$.}
\label{fig:qg_qQQ_graphs}
\end{figure}
We can obtain the current for $g\rightarrow W q \bar{q}$ by evaluating
the current for $W$ plus unordered emissions with the normal arguments
$p_a \leftrightarrow -p_1 $ interchanged. This is a non-trivial
statement: due to the minimality of the approximations made, the
crossing symmetry normally present in the full amplitude may be
extended to the factorised current.
We must again note that swapping $p_a \leftrightarrow -p_1$ will lead
to $u$-spinors with momenta with negative energy. These are identical
to $v$-spinors with momenta with positive energy, up to an overall
phase which is common to all terms, and can therefore be neglected.
Mathematically, this is given by:
\begin{align}\label{eq:crossedJ}
j^\mu_{\rm W,g\to Q\bar{Q}}(p_a,p_1,p_2,p_\ell,p_{\bar{\ell}}) =i \varepsilon_{g\nu}
\langle \ell | \rho | \bar \ell \rangle_L
\left(T^1_{2i} T^d_{ia} (\tilde U_{1,X}^{\nu\mu\rho}-\tilde L^{\nu\mu\rho}_X) + T^d_{2i} T^1_{ia} (\tilde U_{2,X}^{\nu\mu\rho}+\tilde L_X^{\nu\mu\rho}) \right),
\end{align}
where the components are now given by
\begin{align}
\label{eq:U1tensorX}
\begin{split}
\tilde U_{1,X}^{\nu\mu\rho} =&\frac{\langle 2|\nu (\slashed{p}_a- \slashed{p}_2)\mu (\slashed{p}_1 + \slashed{p}_W)\rho P_L |1\rangle }{t_{a2}s_{1W}} + \frac{\langle 2|\nu (\slashed{p}_a- \slashed{p}_2)\rho P_L (\slashed{p}_a-\slashed{p}_2 - \slashed{p}_W)\mu |1\rangle }{t_{a2}t_{a2W}} \\
&- \frac{\langle 2|\rho P_L (\slashed{p}_2+ \slashed{p}_W) \nu
(\slashed{p}_a - \slashed{p}_2-\slashed{p}_W)\mu
|1\rangle}{s_{2W}t_{a2W}}, \\
\tilde U_{2,X}^{\nu\mu\rho} =&-\frac{\langle 2|\mu (\slashed{p}_a-\slashed{p}_W-\slashed{p}_1)\nu (\slashed{p}_1 + \slashed{p}_W)\rho P_L |1\rangle }{t_{aW1}s_{1W}} + \frac{\langle 2|\mu (\slashed{p}_a-\slashed{p}_W- \slashed{p}_1)\rho P_L (\slashed{p}_a-\slashed{p}_1) \nu |1\rangle }{t_{a1W}t_{a1}} \\
&+ \frac{\langle 2|\rho P_L (\slashed{p}_2+ \slashed{p}_W) \mu
(\slashed{p}_a-\slashed{p}_1)\nu |1\rangle}{s_{2W}t_{a1}}, \\
\tilde L^{\nu\mu\rho}_X &= \frac{q_2^2}{2s_{1W2}} \left[\frac{\langle 2 |\mu (\slashed{p}_1 + \slashed{p}_W) \rho P_L | 1\rangle}{s_{1W}} + \frac{\langle 2 |\rho P_L (\slashed{p}_2 + \slashed{p}_W) \mu | 1\rangle }{s_{2W}} \right]
\cdot \left( \frac{p_b^{\nu}}{p_a\cdot p_b} + \frac{p_3^{\nu}}{p_a\cdot p_3} \right) \\
&\quad+\frac{1}{s_{W12}}\left[-\frac{\langle 2 |\sigma (\slashed{p}_1 + \slashed{p}_W) \rho P_L | a\rangle}{t_{aW}} + \frac{\langle 2 |\rho P_L (\slashed{p}_2 + \slashed{p}_W) \sigma | 1\rangle }{s_{2W}} \right] \\
&\vphantom{+\frac{1}{t_{aW2}}}\quad\cdot \left( g^{\sigma \mu} (q_1 +q_2)^\nu + g^{\mu \nu}(-q_2 +p_1)^\sigma+ g^{\nu \sigma}(-p_1 -q_1)^\mu \right).
\end{split}
\end{align}
Notice in particular the similarity to the $W$+uno scenario (from which
this has been derived).
\subsubsection{Central $\mathbf{q\bar{q}}$ Vertex}
The final subleading process in the $W$+Jet case is the Central
$q\bar{q}$ vertex. This subleading process does not require an altered
current, but an effective vertex which is contracted with two regular
\HEJ currents. This complexity is dealt with nicely by the \lstinline!Tensor!
class, which is detailed in section~\ref{sec:tensor}.
The $W$-emission can be from the central effective vertex (scenario
dealt with by the function \texttt{jM2WqqtoqQQq()} in the file
\texttt{src/Wjets.cc}); or from either of the external quark legs
(scenario dealt with by \texttt{jM2WqqtoqQQqW()} in same file). In
the pure jets case, there are 7 separate diagrams which contribute to
this, which can be seen in figure~\ref{fig:qq_qQQq_graphs}. In the $W$+Jets
case, there are then 45 separate contributions.
\begin{figure}
\centering
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{figures/qqbarcen1}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{figures/qqbarcen2}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{figures/qqbarcen3}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{figures/qqbarcen4}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{figures/qqbarcen5}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{figures/qqbarcen6}
\end{subfigure}
\begin{subfigure}{0.45\textwidth}
\centering
\includegraphics{figures/qqbarcen7}
\end{subfigure}
\caption{All Feynman diagrams which contribute to $qq' \to qQ\bar{Q}q'$ at
leading order.}
\label{fig:qq_qQQq_graphs}
\end{figure}
The end result is of the effective vertex, after derivation, is:
\begin{align}
\label{eq:EffectiveVertexqqbar}
\begin{split}
V^{\mu\nu}_{\text{Eff}}=&
\frac{C_1}{s_{23AB}}\left(X^{\mu\nu\sigma}_{1a}\hat{t_1} + X^{\mu\nu\sigma}_{4b}\hat{t_3} +V^{\mu\nu\sigma}_{3g}\right)J_{\text{V} \sigma}(p_2,p_A,p_B,p_3)
\\
&\quad +iC_2X^{\mu\nu}_{Unc}+iC_3X^{\mu\nu}_{Cro},
\end{split}
\end{align}
where:
\begin{eqnarray}
\begin{split}
C_1=&T^e_{1q}T^g_{qa}T^e_{23}T^g_{4b} -
T^g_{1q}T^e_{qa}T^e_{23}T^g_{4b} = f^{egc}T^c_{1a}T^e_{23}T^g_{4b},
\\
C_2=&T^g_{1a}T^g_{2q}T^{g'}_{q3}T^{g'}_{4b}
\\
C_3=&T^g_{1a}T^{g'}_{2q}T^g_{q3}T^{g'}_{4b}
\end{split}
\end{eqnarray}
are the colour factors of different contributions. The following
tensor structures correspond to groupings of diagrams in
figure~\ref{fig:qq_qQQq_graphs}.
\begin{eqnarray}
\label{eq:1aFixed}
X_{1a}^{\mu\nu\sigma} &=
\frac{-g^{\mu\nu}}{s_{23AB}\hat{t_3}}\left(\frac{p^\sigma_a}{(s_{a23AB})} +
\frac{p^\sigma_1}{(s_{123AB})}\right)
\\
\label{eq:4bFixed}
X_{4b}^{\mu\nu\sigma}
&=\frac{g^{\mu\nu}}{s_{23AB}\hat{t_1}}\left(\frac{p^\sigma_b}{(s_{23bAB})}+\frac{p^\sigma_4}{(s_{234AB}}\right)
\end{eqnarray}
correspond to the first and second row of diagrams in figure~\ref{fig:qq_qQQq_graphs}.
\begin{align}
\label{eq:3GluonWEmit}
\begin{split}
X^{\mu\nu}_{3g}=\frac{1}{
\hat{t}_1s_{23AB}\,\hat{t}_3}
\bigg[&\left(q_1+p_2+p_3+p_A+p_B\right)^\nu
g^{\mu\sigma}+
\\
&\quad\left(q_3-p_2-p_3-p_A-p_B\right)^\mu g^{\sigma\nu}-
\\
& \qquad\left(q_1+q_3\right)^\sigma g^{\mu\nu}\bigg]J_{\text{V} \sigma}(p_2,p_A,p_B,p_3)
\end{split}
\end{align}
corresponds to the left diagram on the third row in
figure~\ref{fig:qq_qQQq_graphs}. One notes that all of these contributions have
the same colour factor, and as such we can group them together nicely
before summing over helicities etc. As such, the function
\texttt{MSymW()} in \texttt{src/Wjets.cc} returns a \lstinline!Tensor!
containing the information from these 5 groupings of contributions (30 diagrams
in total).
\begin{align}
\begin{split}
X^{\mu\nu}_{Unc}=\frac{\langle A|\sigma P_L|B\rangle}{\hat{t_1}\hat{t_3}} \bar{u}_2&\left[-\frac{
\gamma^\sigma P_L(\slashed{p}_2+\slashed{p}_A+\slashed{p}_B)\gamma^\mu
(\slashed{q}_3+ \slashed{p}_3)\gamma^\nu}{(s_{2AB})(t_{unc_{2}})}\right.+
\\
&\qquad\left. \frac{\gamma^\mu(\slashed{q}_1-\slashed{p}_2)\gamma^\sigma
P_L(\slashed{q}_3+\slashed{p}_3)\gamma^\nu}{(t_{unc_{1}})(t_{unc_{2}})}\right. +
\\
&\qquad\qquad\left. \frac{\gamma^\mu(\slashed{q}_1-\slashed{p}_2)\gamma^\nu(\slashed{p}_3+\slashed{p}_A+\slashed{p}_B)\gamma^\sigma P_L
}{(t_{unc_1})(s_{3AB})}\right]v_3
\end{split}
\end{align}
corresponds to the diagram on the right of row three in
figure~\ref{fig:qq_qQQq_graphs}. This contribution to the effective vertex can
be obtained in the code with the function \texttt{MUncW()} in file
\texttt{src/Wjets.cc}.
\begin{align}
\begin{split}
X^{\mu\nu}_{Cro}=\frac{\langle
A|\sigma P_L|B\rangle}{\hat{t_1}\hat{t_3}} \bar{u}_2&\left[-\frac{
\gamma^\nu(\slashed{q}_3+\slashed{p}_2)\gamma^\mu
(\slashed{p}_3+\slashed{p}_A+\slashed{p}_B)\gamma^\sigma P_L}{(t_{cro_1})(s_{3AB})}\right.+
\\
&\qquad\left. \frac{\gamma^\nu(\slashed{q}_3+\slashed{p}_2)\gamma^\sigma
P_L(\slashed{q}_1-\slashed{p}_3)\gamma^\mu}{(t_{cro_{1}})(t_{cro_{2}})}\right.+
\\ &\qquad\qquad\left
. \frac{\gamma^\sigma P_L(\slashed{p}_2+\slashed{p}_A+\slashed{p}_B)\gamma^\nu(\slashed{q}_1-\slashed{p}_3)\gamma^\mu
}{(s_{2AB})(t_{cro_2})}\right]v_3
\end{split}
\end{align}
corresponds to the last diagram in figure~\ref{fig:qq_qQQq_graphs}. This
contribution to the effective vertex can be obtained in the code with
the function \texttt{MCroW()} in file \texttt{src/Wjets.cc}.
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "developer_manual"
%%% End:
diff --git a/doc/sphinx/HEJ.rst b/doc/sphinx/HEJ.rst
index cc56fe2..de02a72 100644
--- a/doc/sphinx/HEJ.rst
+++ b/doc/sphinx/HEJ.rst
@@ -1,327 +1,325 @@
.. _`Running HEJ 2`:
Running HEJ 2
=============
Quick start
-----------
In order to run HEJ 2, you need a configuration file and a file
containing fixed-order events. A sample configuration is given by the
:file:`config.yml` file distributed together with HEJ 2. Events in the
Les Houches Event File format can be generated with standard Monte Carlo
generators like `MadGraph5_aMC@NLO <https://launchpad.net/mg5amcnlo>`_
or `Sherpa <https://sherpa.hepforge.org/trac/wiki>`_. If HEJ 2 was
compiled with `HDF5 <https://www.hdfgroup.org/>`_ support, it can also
read event files in the format suggested in
`arXiv:1905.05120 <https://arxiv.org/abs/1905.05120>`_.
HEJ 2 assumes that the cross section is given by the sum of the event
weights. Depending on the fixed-order generator it may be necessary to
adjust the weights in the Les Houches Event File accordingly.
The processes supported by HEJ 2 are
- Pure multijet production
- Production of a Higgs boson with jets
- Production of a W boson with jets
..
- *TODO* Production of a Z boson or photon with jets
where at least two jets are required in each case. For the time being,
only leading-order events are supported.
After generating an event file :file:`events.lhe` adjust the parameters
under the `fixed order jets`_ setting in :file:`config.yml` to the
settings in the fixed-order generation. Resummation can then be added by
running::
HEJ config.yml events.lhe
Using the default settings, this will produce an output event file
:file:`HEJ.lhe` with events including high-energy resummation.
When using the `Docker image <https://hub.docker.com/r/hejdock/hej>`_,
HEJ can be run with
.. code-block:: bash
docker run -v $PWD:$PWD -w $PWD hejdock/hej HEJ config.yml events.lhe
.. _`HEJ 2 settings`:
Settings
--------
HEJ 2 configuration files follow the `YAML <http://yaml.org/>`_
format. The following configuration parameters are supported:
.. _`trials`:
**trials**
High-energy resummation is performed by generating a number of
resummation phase space configurations corresponding to an input
fixed-order event. This parameter specifies how many such
configurations HEJ 2 should try to generate for each input
event. Typical values vary between 10 and 100.
.. _`min extparton pt`:
**min extparton pt**
Specifies the minimum transverse momentum in GeV of the most forward
and the most backward parton. This setting is needed to regulate an
otherwise uncancelled divergence. Its value should be slightly below
the minimum transverse momentum of jets specified by `resummation
jets: min pt`_. See also the `max ext soft pt fraction`_ setting.
.. _`max ext soft pt fraction`:
**max ext soft pt fraction**
Specifies the maximum fraction that soft radiation can contribute to
the transverse momentum of each the most forward and the most backward
jet. Values between around 0.05 and 0.1 are recommended. See also the
`min extparton pt`_ setting.
.. _`fixed order jets`:
**fixed order jets**
This tag collects a number of settings specifying the jet definition
in the event input. The settings should correspond to the ones used in
the fixed-order Monte Carlo that generated the input events.
.. _`fixed order jets: min pt`:
**min pt**
Minimum transverse momentum in GeV of fixed-order jets.
.. _`fixed order jets: algorithm`:
**algorithm**
The algorithm used to define jets. Allowed settings are
:code:`kt`, :code:`cambridge`, :code:`antikt`,
:code:`cambridge for passive`. See the `FastJet
<http://fastjet.fr/>`_ documentation for a description of these
algorithms.
.. _`fixed order jets: R`:
**R**
The R parameter used in the jet algorithm, roughly corresponding
to the jet radius in the plane spanned by the rapidity and the
azimuthal angle.
.. _`resummation jets`:
**resummation jets**
This tag collects a number of settings specifying the jet definition
in the observed, i.e. resummed events. These settings are optional, by
default the same values as for the `fixed order jets`_ are assumed.
.. _`resummation jets: min pt`:
**min pt**
Minimum transverse momentum in GeV of resummation jets. This
should be between 25% and 50% larger than the minimum transverse
momentum of fixed order jets set by `fixed order jets: min pt`_.
.. _`resummation jets: algorithm`:
**algorithm**
The algorithm used to define jets. The HEJ 2 approach to
resummation relies on properties of :code:`antikt` jets, so this
value is strongly recommended. For a list of possible other
values, see the `fixed order jets: algorithm`_ setting.
.. _`resummation jets: R`:
**R**
The R parameter used in the jet algorithm.
.. _`FKL`:
**FKL**
Specifies how to treat events respecting FKL rapidity ordering. These
configurations are dominant in the high-energy limit. The possible
values are :code:`reweight` to enable resummation, :code:`keep` to
keep the events as they are up to a possible change of
renormalisation and factorisation scale, and :code:`discard` to
discard these events.
.. _`unordered`:
**unordered**
Specifies how to treat events with one emission that does not respect FKL
ordering, e.g. :code:`u d => g u d`. In the high-energy limit, such
configurations are logarithmically suppressed compared to FKL configurations.
- The possible values are the same as for the `FKL`_ setting, but
- :code:`reweight` is currently only supported for Higgs or W bosons plus jets
- production.
+ The possible values are the same as for the `FKL`_ setting.
.. _`extremal qqx`:
**extremal qqx**
Specifies how to treat events with a quark-antiquark pair as extremal partons
in rapidity, e.g. :code:`g d => u u_bar d`. In the high-energy limit, such
configurations are logarithmically suppressed compared to FKL configurations.
The possible values are the same as for the `FKL`_ setting, but
:code:`reweight` is currently only supported for W boson plus jets
production.
.. _`central qqx`:
**central qqx**
Specifies how to treat events with a quark-antiquark pair central in
rapidity, e.g. :code:`g g => g u u_bar g`. In the high-energy limit, such
configurations are logarithmically suppressed compared to FKL configurations.
The possible values are the same as for the `FKL`_ setting, but
:code:`reweight` is currently only supported for W boson plus jets
production.
.. _`non-resummable`:
**non-resummable**
Specifies how to treat events where no resummation is possible. The
allowed values are :code:`keep` to keep the events as they are up to
a possible change of renormalisation and factorisation scale and
:code:`discard` to discard these events.
.. _`scales`:
**scales**
Specifies the renormalisation and factorisation scales for the output
events. This can either be a single entry or a list :code:`[scale1,
scale2, ...]`. For the case of a list the first entry defines the
central scale. Possible values are fixed numbers to set the scale in
GeV or the following:
- :code:`H_T`: The sum of the scalar transverse momenta of all
final-state particles
- :code:`max jet pperp`: The maximum transverse momentum of all jets
- :code:`jet invariant mass`: Sum of the invariant masses of all jets
- :code:`m_j1j2`: Invariant mass between the two hardest jets.
Scales can be multiplied or divided by overall factors, e.g. :code:`H_T/2`.
It is also possible to import scales from an external library, see
:ref:`Custom scales`
.. _`scale factors`:
**scale factors**
A list of numeric factors by which each of the `scales`_ should be
multiplied. Renormalisation and factorisation scales are varied
independently. For example, a list with entries :code:`[0.5, 2]`
would give the four scale choices (0.5μ\ :sub:`r`, 0.5μ\ :sub:`f`);
(0.5μ\ :sub:`r`, 2μ\ :sub:`f`); (2μ\ :sub:`r`, 0.5μ\ :sub:`f`); (2μ\
:sub:`r`, 2μ\ :sub:`f`) in this order. The ordering corresponds to
the order of the final event weights.
.. _`max scale ratio`:
**max scale ratio**
Specifies the maximum factor by which renormalisation and
factorisation scales may difer. For a value of :code:`2` and the
example given for the `scale factors`_ the scale choices
(0.5μ\ :sub:`r`, 2μ\ :sub:`f`) and (2μ\ :sub:`r`, 0.5μ\ :sub:`f`)
will be discarded.
.. _`log correction`:
**log correction**
Whether to include corrections due to the evolution of the strong
coupling constant in the virtual corrections. Allowed values are
:code:`true` and :code:`false`.
.. _`event output`:
**event output**
Specifies the name of a single event output file or a list of such
files. The file format is either specified explicitly or derived from
the suffix. For example, :code:`events.lhe` or, equivalently
:code:`Les Houches: events.lhe` generates an output event file
:code:`events.lhe` in the Les Houches format. The supported formats
are
- :code:`file.lhe` or :code:`Les Houches: file`: The Les Houches
event file format.
- :code:`file.hepmc2` or :code:`HepMC2: file`: HepMC format version 2.
- :code:`file.hepmc3` or :code:`HepMC3: file`: HepMC format version 3.
- :code:`file.hepmc` or :code:`HepMC: file`: The latest supported
version of the HepMC format, currently version 3.
.. _`random generator`:
**random generator**
Sets parameters for random number generation.
.. _`random generator: name`:
**name**
Which random number generator to use. Currently, :code:`mixmax`
and :code:`ranlux64` are supported. Mixmax is recommended. See
the `CLHEP documentation
<http://proj-clhep.web.cern.ch/proj-clhep/index.html#docu>`_ for
details on the generators.
.. _`random generator: seed`:
**seed**
The seed for random generation. This should be a single number for
:code:`mixmax` and the name of a state file for :code:`ranlux64`.
.. _`analysis`:
**analysis**
Name and Setting for the event analyses; either a custom
analysis plugin or Rivet. For the first the :code:`plugin` sub-entry
should be set to the analysis file path. All further entries are passed on
to the analysis. To use Rivet a list of Rivet analyses have to be
given in :code:`rivet` and prefix for the yoda file has to be set
through :code:`output`. See :ref:`Writing custom analyses` for details.
.. _`Higgs coupling`:
**Higgs coupling**
This collects a number of settings concerning the effective coupling
of the Higgs boson to gluons. This is only relevant for the
production process of a Higgs boson with jets and only supported if
HEJ 2 was compiled with `QCDLoop
<https://github.com/scarrazza/qcdloop>`_ support.
.. _`Higgs coupling: use impact factors`:
**use impact factors**
Whether to use impact factors for the coupling to the most forward
and most backward partons. Impact factors imply the infinite
top-quark mass limit.
.. _`Higgs coupling: mt`:
**mt**
The value of the top-quark mass in GeV. If this is not specified,
the limit of an infinite mass is taken.
.. _`Higgs coupling: include bottom`:
**include bottom**
Whether to include the Higgs coupling to bottom quarks.
.. _`Higgs coupling: mb`:
**mb**
The value of the bottom-quark mass in GeV. Only used for the Higgs
coupling, external bottom-quarks are always assumed to be massless.
Advanced Settings
~~~~~~~~~~~~~~~~~
All of the following settings are optional. Please **do not set** any of the
following options, unless you know exactly what you are doing. The default
behaviour gives the most reliable results for a wide range of observables.
.. _`regulator parameter`:
**regulator parameter**
Slicing parameter to regularise the subtraction term, called :math:`\lambda`
in `arxiv:1706.01002 <https://arxiv.org/abs/1706.01002>`_. Default is 0.2
diff --git a/doc/sphinx/HEJFOG.rst b/doc/sphinx/HEJFOG.rst
index 70046d7..4a22e7d 100644
--- a/doc/sphinx/HEJFOG.rst
+++ b/doc/sphinx/HEJFOG.rst
@@ -1,311 +1,310 @@
The HEJ Fixed Order Generator
=============================
For high jet multiplicities event generation with standard fixed-order
generators becomes increasingly cumbersome. For example, the
leading-order production of a Higgs Boson with five or more jets is
computationally prohibitively expensive.
To this end, HEJ 2 provides the ``HEJFOG`` fixed-order generator
that allows to generate events with high jet multiplicities. To
facilitate the computation the limit of Multi-Regge Kinematics with
large invariant masses between all outgoing particles is assumed in the
matrix elements. The typical use of the ``HEJFOG`` is to supplement
low-multiplicity events from standard generators with high-multiplicity
events before using the HEJ 2 program to add high-energy
resummation.
Installation
------------
The ``HEJFOG`` comes bundled together with HEJ 2 and the
installation is very similar. After downloading HEJ 2 and
installing the prerequisites as described in :ref:`Installation` the
``HEJFOG`` can be installed with::
cmake /path/to/FixedOrderGen -DCMAKE_INSTALL_PREFIX=target/directory
make install
where :file:`/path/to/FixedOrderGen` refers to the :file:`FixedOrderGen`
subdirectory in the HEJ 2 directory. If HEJ 2 was
installed to a non-standard location, it may be necessary to specify the
directory containing :file:`HEJ-config.cmake`. If the base installation
directory is :file:`/path/to/HEJ`, :file:`HEJ-config.cmake` should be
found in :file:`/path/to/HEJ/lib/cmake/HEJ` and the commands for
installing the ``HEJFOG`` would read::
cmake /path/to/FixedOrderGen -DHEJ_DIR=/path/to/HEJ/lib/cmake/HEJ -DCMAKE_INSTALL_PREFIX=target/directory
make install
The installation can be tested with::
make test
provided that the CT10nlo PDF set is installed.
Running the fixed-order generator
---------------------------------
After installing the ``HEJFOG`` you can modify the provided
configuration file :file:`configFO.yml` and run the generator with::
HEJFOG configFO.yml
The resulting event file, by default named :file:`HEJFO.lhe`, can then be
fed into HEJ 2 like any event file generated from a standard
fixed-order generator, see :ref:`Running HEJ 2`.
Settings
--------
Similar to HEJ 2, the ``HEJFOG`` uses a `YAML
<http://yaml.org/>`_ configuration file. The settings are
.. _`process`:
**process**
The scattering process for which events are being generated. The
format is
:code:`in1 in2 => out1 out2 ...`
The incoming particles, :code:`in1`, :code:`in2` can be
- quarks: :code:`u`, :code:`d`, :code:`u_bar`, and so on
- gluons: :code:`g`
- protons :code:`p` or antiprotons :code:`p_bar`
The outgoing particles, can be
- jets: :code:`j`, multiple jets can be grouped together e.g. :code:`2j`
- bosons: Any gauge boson, they require `particle properties`_
- leptons: if they can be reconstructed to a :code:`W+` or :code:`W-`,
e.g. :code:`e+ nu_e`
At most one of the outgoing particles can be a boson, the rest has to be
partonic. At the moment only Higgs :code:`h`, :code:`W+` and :code:`W-`
bosons are supported. All other outgoing particles are jets. There have to be
at least two jets. Instead of the leptons decays of the bosons can be added
through the :ref:`particle properties<particle properties: particle:
decays>`. The latter is required to decay a Higgs boson. So :code:`p p => Wp
j j` is the same as :code:`p p => e+ nu_e 2j`, if the decay :code:`Wp => e+
nu_e` is specified in `particle properties`_.
.. _`events`:
**events**
Specifies the number of events to generate.
.. _`jets`:
**jets**
Defines the properties of the generated jets.
.. _`jets: min pt`:
**min pt**
Minimum jet transverse momentum in GeV.
.. _`jets: peak pt`:
**peak pt**
Optional setting to specify the dominant jet transverse momentum
in GeV. If the generated events are used as input for HEJ
resummation, this should be set to the minimum transverse momentum
of the resummation jets. In all cases it has to be larger than
:code:`min pt`. The effect is that only a small fraction of jets
will be generated with a transverse momentum below the value of
this setting.
.. _`jets: algorithm`:
**algorithm**
The algorithm used to define jets. Allowed settings are
:code:`kt`, :code:`cambridge`, :code:`antikt`,
:code:`cambridge for passive`. See the `FastJet
<http://fastjet.fr/>`_ documentation for a description of these
algorithms.
.. _`jets: R`:
**R**
The R parameter used in the jet algorithm.
.. _`jets: max rapidity`:
**max rapidity**
Maximum absolute value of the jet rapidity.
.. _`beam`:
**beam**
Defines various properties of the collider beam.
.. _`beam: energy`:
**energy**
The beam energy in GeV. For example, the 13
TeV LHC corresponds to a value of 6500.
.. _`beam: particles`:
**particles**
A list :code:`[p1, p2]` of two beam particles. The only supported
entries are protons :code:`p` and antiprotons :code:`p_bar`.
.. _`pdf`:
**pdf**
The `LHAPDF number <https://lhapdf.hepforge.org/pdfsets>`_ of the PDF set.
For example, 230000 corresponds to an NNPDF 2.3 NLO PDF set.
.. _`subleading fraction`:
**subleading fraction**
This setting is related to the fraction of events that are not a FKL
configuration. All possible subleading process are listed in
:ref:`subleading channels<subleading channels>`. This value must be
positive and not larger than 1. It should typically be chosen between
0.01 and 0.1. Note that while this parameter influences the chance of
generating subleading configurations, it generally does not
correspond to the actual fraction of subleading events.
.. _`subleading channels`:
**subleading channels**
Optional parameters to select a specific subleading process, multiple
channels can be selected at once. If multiple subleading configurations
are possible one will be selected at random for each event, thus each
final state will include at most one subleading process, e.g. either
:code:`unordered` or :code:`qqx`. Only has an effect if
:code:`subleading fraction` is non-zero. The following values are allowed:
- :code:`all`: All channels allowed. This is the default.
- :code:`none`: No subleading contribution, only the leading (FKL)
configurations are allowed. This is equivalent to
:code:`subleading fraction: 0`.
- :code:`unordered`: Unordered emission allowed.
Unordered emission are any rapidity ordering where exactly one gluon is
emitted outside the rapidity ordering required in FKL events. More
precisely, if at least one of the incoming particles is a quark or
antiquark and there are more than two jets in the final state,
:code:`subleading fraction` states the probability that the flavours
of the outgoing particles are assigned in such a way that an unordered
- configuration arises. Unordered emissions are currently not implemented
- for pure jet production.
+ configuration arises.
- :code:`qqx`: Production of a quark-antiquark pair. In the leading
(FKL) configurations all partons except for the most backward and
forward ones are gluons. If the :code:`qqx` channel is allowed,
:code:`subleading fraction` gives the probability of emitting a
quark-antiquark pair in place of two gluons that are adjacent in
rapidity. Quark-antiquark pairs are currently only implemented for
W boson production.
.. _`unweight`:
**unweight**
This setting defines the parameters for the partial unweighting of
events. You can disable unweighting by removing this entry from the
configuration file.
.. _`unweight: sample size`:
**sample size**
The number of weighted events used to calibrate the unweighting.
A good default is to set this to the number of target
`events`_. If the number of `events`_ is large this can
lead to significant memory consumption and a lower value should be
chosen. Contrarily, for large multiplicities the unweighting
efficiency becomes worse and the sample size should be increased.
.. _`unweight: max deviation`:
**max deviation**
Controls the range of events to which unweighting is applied. A
larger value means that a larger fraction of events are unweighted.
Typical values are between -1 and 1.
.. _`particle properties`:
**particle properties**
Specifies various properties of the different particles (Higgs, W or Z).
This is only relevant if the chosen `process`_ is the production of the
corresponding particles with jets. E.g. for the `process`_
:code:`p p => h 2j` the :code:`mass`, :code:`width` and (optionally)
:code:`decays` of the :code:`Higgs` boson are required, while all other
particle properties will be ignored.
.. _`particle properties: particle`:
**Higgs, W+, W- or Z**
The particle (Higgs, |W+|, |W-|, Z) for which the following
properties are defined.
.. |W+| replace:: W\ :sup:`+`
.. |W-| replace:: W\ :sup:`-`
.. _`particle properties: particle: mass`:
**mass**
The mass of the particle in GeV.
.. _`particle properties: particle: width`:
**width**
The total decay width of the particle in GeV.
.. _`particle properties: particle: decays`:
**decays**
Optional setting specifying the decays of the particle. Only the decay
into two particles is implemented. Each decay has the form
:code:`{into: [p1,p2], branching ratio: r}`
where :code:`p1` and :code:`p2` are the particle names of the
decay product (e.g. :code:`photon`) and :code:`r` is the branching
ratio. The branching ratio is optional (:code:`1` by default).
Decays of a Higgs boson are treated as the production and subsequent
decay of an on-shell Higgs boson, so decays into e.g. Z bosons are not
supported. In contrast W bosons are decayed off-shell, thus the
branching ratio should not be changed or set to :code:`1`.
.. _`scales`:
**scales**
Specifies the renormalisation and factorisation scales for the output
events. For details, see the corresponding entry in the HEJ 2
:ref:`HEJ 2 settings`. Note that this should usually be a
single value, as the weights resulting from additional scale choices
will simply be ignored when adding high-energy resummation with HEJ 2.
.. _`event output`:
**event output**
Specifies the name of a single event output file or a list of such
files. See the corresponding entry in the HEJ 2
:ref:`HEJ 2 settings` for details.
.. _`RanLux init`:
.. _`random generator`:
**random generator**
Sets parameters for random number generation. See the HEJ 2
:ref:`HEJ 2 settings` for details.
.. _`analysis`:
**analysis**
Specifies the name and settings for a custom analysis library. This
can be useful to specify cuts at the fixed-order level. See the
corresponding entry in the HEJ 2 :ref:`HEJ 2 settings`
for details.
.. _`Higgs coupling`:
**Higgs coupling**
This collects a number of settings concerning the effective coupling
of the Higgs boson to gluons. See the corresponding entry in the
HEJ 2 :ref:`HEJ 2 settings` for details.
diff --git a/include/HEJ/jets.hh b/include/HEJ/jets.hh
index 94ba2c5..178a631 100644
--- a/include/HEJ/jets.hh
+++ b/include/HEJ/jets.hh
@@ -1,257 +1,339 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019
* \copyright GPLv2 or later
*/
/** \file
* \brief Functions computing the square of current contractions in pure jets.
*
* This file contains all the necessary functions to compute the
- * current contractions for all valid pure jet HEJ processes. It will
- * also contain some pure jet ME components used in other process ME
- * calculations
+ * current contractions for all valid pure jet HEJ processes, which
+ * so far is FKL and unordered processes. It will also contain some
+ * pure jet ME components used in other process ME calculations
*
* @TODO add a namespace
*/
#pragma once
#include <complex>
#include <ostream>
#include <CLHEP/Vector/LorentzVector.h>
typedef std::complex<double> COM;
typedef COM current[4];
typedef CLHEP::HepLorentzVector HLV;
//! Square of qQ->qQ Pure Jets Scattering Current
/**
* @param p1out Momentum of final state quark
* @param p1in Momentum of initial state quark
* @param p2out Momentum of final state quark
* @param p2in Momentum of intial state quark
* @returns Square of the current contractions for qQ->qQ Scattering
*/
double ME_qQ (HLV p1out, HLV p1in, HLV p2out, HLV p2in);
//! Square of qQbar->qQbar Pure Jets Scattering Current
/**
* @param p1out Momentum of final state quark
* @param p1in Momentum of initial state quark
* @param p2out Momentum of final state anti-quark
* @param p2in Momentum of intial state anti-quark
* @returns Square of the current contractions for qQbar->qQbar Scattering
*
* @note this can be used for qbarQ->qbarQ Scattering by inputting arguments
* appropriately.
*/
double ME_qQbar (HLV p1out, HLV p1in, HLV p2out, HLV p2in);
//! Square of qbarQbar->qbarQbar Pure Jets Scattering Current
/**
* @param p1out Momentum of final state anti-quark
* @param p1in Momentum of initial state anti-quark
* @param p2out Momentum of final state anti-quark
* @param p2in Momentum of intial state anti-quark
* @returns Square of the current contractions for qbarQbar->qbarQbar Scattering
*/
double ME_qbarQbar (HLV p1out, HLV p1in, HLV p2out, HLV p2in);
//! Square of qg->qg Pure Jets Scattering Current
/**
* @param p1out Momentum of final state quark
* @param p1in Momentum of initial state quark
* @param p2out Momentum of final state gluon
* @param p2in Momentum of intial state gluon
* @returns Square of the current contractions for qg->qg Scattering
*
* @note this can be used for gq->gq Scattering by inputting arguments
* appropriately.
*/
double ME_qg (HLV p1out, HLV p1in, HLV p2out, HLV p2in);
//! Square of qbarg->qbarg Pure Jets Scattering Current
/**
* @param p1out Momentum of final state anti-quark
* @param p1in Momentum of initial state anti-quark
* @param p2out Momentum of final state gluon
* @param p2in Momentum of intial state gluon
* @returns Square of the current contractions for qbarg->qbarg Scattering
*
* @note this can be used for gqbar->gqbar Scattering by inputting arguments
* appropriately.
*/
double ME_qbarg (HLV p1out, HLV p1in, HLV p2out, HLV p2in);
//! Square of gg->gg Pure Jets Scattering Current
/**
* @param p1out Momentum of final state gluon
* @param p1in Momentum of initial state gluon
* @param p2out Momentum of final state gluon
* @param p2in Momentum of intial state gluon
* @returns Square of the current contractions for gg->gg Scattering
*/
double ME_gg (HLV p1out, HLV p1in, HLV p2out, HLV p2in);
+//Unordered Backwards contributions:
+//! Square of qQ->qQ Pure Jets Scattering Current
+/**
+ * @param p1out Momentum of final state quark
+ * @param p1in Momentum of initial state quark
+ * @param pg Momentum of unordered gluon
+ * @param p2out Momentum of final state quark
+ * @param p2in Momentum of intial state quark
+ * @returns Square of the current contractions for qQ->qQ Scattering
+ */
+double ME_unob_qQ (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in);
+
+//! Square of qbarQ->qbarQ Pure Jets Unordered backwards Scattering Current
+/**
+ * @param p1out Momentum of final state anti-quark
+ * @param p1in Momentum of initial state anti-quark
+ * @param pg Momentum of unordered gluon
+ * @param p2out Momentum of final state quark
+ * @param p2in Momentum of intial state quark
+ * @returns Square of the current contractions for qbarQ->qbarQ Scattering
+ *
+ * @note this can be used for unof contributions by inputting
+ * arguments appropriately.
+ */
+double ME_unob_qbarQ (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in);
+
+//! Square of qQbar->qQbar Pure Jets Unordered backwards Scattering Current
+/**
+ * @param p1out Momentum of final state quark
+ * @param p1in Momentum of initial state quark
+ * @param pg Momentum of unordered gluon
+ * @param p2out Momentum of final state anti-quark
+ * @param p2in Momentum of intial state anti-quark
+ * @returns Square of the current contractions for qQbar->qQbar Scattering
+ *
+ * @note this can be used for unof contributions by inputting
+ * arguments appropriately.
+ */
+double ME_unob_qQbar (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in);
+
+//! Square of qbarQbar->qbarQbar Pure Jets Unordered backwards Scattering Current
+/**
+ * @param p1out Momentum of final state anti-quark
+ * @param p1in Momentum of initial state anti-quark
+ * @param pg Momentum of unordered gluon
+ * @param p2out Momentum of final state anti-quark
+ * @param p2in Momentum of intial state anti-quark
+ * @returns Square of the current contractions for qbarQbar->qbarQbar Scattering
+ *
+ * @note this can be used for unof contributions by inputting
+ * arguments appropriately.
+ */
+double ME_unob_qbarQbar (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in);
+
+//! Square of qg->qg Pure Jets Unordered backwards Scattering Current
+/**
+ * @param p1out Momentum of final state gluon
+ * @param p1in Momentum of initial state gluon
+ * @param pg Momentum of unordered gluon
+ * @param p2out Momentum of final state quark
+ * @param p2in Momentum of intial state quark
+ * @returns Square of the current contractions for qg->qg Scattering
+ *
+ * @note this can be used for unof contributions by inputting
+ * arguments appropriately.
+ */
+double ME_unob_qg (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in);
+
+//! Square of qbarg->qbarg Pure Jets Unordered backwards Scattering Current
+/**
+ * @param p1out Momentum of final state gluon
+ * @param p1in Momentum of initial state gluon
+ * @param pg Momentum of unordered gluon
+ * @param p2out Momentum of final state anti-quark
+ * @param p2in Momentum of intial state anti-quark
+ * @returns Square of the current contractions for qbarg->qbarg Scattering
+ *
+ * @note this can be used for unof contributions by inputting
+ * arguments appropriately.
+ */
+double ME_unob_qbarg (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in);
+
/** \class CCurrent jets.hh "include/HEJ/jets.hh"
* \brief This is the a new class structure for currents.
*/
class CCurrent
{
public:
CCurrent(COM sc0, COM sc1, COM sc2, COM sc3)
:c0(sc0),c1(sc1),c2(sc2),c3(sc3)
{};
CCurrent(const HLV p)
{
c0=p.e();
c1=p.px();
c2=p.py();
c3=p.pz();
};
CCurrent()
{};
CCurrent operator+(const CCurrent& other);
CCurrent operator-(const CCurrent& other);
CCurrent operator*(const double x);
CCurrent operator*(const COM x);
CCurrent operator/(const double x);
CCurrent operator/(const COM x);
friend std::ostream& operator<<(std::ostream& os, const CCurrent& cur);
COM dot(HLV p1);
COM dot(CCurrent p1);
COM c0,c1,c2,c3;
};
/* std::ostream& operator <<(std::ostream& os, const CCurrent& cur); */
CCurrent operator * ( double x, CCurrent& m);
CCurrent operator * ( COM x, CCurrent& m);
CCurrent operator / ( double x, CCurrent& m);
CCurrent operator / ( COM x, CCurrent& m);
//! Current <incoming state | mu | outgoing state>
/**
* This is a wrapper function around \see joi() note helicity flip to
* give same answer.
*/
void jio(HLV pin, bool helin, HLV pout, bool helout, current &cur);
//! Current <outgoing state | mu | outgoing state>
/**
* @param pi bra state momentum
* @param heli helicity of pi
* @param pj ket state momentum
* @param helj helicity of pj. (must be same as heli)
* @param cur reference to current which is saved.
*
* This function is for building <i (out)| mu |j (out)> currents. It
* must be called with pi as the bra, and pj as the ket.
*
* @TODO Remove heli/helj and just have helicity of current as argument.
*/
void joo(HLV pi, bool heli, HLV pj, bool helj, current &cur);
//! Current <outgoing state | mu | incoming state>
/**
* @param pout bra state momentum
* @param helout helicity of pout
* @param pin ket state momentum
* @param helin helicity of pin. (must be same as helout)
* @param cur reference to current which is saved.
*
* This function is for building <out| mu |in> currents. It must be
* called with pout as the bra, and pin as the ket. jio calls this
* with flipped helicity
*
* @TODO Remove helout/helin and just have helicity of current as argument.
*/
void joi(HLV pout, bool helout, HLV pin, bool helin, current &cur);
//! Current <outgoing state | mu | incoming state>
/**
* This is a wrapper function around the void function of the same name. \see joi
*/
CCurrent joi (HLV pout, bool helout, HLV pin, bool helin);
//! Current <incoming state | mu | outgoing state>
/**
* This is a wrapper function around the void function of the same name. \see jio
*/
CCurrent jio (HLV pout, bool helout, HLV pin, bool helin);
//! Current <outgoing state | mu | outgoing state>
/**
* This is a wrapper function around the void function of the same name. \see joo
*/
CCurrent joo (HLV pout, bool helout, HLV pin, bool helin);
inline COM cdot(const current & j1, const current & j2)
{
return j1[0]*j2[0]-j1[1]*j2[1]-j1[2]*j2[2]-j1[3]*j2[3];
}
inline COM cdot(const HLV & p, const current & j1) {
return j1[0]*p.e()-j1[1]*p.x()-j1[2]*p.y()-j1[3]*p.z();
}
inline void cmult(const COM & factor, const current & j1, current &cur)
{
cur[0]=factor*j1[0];
cur[1]=factor*j1[1];
cur[2]=factor*j1[2];
cur[3]=factor*j1[3];
}
// WHY!?!
inline void cadd(const current & j1, const current & j2, const current & j3,
const current & j4, const current & j5, current &sum)
{
sum[0]=j1[0]+j2[0]+j3[0]+j4[0]+j5[0];
sum[1]=j1[1]+j2[1]+j3[1]+j4[1]+j5[1];
sum[2]=j1[2]+j2[2]+j3[2]+j4[2]+j5[2];
sum[3]=j1[3]+j2[3]+j3[3]+j4[3]+j5[3];
}
inline void cadd(const current & j1, const current & j2, const current & j3,
const current & j4, current &sum) {
sum[0] = j1[0] + j2[0] + j3[0] + j4[0];
sum[1] = j1[1] + j2[1] + j3[1] + j4[1];
sum[2] = j1[2] + j2[2] + j3[2] + j4[2];
sum[3] = j1[3] + j2[3] + j3[3] + j4[3];
}
inline void cadd(const current & j1, const current & j2, const current & j3,
current &sum)
{
sum[0]=j1[0]+j2[0]+j3[0];
sum[1]=j1[1]+j2[1]+j3[1];
sum[2]=j1[2]+j2[2]+j3[2];
sum[3]=j1[3]+j2[3]+j3[3];
}
inline void cadd(const current & j1, const current & j2, current &sum)
{
sum[0]=j1[0]+j2[0];
sum[1]=j1[1]+j2[1];
sum[2]=j1[2]+j2[2];
sum[3]=j1[3]+j2[3];
}
inline double abs2(const COM & a)
{
return (a*conj(a)).real();
}
inline double vabs2(const CCurrent & cur)
{
return abs2(cur.c0)-abs2(cur.c1)-abs2(cur.c2)-abs2(cur.c3);
}
inline double vre(const CCurrent & a, const CCurrent & b)
{
return real(a.c0*conj(b.c0)-a.c1*conj(b.c1)-a.c2*conj(b.c2)-a.c3*conj(b.c3));
}
//! @TODO These are not currents and should be moved elsewhere.
double K_g(double p1minus, double paminus);
double K_g(HLV const & pout, HLV const & pin);
diff --git a/src/MatrixElement.cc b/src/MatrixElement.cc
index a4aaaa5..633a070 100644
--- a/src/MatrixElement.cc
+++ b/src/MatrixElement.cc
@@ -1,1728 +1,1797 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019
* \copyright GPLv2 or later
*/
#include "HEJ/MatrixElement.hh"
#include <algorithm>
#include <assert.h>
#include <limits>
#include <math.h>
#include <stddef.h>
#include <unordered_map>
#include <utility>
#include "CLHEP/Vector/LorentzVector.h"
#include "fastjet/ClusterSequence.hh"
#include "HEJ/Constants.hh"
#include "HEJ/Wjets.hh"
#include "HEJ/Hjets.hh"
#include "HEJ/jets.hh"
#include "HEJ/PDG_codes.hh"
#include "HEJ/event_types.hh"
#include "HEJ/Event.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/Particle.hh"
#include "HEJ/utility.hh"
namespace HEJ{
double MatrixElement::omega0(
double alpha_s, double mur,
fastjet::PseudoJet const & q_j
) const {
const double lambda = param_.regulator_lambda;
const double result = - alpha_s*N_C/M_PI*log(q_j.perp2()/(lambda*lambda));
if(! param_.log_correction) return result;
// use alpha_s(sqrt(q_j*lambda)), evolved to mur
return (
1. + alpha_s/(4.*M_PI)*beta0*log(mur*mur/(q_j.perp()*lambda))
)*result;
}
Weights MatrixElement::operator()(Event const & event) const {
return tree(event)*virtual_corrections(event);
}
Weights MatrixElement::tree(Event const & event) const {
return tree_param(event)*tree_kin(event);
}
Weights MatrixElement::tree_param(Event const & event) const {
if(! is_resummable(event.type())) {
return Weights{0., std::vector<double>(event.variations().size(), 0.)};
}
Weights result;
// only compute once for each renormalisation scale
std::unordered_map<double, double> known;
result.central = tree_param(event, event.central().mur);
known.emplace(event.central().mur, result.central);
for(auto const & var: event.variations()) {
const auto ME_it = known.find(var.mur);
if(ME_it == end(known)) {
const double wt = tree_param(event, var.mur);
result.variations.emplace_back(wt);
known.emplace(var.mur, wt);
}
else {
result.variations.emplace_back(ME_it->second);
}
}
return result;
}
Weights MatrixElement::virtual_corrections(Event const & event) const {
if(! is_resummable(event.type())) {
return Weights{0., std::vector<double>(event.variations().size(), 0.)};
}
Weights result;
// only compute once for each renormalisation scale
std::unordered_map<double, double> known;
result.central = virtual_corrections(event, event.central().mur);
known.emplace(event.central().mur, result.central);
for(auto const & var: event.variations()) {
const auto ME_it = known.find(var.mur);
if(ME_it == end(known)) {
const double wt = virtual_corrections(event, var.mur);
result.variations.emplace_back(wt);
known.emplace(var.mur, wt);
}
else {
result.variations.emplace_back(ME_it->second);
}
}
return result;
}
double MatrixElement::virtual_corrections_W(
Event const & event,
double mur,
Particle const & WBoson
) const{
auto const & in = event.incoming();
const auto partons = filter_partons(event.outgoing());
fastjet::PseudoJet const & pa = in.front().p;
#ifndef NDEBUG
fastjet::PseudoJet const & pb = in.back().p;
double const norm = (in.front().p + in.back().p).E();
#endif
assert(std::is_sorted(partons.begin(), partons.end(), rapidity_less{}));
assert(partons.size() >= 2);
assert(pa.pz() < pb.pz());
fastjet::PseudoJet q = pa - partons[0].p;
size_t first_idx = 0;
size_t last_idx = partons.size() - 1;
bool wc = true;
bool wqq = false;
// With extremal qqx or unordered gluon outside the extremal
// partons then it is not part of the FKL ladder and does not
// contribute to the virtual corrections. W emitted from the
// most backward leg must be taken into account in t-channel
if (event.type() == event_type::FKL) {
if (in[0].type != partons[0].type ){
q -= WBoson.p;
wc = false;
}
}
else if (event.type() == event_type::unob) {
q -= partons[1].p;
++first_idx;
if (in[0].type != partons[1].type ){
q -= WBoson.p;
wc = false;
}
}
else if (event.type() == event_type::qqxexb) {
q -= partons[1].p;
++first_idx;
if (abs(partons[0].type) != abs(partons[1].type)){
q -= WBoson.p;
wc = false;
}
}
if(event.type() == event_type::unof
|| event.type() == event_type::qqxexf){
--last_idx;
}
size_t first_idx_qqx = last_idx;
size_t last_idx_qqx = last_idx;
//if qqxMid event, virtual correction do not occur between
//qqx pair.
if(event.type() == event_type::qqxmid){
const auto backquark = std::find_if(
begin(partons) + 1, end(partons) - 1 ,
[](Particle const & s){ return (s.type != pid::gluon); }
);
if(backquark == end(partons) || (backquark+1)->type==pid::gluon) return 0;
if(abs(backquark->type) != abs((backquark+1)->type)) {
wqq=true;
wc=false;
}
last_idx = std::distance(begin(partons), backquark);
first_idx_qqx = last_idx+1;
}
double exponent = 0;
const double alpha_s = alpha_s_(mur);
for(size_t j = first_idx; j < last_idx; ++j){
exponent += omega0(alpha_s, mur, q)*(
partons[j+1].rapidity() - partons[j].rapidity()
);
q -=partons[j+1].p;
} // End Loop one
if (last_idx != first_idx_qqx) q -= partons[last_idx+1].p;
if (wqq) q -= WBoson.p;
for(size_t j = first_idx_qqx; j < last_idx_qqx; ++j){
exponent += omega0(alpha_s, mur, q)*(
partons[j+1].rapidity() - partons[j].rapidity()
);
q -= partons[j+1].p;
}
if (wc) q -= WBoson.p;
assert(
nearby(q, -1*pb, norm)
|| is_AWZH_boson(partons.back().type)
|| event.type() == event_type::unof
|| event.type() == event_type::qqxexf
);
return exp(exponent);
}
double MatrixElement::virtual_corrections(
Event const & event,
double mur
) const{
auto const & in = event.incoming();
auto const & out = event.outgoing();
fastjet::PseudoJet const & pa = in.front().p;
#ifndef NDEBUG
fastjet::PseudoJet const & pb = in.back().p;
double const norm = (in.front().p + in.back().p).E();
#endif
const auto AWZH_boson = std::find_if(
begin(out), end(out),
[](Particle const & p){ return is_AWZH_boson(p); }
);
if(AWZH_boson != end(out) && abs(AWZH_boson->type) == pid::Wp){
return virtual_corrections_W(event, mur, *AWZH_boson);
}
assert(std::is_sorted(out.begin(), out.end(), rapidity_less{}));
assert(out.size() >= 2);
assert(pa.pz() < pb.pz());
fastjet::PseudoJet q = pa - out[0].p;
size_t first_idx = 0;
size_t last_idx = out.size() - 1;
// if there is a Higgs boson, extremal qqx or unordered gluon
// outside the extremal partons then it is not part of the FKL
// ladder and does not contribute to the virtual corrections
if((out.front().type == pid::Higgs)
|| event.type() == event_type::unob
|| event.type() == event_type::qqxexb){
q -= out[1].p;
++first_idx;
}
if((out.back().type == pid::Higgs)
|| event.type() == event_type::unof
|| event.type() == event_type::qqxexf){
--last_idx;
}
size_t first_idx_qqx = last_idx;
size_t last_idx_qqx = last_idx;
//if qqxMid event, virtual correction do not occur between
//qqx pair.
if(event.type() == event_type::qqxmid){
const auto backquark = std::find_if(
begin(out) + 1, end(out) - 1 ,
[](Particle const & s){ return (s.type != pid::gluon && is_parton(s.type)); }
);
if(backquark == end(out) || (backquark+1)->type==pid::gluon) return 0;
last_idx = std::distance(begin(out), backquark);
first_idx_qqx = last_idx+1;
}
double exponent = 0;
const double alpha_s = alpha_s_(mur);
for(size_t j = first_idx; j < last_idx; ++j){
exponent += omega0(alpha_s, mur, q)*(
out[j+1].rapidity() - out[j].rapidity()
);
q -= out[j+1].p;
}
if (last_idx != first_idx_qqx) q -= out[last_idx+1].p;
for(size_t j = first_idx_qqx; j < last_idx_qqx; ++j){
exponent += omega0(alpha_s, mur, q)*(
out[j+1].rapidity() - out[j].rapidity()
);
q -= out[j+1].p;
}
assert(
nearby(q, -1*pb, norm)
|| out.back().type == pid::Higgs
|| event.type() == event_type::unof
|| event.type() == event_type::qqxexf
);
return exp(exponent);
}
} // namespace HEJ
namespace {
//! Lipatov vertex for partons emitted into extremal jets
double C2Lipatov(
CLHEP::HepLorentzVector const & qav,
CLHEP::HepLorentzVector const & qbv,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & p2
){
CLHEP::HepLorentzVector temptrans=-(qav+qbv);
CLHEP::HepLorentzVector p5=qav-qbv;
CLHEP::HepLorentzVector CL=temptrans
+ p1*(qav.m2()/p5.dot(p1) + 2.*p5.dot(p2)/p1.dot(p2))
- p2*(qbv.m2()/p5.dot(p2) + 2.*p5.dot(p1)/p1.dot(p2));
return -CL.dot(CL);
}
//! Lipatov vertex with soft subtraction for partons emitted into extremal jets
double C2Lipatovots(
CLHEP::HepLorentzVector const & qav,
CLHEP::HepLorentzVector const & qbv,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & p2,
double lambda
) {
double kperp=(qav-qbv).perp();
if (kperp>lambda)
return C2Lipatov(qav, qbv, p1, p2)/(qav.m2()*qbv.m2());
double Cls=(C2Lipatov(qav, qbv, p1, p2)/(qav.m2()*qbv.m2()));
return Cls-4./(kperp*kperp);
}
//! Lipatov vertex
double C2Lipatov( // B
CLHEP::HepLorentzVector const & qav,
CLHEP::HepLorentzVector const & qbv,
CLHEP::HepLorentzVector const & pim,
CLHEP::HepLorentzVector const & pip,
CLHEP::HepLorentzVector const & pom,
CLHEP::HepLorentzVector const & pop
){
CLHEP::HepLorentzVector temptrans=-(qav+qbv);
CLHEP::HepLorentzVector p5=qav-qbv;
CLHEP::HepLorentzVector CL=temptrans
+ qav.m2()*(1./p5.dot(pip)*pip + 1./p5.dot(pop)*pop)/2.
- qbv.m2()*(1./p5.dot(pim)*pim + 1./p5.dot(pom)*pom)/2.
+ ( pip*(p5.dot(pim)/pip.dot(pim) + p5.dot(pom)/pip.dot(pom))
+ pop*(p5.dot(pim)/pop.dot(pim) + p5.dot(pom)/pop.dot(pom))
- pim*(p5.dot(pip)/pip.dot(pim) + p5.dot(pop)/pop.dot(pim))
- pom*(p5.dot(pip)/pip.dot(pom) + p5.dot(pop)/pop.dot(pom)) )/2.;
return -CL.dot(CL);
}
//! Lipatov vertex with soft subtraction
double C2Lipatovots(
CLHEP::HepLorentzVector const & qav,
CLHEP::HepLorentzVector const & qbv,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & p2,
double lambda
) {
double kperp=(qav-qbv).perp();
if (kperp>lambda)
return C2Lipatov(qav, qbv, pa, pb, p1, p2)/(qav.m2()*qbv.m2());
double Cls=(C2Lipatov(qav, qbv, pa, pb, p1, p2)/(qav.m2()*qbv.m2()));
double temp=Cls-4./(kperp*kperp);
return temp;
}
/** Matrix element squared for tree-level current-current scattering
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
+ * @param pg Unordered gluon momentum
+ * @param pn Particle n Momentum
+ * @param pb Particle b Momentum
+ * @param p1 Particle 1 Momentum
+ * @param pa Particle a Momentum
+ * @returns ME Squared for Tree-Level Current-Current Scattering
+ */
+ double ME_uno_current(
+ int aptype, int bptype,
+ CLHEP::HepLorentzVector const & pg,
+ CLHEP::HepLorentzVector const & pn,
+ CLHEP::HepLorentzVector const & pb,
+ CLHEP::HepLorentzVector const & p1,
+ CLHEP::HepLorentzVector const & pa
+ ){
+ assert(aptype!=21); // aptype cannot be gluon
+ if (bptype==21) {
+ if (aptype > 0)
+ return ME_unob_qg(pg,p1,pa,pn,pb);
+ else
+ return ME_unob_qbarg(pg,p1,pa,pn,pb);
+ }
+ else if (bptype<0) { // ----- || -----
+ if (aptype > 0)
+ return ME_unob_qQbar(pg,p1,pa,pn,pb);
+ else
+ return ME_unob_qbarQbar(pg,p1,pa,pn,pb);
+ }
+ else { //bptype == quark
+ if (aptype > 0)
+ return ME_unob_qQ(pg,p1,pa,pn,pb);
+ else
+ return ME_unob_qbarQ(pg,p1,pa,pn,pb);
+ }
+ }
+
+ /** Matrix element squared for tree-level current-current scattering
+ * @param aptype Particle a PDG ID
+ * @param bptype Particle b PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @returns ME Squared for Tree-Level Current-Current Scattering
*/
double ME_current(
int aptype, int bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa
){
if (aptype==21&&bptype==21) {
return ME_gg(pn,pb,p1,pa);
} else if (aptype==21&&bptype!=21) {
if (bptype > 0)
return ME_qg(pn,pb,p1,pa);
else
return ME_qbarg(pn,pb,p1,pa);
}
else if (bptype==21&&aptype!=21) { // ----- || -----
if (aptype > 0)
return ME_qg(p1,pa,pn,pb);
else
return ME_qbarg(p1,pa,pn,pb);
}
else { // they are both quark
if (bptype>0) {
if (aptype>0)
return ME_qQ(pn,pb,p1,pa);
else
return ME_qQbar(pn,pb,p1,pa);
}
else {
if (aptype>0)
return ME_qQbar(p1,pa,pn,pb);
else
return ME_qbarQbar(pn,pb,p1,pa);
}
}
throw std::logic_error("unknown particle types");
}
/** Matrix element squared for tree-level current-current scattering With W+Jets
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param wc Boolean. True->W Emitted from b. Else; emitted from leg a
* @returns ME Squared for Tree-Level Current-Current Scattering
*/
double ME_W_current(
int aptype, int bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
bool const wc
){
// We know it cannot be gg incoming.
assert(!(aptype==21 && bptype==21));
if (aptype==21&&bptype!=21) {
if (bptype > 0)
return ME_W_qg(pn,plbar,pl,pb,p1,pa);
else
return ME_W_qbarg(pn,plbar,pl,pb,p1,pa);
}
else if (bptype==21&&aptype!=21) { // ----- || -----
if (aptype > 0)
return ME_W_qg(p1,plbar,pl,pa,pn,pb);
else
return ME_W_qbarg(p1,plbar,pl,pa,pn,pb);
}
else { // they are both quark
if (wc==true){ // emission off b, (first argument pbout)
if (bptype>0) {
if (aptype>0)
return ME_W_qQ(pn,plbar,pl,pb,p1,pa);
else
return ME_W_qQbar(pn,plbar,pl,pb,p1,pa);
}
else {
if (aptype>0)
return ME_W_qbarQ(pn,plbar,pl,pb,p1,pa);
else
return ME_W_qbarQbar(pn,plbar,pl,pb,p1,pa);
}
}
else{ // emission off a, (first argument paout)
if (aptype > 0) {
if (bptype > 0)
return ME_W_qQ(p1,plbar,pl,pa,pn,pb);
else
return ME_W_qQbar(p1,plbar,pl,pa,pn,pb);
}
else { // a is anti-quark
if (bptype > 0)
return ME_W_qbarQ(p1,plbar,pl,pa,pn,pb);
else
return ME_W_qbarQbar(p1,plbar,pl,pa,pn,pb);
}
}
}
throw std::logic_error("unknown particle types");
}
/** Matrix element squared for backwards uno tree-level current-current
* scattering With W+Jets
*
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param pg Unordered gluon momentum
* @param wc Boolean. True->W Emitted from b. Else; emitted from leg a
* @returns ME Squared for unob Tree-Level Current-Current Scattering
*/
double ME_W_unob_current(
int aptype, int bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pg,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
bool const wc
){
// we know they are not both gluons
if (bptype == 21 && aptype != 21) { // b gluon => W emission off a
if (aptype > 0)
return ME_Wuno_qg(p1,pa,pn,pb,pg,plbar,pl);
else
return ME_Wuno_qbarg(p1,pa,pn,pb,pg,plbar,pl);
}
else { // they are both quark
if (wc) {// emission off b, i.e. b is first current
if (bptype>0){
if (aptype>0)
return ME_W_unob_qQ(p1,pa,pn,pb,pg,plbar,pl);
else
return ME_W_unob_qQbar(p1,pa,pn,pb,pg,plbar,pl);
}
else{
if (aptype>0)
return ME_W_unob_qbarQ(p1,pa,pn,pb,pg,plbar,pl);
else
return ME_W_unob_qbarQbar(p1,pa,pn,pb,pg,plbar,pl);
}
}
else {// wc == false, emission off a, i.e. a is first current
if (aptype > 0) {
if (bptype > 0) //qq
return ME_Wuno_qQ(p1,pa,pn,pb,pg,plbar,pl);
else //qqbar
return ME_Wuno_qQbar(p1,pa,pn,pb,pg,plbar,pl);
}
else { // a is anti-quark
if (bptype > 0) //qbarq
return ME_Wuno_qbarQ(p1,pa,pn,pb,pg,plbar,pl);
else //qbarqbar
return ME_Wuno_qbarQbar(p1,pa,pn,pb,pg,plbar,pl);
}
}
}
throw std::logic_error("unknown particle types");
}
/** Matrix element squared for uno forward tree-level current-current
* scattering With W+Jets
*
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param pg Unordered gluon momentum
* @param wc Boolean. True->W Emitted from b. Else; emitted from leg a
* @returns ME Squared for unof Tree-Level Current-Current Scattering
*/
double ME_W_unof_current(
int aptype, int bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pg,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
bool const wc
){
// we know they are not both gluons
if (aptype==21 && bptype!=21) {//a gluon => W emission off b
if (bptype > 0)
return ME_Wuno_qg(pn, pb, p1, pa, pg, plbar, pl);
else
return ME_Wuno_qbarg(pn, pb, p1, pa, pg, plbar, pl);
}
else { // they are both quark
if (wc) {// emission off b, i.e. b is first current
if (bptype>0){
if (aptype>0)
return ME_Wuno_qQ(pn, pb, p1, pa, pg, plbar, pl);
else
return ME_Wuno_qQbar(pn, pb, p1, pa, pg, plbar, pl);
}
else{
if (aptype>0)
return ME_Wuno_qbarQ(pn, pb, p1, pa, pg, plbar, pl);
else
return ME_Wuno_qbarQbar(pn, pb, p1, pa, pg, plbar, pl);
}
}
else {// wc == false, emission off a, i.e. a is first current
if (aptype > 0) {
if (bptype > 0) //qq
return ME_W_unof_qQ(p1, pa, pn, pb, pg, plbar, pl);
- // return ME_W_unof_qQ(pn,pb,p1,pa,pg,plbar,pl);
else //qqbar
return ME_W_unof_qQbar(p1, pa, pn, pb, pg, plbar, pl);
}
else { // a is anti-quark
if (bptype > 0) //qbarq
return ME_W_unof_qbarQ(p1, pa, pn, pb, pg, plbar, pl);
else //qbarqbar
return ME_W_unof_qbarQbar(p1, pa, pn, pb, pg, plbar, pl);
}
}
}
throw std::logic_error("unknown particle types");
}
/** \brief Matrix element squared for backward qqx tree-level current-current
* scattering With W+Jets
*
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pa Initial state a Momentum
* @param pb Initial state b Momentum
* @param pq Final state q Momentum
* @param pqbar Final state qbar Momentum
* @param pn Final state n Momentum
* @param plbar Final state anti-lepton momentum
* @param pl Final state lepton momentum
* @param wc Boolean. True->W Emitted from b. Else; emitted from leg a
* @returns ME Squared for qqxb Tree-Level Current-Current Scattering
*/
double ME_W_qqxb_current(
int aptype, int bptype,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & pq,
CLHEP::HepLorentzVector const & pqbar,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
bool const wc
){
// CAM factors for the qqx amps, and qqbar ordering (default, qbar extremal)
bool swapQuarkAntiquark=false;
double CFbackward;
if (pqbar.rapidity() > pq.rapidity()){
swapQuarkAntiquark=true;
CFbackward = (0.5*(3.-1./3.)*(pa.minus()/(pq.minus())+(pq.minus())/pa.minus())+1./3.)*3./4.;
}
else{
CFbackward = (0.5*(3.-1./3.)*(pa.minus()/(pqbar.minus())+(pqbar.minus())/pa.minus())+1./3.)*3./4.;
}
// With qqbar we could have 2 incoming gluons and W Emission
if (aptype==21&&bptype==21) {//a gluon, b gluon gg->qqbarWg
// This will be a wqqx emission as there is no other possible W Emission Site.
if (swapQuarkAntiquark)
return ME_WExqqx_qqbarg(pa, pqbar, plbar, pl, pq, pn, pb)*CFbackward;
else
return ME_WExqqx_qbarqg(pa, pq, plbar, pl, pqbar, pn, pb)*CFbackward;
}
else if (aptype==21&&bptype!=21 ) {//a gluon => W emission off b leg or qqx
if (!wc){ // W Emitted from backwards qqx
if (swapQuarkAntiquark)
return ME_WExqqx_qqbarQ(pa, pqbar, plbar, pl, pq, pn, pb)*CFbackward;
else
return ME_WExqqx_qbarqQ(pa, pq, plbar, pl, pqbar, pn, pb)*CFbackward;
}
else { // W Must be emitted from forwards leg.
if(bptype > 0){
if (swapQuarkAntiquark)
return ME_W_Exqqx_QQq(pb, pa, pn, pqbar, pq, plbar, pl, false)*CFbackward;
else
return ME_W_Exqqx_QQq(pb, pa, pn, pq, pqbar, plbar, pl, false)*CFbackward;
} else {
if (swapQuarkAntiquark)
return ME_W_Exqqx_QQq(pb, pa, pn, pqbar, pq, plbar, pl, true)*CFbackward;
else
return ME_W_Exqqx_QQq(pb, pa, pn, pq, pqbar, plbar, pl, true)*CFbackward;
}
}
}
throw std::logic_error("Incompatible incoming particle types with qqxb");
}
/* \brief Matrix element squared for forward qqx tree-level current-current
* scattering With W+Jets
*
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pa Initial state a Momentum
* @param pb Initial state b Momentum
* @param pq Final state q Momentum
* @param pqbar Final state qbar Momentum
* @param p1 Final state 1 Momentum
* @param plbar Final state anti-lepton momentum
* @param pl Final state lepton momentum
* @param wc Boolean. True->W Emitted from b. Else; emitted from leg a
* @returns ME Squared for qqxf Tree-Level Current-Current Scattering
*/
double ME_W_qqxf_current(
int aptype, int bptype,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & pq,
CLHEP::HepLorentzVector const & pqbar,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
bool const wc
){
// CAM factors for the qqx amps, and qqbar ordering (default, qbar extremal)
bool swapQuarkAntiquark=false;
double CFforward;
if (pqbar.rapidity() < pq.rapidity()){
swapQuarkAntiquark=true;
CFforward = (0.5*(3.-1./3.)*(pb.plus()/(pq.plus())+(pq.plus())/pb.plus())+1./3.)*3./4.;
}
else{
CFforward = (0.5*(3.-1./3.)*(pb.plus()/(pqbar.plus())+(pqbar.plus())/pb.plus())+1./3.)*3./4.;
}
// With qqbar we could have 2 incoming gluons and W Emission
if (aptype==21&&bptype==21) {//a gluon, b gluon gg->qqbarWg
// This will be a wqqx emission as there is no other possible W Emission Site.
if (swapQuarkAntiquark)
return ME_WExqqx_qqbarg(pb, pqbar, plbar, pl, pq, p1, pa)*CFforward;
else
return ME_WExqqx_qbarqg(pb, pq, plbar, pl, pqbar, p1, pa)*CFforward;
}
else if (bptype==21&&aptype!=21) {// b gluon => W emission off a or qqx
if (wc){ // W Emitted from forwards qqx
if (swapQuarkAntiquark)
return ME_WExqqx_qqbarQ(pb, pqbar, plbar, pl, pq, p1, pa)*CFforward;
else
return ME_WExqqx_qbarqQ(pb, pq, plbar, pl, pqbar, p1, pa)*CFforward;
}
// W Must be emitted from backwards leg.
if (aptype > 0){
if (swapQuarkAntiquark)
return ME_W_Exqqx_QQq(pa, pb, p1, pqbar, pq, plbar, pl, false)*CFforward;
else
return ME_W_Exqqx_QQq(pa, pb, p1, pq, pqbar, plbar, pl, false)*CFforward;
} else {
if (swapQuarkAntiquark)
return ME_W_Exqqx_QQq(pa, pb, p1, pqbar, pq, plbar, pl, true)*CFforward;
else
return ME_W_Exqqx_QQq(pa, pb, p1, pq, pqbar, plbar, pl, true)*CFforward;
}
}
throw std::logic_error("Incompatible incoming particle types with qqxf");
}
/* \brief Matrix element squared for central qqx tree-level current-current
* scattering With W+Jets
*
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param nabove Number of gluons emitted before central qqxpair
* @param nbelow Number of gluons emitted after central qqxpair
* @param pa Initial state a Momentum
* @param pb Initial state b Momentum\
* @param pq Final state qbar Momentum
* @param pqbar Final state q Momentum
* @param partons Vector of all outgoing partons
* @param plbar Final state anti-lepton momentum
* @param pl Final state lepton momentum
* @param wqq Boolean. True siginfies W boson is emitted from Central qqx
* @param wc Boolean. wc=true signifies w boson emitted from leg b; if wqq=false.
* @returns ME Squared for qqxmid Tree-Level Current-Current Scattering
*/
double ME_W_qqxmid_current(
int aptype, int bptype,
int nabove, int nbelow,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & pq,
CLHEP::HepLorentzVector const & pqbar,
std::vector<HLV> const & partons,
CLHEP::HepLorentzVector const & plbar,
CLHEP::HepLorentzVector const & pl,
bool const wqq, bool const wc
){
// CAM factors for the qqx amps, and qqbar ordering (default, pq backwards)
bool swapQuarkAntiquark=false;
if (pqbar.rapidity() < pq.rapidity()){
swapQuarkAntiquark=true;
}
double wt=1.;
if (aptype==21) wt*=K_g(partons.front(),pa)/HEJ::C_F;
if (bptype==21) wt*=K_g(partons.back(),pb)/HEJ::C_F;
if (aptype <=0 && bptype <=0){ // Both External AntiQuark
if (wqq==1){//emission from central qqbar
return wt*ME_WCenqqx_qq(pa, pb, pl, plbar, partons,true,true,
swapQuarkAntiquark, nabove);
}
else if (wc==1){//emission from b leg
return wt*ME_W_Cenqqx_qq(pa, pb, pl, plbar, partons, true,true,
swapQuarkAntiquark, nabove, nbelow, true);
}
else { // emission from a leg
return wt*ME_W_Cenqqx_qq(pa, pb, pl,plbar, partons, true,true,
swapQuarkAntiquark, nabove, nbelow, false);
}
} // end both antiquark
else if (aptype<=0){ // a is antiquark
if (wqq==1){//emission from central qqbar
return wt*ME_WCenqqx_qq(pa, pb, pl, plbar, partons, false, true,
swapQuarkAntiquark, nabove);
}
else if (wc==1){//emission from b leg
return wt*ME_W_Cenqqx_qq(pa, pb, pl, plbar, partons,false,true,
swapQuarkAntiquark, nabove, nbelow, true);
}
else { // emission from a leg
return wt*ME_W_Cenqqx_qq(pa, pb, pl, plbar, partons, false, true,
swapQuarkAntiquark, nabove, nbelow, false);
}
} // end a is antiquark
else if (bptype<=0){ // b is antiquark
if (wqq==1){//emission from central qqbar
return wt*ME_WCenqqx_qq(pa, pb, pl, plbar, partons, true, false,
swapQuarkAntiquark, nabove);
}
else if (wc==1){//emission from b leg
return wt*ME_W_Cenqqx_qq(pa, pb, pl, plbar, partons, true, false,
swapQuarkAntiquark, nabove, nbelow, true);
}
else { // emission from a leg
return wt*ME_W_Cenqqx_qq(pa, pb, pl, plbar, partons, true, false,
swapQuarkAntiquark, nabove, nbelow, false);
}
} //end b is antiquark
else{ //Both Quark or gluon
if (wqq==1){//emission from central qqbar
return wt*ME_WCenqqx_qq(pa, pb, pl, plbar, partons, false, false,
swapQuarkAntiquark, nabove);}
else if (wc==1){//emission from b leg
return wt*ME_W_Cenqqx_qq(pa, pb, pl, plbar, partons, false, false,
swapQuarkAntiquark, nabove, nbelow, true);
}
else { // emission from a leg
return wt*ME_W_Cenqqx_qq(pa, pb, pl, plbar, partons, false, false,
swapQuarkAntiquark, nabove, nbelow, false);
}
}
throw std::logic_error("unknown particle types");
}
/** \brief Matrix element squared for tree-level current-current scattering with Higgs
* @param aptype Particle a PDG ID
* @param bptype Particle b PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param qH t-channel momentum before Higgs
* @param qHp1 t-channel momentum after Higgs
* @returns ME Squared for Tree-Level Current-Current Scattering with Higgs
*/
double ME_Higgs_current(
int aptype, int bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & qH, // t-channel momentum before Higgs
CLHEP::HepLorentzVector const & qHp1, // t-channel momentum after Higgs
double mt, bool include_bottom, double mb
){
if (aptype==21&&bptype==21) // gg initial state
return ME_H_gg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else if (aptype==21&&bptype!=21) {
if (bptype > 0)
return ME_H_qg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4./9.;
else
return ME_H_qbarg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4./9.;
}
else if (bptype==21&&aptype!=21) {
if (aptype > 0)
return ME_H_qg(p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb)*4./9.;
else
return ME_H_qbarg(p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb)*4./9.;
}
else { // they are both quark
if (bptype>0) {
if (aptype>0)
return ME_H_qQ(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4.*4./(9.*9.);
else
return ME_H_qQbar(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4.*4./(9.*9.);
}
else {
if (aptype>0)
return ME_H_qQbar(p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb)*4.*4./(9.*9.);
else
return ME_H_qbarQbar(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4.*4./(9.*9.);
}
}
throw std::logic_error("unknown particle types");
}
/** \brief Current matrix element squared with Higgs and unordered forward emission
* @param aptype Particle A PDG ID
* @param bptype Particle B PDG ID
* @param punof Unordered Particle Momentum
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param qH t-channel momentum before Higgs
* @param qHp1 t-channel momentum after Higgs
* @returns ME Squared with Higgs and unordered forward emission
*/
double ME_Higgs_current_unof(
int aptype, int bptype,
CLHEP::HepLorentzVector const & punof,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & qH, // t-channel momentum before Higgs
CLHEP::HepLorentzVector const & qHp1, // t-channel momentum after Higgs
double mt, bool include_bottom, double mb
){
if (aptype==21&&bptype!=21) {
if (bptype > 0)
return ME_H_unof_qg(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return ME_H_unof_qbarg(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
}
else { // they are both quark
if (bptype>0) {
if (aptype>0)
return ME_H_unof_qQ(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return ME_H_unof_qQbar(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
}
else {
if (aptype>0)
return ME_H_unof_qbarQ(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return ME_H_unof_qbarQbar(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
}
}
throw std::logic_error("unknown particle types");
}
/** \brief Current matrix element squared with Higgs and unordered backward emission
* @param aptype Particle A PDG ID
* @param bptype Particle B PDG ID
* @param pn Particle n Momentum
* @param pb Particle b Momentum
* @param punob Unordered back Particle Momentum
* @param p1 Particle 1 Momentum
* @param pa Particle a Momentum
* @param qH t-channel momentum before Higgs
* @param qHp1 t-channel momentum after Higgs
* @returns ME Squared with Higgs and unordered backward emission
*/
double ME_Higgs_current_unob(
int aptype, int bptype,
CLHEP::HepLorentzVector const & pn,
CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & punob,
CLHEP::HepLorentzVector const & p1,
CLHEP::HepLorentzVector const & pa,
CLHEP::HepLorentzVector const & qH, // t-channel momentum before Higgs
CLHEP::HepLorentzVector const & qHp1, // t-channel momentum after Higgs
double mt, bool include_bottom, double mb
){
if (bptype==21&&aptype!=21) {
if (aptype > 0)
return ME_H_unob_gQ(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return ME_H_unob_gQbar(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
}
else { // they are both quark
if (aptype>0) {
if (bptype>0)
return ME_H_unob_qQ(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return ME_H_unob_qbarQ(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
}
else {
if (bptype>0)
return ME_H_unob_qQbar(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return ME_H_unob_qbarQbar(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
}
}
throw std::logic_error("unknown particle types");
}
CLHEP::HepLorentzVector to_HepLorentzVector(HEJ::Particle const & particle){
return {particle.p.px(), particle.p.py(), particle.p.pz(), particle.p.E()};
}
void validate(HEJ::MatrixElementConfig const & config) {
#ifndef HEJ_BUILD_WITH_QCDLOOP
if(!config.Higgs_coupling.use_impact_factors) {
throw std::invalid_argument{
"Invalid Higgs coupling settings.\n"
"HEJ without QCDloop support can only use impact factors.\n"
"Set use_impact_factors to true or recompile HEJ.\n"
};
}
#endif
if(config.Higgs_coupling.use_impact_factors
&& config.Higgs_coupling.mt != std::numeric_limits<double>::infinity()) {
throw std::invalid_argument{
"Conflicting settings: "
"impact factors may only be used in the infinite top mass limit"
};
}
}
} // namespace anonymous
namespace HEJ{
MatrixElement::MatrixElement(
std::function<double (double)> alpha_s,
MatrixElementConfig conf
):
alpha_s_{std::move(alpha_s)},
param_{std::move(conf)}
{
validate(param_);
}
double MatrixElement::tree_kin(
Event const & ev
) const {
if(! is_resummable(ev.type())) return 0.;
auto AWZH_boson = std::find_if(
begin(ev.outgoing()), end(ev.outgoing()),
[](Particle const & p){return is_AWZH_boson(p);}
);
if(AWZH_boson == end(ev.outgoing()))
return tree_kin_jets(ev);
switch(AWZH_boson->type){
case pid::Higgs:
return tree_kin_Higgs(ev);
case pid::Wp:
case pid::Wm:
return tree_kin_W(ev);
// TODO
case pid::photon:
case pid::Z:
default:
throw not_implemented("Emission of boson of unsupported type");
}
}
namespace{
constexpr int extremal_jet_idx = 1;
constexpr int no_extremal_jet_idx = 0;
bool treat_as_extremal(Particle const & parton){
return parton.p.user_index() == extremal_jet_idx;
}
template<class InputIterator>
double FKL_ladder_weight(
InputIterator begin_gluon, InputIterator end_gluon,
CLHEP::HepLorentzVector const & q0,
CLHEP::HepLorentzVector const & pa, CLHEP::HepLorentzVector const & pb,
CLHEP::HepLorentzVector const & p1, CLHEP::HepLorentzVector const & pn,
double lambda
){
double wt = 1;
auto qi = q0;
for(auto gluon_it = begin_gluon; gluon_it != end_gluon; ++gluon_it){
assert(gluon_it->type == pid::gluon);
const auto g = to_HepLorentzVector(*gluon_it);
const auto qip1 = qi - g;
if(treat_as_extremal(*gluon_it)){
wt *= C2Lipatovots(qip1, qi, pa, pb, lambda)*C_A;
} else{
wt *= C2Lipatovots(qip1, qi, pa, pb, p1, pn, lambda)*C_A;
}
qi = qip1;
}
return wt;
}
} // namespace anonymous
std::vector<Particle> MatrixElement::tag_extremal_jet_partons(
Event const & ev
) const{
auto out_partons = filter_partons(ev.outgoing());
if(out_partons.size() == ev.jets().size()){
// no additional emissions in extremal jets, don't need to tag anything
for(auto & parton: out_partons){
parton.p.set_user_index(no_extremal_jet_idx);
}
return out_partons;
}
// TODO: avoid reclustering
fastjet::ClusterSequence cs(to_PseudoJet(out_partons), ev.jet_def());
const auto jets = sorted_by_rapidity(cs.inclusive_jets(ev.min_jet_pt()));
assert(jets.size() >= 2);
auto most_backward = begin(jets);
auto most_forward = end(jets) - 1;
// skip jets caused by unordered emission or qqx
if(ev.type() == event_type::unob || ev.type() == event_type::qqxexb){
assert(jets.size() >= 3);
++most_backward;
}
else if(ev.type() == event_type::unof || ev.type() == event_type::qqxexf){
assert(jets.size() >= 3);
--most_forward;
}
const auto extremal_jet_indices = cs.particle_jet_indices(
{*most_backward, *most_forward}
);
assert(extremal_jet_indices.size() == out_partons.size());
for(size_t i = 0; i < out_partons.size(); ++i){
assert(HEJ::is_parton(out_partons[i]));
const int idx = (extremal_jet_indices[i]>=0)?
extremal_jet_idx:
no_extremal_jet_idx;
out_partons[i].p.set_user_index(idx);
}
return out_partons;
}
+ namespace {
+ template<class InIter, class partIter>
+ double tree_kin_jets_uno(InIter BeginIn, InIter EndIn, partIter BeginPart,
+ partIter EndPart, double lambda){
+
+ const auto pa = to_HepLorentzVector(*BeginIn);
+ const auto pb = to_HepLorentzVector(*(EndIn-1));
+
+ const auto pg = to_HepLorentzVector(*BeginPart);
+ const auto p1 = to_HepLorentzVector(*(BeginPart+1));
+ const auto pn = to_HepLorentzVector(*(EndPart-1));
+
+ const double current_factor = ME_uno_current(
+ (BeginIn)->type, (EndIn-1)->type, pg, pn, pb, p1, pa
+ )/(4.*(N_C*N_C - 1.));
+ const double ladder_factor = FKL_ladder_weight(
+ (BeginPart+2), (EndPart-1),
+ pa-p1-pg, pa, pb, p1, pn, lambda
+ );
+
+ return current_factor*ladder_factor;
+ }
+ }
+
double MatrixElement::tree_kin_jets(Event const & ev) const {
auto const & incoming = ev.incoming();
const auto partons = tag_extremal_jet_partons(ev);
- if(is_uno(ev.type())){
- throw not_implemented("unordered emission not implemented for pure jets");
- }
+ if (ev.type()==HEJ::event_type::unordered_backward){
+ return tree_kin_jets_uno(incoming.begin(), incoming.end(),
+ partons.begin(), partons.end(),
+ param_.regulator_lambda);
+ }
+ else if (ev.type()==HEJ::event_type::unordered_forward){
+ return tree_kin_jets_uno(incoming.rbegin(), incoming.rend(),
+ partons.rbegin(), partons.rend(),
+ param_.regulator_lambda);
+ }
const auto pa = to_HepLorentzVector(incoming[0]);
const auto pb = to_HepLorentzVector(incoming[1]);
const auto p1 = to_HepLorentzVector(partons.front());
const auto pn = to_HepLorentzVector(partons.back());
return ME_current(
incoming[0].type, incoming[1].type,
pn, pb, p1, pa
)/(4.*(N_C*N_C - 1.))*FKL_ladder_weight(
begin(partons) + 1, end(partons) - 1,
pa - p1, pa, pb, p1, pn,
param_.regulator_lambda
);
}
namespace{
double tree_kin_W_FKL(
int aptype, int bptype, HLV pa, HLV pb,
std::vector<Particle> const & partons,
HLV plbar, HLV pl,
double lambda
){
auto p1 = to_HepLorentzVector(partons[0]);
auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
const auto begin_ladder = cbegin(partons) + 1;
const auto end_ladder = cend(partons) - 1;
bool wc = aptype==partons[0].type; //leg b emits w
auto q0 = pa - p1;
if(!wc)
q0 -= pl + plbar;
const double current_factor = ME_W_current(
aptype, bptype, pn, pb,
p1, pa, plbar, pl, wc
);
const double ladder_factor = FKL_ladder_weight(
begin_ladder, end_ladder,
q0, pa, pb, p1, pn,
lambda
);
return current_factor*ladder_factor;
}
double tree_kin_W_unob(
int aptype, int bptype, HLV pa, HLV pb,
std::vector<Particle> const & partons,
HLV plbar, HLV pl,
double lambda
){
auto pg = to_HepLorentzVector(partons[0]);
auto p1 = to_HepLorentzVector(partons[1]);
auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
const auto begin_ladder = cbegin(partons) + 2;
const auto end_ladder = cend(partons) - 1;
bool wc = aptype==partons[1].type; //leg b emits w
auto q0 = pa - p1 -pg;
if(!wc)
q0 -= pl + plbar;
const double current_factor = ME_W_unob_current(
aptype, bptype, pn, pb,
p1, pa, pg, plbar, pl, wc
);
const double ladder_factor = FKL_ladder_weight(
begin_ladder, end_ladder,
q0, pa, pb, p1, pn,
lambda
);
return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
}
double tree_kin_W_unof(
int aptype, int bptype, HLV pa, HLV pb,
std::vector<Particle> const & partons,
HLV plbar, HLV pl,
double lambda
){
auto p1 = to_HepLorentzVector(partons[0]);
auto pn = to_HepLorentzVector(partons[partons.size() - 2]);
auto pg = to_HepLorentzVector(partons[partons.size() - 1]);
const auto begin_ladder = cbegin(partons) + 1;
const auto end_ladder = cend(partons) - 2;
bool wc = aptype==partons[0].type; //leg b emits w
auto q0 = pa - p1;
if(!wc)
q0 -= pl + plbar;
const double current_factor = ME_W_unof_current(
aptype, bptype, pn, pb,
p1, pa, pg, plbar, pl, wc
);
const double ladder_factor = FKL_ladder_weight(
begin_ladder, end_ladder,
q0, pa, pb, p1, pn,
lambda
);
return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
}
double tree_kin_W_qqxb(
int aptype, int bptype, HLV pa, HLV pb,
std::vector<Particle> const & partons,
HLV plbar, HLV pl,
double lambda
){
HLV pq,pqbar;
if(is_quark(partons[0])){
pq = to_HepLorentzVector(partons[0]);
pqbar = to_HepLorentzVector(partons[1]);
}
else{
pq = to_HepLorentzVector(partons[1]);
pqbar = to_HepLorentzVector(partons[0]);
}
auto p1 = to_HepLorentzVector(partons[0]);
auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
const auto begin_ladder = cbegin(partons) + 2;
const auto end_ladder = cend(partons) - 1;
bool wc = bptype!=partons.back().type; //leg b emits w
auto q0 = pa - pq - pqbar;
if(!wc)
q0 -= pl + plbar;
const double current_factor = ME_W_qqxb_current(
aptype, bptype, pa, pb,
pq, pqbar, pn, plbar, pl, wc
);
const double ladder_factor = FKL_ladder_weight(
begin_ladder, end_ladder,
q0, pa, pb, p1, pn,
lambda
);
return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
}
double tree_kin_W_qqxf(
int aptype, int bptype, HLV pa, HLV pb,
std::vector<Particle> const & partons,
HLV plbar, HLV pl,
double lambda
){
HLV pq,pqbar;
if(is_quark(partons[partons.size() - 1])){
pq = to_HepLorentzVector(partons[partons.size() - 1]);
pqbar = to_HepLorentzVector(partons[partons.size() - 2]);
}
else{
pq = to_HepLorentzVector(partons[partons.size() - 2]);
pqbar = to_HepLorentzVector(partons[partons.size() - 1]);
}
auto p1 = to_HepLorentzVector(partons[0]);
auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
const auto begin_ladder = cbegin(partons) + 1;
const auto end_ladder = cend(partons) - 2;
bool wc = aptype==partons.front().type; //leg b emits w
auto q0 = pa - p1;
if(!wc)
q0 -= pl + plbar;
const double current_factor = ME_W_qqxf_current(
aptype, bptype, pa, pb,
pq, pqbar, p1, plbar, pl, wc
);
const double ladder_factor = FKL_ladder_weight(
begin_ladder, end_ladder,
q0, pa, pb, p1, pn,
lambda
);
return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
}
double tree_kin_W_qqxmid(
int aptype, int bptype, HLV pa, HLV pb,
std::vector<Particle> const & partons,
HLV plbar, HLV pl,
double lambda
){
HLV pq,pqbar;
const auto backmidquark = std::find_if(
begin(partons)+1, end(partons)-1,
[](Particle const & s){ return s.type != pid::gluon; }
);
assert(backmidquark!=end(partons)-1);
if (is_quark(backmidquark->type)){
pq = to_HepLorentzVector(*backmidquark);
pqbar = to_HepLorentzVector(*(backmidquark+1));
}
else {
pqbar = to_HepLorentzVector(*backmidquark);
pq = to_HepLorentzVector(*(backmidquark+1));
}
auto p1 = to_HepLorentzVector(partons[0]);
auto pn = to_HepLorentzVector(partons[partons.size() - 1]);
auto q0 = pa - p1;
// t-channel momentum after qqx
auto qqxt = q0;
bool wc, wqq;
if (backmidquark->type == -(backmidquark+1)->type){ // Central qqx does not emit
wqq=false;
if (aptype==partons[0].type) {
wc = true;
}
else{
wc = false;
q0-=pl+plbar;
}
}
else{
wqq = true;
wc = false;
qqxt-=pl+plbar;
}
const auto begin_ladder = cbegin(partons) + 1;
const auto end_ladder_1 = (backmidquark);
const auto begin_ladder_2 = (backmidquark+2);
const auto end_ladder = cend(partons) - 1;
for(auto parton_it = begin_ladder; parton_it < begin_ladder_2; ++parton_it){
qqxt -= to_HepLorentzVector(*parton_it);
}
int nabove = std::distance(begin_ladder, backmidquark);
int nbelow = std::distance(begin_ladder_2, end_ladder);
std::vector<HLV> partonsHLV;
partonsHLV.reserve(partons.size());
for (size_t i = 0; i != partons.size(); ++i) {
partonsHLV.push_back(to_HepLorentzVector(partons[i]));
}
const double current_factor = ME_W_qqxmid_current(
aptype, bptype, nabove, nbelow, pa, pb,
pq, pqbar, partonsHLV, plbar, pl, wqq, wc
);
const double ladder_factor = FKL_ladder_weight(
begin_ladder, end_ladder_1,
q0, pa, pb, p1, pn,
lambda
)*FKL_ladder_weight(
begin_ladder_2, end_ladder,
qqxt, pa, pb, p1, pn,
lambda
);
return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
}
} // namespace anonymous
double MatrixElement::tree_kin_W(Event const & ev) const {
using namespace event_type;
auto const & incoming(ev.incoming());
auto const & decays(ev.decays());
HLV plbar, pl;
for (auto& x: decays) {
if (x.second.at(0).type < 0){
plbar = to_HepLorentzVector(x.second.at(0));
pl = to_HepLorentzVector(x.second.at(1));
}
else{
pl = to_HepLorentzVector(x.second.at(0));
plbar = to_HepLorentzVector(x.second.at(1));
}
}
const auto pa = to_HepLorentzVector(incoming[0]);
const auto pb = to_HepLorentzVector(incoming[1]);
const auto partons = tag_extremal_jet_partons(ev);
if(ev.type() == unordered_backward){
return tree_kin_W_unob(incoming[0].type, incoming[1].type,
pa, pb, partons, plbar, pl,
param_.regulator_lambda);
}
if(ev.type() == unordered_forward){
return tree_kin_W_unof(incoming[0].type, incoming[1].type,
pa, pb, partons, plbar, pl,
param_.regulator_lambda);
}
if(ev.type() == extremal_qqxb){
return tree_kin_W_qqxb(incoming[0].type, incoming[1].type,
pa, pb, partons, plbar, pl,
param_.regulator_lambda);
}
if(ev.type() == extremal_qqxf){
return tree_kin_W_qqxf(incoming[0].type, incoming[1].type,
pa, pb, partons, plbar, pl,
param_.regulator_lambda);
}
if(ev.type() == central_qqx){
return tree_kin_W_qqxmid(incoming[0].type, incoming[1].type,
pa, pb, partons, plbar, pl,
param_.regulator_lambda);
}
return tree_kin_W_FKL(incoming[0].type, incoming[1].type,
pa, pb, partons, plbar, pl,
param_.regulator_lambda);
}
double MatrixElement::tree_kin_Higgs(Event const & ev) const {
if(is_uno(ev.type())){
return tree_kin_Higgs_between(ev);
}
if(ev.outgoing().front().type == pid::Higgs){
return tree_kin_Higgs_first(ev);
}
if(ev.outgoing().back().type == pid::Higgs){
return tree_kin_Higgs_last(ev);
}
return tree_kin_Higgs_between(ev);
}
namespace {
// Colour acceleration multipliers, for gluons see eq. (7) in arXiv:0910.5113
#ifdef HEJ_BUILD_WITH_QCDLOOP
// TODO: code duplication with jets.cc
double K_g(double p1minus, double paminus) {
return 1./2.*(p1minus/paminus + paminus/p1minus)*(C_A - 1./C_A) + 1./C_A;
}
double K_g(
CLHEP::HepLorentzVector const & pout,
CLHEP::HepLorentzVector const & pin
) {
if(pin.z() > 0) return K_g(pout.plus(), pin.plus());
return K_g(pout.minus(), pin.minus());
}
double K(
ParticleID type,
CLHEP::HepLorentzVector const & pout,
CLHEP::HepLorentzVector const & pin
) {
if(type == ParticleID::gluon) return K_g(pout, pin);
return C_F;
}
#endif
// Colour factor in strict MRK limit
double K_MRK(ParticleID type) {
return (type == ParticleID::gluon)?C_A:C_F;
}
}
double MatrixElement::MH2_forwardH(
CLHEP::HepLorentzVector const & p1out,
CLHEP::HepLorentzVector const & p1in,
ParticleID type2,
CLHEP::HepLorentzVector const & p2out,
CLHEP::HepLorentzVector const & p2in,
CLHEP::HepLorentzVector const & pH,
double t1, double t2
) const{
ignore(p2out, p2in);
const double shat = p1in.invariantMass2(p2in);
// gluon case
#ifdef HEJ_BUILD_WITH_QCDLOOP
if(!param_.Higgs_coupling.use_impact_factors){
return K(type2, p2out, p2in)*C_A*1./(16*M_PI*M_PI)*t1/t2*ME_Houtside_gq(
p1out, p1in, p2out, p2in, pH,
param_.Higgs_coupling.mt, param_.Higgs_coupling.include_bottom,
param_.Higgs_coupling.mb
)/(4*(N_C*N_C - 1));
}
#endif
return K_MRK(type2)/C_A*9./2.*shat*shat*(
C2gHgp(p1in,p1out,pH) + C2gHgm(p1in,p1out,pH)
)/(t1*t2);
}
double MatrixElement::tree_kin_Higgs_first(Event const & ev) const {
auto const & incoming = ev.incoming();
auto const & outgoing = ev.outgoing();
assert(outgoing.front().type == pid::Higgs);
if(outgoing[1].type != pid::gluon) {
assert(incoming.front().type == outgoing[1].type);
return tree_kin_Higgs_between(ev);
}
const auto pH = to_HepLorentzVector(outgoing.front());
const auto partons = tag_extremal_jet_partons(
ev
);
const auto pa = to_HepLorentzVector(incoming[0]);
const auto pb = to_HepLorentzVector(incoming[1]);
const auto p1 = to_HepLorentzVector(partons.front());
const auto pn = to_HepLorentzVector(partons.back());
const auto q0 = pa - p1 - pH;
const double t1 = q0.m2();
const double t2 = (pn - pb).m2();
return MH2_forwardH(
p1, pa, incoming[1].type, pn, pb, pH,
t1, t2
)*FKL_ladder_weight(
begin(partons) + 1, end(partons) - 1,
q0, pa, pb, p1, pn,
param_.regulator_lambda
);
}
double MatrixElement::tree_kin_Higgs_last(Event const & ev) const {
auto const & incoming = ev.incoming();
auto const & outgoing = ev.outgoing();
assert(outgoing.back().type == pid::Higgs);
if(outgoing[outgoing.size()-2].type != pid::gluon) {
assert(incoming.back().type == outgoing[outgoing.size()-2].type);
return tree_kin_Higgs_between(ev);
}
const auto pH = to_HepLorentzVector(outgoing.back());
const auto partons = tag_extremal_jet_partons(
ev
);
const auto pa = to_HepLorentzVector(incoming[0]);
const auto pb = to_HepLorentzVector(incoming[1]);
auto p1 = to_HepLorentzVector(partons.front());
const auto pn = to_HepLorentzVector(partons.back());
auto q0 = pa - p1;
const double t1 = q0.m2();
const double t2 = (pn + pH - pb).m2();
return MH2_forwardH(
pn, pb, incoming[0].type, p1, pa, pH,
t2, t1
)*FKL_ladder_weight(
begin(partons) + 1, end(partons) - 1,
q0, pa, pb, p1, pn,
param_.regulator_lambda
);
}
double MatrixElement::tree_kin_Higgs_between(Event const & ev) const {
using namespace event_type;
auto const & incoming = ev.incoming();
auto const & outgoing = ev.outgoing();
const auto the_Higgs = std::find_if(
begin(outgoing), end(outgoing),
[](Particle const & s){ return s.type == pid::Higgs; }
);
assert(the_Higgs != end(outgoing));
const auto pH = to_HepLorentzVector(*the_Higgs);
const auto partons = tag_extremal_jet_partons(ev);
const auto pa = to_HepLorentzVector(incoming[0]);
const auto pb = to_HepLorentzVector(incoming[1]);
auto p1 = to_HepLorentzVector(
partons[(ev.type() == unob)?1:0]
);
auto pn = to_HepLorentzVector(
partons[partons.size() - ((ev.type() == unof)?2:1)]
);
auto first_after_Higgs = begin(partons) + (the_Higgs-begin(outgoing));
assert(
(first_after_Higgs == end(partons) && (
(ev.type() == unob)
|| partons.back().type != pid::gluon
))
|| first_after_Higgs->rapidity() >= the_Higgs->rapidity()
);
assert(
(first_after_Higgs == begin(partons) && (
(ev.type() == unof)
|| partons.front().type != pid::gluon
))
|| (first_after_Higgs-1)->rapidity() <= the_Higgs->rapidity()
);
// always treat the Higgs as if it were in between the extremal FKL partons
if(first_after_Higgs == begin(partons)) ++first_after_Higgs;
else if(first_after_Higgs == end(partons)) --first_after_Higgs;
// t-channel momentum before Higgs
auto qH = pa;
for(auto parton_it = begin(partons); parton_it != first_after_Higgs; ++parton_it){
qH -= to_HepLorentzVector(*parton_it);
}
auto q0 = pa - p1;
auto begin_ladder = begin(partons) + 1;
auto end_ladder = end(partons) - 1;
double current_factor;
if(ev.type() == unob){
current_factor = C_A*C_A/2.*ME_Higgs_current_unob( // 1/2 = "K_uno"
incoming[0].type, incoming[1].type,
pn, pb, to_HepLorentzVector(partons.front()), p1, pa, qH, qH - pH,
param_.Higgs_coupling.mt,
param_.Higgs_coupling.include_bottom, param_.Higgs_coupling.mb
);
const auto p_unob = to_HepLorentzVector(partons.front());
q0 -= p_unob;
p1 += p_unob;
++begin_ladder;
}
else if(ev.type() == unof){
current_factor = C_A*C_A/2.*ME_Higgs_current_unof( // 1/2 = "K_uno"
incoming[0].type, incoming[1].type,
to_HepLorentzVector(partons.back()), pn, pb, p1, pa, qH, qH - pH,
param_.Higgs_coupling.mt,
param_.Higgs_coupling.include_bottom, param_.Higgs_coupling.mb
);
pn += to_HepLorentzVector(partons.back());
--end_ladder;
}
else{
current_factor = ME_Higgs_current(
incoming[0].type, incoming[1].type,
pn, pb, p1, pa, qH, qH - pH,
param_.Higgs_coupling.mt,
param_.Higgs_coupling.include_bottom, param_.Higgs_coupling.mb
);
}
const double ladder_factor = FKL_ladder_weight(
begin_ladder, first_after_Higgs,
q0, pa, pb, p1, pn,
param_.regulator_lambda
)*FKL_ladder_weight(
first_after_Higgs, end_ladder,
qH - pH, pa, pb, p1, pn,
param_.regulator_lambda
);
return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
}
namespace {
double get_AWZH_coupling(Event const & ev, double alpha_s) {
const auto AWZH_boson = std::find_if(
begin(ev.outgoing()), end(ev.outgoing()),
[](auto const & p){return is_AWZH_boson(p);}
);
if(AWZH_boson == end(ev.outgoing())) return 1.;
switch(AWZH_boson->type){
case pid::Higgs:
return alpha_s*alpha_s;
case pid::Wp:
case pid::Wm:
return gw*gw*gw*gw/4.;
// TODO
case pid::photon:
case pid::Z:
default:
throw not_implemented("Emission of boson of unsupported type");
}
}
}
double MatrixElement::tree_param(Event const & ev, double mur) const {
assert(is_resummable(ev.type()));
const auto begin_partons = ev.begin_partons();
const auto end_partons = ev.end_partons();
const auto num_partons = std::distance(begin_partons, end_partons);
const double alpha_s = alpha_s_(mur);
const double gs2 = 4.*M_PI*alpha_s;
double res = std::pow(gs2, num_partons);
if(param_.log_correction){
// use alpha_s(q_perp), evolved to mur
assert(num_partons >= 2);
const auto first_emission = std::next(begin_partons);
const auto last_emission = std::prev(end_partons);
for(auto parton = first_emission; parton != last_emission; ++parton){
res *= 1. + alpha_s/(2.*M_PI)*beta0*log(mur/parton->perp());
}
}
return get_AWZH_coupling(ev, alpha_s)*res;
}
} // namespace HEJ
diff --git a/src/jets.cc b/src/jets.cc
index fb90832..c97ca19 100644
--- a/src/jets.cc
+++ b/src/jets.cc
@@ -1,276 +1,369 @@
/**
* \authors The HEJ collaboration (see AUTHORS for details)
* \date 2019
* \copyright GPLv2 or later
*/
#include "HEJ/jets.hh"
#include "HEJ/Constants.hh"
// Colour acceleration multiplier for gluons see eq. (7) in arXiv:0910.5113
// @TODO: this is not a current and should be moved somewhere else
double K_g(double p1minus, double paminus) {
return 1./2.*(p1minus/paminus + paminus/p1minus)*(HEJ::C_A - 1./HEJ::C_A) + 1./HEJ::C_A;
}
double K_g(
HLV const & pout,
HLV const & pin
) {
if(pin.z() > 0) return K_g(pout.plus(), pin.plus());
return K_g(pout.minus(), pin.minus());
}
CCurrent CCurrent::operator+(const CCurrent& other)
{
COM result_c0=c0 + other.c0;
COM result_c1=c1 + other.c1;
COM result_c2=c2 + other.c2;
COM result_c3=c3 + other.c3;
return CCurrent(result_c0,result_c1,result_c2,result_c3);
}
CCurrent CCurrent::operator-(const CCurrent& other)
{
COM result_c0=c0 - other.c0;
COM result_c1=c1 - other.c1;
COM result_c2=c2 - other.c2;
COM result_c3=c3 - other.c3;
return CCurrent(result_c0,result_c1,result_c2,result_c3);
}
CCurrent CCurrent::operator*(const double x)
{
COM result_c0=x*CCurrent::c0;
COM result_c1=x*CCurrent::c1;
COM result_c2=x*CCurrent::c2;
COM result_c3=x*CCurrent::c3;
return CCurrent(result_c0,result_c1,result_c2,result_c3);
}
CCurrent CCurrent::operator/(const double x)
{
COM result_c0=CCurrent::c0/x;
COM result_c1=CCurrent::c1/x;
COM result_c2=CCurrent::c2/x;
COM result_c3=CCurrent::c3/x;
return CCurrent(result_c0,result_c1,result_c2,result_c3);
}
CCurrent CCurrent::operator*(const COM x)
{
COM result_c0=x*CCurrent::c0;
COM result_c1=x*CCurrent::c1;
COM result_c2=x*CCurrent::c2;
COM result_c3=x*CCurrent::c3;
return CCurrent(result_c0,result_c1,result_c2,result_c3);
}
CCurrent CCurrent::operator/(const COM x)
{
COM result_c0=(CCurrent::c0)/x;
COM result_c1=(CCurrent::c1)/x;
COM result_c2=(CCurrent::c2)/x;
COM result_c3=(CCurrent::c3)/x;
return CCurrent(result_c0,result_c1,result_c2,result_c3);
}
std::ostream& operator <<(std::ostream& os, const CCurrent& cur)
{
os << "("<<cur.c0<< " ; "<<cur.c1<<" , "<<cur.c2<<" , "<<cur.c3<<")";
return os;
}
CCurrent operator * ( double x, CCurrent& m)
{
return m*x;
}
CCurrent operator * ( COM x, CCurrent& m)
{
return m*x;
}
CCurrent operator / ( double x, CCurrent& m)
{
return m/x;
}
CCurrent operator / ( COM x, CCurrent& m)
{
return m/x;
}
COM CCurrent::dot(HLV p1)
{
// Current goes (E,px,py,pz)
// Vector goes (px,py,pz,E)
return p1[3]*c0-p1[0]*c1-p1[1]*c2-p1[2]*c3;
}
COM CCurrent::dot(CCurrent p1)
{
return p1.c0*c0-p1.c1*c1-p1.c2*c2-p1.c3*c3;
}
//Current Functions
void joi(HLV pout, bool helout, HLV pin, bool helin, current &cur) {
cur[0]=0.;
cur[1]=0.;
cur[2]=0.;
cur[3]=0.;
const double sqpop = sqrt(pout.plus());
const double sqpom = sqrt(pout.minus());
const COM poperp = pout.x() + COM(0, 1) * pout.y();
if (helout != helin) {
throw std::invalid_argument{"Non-matching helicities"};
} else if (helout == false) { // negative helicity
if (pin.plus() > pin.minus()) { // if forward
const double sqpip = sqrt(pin.plus());
cur[0] = sqpop * sqpip;
cur[1] = sqpom * sqpip * poperp / abs(poperp);
cur[2] = -COM(0,1) * cur[1];
cur[3] = cur[0];
} else { // if backward
const double sqpim = sqrt(pin.minus());
cur[0] = -sqpom * sqpim * poperp / abs(poperp);
cur[1] = -sqpim * sqpop;
cur[2] = COM(0,1) * cur[1];
cur[3] = -cur[0];
}
} else { // positive helicity
if (pin.plus() > pin.minus()) { // if forward
const double sqpip = sqrt(pin.plus());
cur[0] = sqpop * sqpip;
cur[1] = sqpom * sqpip * conj(poperp) / abs(poperp);
cur[2] = COM(0,1) * cur[1];
cur[3] = cur[0];
} else { // if backward
const double sqpim = sqrt(pin.minus());
cur[0] = -sqpom * sqpim * conj(poperp) / abs(poperp);
cur[1] = -sqpim * sqpop;
cur[2] = -COM(0,1) * cur[1];
cur[3] = -cur[0];
}
}
}
CCurrent joi (HLV pout, bool helout, HLV pin, bool helin)
{
current cur;
joi(pout, helout, pin, helin, cur);
return CCurrent(cur[0],cur[1],cur[2],cur[3]);
}
void jio(HLV pin, bool helin, HLV pout, bool helout, current &cur) {
joi(pout, !helout, pin, !helin, cur);
}
CCurrent jio (HLV pin, bool helin, HLV pout, bool helout)
{
current cur;
jio(pin, helin, pout, helout, cur);
return CCurrent(cur[0],cur[1],cur[2],cur[3]);
}
void joo(HLV pi, bool heli, HLV pj, bool helj, current &cur) {
// Zero our current
cur[0] = 0.0;
cur[1] = 0.0;
cur[2] = 0.0;
cur[3] = 0.0;
if (heli!=helj) {
throw std::invalid_argument{"Non-matching helicities"};
} else if ( heli == true ) { // If positive helicity swap momenta
std::swap(pi,pj);
}
const double sqpjp = sqrt(pj.plus());
const double sqpjm = sqrt(pj.minus());
const double sqpip = sqrt(pi.plus());
const double sqpim = sqrt(pi.minus());
const COM piperp = pi.x() + COM(0,1) * pi.y();
const COM pjperp = pj.x() + COM(0,1) * pj.y();
const COM phasei = piperp / abs(piperp);
const COM phasej = pjperp / abs(pjperp);
cur[0] = sqpim * sqpjm * phasei * conj(phasej) + sqpip * sqpjp;
cur[1] = sqpim * sqpjp * phasei + sqpip * sqpjm * conj(phasej);
cur[2] = -COM(0, 1) * (sqpim * sqpjp * phasei - sqpip * sqpjm * conj(phasej));
cur[3] = -sqpim * sqpjm * phasei * conj(phasej) + sqpip * sqpjp;
}
CCurrent joo (HLV pi, bool heli, HLV pj, bool helj)
{
current cur;
joo(pi, heli, pj, helj, cur);
return CCurrent(cur[0],cur[1],cur[2],cur[3]);
}
namespace{
//@{
/**
* @brief Pure Jet FKL Contributions, function to handle all incoming types.
* @param p1out Outgoing Particle 1.
* @param p1in Incoming Particle 1.
* @param p2out Outgoing Particle 2
* @param p2in Incoming Particle 2
* @param aqlineb Bool. Is Backwards quark line an anti-quark line?
* @param aqlinef Bool. Is Forwards quark line an anti-quark line?
*
* Calculates j_\mu j^\mu.
* Handles all possible incoming states.
*/
double j_j(HLV p1out, HLV p1in, HLV p2out, HLV p2in, bool aqlineb, bool aqlinef){
HLV q1=p1in-p1out;
HLV q2=-(p2in-p2out);
current mj1m,mj1p,mj2m,mj2p;
// Note need to flip helicities in anti-quark case.
joi(p1out,!aqlineb, p1in,!aqlineb, mj1p);
joi(p1out, aqlineb, p1in, aqlineb, mj1m);
joi(p2out,!aqlinef, p2in,!aqlinef, mj2p);
joi(p2out, aqlinef, p2in, aqlinef, mj2m);
COM Mmp=cdot(mj1m,mj2p);
COM Mmm=cdot(mj1m,mj2m);
COM Mpp=cdot(mj1p,mj2p);
COM Mpm=cdot(mj1p,mj2m);
double sst=abs2(Mmm)+abs2(Mmp)+abs2(Mpp)+abs2(Mpm);
// Multiply by Cf^2
return HEJ::C_F*HEJ::C_F*(sst)/(q1.m2()*q2.m2());
}
} //anonymous namespace
double ME_qQ(HLV p1out, HLV p1in, HLV p2out, HLV p2in){
return j_j(p1out, p1in, p2out, p2in, false, false);
}
double ME_qQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in){
return j_j(p1out, p1in, p2out, p2in, false, true);
}
double ME_qbarQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in){
return j_j(p1out, p1in, p2out, p2in, true, true);
}
double ME_qg(HLV p1out, HLV p1in, HLV p2out, HLV p2in){
return j_j(p1out, p1in, p2out, p2in, false, false)*K_g(p2out, p2in)/HEJ::C_F;
}
double ME_qbarg(HLV p1out, HLV p1in, HLV p2out, HLV p2in){
return j_j(p1out, p1in, p2out, p2in, true, false)*K_g(p2out, p2in)/(HEJ::C_F);
}
double ME_gg(HLV p1out, HLV p1in, HLV p2out, HLV p2in){
return j_j(p1out, p1in, p2out, p2in, false, false)*K_g(p1out, p1in)*K_g(p2out, p2in)/(HEJ::C_F*HEJ::C_F);
}
//@}
+
+namespace{
+ double juno_j(HLV pg, HLV p1out, HLV p1in, HLV p2out,
+ HLV p2in, bool aqlinea, bool aqlineb){
+ // This construction is taking rapidity order: pg > p1out >> p2out
+ HLV q1=p1in-p1out; // Top End
+ HLV q2=-(p2in-p2out); // Bottom End
+ HLV qg=p1in-p1out-pg; // Extra bit post-gluon
+
+ // Note <p1|eps|pa> current split into two by gauge choice.
+ // See James C's Thesis (p72). <p1|eps|pa> -> <p1|pg><pg|pa>
+ CCurrent mj1p=joi(p1out,!aqlinea,p1in,!aqlinea);
+ CCurrent mj1m=joi(p1out,aqlinea,p1in,aqlinea);
+ CCurrent jgap=joi(pg,!aqlinea,p1in,!aqlinea);
+ CCurrent jgam=joi(pg,aqlinea,p1in,aqlinea);
+
+ // Note for function joo(): <p1+|pg+> = <pg-|p1->.
+ CCurrent j2gp=joo(p1out,!aqlinea,pg,!aqlinea);
+ CCurrent j2gm=joo(p1out,aqlinea,pg,aqlinea);
+
+ CCurrent mj2p=joi(p2out,!aqlineb,p2in,!aqlineb);
+ CCurrent mj2m=joi(p2out,aqlineb,p2in,aqlineb);
+
+ // Dot products of these which occur again and again
+ COM Mmp=mj1m.dot(mj2p);
+ COM Mmm=mj1m.dot(mj2m);
+ COM Mpp=mj1p.dot(mj2p);
+ COM Mpm=mj1p.dot(mj2m);
+
+ CCurrent p1o(p1out),p2o(p2out),p2i(p2in),qsum(q1+qg),p1i(p1in);
+
+ CCurrent Lmm=(qsum*(Mmm)+(-2.*mj2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mj2m
+ +(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*Mmm/2.))/q1.m2();
+ CCurrent Lmp=(qsum*(Mmp) + (-2.*mj2p.dot(pg))*mj1m+2.*mj1m.dot(pg)*mj2p
+ +(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*Mmp/2.))/q1.m2();
+ CCurrent Lpm=(qsum*(Mpm) + (-2.*mj2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mj2m
+ +(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*Mpm/2.))/q1.m2();
+ CCurrent Lpp=(qsum*(Mpp) + (-2.*mj2p.dot(pg))*mj1p+2.*mj1p.dot(pg)*mj2p
+ +(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*Mpp/2.))/q1.m2();
+
+ CCurrent U1mm=(jgam.dot(mj2m)*j2gm+2.*p1o*Mmm)/(p1out+pg).m2();
+ CCurrent U1mp=(jgam.dot(mj2p)*j2gm+2.*p1o*Mmp)/(p1out+pg).m2();
+ CCurrent U1pm=(jgap.dot(mj2m)*j2gp+2.*p1o*Mpm)/(p1out+pg).m2();
+ CCurrent U1pp=(jgap.dot(mj2p)*j2gp+2.*p1o*Mpp)/(p1out+pg).m2();
+ CCurrent U2mm=((-1.)*j2gm.dot(mj2m)*jgam+2.*p1i*Mmm)/(p1in-pg).m2();
+ CCurrent U2mp=((-1.)*j2gm.dot(mj2p)*jgam+2.*p1i*Mmp)/(p1in-pg).m2();
+ CCurrent U2pm=((-1.)*j2gp.dot(mj2m)*jgap+2.*p1i*Mpm)/(p1in-pg).m2();
+ CCurrent U2pp=((-1.)*j2gp.dot(mj2p)*jgap+2.*p1i*Mpp)/(p1in-pg).m2();
+
+ constexpr double cf=HEJ::C_F;
+
+ double amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
+ double amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
+ double apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
+ double app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
+ double ampsq=-(amm+amp+apm+app);
+
+ //Divide by t-channels
+ ampsq/=q2.m2()*qg.m2();
+ ampsq/=16.;
+
+ // Factor of (Cf/Ca) for each quark to match j_j.
+ ampsq*=(HEJ::C_F*HEJ::C_F)/(HEJ::C_A*HEJ::C_A);
+
+ return ampsq;
+
+ }
+}
+
+//Unordered bits for pure jet
+double ME_unob_qQ (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in){
+ return juno_j(pg, p1out, p1in, p2out, p2in, false, false);
+}
+
+double ME_unob_qbarQ (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in){
+ return juno_j(pg, p1out, p1in, p2out, p2in, true, false);
+}
+
+double ME_unob_qQbar (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in){
+ return juno_j(pg, p1out, p1in, p2out, p2in, false, true);
+}
+
+double ME_unob_qbarQbar (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in){
+ return juno_j(pg, p1out, p1in, p2out, p2in, true, true);
+}
+
+double ME_unob_qg (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in){
+ return juno_j(pg, p1out, p1in, p2out, p2in, false, false)*K_g(p2out,p2in)/HEJ::C_F;
+}
+
+double ME_unob_qbarg (HLV pg, HLV p1out, HLV p1in, HLV p2out, HLV p2in){
+ return juno_j(pg, p1out, p1in, p2out, p2in, true, false)*K_g(p2out,p2in)/HEJ::C_F;
+}
diff --git a/t/ME_data/ME_jets_tree.dat b/t/ME_data/ME_jets_tree.dat
index fc2be65..0f36db3 100644
--- a/t/ME_data/ME_jets_tree.dat
+++ b/t/ME_data/ME_jets_tree.dat
@@ -1,672 +1,742 @@
1089423.187
16.03009374
6634.608547
75414606.57
77554.50738
197575.0454
76983.13177
38.35809694
14.34964854
2.299306716e+10
769524899.8
20.89671172
76.68018946
8308.664153
2450736.574
52.24359459
497.7665557
5051.865522
94571.50832
1362099715
3690.443315
4732694.851
33060865.81
38851015.2
30289.18618
283948.732
14123.1659
40.56212546
6.779515122e+12
25724.24084
4.464903667
26.15970999
28358522.83
481820.3073
33.14640689
91.72649968
322690.8843
39.04279288
65541087.6
2256.832837
51.04918081
21658.09425
675.8508089
0.003214397574
413076.4025
1194042.703
15261824.18
1.190018997e+13
25852091.94
765101.1953
579.2342295
23845182.04
92.16369985
705.5684735
828764.9832
81.971147
1436684.808
70.01623522
230.5658106
8794.725516
890.1697598
97617236.05
31101.11974
10351668.97
187539232.1
93875.71518
43031260.49
4.067125353
6035.796288
16569782.71
46.2510317
52.88862266
0.5556956436
606771384.7
293585.0788
8415963.902
29.5069149
18.96420915
6.321441102e+14
3.592998225
129.9175932
19.85723932
20438567.28
2.633206648e+10
2051545.14
13.98077027
342.1399233
17.65245465
79250.23744
1030.69768
73407.42532
237883.1282
79.44231257
81668.43497
93415340.81
430.286772
2209.749603
568258.2296
173145.2499
1620285.613
337.6920671
153.562771
416.0616338
2187.267876
22.41576042
49.58992905
559801.7855
45.11194021
584508.9206
35.3041943
202.7925831
15.00277101
46.15144698
4.588470323e+13
597.3210575
39.62999028
5228016720
822065.5972
1.826581842e+10
6.479966482
486208349.5
62.22613221
21.46207828
792.2244925
98.46049107
192.195726
539903191.6
7888.570415
559946441.6
99.19582481
967.8349215
1186287.112
296.9970515
393.8848181
46.84865591
27.79939609
70102.51858
68.89626885
2702.415147
257.708207
155288432.1
1225359.249
90576.73064
9434.676956
88.90057162
4378317.363
15680420.87
6567.795332
94.80131393
44.21436446
61.79707787
44.41095665
7385.16094
227.1571585
94986.49609
67239897.71
96.37463492
2911.906879
49.889402
6585.792276
336579403.2
564.3980943
1554303.479
33573.8975
2.437369584e+10
226746.4443
75.83290452
27.75735686
94778193.37
59.97102623
64.15185493
7.774417686e+13
7438.779369
22.08782146
434613.7211
34293520.02
68775.95004
307606184.4
150615.387
899713.4452
9.223973371e+11
59817.02462
348.4932635
2609243018
24597079.8
98.70527236
83.33745442
12560815.61
1358729.011
6976819.18
7425.681281
488.6665953
13.67398052
401.1059245
1888.653087
4009.955386
175.1044182
864180.0454
37.7515354
47187493.74
109.4430381
359.7148155
2.340917207e+11
179.4280073
9827.615509
51.43706602
159.8742767
2066998.073
21197190.52
154.5419162
20.22828093
96.58078786
54.45061659
65.30848921
27.46863884
399638.3233
48.71138495
1579072.132
67717150.9
1034311422
2300.166812
542.347043
225.023696
15.39245502
5.045806172
408439.9118
2850069.206
412.6441358
461.2402375
22.40894016
37199025.96
16799601.72
1283263.103
19.12993911
4119931.525
138990.0255
122.7744597
18733.45006
56.21459033
343399063.9
40.69967214
1257.945403
2.549605794e+11
100938.8483
197079455.9
18898.20284
65974.22935
2007851.613
6824.687033
4076901842
7253481.757
3.002058086
1662154.497
3.070682383e+12
163.8653423
560506230.7
1510.132538
26693.22493
0.1285518109
494554.148
24594487.35
271745.3087
155.6774454
0.01468054527
3.34264067
1588023.004
11.02440854
2.276304783
2060679.506
1.060994634
7899476.433
11392931.55
0.002283073032
223.8249674
64.14820176
222013139.2
17285137.17
4904.948169
4.325556105e+10
2.025060646
64.72904144
0.7119503103
0.3108282312
127.8083553
231480500.9
3004499.276
35310522.85
9501.295688
34.48365857
0.1237148274
137.304491
22906.44193
2845.690168
1425.623527
8.059398488
2836.653576
545.9404471
6676238.836
453869217.1
3046455.67
3824.741211
1733.364341
163997517.5
46856740.63
18247.63995
55504734.26
1281.154525
0.01317003733
26796232.71
614.7809373
124.9917797
13.32414443
2.061438665
1437324478
7.653466138
215267780.4
304925.7977
12340855.35
1.292474046
4012100939
918.1699992
0.001829689464
266.1514907
19586.50145
9843.077092
34563.10338
2.665695419e+14
194168.4335
182.9208313
1.789617285
115011741.8
1.600475143
0.9039184064
54.16404691
3836249.251
0.1453799136
83576.30659
75918.72599
255875.4377
0.0940918961
8139.618634
+41.2113043
+41.2113043
+18.2434106
+18.2434106
+18.2434106
+18.2434106
497813992.4
9158737.332
81.5174511
+0.1756986828
+0.1756986828
+0.07788028858
+0.07788028858
+0.07788028858
+0.07788028858
85205.83347
1827.041926
5434428.481
34601.43212
645859.4651
8.409921219
+0.00878465753
+0.00878465753
+0.00878465753
+0.0200891802
+0.0200891802
102240.6791
0.3455555689
+5.186512555e-05
+5.186512555e-05
+2.095582296e-05
+2.095582296e-05
+2.095582296e-05
+2.095582296e-05
2.273623498e+11
2139040773
82682.82602
+1.697773045
+1.697773045
+1.697773045
+3.928017028
+3.928017028
164684299.3
6840.694229
6292.264217
1.266028837
23696.0817
9776772.75
146.8084842
40186.198
578656.2198
0.05760079494
1308.62247
2846240637
2269.666603
0.05728404415
97.64433608
816.0835471
+2.245768012
+2.245768012
+2.245768012
+5.059168555
+5.059168555
0.003537766648
715128749.1
581519.0926
28878.33931
606.7268882
8.540999968
1.843057112
14728.95688
0.09287199376
+0.0001302392694
+0.0001302392694
+5.236903901e-05
+5.236903901e-05
+5.236903901e-05
4.952792168
+0.03410256159
+0.03410256159
+0.01401286426
+0.01401286426
+0.01401286426
39703045.24
0.2253239938
0.4007086942
0.6679356978
8985.245646
1459.149121
222.574255
1410.034894
49.66459517
280057.7217
11990414.03
22.39502507
6652.821533
412.6309921
3976669.212
376.5293878
0.04993631096
325.2221445
0.001056663136
0.6094009495
0.01755460768
4169089.697
120922.3418
19.94386406
1.034905758
899064.7273
13370.52361
12.9511581
7.43997218
0.2195708041
22.69922572
1364456.758
37.31335252
193721994.5
5387171012
83382.68593
4356.219769
4.959390234
280348.136
4068.591503
497.1128967
1220.499616
37070808.46
5.029130002
13411.495
21606019.92
13.50033011
10356.03697
0.853804882
0.004144159842
66.5696697
215.1472766
1.80856617
47652781.08
187.4720271
0.02309225892
221825.3003
68502271.85
89524.33999
63.06068401
35193.88681
0.1324344626
0.07415048828
1.316536312
1914484.13
239.8833788
404.8578233
311149.7413
31.91203802
6765.191464
3683.120991
111.8561994
622181.6379
3.495906967
1.324392325
2932853.167
1221.022853
0.3964612919
772.5117573
1587.443569
16407.82538
1153370.819
697976.9971
5293.102236
0.6273574623
433333.6561
667.0010151
279.5253754
13.71499773
27581.98765
0.1265026607
0.1265655615
0.217545965
119235.7842
1207.825866
1.168584528
442927.4532
11025.74448
12920.20556
6.440028505
0.01867492246
0.009209754218
3.078810838
1.895501574
4354.355041
1376.801012
281.0956164
12.62981914
0.01896307384
1.469952339
1070.389041
0.3140297342
17576.52171
19.46940005
72639.28176
1.00064982
10.58896856
146.5709549
240963.5215
21441702.88
9436.867787
1807651761
253.6931177
33906.26088
73290.29485
58.88693751
0.1874080618
128856.1698
37.9170344
999.730091
79.29102322
4297075.439
2815203002
1.065757865
41.63356752
3132937.645
0.006570811459
114610718.1
19766422.36
104.7817608
978.6047854
1114.98705
2962094.183
4303175.509
40918.11534
6.458644406
0.01513394186
10888.55623
1429.371661
72470.14267
1239031.521
0.01533517898
9486.889743
9312.872953
0.001369262882
263.7126988
27397.40987
6.460887231e+11
20.47552795
11886.05681
359511.4015
16322071.14
5.495229
94.06819575
11159.01276
497280.7644
152.8232363
2819.864026
1840.922093
105.3416519
1.51196546
893.0699171
274.2733387
213.9840929
29.84435445
0.06575134529
68473.33981
0.04814411438
95307.18205
0.2103887883
87533.03201
170.1269759
12266.74779
4.906472106
1289.949588
206.2206679
1339736.494
3265180.524
817632.5321
777148.2976
45580.38902
112.3471097
40.46375548
113.0563114
0.5022425417
125.6469752
1250753.214
119.6687695
7890.066678
255592.6823
0.09544112407
80.43028795
168.8638851
231.3586602
9.003352253
3865310.035
0.0327080534
0.2259241849
0.3309640842
70628514.93
1.342293964
1558415395
1.535156072
1105643165
11.12340492
19553.68065
0.03262635444
43.60758633
149.96132
16.71798701
862303.2755
3779.707836
227.1354158
0.04181934127
0.007441956106
0.06547652512
562.1841603
0.1962099745
47427.77928
278196156.8
3272270.994
3.274695664
3.671659367
0.8773587215
3475.635402
150.1691185
79249376.57
100282855
1034000.854
34631.08123
0.2021471708
11338.25051
365.9254869
3614.640649
38892.33006
3206.818315
495.3831508
3131.024396
1216.930767
3.68554273
0.0007587392874
27267.82366
66215.88611
12270.6996
2181.519341
9.799873017
84.23360373
350624.9294
2324.233559
0.210264797
1438761.868
160.6723109
39.13994322
2317.668587
32196.71663
0.02293846799
177.7024259
294490.6299
963.9483044
683.7845476
12.22284439
4350.875864
132.6662523
800.0540763
0.6752102469
6384.094581
667.7145567
88.5979278
65957.42139
0.1009745291
7074.842515
512.2889019
11.48214352
2.877973951
1.31777398
7.553015302
0.01771209643
0.01420982393
+3.754178119e-07
+1.116826573e-06
+1.116826573e-06
+3.754178119e-07
+3.754178119e-07
+3.754178119e-07
+1.769703186e-06
+4.356179554e-06
+4.356179554e-06
+1.769703186e-06
+1.769703186e-06
+1.769703186e-06
5.350111784
5171856.193
0.6877419322
+1.22182262e-05
+1.22182262e-05
+1.22182262e-05
+2.818920729e-05
+2.818920729e-05
+2.708089303e-05
+2.708089303e-05
+2.708089303e-05
+6.339285468e-05
+6.339285468e-05
+222.6777557
+222.6777557
+222.6777557
+501.1839533
+501.1839533
diff --git a/t/ME_data/PSP_jets.lhe.gz b/t/ME_data/PSP_jets.lhe.gz
index b471729..3ac0130 100644
--- a/t/ME_data/PSP_jets.lhe.gz
+++ b/t/ME_data/PSP_jets.lhe.gz
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:98254005df93663441f19013925d3dd40575ffcbfd666387a05cfd6d1b64c489
-size 161645
+oid sha256:c8a0adcc7453343934c235a295515b2838b371f8aef4d52b6ffe61301774efe6
+size 163612

File Metadata

Mime Type
text/x-diff
Expires
Sun, Feb 23, 2:26 PM (15 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4486582
Default Alt Text
(181 KB)

Event Timeline