Page MenuHomeHEPForge

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8f3ed56..903f689 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,280 +1,292 @@
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)
endif()
if(${HepMC_FOUND})
set(
CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -DHEJ_BUILD_WITH_HepMC_VERSION=${HepMC_VERSION_MAJOR}"
)
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_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()
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 lhef_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/LHEF/*.h)
install(FILES ${hej_headers} DESTINATION ${INSTALL_INCLUDE_DIR})
install(FILES ${lhef_headers} DESTINATION include/LHEF/)
install(TARGETS HEJ HEJ-config DESTINATION ${INSTALL_BIN_DIR})
## tests
enable_testing()
set(tst_dir "${CMAKE_CURRENT_SOURCE_DIR}/t")
add_executable(test_classify ${tst_dir}/test_classify.cc)
add_executable(test_psp ${tst_dir}/test_psp.cc)
add_executable(test_ME_generic ${tst_dir}/test_ME_generic.cc)
add_executable(check_res ${tst_dir}/check_res.cc)
add_executable(check_lhe ${tst_dir}/check_lhe.cc)
add_library(scales SHARED ${tst_dir}/scales.cc)
add_executable(test_scale_import ${tst_dir}/test_scale_import)
add_executable(test_descriptions ${tst_dir}/test_descriptions)
add_executable(test_scale_arithmetics ${tst_dir}/test_scale_arithmetics)
add_executable(test_parameters ${tst_dir}/test_parameters)
add_executable(test_colours ${tst_dir}/test_colours)
target_link_libraries(test_classify hejlib)
target_link_libraries(test_psp hejlib)
target_link_libraries(test_ME_generic hejlib)
target_link_libraries(check_res hejlib)
target_link_libraries(check_lhe hejlib)
target_link_libraries(test_scale_import hejlib)
target_link_libraries(test_descriptions hejlib)
target_link_libraries(test_scale_arithmetics hejlib)
target_link_libraries(test_parameters hejlib)
target_link_libraries(test_colours hejlib)
## add tests
add_test(
NAME t_classify
COMMAND test_classify ${tst_dir}/classify.lhe.gz
)
add_test(
NAME t_psp
COMMAND test_psp ${tst_dir}/psp_gen.lhe.gz
)
set(tst_ME_data_dir "${tst_dir}/ME_data")
add_test(
NAME t_ME_j
- COMMAND test_ME_generic ${tst_ME_data_dir}/config_mtinf.yml ${tst_ME_data_dir}/ME_jets.dat ${tst_ME_data_dir}/PSP_jets.lhe.gz
+ 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.dat ${tst_ME_data_dir}/PSP_h.lhe.gz
+ 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
+ )
+# add_test(
+# NAME t_ME_w
+# COMMAND test_ME_generic ${tst_ME_data_dir}/config_w_ME.yml ${tst_ME_data_dir}/ME_w_tree.dat ${tst_ME_data_dir}/PSP_w.lhe.gz
+# )
+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
)
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.dat ${tst_ME_data_dir}/PSP_h.lhe.gz
+ 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.dat ${tst_ME_data_dir}/PSP_h.lhe.gz
+ 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_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_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_uno
COMMAND check_res ${tst_dir}/h_3j_uno.lhe.gz 0.0261968 0.000341549 uno
)
if(${HepMC_FOUND})
file(READ "${tst_dir}/jet_config.yml" config)
file(WRITE "${tst_dir}/jet_config_withHepMC.yml" "${config} - tst.hepmc")
if(${rivet_FOUND})
file(READ "${tst_dir}/jet_config_withHepMC.yml" config)
file(WRITE "${tst_dir}/jet_config_withRivet.yml" "${config}\n\nanalysis:\n rivet: MC_XS\n output: tst")
add_test(
NAME t_main
COMMAND HEJ ${tst_dir}/jet_config_withRivet.yml ${tst_dir}/2j.lhe.gz
)
else()
add_test(
NAME t_main
COMMAND HEJ ${tst_dir}/jet_config_withHepMC.yml ${tst_dir}/2j.lhe.gz
)
endif()
if(${HepMC_VERSION_MAJOR} GREATER 2)
add_executable(check_hepmc ${tst_dir}/check_hepmc.cc)
target_link_libraries(check_hepmc hejlib)
add_test(
NAME t_hepmc
COMMAND check_hepmc tst.hepmc
)
endif()
else()
add_test(
NAME t_main
COMMAND HEJ ${tst_dir}/jet_config.yml ${tst_dir}/2j.lhe.gz
)
endif()
add_test(
NAME t_lhe
COMMAND check_lhe tst.lhe
)
add_test(
NAME t_scale_import
COMMAND test_scale_import ${tst_dir}/jet_config_with_import.yml
)
add_test(
NAME t_descriptions
COMMAND test_descriptions
)
add_test(
NAME t_scale_arithmetics
COMMAND test_scale_arithmetics ${tst_dir}/jet_config.yml ${tst_dir}/2j.lhe.gz
)
add_test(
NAME test_parameters
COMMAND test_parameters
)
add_test(
NAME t_colour_flow
COMMAND test_colours
)
diff --git a/Changes.md b/Changes.md
index 03df478..f1d36fb 100644
--- a/Changes.md
+++ b/Changes.md
@@ -1,41 +1,43 @@
# 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
* 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)
## 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/CMakeLists.txt b/FixedOrderGen/CMakeLists.txt
index aec1fbb..ef16662 100644
--- a/FixedOrderGen/CMakeLists.txt
+++ b/FixedOrderGen/CMakeLists.txt
@@ -1,113 +1,113 @@
cmake_minimum_required(VERSION 3.1 FATAL_ERROR)
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
project("HEJ Fixed Order Generation" 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
)
CONFIGURE_FILE( ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Templates/Version.hh.in
${PROJECT_BINARY_DIR}/include/Version.hh @ONLY )
## Add directories and find dependences
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/../cmake/Modules/")
find_package(HEJ 2 REQUIRED)
include_directories(${HEJ_INCLUDE_DIR})
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})
## define executable
file(GLOB HEJFOG_source ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cc)
list(REMOVE_ITEM HEJFOG_source ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc)
add_library(hejfog STATIC ${HEJFOG_source})
add_executable(HEJFOG ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cc)
## link libraries
set(libraries ${CMAKE_DL_LIBS} ${LHAPDF_LIBRARIES} ${CLHEP_LIBRARIES}
${fastjet_LIBRARIES} ${Boost_LIBRARIES} ${YAML_CPP_LIBRARIES} ${HEJ_LIBRARIES})
target_link_libraries(hejfog ${libraries})
target_link_libraries(HEJFOG hejfog)
install(TARGETS HEJFOG DESTINATION bin)
## tests
enable_testing()
set(tst_dir "${CMAKE_CURRENT_SOURCE_DIR}/t")
-foreach(tst h_2j h_3j h_5j h_3j_uno1 h_3j_uno2 h_2j_decay 2j 4j)
+foreach(tst h_2j h_3j h_5j h_3j_uno1 h_3j_uno2 h_2j_decay 2j 4j W_2j_classify W_nj_classify)
add_executable(test_${tst} ${tst_dir}/${tst}.cc)
target_link_libraries(test_${tst} hejfog)
add_test(NAME t_${tst} COMMAND test_${tst} WORKING_DIRECTORY ${tst_dir})
endforeach()
add_test(
NAME t_main_2j
COMMAND HEJFOG ${tst_dir}/config_2j.yml
)
add_test(
NAME t_main_h2j
COMMAND HEJFOG ${tst_dir}/config_h_2j.yml
)
add_test(
NAME t_main_h2j_decay
COMMAND HEJFOG ${tst_dir}/config_h_2j_decay.yml
)
diff --git a/FixedOrderGen/configFO.yml b/FixedOrderGen/configFO.yml
index f14188c..3cce48a 100644
--- a/FixedOrderGen/configFO.yml
+++ b/FixedOrderGen/configFO.yml
@@ -1,68 +1,79 @@
-# number of generated events
+## number of generated events
events: 200
jets:
min pt: 20
peak pt: 30
algorithm: antikt
R: 0.4
max rapidity: 5
beam:
energy: 6500
particles: [p, p]
pdf: 230000
process: p p => h 4j
-# fraction of events with two extremal emissions in one direction
-# that contain an subleading emission e.g. unordered emission
-subleading fraction: 0.05
-# Allow different subleading configurations
-# By default all implemented processes are allowed
+## fraction of events with two extremal emissions in one direction
+## that contain an subleading emission e.g. unordered emission
+subleading fraction: 0.00
+
+## Allow different subleading configurations
+## By default all implemented processes are allowed.
#
-# subleading channels: unordered
+# subleading channels:
+# - unordered
+# - qqx
scales: max jet pperp
event output:
- HEJFO.lhe
-# - HEJ.lhe
-# - HEJ_events.hepmc
+# - HEJFO_events.hepmc
particle properties:
Higgs:
mass: 125
width: 0.004165
decays: {into: [photon, photon], branching ratio: 0.0023568762400521404}
+ Wp:
+ mass: 80.385
+ width: 2.085
+ decays: {into: [e+, nu_e], branching ratio: 1}
+ Wm:
+ mass: 80.385
+ width: 2.085
+ decays: {into: [e, nu_e_bar], branching ratio: 1}
random generator:
name: mixmax
+# seed: 1
-# unweighting parameters
-# remove to obtain weighted events
-unweight:
- sample size: 200 # should be similar to "events:", but not more than ~10000
- max deviation: 0
+## unweighting parameters
+## remove to obtain weighted events
+# unweight:
+# sample size: 200 # should be similar to "events:", but not more than ~10000
+# max deviation: 0
-# to use a rivet analysis
+## to use a rivet analysis
#
# analysis:
# rivet: MC_XS # rivet analysis name
# output: HEJ # name of the yoda files, ".yoda" and scale suffix will be added
#
-# to use a custom analysis
+## to use a custom analysis
#
# analysis:
# plugin: /path/to/libmyanalysis.so
# my analysis parameter: some value
-# parameters for Higgs-gluon couplings
-# this requires compilation with qcdloop
+## parameters for Higgs-gluon couplings
+## this requires compilation with qcdloop
#
# Higgs coupling:
# use impact factors: false
# mt: 174
# include bottom: true
# mb: 4.7
diff --git a/FixedOrderGen/include/PhaseSpacePoint.hh b/FixedOrderGen/include/PhaseSpacePoint.hh
index 6ffdfec..d2234b4 100644
--- a/FixedOrderGen/include/PhaseSpacePoint.hh
+++ b/FixedOrderGen/include/PhaseSpacePoint.hh
@@ -1,187 +1,216 @@
/** \file PhaseSpacePoint.hh
* \brief Contains the PhaseSpacePoint Class
*/
#pragma once
+#include <bitset>
#include <vector>
#include "HEJ/Event.hh"
#include "HEJ/Particle.hh"
#include "HEJ/PDF.hh"
#include "HEJ/PDG_codes.hh"
#include "HEJ/RNG.hh"
#include "JetParameters.hh"
#include "ParticleProperties.hh"
#include "Status.hh"
namespace HEJFOG{
class Process;
using HEJ::Particle;
//! A point in resummation phase space
class PhaseSpacePoint{
public:
//! Default PhaseSpacePoint Constructor
PhaseSpacePoint() = default;
//! PhaseSpacePoint Constructor
/**
* @param proc The process to generate
* @param jet_properties Jet defintion & cuts
* @param pdf The pdf set (used for sampling)
* @param E_beam Energie of the beam
* @param subl_chance Chance to turn a potentially unordered
* emission into an actual one
* @param subl_channels Possible subleading channels.
* see HEJFOG::Subleading
* @param particle_properties Properties of producted boson
*
- * Initially, only FKL phase space points are generated. If the most
- * extremal emission in any direction is a quark or anti-quark and the
- * next emission is a gluon, subl_chance is the chance to turn this into
- * an unordered emission event by swapping the two flavours. At most one
- * unordered emission will be generated in this way.
+ * Initially, only FKL phase space points are generated. subl_chance gives
+ * the change of turning one emissions into a subleading configuration,
+ * i.e. either unordered or central quark/anti-quark pair. Unordered
+ * emissions require that the most extremal emission in any direction is
+ * a quark or anti-quark and the next emission is a gluon. Quark/anti-quark
+ * pairs are only generated for W processes. At most one subleading
+ * emission will be generated in this way.
*/
PhaseSpacePoint(
Process const & proc,
JetParameters const & jet_properties,
HEJ::PDF & pdf, double E_beam,
double subl_chance,
unsigned int subl_channels,
ParticlesPropMap const & particles_properties,
HEJ::RNG & ran
);
//! Get Weight Function
/**
* @returns Weight of Event
*/
double weight() const{
return weight_;
}
Status status() const{
return status_;
}
//! Get Incoming Function
/**
* @returns Incoming Particles
*/
std::array<Particle, 2> const & incoming() const{
return incoming_;
}
//! Get Outgoing Function
/**
* @returns Outgoing Particles
*/
std::vector<Particle> const & outgoing() const{
return outgoing_;
}
std::unordered_map<size_t, std::vector<Particle>> const & decays() const{
return decays_;
}
- private:
+ private:
/**
- * \internal
- * \brief Generate LO parton momentum
+ * @internal
+ * @brief Generate LO parton momentum
*
* @param count Number of partons to generate
* @param is_pure_jets If true ensures momentum conservation in x and y
* @param jet_param Jet properties to fulfil
* @param max_pt max allowed pt for a parton (typically E_CMS)
* @param ran Random Number Generator
*
* @returns Momentum of partons
*
* Ensures that each parton is in its own jet.
* Generation is independent of parton flavour. Output is sorted in rapidity.
*/
std::vector<fastjet::PseudoJet> gen_LO_partons(
int count, bool is_pure_jets,
JetParameters const & jet_param,
double max_pt,
HEJ::RNG & ran
);
Particle gen_boson(
HEJ::ParticleID bosonid, double mass, double width,
HEJ::RNG & ran
);
template<class ParticleMomenta>
fastjet::PseudoJet gen_last_momentum(
ParticleMomenta const & other_momenta,
double mass_square, double y
) const;
bool jets_ok(
std::vector<fastjet::PseudoJet> const & Born_jets,
std::vector<fastjet::PseudoJet> const & partons
) const;
/**
- * \internal
- * \brief Generate incoming partons according to the PDF
+ * @internal
+ * @brief Generate incoming partons according to the PDF
*
* @param uf Scale used in the PDF
*/
void reconstruct_incoming(
- std::array<HEJ::ParticleID, 2> const & ids,
+ Process const & proc, unsigned int subl_channels,
HEJ::PDF & pdf, double E_beam,
double uf,
HEJ::RNG & ran
);
+ /**
+ * @internal
+ * @brief Returns list of all allowed initial states partons
+ */
+ std::array<std::bitset<11>,2> filter_partons(
+ Process const & proc, unsigned int const subl_channels,
+ HEJ::RNG & ran
+ );
HEJ::ParticleID generate_incoming_id(
size_t beam_idx, double x, double uf, HEJ::PDF & pdf,
- HEJ::RNG & ran
+ std::bitset<11> allowed_partons, HEJ::RNG & ran
);
bool momentum_conserved(double ep) const;
HEJ::Particle const & most_backward_FKL(
std::vector<HEJ::Particle> const & partons
) const;
HEJ::Particle const & most_forward_FKL(
std::vector<HEJ::Particle> const & partons
) const;
HEJ::Particle & most_backward_FKL(std::vector<HEJ::Particle> & partons) const;
HEJ::Particle & most_forward_FKL(std::vector<HEJ::Particle> & partons) const;
bool extremal_FKL_ok(
std::vector<fastjet::PseudoJet> const & partons
) const;
double random_normal(double stddev, HEJ::RNG & ran);
- void maybe_turn_to_uno(double chance, HEJ::RNG & ran);
+ /**
+ * @internal
+ * @brief Turns a FKL configuration into a subleading one
+ *
+ * @param chance Change to switch to subleading configuration
+ * @param channels Allowed channels for subleading process
+ * @param proc Process to decide which subleading
+ * configurations are allowed
+ *
+ * With a chance of "chance" the FKL configuration is either turned into
+ * a unordered configuration or, for A/W/Z bosons, a configuration with
+ * a central quark/anti-quark pair.
+ */
+ void maybe_turn_to_subl(double chance, unsigned int channels,
+ Process const & proc, HEJ::RNG & ran);
+ void turn_to_uno(bool can_be_uno_backward, bool can_be_uno_forward, HEJ::RNG & ran);
+ void turn_to_qqx(bool allow_strange, HEJ::RNG & ran);
std::vector<Particle> decay_boson(
HEJ::Particle const & parent,
std::vector<Decay> const & decays,
HEJ::RNG & ran
);
+ /// @brief setup outgoing partons to ensure correct coupling to boson
+ void couple_boson(HEJ::ParticleID boson, HEJ::RNG & ran);
Decay select_decay_channel(
std::vector<Decay> const & decays,
HEJ::RNG & ran
);
double gen_hard_pt(
int np, double ptmin, double ptmax, double y,
HEJ::RNG & ran
);
double gen_soft_pt(int np, double ptmax, HEJ::RNG & ran);
double gen_parton_pt(
int count, JetParameters const & jet_param, double ptmax, double y,
HEJ::RNG & ran
);
double weight_;
Status status_;
std::array<Particle, 2> incoming_;
std::vector<Particle> outgoing_;
//! Particle decays in the format {outgoing index, decay products}
std::unordered_map<size_t, std::vector<Particle>> decays_;
};
HEJ::Event::EventData to_EventData(PhaseSpacePoint const & psp);
}
diff --git a/FixedOrderGen/include/Status.hh b/FixedOrderGen/include/Status.hh
index 54fdc0b..599af0b 100644
--- a/FixedOrderGen/include/Status.hh
+++ b/FixedOrderGen/include/Status.hh
@@ -1,22 +1,22 @@
#pragma once
#include <string>
#include <stdexcept>
namespace HEJFOG{
enum Status{
good,
not_enough_jets,
too_much_energy
};
inline std::string to_string(Status s){
switch(s){
- case good: return "good";
- case not_enough_jets: return "not enough jets";
- case too_much_energy: return "too much energy";
- default:;
+ case good: return "good";
+ case not_enough_jets: return "not enough jets";
+ case too_much_energy: return "too much energy";
+ default:;
}
throw std::logic_error{"unreachable"};
}
}
diff --git a/FixedOrderGen/include/Subleading.hh b/FixedOrderGen/include/Subleading.hh
index 0edc565..57ea71a 100644
--- a/FixedOrderGen/include/Subleading.hh
+++ b/FixedOrderGen/include/Subleading.hh
@@ -1,14 +1,15 @@
#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
+ unordered = uno,
+ qqx = 2u
};
}
diff --git a/FixedOrderGen/src/PhaseSpacePoint.cc b/FixedOrderGen/src/PhaseSpacePoint.cc
index 0fd5b7c..4543185 100644
--- a/FixedOrderGen/src/PhaseSpacePoint.cc
+++ b/FixedOrderGen/src/PhaseSpacePoint.cc
@@ -1,458 +1,654 @@
#include "PhaseSpacePoint.hh"
-#include <random>
-
-#include <CLHEP/Random/Randomize.h>
-#include <CLHEP/Random/RanluxEngine.h>
+#include <algorithm>
+#include "HEJ/Constants.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/kinematics.hh"
#include "HEJ/Particle.hh"
#include "HEJ/utility.hh"
#include "Process.hh"
#include "Subleading.hh"
-
using namespace HEJ;
namespace HEJFOG{
static_assert(
std::numeric_limits<double>::has_quiet_NaN,
"no quiet NaN for double"
);
constexpr double NaN = std::numeric_limits<double>::quiet_NaN();
HEJ::Event::EventData to_EventData(PhaseSpacePoint const & psp){
HEJ::Event::EventData result;
result.incoming = psp.incoming();
assert(result.incoming.size() == 2);
result.outgoing=psp.outgoing();
// technically Event::EventData doesn't have to be sorted,
// but PhaseSpacePoint should be anyway
assert(
std::is_sorted(
begin(result.outgoing), end(result.outgoing),
HEJ::rapidity_less{}
)
);
assert(result.outgoing.size() >= 2);
result.decays=psp.decays();
result.parameters.central= {NaN, NaN, psp.weight() };
return result;
}
namespace{
bool can_swap_to_uno(
HEJ::Particle const & p1, HEJ::Particle const & p2
){
return is_parton(p1)
- && p1.type != HEJ::pid::gluon
- && p2.type == HEJ::pid::gluon;
+ && p1.type != pid::gluon
+ && p2.type == pid::gluon;
+ }
+
+ size_t count_gluons(std::vector<Particle>::const_iterator first,
+ std::vector<Particle>::const_iterator last){
+ return std::count_if(first, last, [](Particle const & p)
+ {return p.type == pid::gluon;});
+ }
+
+ /** assumes FKL configurations between first and last,
+ * else there can be a quark in a non-extreme position
+ * e.g. uno configuration gqg would pass
+ */
+ bool can_change_to_qqx(
+ std::vector<Particle>::const_iterator first,
+ std::vector<Particle>::const_iterator last){
+ return 1 < count_gluons(first,last);
+ }
+ bool is_AWZ_proccess(Process const & proc){
+ return proc.boson && is_AWZ_boson(*proc.boson);
+ }
+
+ bool is_up_type(Particle const & part){
+ return HEJ::is_anyquark(part) && !(abs(part.type)%2);
+ }
+ bool is_down_type(Particle const & part){
+ return HEJ::is_anyquark(part) && abs(part.type)%2;
+ }
+ bool can_couple_to_W(Particle const & part, pid::ParticleID const W_id){
+ const int W_charge = W_id>0?1:-1;
+ return abs(part.type)<5
+ && ( (W_charge*part.type > 0 && is_up_type(part))
+ || (W_charge*part.type < 0 && is_down_type(part)) );
}
}
- void PhaseSpacePoint::maybe_turn_to_uno(
+ void PhaseSpacePoint::maybe_turn_to_subl(
double chance,
+ unsigned int const channels,
+ Process const & proc,
HEJ::RNG & ran
){
+ if(proc.njets <= 2) return;
assert(outgoing_.size() >= 2);
+
+ // decide what kind of subleading process is allowed
+ bool allow_uno = false;
+ bool allow_strange = true;
const size_t nout = outgoing_.size();
- const bool can_be_uno_backward = can_swap_to_uno(
- outgoing_[0], outgoing_[1]
- );
- const bool can_be_uno_forward = can_swap_to_uno(
- outgoing_[nout-1], outgoing_[nout-2]
- );
- if(!can_be_uno_backward && !can_be_uno_forward) return;
+ const bool can_be_uno_backward = (channels&Subleading::uno)
+ && can_swap_to_uno(outgoing_[0], outgoing_[1]);
+ const bool can_be_uno_forward = (channels&Subleading::uno)
+ && can_swap_to_uno(outgoing_[nout-1], outgoing_[nout-2]);
+ allow_uno = can_be_uno_backward || can_be_uno_forward;
+
+ bool allow_qqx = false;
+ if(is_AWZ_proccess(proc)) {
+ allow_qqx = (channels&Subleading::qqx)
+ && can_change_to_qqx(outgoing_.cbegin(), outgoing_.cend());
+ if(std::none_of(outgoing_.cbegin(), outgoing_.cend(),
+ [&proc](Particle const & p){ return can_couple_to_W(p, *proc.boson);})) {
+ // enforce qqx if A/W/Z can't couple somewhere else
+ assert(allow_qqx);
+ allow_uno = false;
+ chance = 1.;
+ // strange not allowed for W
+ if(abs(*proc.boson)== pid::Wp) allow_strange = false;
+ }
+ }
+
+ if(!allow_uno && !allow_qqx) return;
if(ran.flat() < chance){
weight_ /= chance;
- if(can_be_uno_backward && can_be_uno_forward){
- if(ran.flat() < 0.5){
- std::swap(outgoing_[0].type, outgoing_[1].type);
- }
- else{
- std::swap(outgoing_[nout-1].type, outgoing_[nout-2].type);
- }
+ if(allow_uno && !allow_qqx){
+ turn_to_uno(can_be_uno_backward, can_be_uno_forward, ran);
+ } else if (!allow_uno && allow_qqx) {
+ turn_to_qqx(allow_strange, ran);
+ } else {
+ assert( allow_uno && allow_qqx);
+ if(ran.flat() < 0.5) turn_to_uno(can_be_uno_backward, can_be_uno_forward, ran);
+ else turn_to_qqx(allow_strange, ran);
weight_ *= 2.;
}
- else if(can_be_uno_backward){
+ } else weight_ /= 1 - chance;
+
+ }
+
+ void PhaseSpacePoint::turn_to_uno(
+ const bool can_be_uno_backward, const bool can_be_uno_forward,
+ HEJ::RNG & ran
+ ){
+ if(!can_be_uno_backward && !can_be_uno_forward) return;
+ const size_t nout = outgoing_.size();
+ if(can_be_uno_backward && can_be_uno_forward){
+ if(ran.flat() < 0.5){
std::swap(outgoing_[0].type, outgoing_[1].type);
- }
- else{
- assert(can_be_uno_forward);
+ } else {
std::swap(outgoing_[nout-1].type, outgoing_[nout-2].type);
}
+ weight_ *= 2.;
+ } else if(can_be_uno_backward){
+ std::swap(outgoing_[0].type, outgoing_[1].type);
+ } else {
+ assert(can_be_uno_forward);
+ std::swap(outgoing_[nout-1].type, outgoing_[nout-2].type);
}
- else weight_ /= 1 - chance;
+ }
+
+ void PhaseSpacePoint::turn_to_qqx(const bool allow_strange, HEJ::RNG & ran){
+ /// find first and last gluon in FKL chain
+ auto first = std::find_if(outgoing_.begin(), outgoing_.end(),
+ [](Particle const & p){return p.type == pid::gluon;});
+ std::vector<Particle*> FKL_gluons;
+ for(auto p = first; p!=outgoing_.end(); ++p){
+ if(p->type == pid::gluon) FKL_gluons.push_back(&*p);
+ else if(is_anyquark(*p)) break;
+ }
+ const size_t ng = FKL_gluons.size();
+ if(ng < 2)
+ throw std::logic_error("not enough gluons to create qqx");
+ // select flavour of quark
+ const double r1 = 2.*ran.flat()-1.;
+ const double max_flavour = allow_strange?n_f:n_f-1;
+ weight_ *= max_flavour*2;
+ int flavour = pid::down + std::floor(std::abs(r1)*max_flavour);
+ flavour*=r1<0.?-1:1;
+ // select gluon for switch
+ const size_t idx = floor((ng-1) * ran.flat());
+ weight_ *= (ng-1);
+ FKL_gluons[idx]->type = ParticleID(flavour);
+ FKL_gluons[idx+1]->type = ParticleID(-flavour);
}
template<class ParticleMomenta>
fastjet::PseudoJet PhaseSpacePoint::gen_last_momentum(
ParticleMomenta const & other_momenta,
const double mass_square, const double y
) const {
std::array<double,2> pt{0.,0.};
for (auto const & p: other_momenta) {
pt[0]-= p.px();
pt[1]-= p.py();
}
const double mperp = sqrt(pt[0]*pt[0]+pt[1]*pt[1]+mass_square);
const double pz=mperp*sinh(y);
const double E=mperp*cosh(y);
return {pt[0], pt[1], pz, E};
}
PhaseSpacePoint::PhaseSpacePoint(
Process const & proc,
JetParameters const & jet_param,
HEJ::PDF & pdf, double E_beam,
- double subl_change,
- unsigned int subl_channels,
+ double const subl_chance,
+ unsigned int const subl_channels,
ParticlesPropMap const & particles_properties,
HEJ::RNG & ran
)
{
assert(proc.njets >= 2);
if(proc.boson
&& particles_properties.find(*(proc.boson))
== particles_properties.end())
throw HEJ::missing_option("Boson "
+std::to_string(*(proc.boson))+" can't be generated: missing properties");
status_ = good;
weight_ = 1;
const int nout = proc.njets + (proc.boson?1:0);
outgoing_.reserve(nout);
+ // generate parton momenta
const bool is_pure_jets = !proc.boson;
auto partons = gen_LO_partons(
proc.njets, is_pure_jets, jet_param, E_beam, ran
);
+ // pre fill flavour with gluons
for(auto&& p_out: partons) {
outgoing_.emplace_back(Particle{pid::gluon, std::move(p_out), {}});
}
if(status_ != good) return;
// create boson
if(proc.boson){
const auto & boson_prop = particles_properties.at(*proc.boson);
auto boson(gen_boson(*proc.boson, boson_prop.mass, boson_prop.width, ran));
const auto pos = std::upper_bound(
begin(outgoing_),end(outgoing_),boson,rapidity_less{}
);
outgoing_.insert(pos, std::move(boson));
if(! boson_prop.decays.empty()){
const size_t boson_idx = std::distance(begin(outgoing_), pos);
decays_.emplace(
boson_idx,
decay_boson(outgoing_[boson_idx], boson_prop.decays, ran)
);
}
}
// normalisation of momentum-conserving delta function
weight_ *= pow(2*M_PI, 4);
- reconstruct_incoming(proc.incoming, pdf, E_beam, jet_param.min_pt, ran);
+ /** @TODO
+ * uf (jet_param.min_pt) doesn't correspond to our final scale choice.
+ * The HEJ scale generators currently expect a full event as input,
+ * so fixing this is not completely trivial
+ */
+ reconstruct_incoming(proc, subl_channels, pdf, E_beam, jet_param.min_pt, ran);
if(status_ != good) return;
// set outgoing states
most_backward_FKL(outgoing_).type = incoming_[0].type;
most_forward_FKL(outgoing_).type = incoming_[1].type;
- if(proc.njets > 2 && subl_channels & Subleading::uno) maybe_turn_to_uno(subl_change, ran);
+ maybe_turn_to_subl(subl_chance, subl_channels, proc, ran);
+
+ if(proc.boson) couple_boson(*proc.boson, ran);
}
double PhaseSpacePoint::gen_hard_pt(
int np , double ptmin, double ptmax, double y,
HEJ::RNG & ran
) {
// heuristic parameters for pt sampling
const double ptpar = ptmin + np/5.;
const double arg_small_y = atan((ptmax - ptmin)/ptpar);
const double y_cut = 3.;
const double r1 = ran.flat();
if(y < y_cut){
const double pt = ptmin + ptpar*tan(r1*arg_small_y);
const double temp = cos(r1*arg_small_y);
weight_ *= pt*ptpar*arg_small_y/(temp*temp);
return pt;
}
const double ptpar2 = ptpar/(1 + 5*(y-y_cut));
const double temp = 1. - std::exp((ptmin-ptmax)/ptpar2);
const double pt = ptmin - ptpar2*std::log(1-r1*temp);
weight_ *= pt*ptpar2*temp/(1-r1*temp);
return pt;
}
double PhaseSpacePoint::gen_soft_pt(int np, double max_pt, HEJ::RNG & ran) {
constexpr double ptpar = 4.;
const double r = ran.flat();
const double pt = max_pt + ptpar/np*std::log(r);
weight_ *= pt*ptpar/(np*r);
return pt;
}
double PhaseSpacePoint::gen_parton_pt(
int count, JetParameters const & jet_param, double max_pt, double y,
HEJ::RNG & ran
) {
constexpr double p_small_pt = 0.02;
if(! jet_param.peak_pt) {
return gen_hard_pt(count, jet_param.min_pt, max_pt, y, ran);
}
const double r = ran.flat();
if(r > p_small_pt) {
weight_ /= 1. - p_small_pt;
return gen_hard_pt(count, *jet_param.peak_pt, max_pt, y, ran);
}
weight_ /= p_small_pt;
const double pt = gen_soft_pt(count, *jet_param.peak_pt, ran);
if(pt < jet_param.min_pt) {
weight_=0.0;
status_ = not_enough_jets;
return jet_param.min_pt;
}
return pt;
}
std::vector<fastjet::PseudoJet> PhaseSpacePoint::gen_LO_partons(
int np, bool is_pure_jets,
JetParameters const & jet_param,
double max_pt,
HEJ::RNG & ran
){
if (np<2) throw std::invalid_argument{"Not enough partons in gen_LO_partons"};
weight_ /= pow(16.*pow(M_PI,3),np);
weight_ /= std::tgamma(np+1); //remove rapidity ordering
std::vector<fastjet::PseudoJet> partons;
partons.reserve(np);
for(int i = 0; i < np; ++i){
const double y = -jet_param.max_y + 2*jet_param.max_y*ran.flat();
weight_ *= 2*jet_param.max_y;
const bool is_last_parton = i+1 == np;
if(is_pure_jets && is_last_parton) {
constexpr double parton_mass_sq = 0.;
partons.emplace_back(gen_last_momentum(partons, parton_mass_sq, y));
break;
}
const double phi = 2*M_PI*ran.flat();
weight_ *= 2.0*M_PI;
const double pt = gen_parton_pt(np, jet_param, max_pt, y, ran);
if(weight_ == 0.0) return {};
partons.emplace_back(fastjet::PtYPhiM(pt, y, phi));
assert(jet_param.min_pt <= partons[i].pt());
assert(partons[i].pt() <= max_pt+1e-5);
}
// Need to check that at LO, the number of jets = number of partons;
fastjet::ClusterSequence cs(partons, jet_param.def);
auto cluster_jets=cs.inclusive_jets(jet_param.min_pt);
if (cluster_jets.size()!=unsigned(np)){
weight_=0.0;
status_ = not_enough_jets;
return {};
}
std::sort(begin(partons), end(partons), rapidity_less{});
return partons;
}
Particle PhaseSpacePoint::gen_boson(
HEJ::ParticleID bosonid, double mass, double width,
HEJ::RNG & ran
){
- if(bosonid != HEJ::pid::Higgs)
- throw HEJ::not_implemented("Production of boson "+std::to_string(bosonid)
- +" not implemented yet.");
// Usual phase space measure
weight_ /= 16.*pow(M_PI, 3);
// Generate a y Gaussian distributed around 0
- // TODO: magic number only for Higgs
+ /// @TODO: magic number only for Higgs
+ /// @TODO better sampling for W
const double y = random_normal(1.6, ran);
const double r1 = ran.flat();
const double sH = mass*(
mass + width*tan(M_PI/2.*r1 + (r1-1.)*atan(mass/width))
);
auto p = gen_last_momentum(outgoing_, sH, y);
return Particle{bosonid, std::move(p), {}};
}
Particle const & PhaseSpacePoint::most_backward_FKL(
std::vector<Particle> const & partons
) const{
if(!HEJ::is_parton(partons[0])) return partons[1];
return partons[0];
}
Particle const & PhaseSpacePoint::most_forward_FKL(
std::vector<Particle> const & partons
) const{
const size_t last_idx = partons.size() - 1;
if(!HEJ::is_parton(partons[last_idx])) return partons[last_idx-1];
return partons[last_idx];
}
Particle & PhaseSpacePoint::most_backward_FKL(
std::vector<Particle> & partons
) const{
if(!HEJ::is_parton(partons[0])) return partons[1];
return partons[0];
}
Particle & PhaseSpacePoint::most_forward_FKL(
std::vector<Particle> & partons
) const{
const size_t last_idx = partons.size() - 1;
if(!HEJ::is_parton(partons[last_idx])) return partons[last_idx-1];
return partons[last_idx];
}
+ namespace {
+ /// partons are ordered: even = anti, 0 = gluon
+ ParticleID index_to_pid(size_t i){
+ if(!i) return pid::gluon;
+ return static_cast<ParticleID>(i%2?(i+1)/2:-i/2);
+ }
+
+ /// partons are ordered: even = anti, 0 = gluon
+ size_t pid_to_index(ParticleID id){
+ if(id==pid::gluon) return 0;
+ return id>0?id*2-1:abs(id)*2;
+ }
+
+ std::bitset<11> init_allowed(ParticleID const id){
+ if(abs(id) == pid::proton)
+ return ~0;
+ std::bitset<11> out = 0;
+ if(is_parton(id))
+ out[pid_to_index(id)] = 1;
+ return out;
+ }
+
+ /// decides which "index" (see index_to_pid) are allowed for process
+ std::bitset<11> allowed_quarks(ParticleID const boson){
+ std::bitset<11> allowed = ~0;
+ if(abs(boson) == pid::Wp){
+ // special case W:
+ // Wp: anti-down or up-type quark, no b/t -> 0001100110(1) = 205
+ // Wm: down or anti-up-type quark, no b/t -> 0010011001(1) = 307
+ allowed = boson>0?205:307;
+ }
+ return allowed;
+ }
+ }
+
+ /**
+ * checks which partons are allowed as initial state:
+ * 1. only allow what is given in the Runcard (p -> all)
+ * 2. A/W/Z require something to couple to
+ * a) no qqx => no incoming gluon
+ * b) 2j => no incoming gluon
+ * c) 3j => can couple OR is gluon => 2 gluons become qqx later
+ */
+ std::array<std::bitset<11>,2> PhaseSpacePoint::filter_partons(
+ Process const & proc, unsigned int const subl_channels, HEJ::RNG & ran
+ ){
+ std::array<std::bitset<11>,2> allowed_partons{
+ init_allowed(proc.incoming[0]),
+ init_allowed(proc.incoming[1])
+ };
+ bool const allow_qqx = subl_channels&Subleading::qqx;
+ // special case A/W/Z
+ if(is_AWZ_proccess(proc) && ((proc.njets < 4) || !allow_qqx)){
+ // all possible incoming states
+ auto allowed(allowed_quarks(*proc.boson));
+ if(proc.njets == 2 || !allow_qqx) allowed[0]=0;
+
+ // possible states per leg
+ std::array<std::bitset<11>,2> const maybe_partons{
+ allowed_partons[0]&allowed, allowed_partons[1]&allowed};
+
+ if(maybe_partons[0].any() && maybe_partons[1].any()){
+ // two options to get allowed initial state => choose one at random
+ const size_t idx = ran.flat() < 0.5;
+ allowed_partons[idx] = maybe_partons[idx];
+ // else choose the possible
+ } else if(maybe_partons[0].any()) {
+ allowed_partons[0] = maybe_partons[0];
+ } else if(maybe_partons[1].any()) {
+ allowed_partons[1] = maybe_partons[1];
+ } else{
+ throw std::invalid_argument{"Incoming state not allowed."};
+ }
+ }
+ return allowed_partons;
+ }
+
void PhaseSpacePoint::reconstruct_incoming(
- std::array<HEJ::ParticleID, 2> const & ids,
+ Process const & proc, unsigned int const subl_channels,
HEJ::PDF & pdf, double E_beam,
double uf,
HEJ::RNG & ran
){
std::tie(incoming_[0].p, incoming_[1].p) = incoming_momenta(outgoing_);
// calculate xa, xb
const double sqrts=2*E_beam;
const double xa=(incoming_[0].p.e()-incoming_[0].p.pz())/sqrts;
const double xb=(incoming_[1].p.e()+incoming_[1].p.pz())/sqrts;
// abort if phase space point is outside of collider energy reach
if (xa>1. || xb>1.){
weight_=0;
status_ = too_much_energy;
return;
}
- // pick pdfs
- /** @TODO:
- * ufa, ufb don't correspond to our final scale choice.
- * The HEJ scale generators currently expect a full event as input,
- * so fixing this is not completely trivial
- */
+ auto const & ids = proc.incoming;
+ std::array<std::bitset<11>,2> allowed_partons(
+ filter_partons(proc, subl_channels, ran));
for(size_t i = 0; i < 2; ++i){
if(ids[i] == pid::proton || ids[i] == pid::p_bar){
- incoming_[i].type = generate_incoming_id(i, i?xb:xa, uf, pdf, ran);
- }
- else {
+ // pick ids according to pdfs
+ incoming_[i].type =
+ generate_incoming_id(i, i?xb:xa, uf, pdf, allowed_partons[i], ran);
+ } else {
+ assert(allowed_partons[i][pid_to_index(ids[i])]);
incoming_[i].type = ids[i];
}
}
assert(momentum_conserved(1e-7));
}
- namespace {
- /// particles are ordered, odd = anti
- ParticleID index_to_pid(size_t i){
- if(!i) return pid::gluon;
- return static_cast<ParticleID>(i%2?(i+1)/2:-i/2);
- }
- }
-
HEJ::ParticleID PhaseSpacePoint::generate_incoming_id(
size_t const beam_idx, double const x, double const uf,
- HEJ::PDF & pdf, HEJ::RNG & ran
+ HEJ::PDF & pdf, std::bitset<11> allowed_partons, HEJ::RNG & ran
){
std::array<double,11> pdf_wt;
- pdf_wt[0] = fabs(pdf.pdfpt(beam_idx,x,uf,pid::gluon));
+ pdf_wt[0] = allowed_partons[0]?fabs(pdf.pdfpt(beam_idx,x,uf,pid::gluon)):0.;
double pdftot = pdf_wt[0];
- for(size_t i = 1; i < pdf_wt.size(); ++i){
- pdf_wt[i] = 4./9.*fabs(pdf.pdfpt(beam_idx,x,uf,index_to_pid(i)));
+ for(size_t i = 1; i < pdf_wt.size(); ++i){
+ pdf_wt[i] = allowed_partons[i]?4./9.*fabs(pdf.pdfpt(beam_idx,x,uf,index_to_pid(i))):0;
pdftot += pdf_wt[i];
}
const double r1 = pdftot * ran.flat();
double sum = 0;
for(size_t i=0; i < pdf_wt.size(); ++i){
if (r1 < (sum+=pdf_wt[i])){
weight_*= pdftot/pdf_wt[i];
return index_to_pid(i);
}
}
std::cerr << "Error in choosing incoming parton: "<<x<<" "<<uf<<" "
<<sum<<" "<<pdftot<<" "<<r1<<std::endl;
throw std::logic_error{"Failed to choose parton flavour"};
}
+ void PhaseSpacePoint::couple_boson(
+ HEJ::ParticleID const boson, HEJ::RNG & ran
+ ){
+ if(abs(boson) != pid::Wp) return; // only matters for W
+ /// @TODO this could be use to sanity check gamma and Z
+
+ // find all possible quarks
+ std::vector<Particle*> allowed_parts;
+ for(auto & part: outgoing_){
+ // Wp -> up OR anti-down, Wm -> anti-up OR down, no bottom
+ if ( can_couple_to_W(part, boson) )
+ allowed_parts.push_back(&part);
+ }
+ if(allowed_parts.size() == 0){
+ throw std::logic_error{"Found no parton for coupling with boson"};
+ }
+
+ // select one and flip it
+ size_t idx = 0;
+ if(allowed_parts.size() > 1){
+ /// @TODO more efficient sampling
+ /// old code: probability[i] = exp(parton[i].y - W.y)
+ idx = floor(ran.flat()*allowed_parts.size());
+ weight_ *= allowed_parts.size();
+ }
+ const int W_charge = boson>0?1:-1;
+ allowed_parts[idx]->type =
+ static_cast<ParticleID>( allowed_parts[idx]->type - W_charge );
+ }
+
double PhaseSpacePoint::random_normal(
double stddev,
HEJ::RNG & ran
){
const double r1 = ran.flat();
const double r2 = ran.flat();
const double lninvr1 = -log(r1);
const double result = stddev*sqrt(2.*lninvr1)*cos(2.*M_PI*r2);
weight_ *= exp(result*result/(2*stddev*stddev))*sqrt(2.*M_PI)*stddev;
return result;
}
bool PhaseSpacePoint::momentum_conserved(double ep) const{
fastjet::PseudoJet diff;
for(auto const & in: incoming()) diff += in.p;
for(auto const & out: outgoing()) diff -= out.p;
return nearby_ep(diff, fastjet::PseudoJet{}, ep);
}
Decay PhaseSpacePoint::select_decay_channel(
std::vector<Decay> const & decays,
HEJ::RNG & ran
){
double br_total = 0.;
for(auto const & decay: decays) br_total += decay.branching_ratio;
// adjust weight
// this is given by (channel branching ratio)/(chance to pick channel)
// where (chance to pick channel) =
// (channel branching ratio)/(total branching ratio)
weight_ *= br_total;
const double r1 = br_total*ran.flat();
double br_sum = 0.;
for(auto const & decay: decays){
br_sum += decay.branching_ratio;
if(r1 < br_sum) return decay;
}
throw std::logic_error{"unreachable"};
}
std::vector<Particle> PhaseSpacePoint::decay_boson(
HEJ::Particle const & parent,
std::vector<Decay> const & decays,
HEJ::RNG & ran
){
const auto channel = select_decay_channel(decays, ran);
if(channel.products.size() != 2){
throw HEJ::not_implemented{
"only decays into two particles are implemented"
};
}
std::vector<Particle> decay_products(channel.products.size());
for(size_t i = 0; i < channel.products.size(); ++i){
decay_products[i].type = channel.products[i];
}
// choose polar and azimuth angle in parent rest frame
const double E = parent.m()/2;
const double theta = 2.*M_PI*ran.flat();
const double cos_phi = 2.*ran.flat()-1.;
const double sin_phi = sqrt(1. - cos_phi*cos_phi); // Know 0 < phi < pi
const double px = E*cos(theta)*sin_phi;
const double py = E*sin(theta)*sin_phi;
const double pz = E*cos_phi;
decay_products[0].p.reset(px, py, pz, E);
decay_products[1].p.reset(-px, -py, -pz, E);
for(auto & particle: decay_products) particle.p.boost(parent.p);
return decay_products;
}
}
diff --git a/FixedOrderGen/src/config.cc b/FixedOrderGen/src/config.cc
index 1c82bd7..9e0b3b5 100644
--- a/FixedOrderGen/src/config.cc
+++ b/FixedOrderGen/src/config.cc
@@ -1,357 +1,359 @@
#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;
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', 'W+', 'W-', 'Z', 'H'"
};
}
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(!HEJ::is_AWZH_boson(pid)){
throw invalid_outgoing(particles[i]);
}
if(result.boson){
throw std::invalid_argument{
"More than one outgoing boson is not supported"
};
}
result.boson = pid;
}
}
if(result.njets < 2){
throw std::invalid_argument{
"Process has to include at least two jets ('j')"
};
}
return result;
}
HEJFOG::Subleading to_subleading_channel(YAML::Node const & yaml){
std::string name;
using HEJFOG::Subleading;
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;
// 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");
set_from_yaml(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();
set_from_yaml(result.back().products, decay_str, "into");
set_from_yaml(result.back().branching_ratio, decay_str, "branching ratio");
}
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/FixedOrderGen/t/W_2j_classify.cc b/FixedOrderGen/t/W_2j_classify.cc
new file mode 100644
index 0000000..4cddbf0
--- /dev/null
+++ b/FixedOrderGen/t/W_2j_classify.cc
@@ -0,0 +1,147 @@
+// check that the PSP generates only "valid" W + 2 jets events
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include "JetParameters.hh"
+#include "ParticleProperties.hh"
+#include "PhaseSpacePoint.hh"
+#include "Process.hh"
+#include "Subleading.hh"
+
+#include "HEJ/Mixmax.hh"
+#include "HEJ/PDF.hh"
+#include "HEJ/utility.hh"
+
+using namespace HEJFOG;
+using namespace HEJ;
+
+namespace {
+ void print_psp(PhaseSpacePoint const & psp){
+ std::cerr << "Process:\n"
+ << psp.incoming()[0].type << " + "<< psp.incoming()[1].type << " -> ";
+ for(auto const & out: psp.outgoing()){
+ std::cerr << out.type << " ";
+ }
+ std::cerr << "\n";
+ }
+
+ void bail_out(PhaseSpacePoint const & psp, std::string msg){
+ print_psp(psp);
+ throw std::logic_error{msg};
+ }
+
+ bool is_up_type(Particle const & part){
+ return HEJ::is_anyquark(part) && !(abs(part.type)%2);
+ }
+ bool is_down_type(Particle const & part){
+ return HEJ::is_anyquark(part) && abs(part.type)%2;
+ }
+
+ bool check_W2j(PhaseSpacePoint const & psp, ParticleID const W_type){
+ bool found_quark = false;
+ bool found_anti = false;
+ std::vector<Particle> out_partons;
+ std::vector<Particle> Wp;
+ for(auto const & p: psp.outgoing()){
+ if(p.type == W_type) Wp.push_back(p);
+ else if(is_parton(p)) out_partons.push_back(p);
+ else bail_out(psp, "Found particle with is not "
+ +std::to_string(int(W_type))+" or parton");
+ }
+ if(Wp.size() != 1 || out_partons.size() != 2){
+ bail_out(psp, "Found wrong number of outgoing partons");
+ }
+ for(size_t j=0; j<2; ++j){
+ auto const & in = psp.incoming()[j];
+ auto const & out = out_partons[j];
+ if(is_quark(in) || is_antiquark(in)) {
+ found_quark = true;
+ if(in.type != out.type) { // switch in quark type -> Wp couples to it
+ if(found_anti){ // already found qq for coupling to W
+ bail_out(psp, "Found second up/down pair");
+ } else if(abs(in.type)>4 || abs(out.type)>4){
+ bail_out(psp, "Found bottom/top pair");
+ }
+ found_anti = true;
+ if( is_up_type(in)) { // "up" in
+ if(W_type > 0){
+ // -> only allowed u -> Wp + d
+ if(in.type < 0 || is_up_type(out) || out.type < 0)
+ bail_out(psp, "u -/> Wp + d");
+
+ } else {
+ // -> only allowed ux -> Wm + dx
+ if(in.type > 0 || is_up_type(out) || out.type > 0)
+ bail_out(psp, "ux -/> Wm + dx");
+ }
+ } else { // "down" in
+ if(W_type > 0){
+ // -> only allowed dx -> Wp + ux
+ if(in.type > 0 || is_down_type(out) || out.type > 0)
+ bail_out(psp, "dx -/> Wp + ux");
+ } else {
+ // -> only allowed d -> Wm + u
+ if(in.type < 0 || is_down_type(out) || out.type < 0)
+ bail_out(psp, "d -/> Wm + u");
+ }
+ }
+ }
+ }
+ }
+ if(!found_quark) {
+ bail_out(psp, "Found no initial quarks");
+ } else if(!found_anti){
+ bail_out(psp, "Found no up/down pair");
+ }
+ return true;
+ }
+}
+
+int main(){
+ constexpr size_t n_psp_base = 1337;
+ const JetParameters jet_para{
+ fastjet::JetDefinition(fastjet::JetAlgorithm::antikt_algorithm, 0.4), 30, 5, 30};
+ PDF pdf(11000, pid::proton, pid::proton);
+ constexpr double E_cms = 13000.;
+ constexpr double subl_change = 0.5;
+ constexpr auto subl_channels = Subleading::all;
+ const ParticlesPropMap boson_prop{
+ {pid::Wp, {91.1876, 2.085, {Decay{ {pid::e_bar, pid::nu_e}, 1.}} }},
+ {pid::Wm, {91.1876, 2.085, {Decay{ {pid::e, pid::nu_e_bar}, 1.}} }}
+ };
+ HEJ::Mixmax ran{};
+
+ // Wp2j
+ Process proc {{pid::proton,pid::proton}, 2, pid::Wp};
+ size_t n_psp = n_psp_base;
+ for( size_t i = 0; i<n_psp; ++i){
+ const PhaseSpacePoint psp{proc,jet_para,pdf,E_cms, subl_change,subl_channels,
+ boson_prop, ran};
+ if(psp.status()==good){
+ check_W2j(psp, *proc.boson);
+ } else { // bad process -> try again
+ ++n_psp;
+ }
+ }
+ std::cout << "Wp+2j: Took " << n_psp << " to generate "
+ << n_psp_base << " successfully PSP (" << 1.*n_psp/n_psp_base << " trials/PSP)" << std::endl;
+ // Wm2j
+ proc = Process{{pid::proton,pid::proton}, 2, pid::Wm};
+ n_psp = n_psp_base;
+ for( size_t i = 0; i<n_psp; ++i){
+ const PhaseSpacePoint psp{proc,jet_para,pdf,E_cms, subl_change,subl_channels,
+ boson_prop, ran};
+ if(psp.status()==good){
+ check_W2j(psp, *proc.boson);
+ } else { // bad process -> try again
+ ++n_psp;
+ }
+ }
+ std::cout << "Wm+2j: Took " << n_psp << " to generate "
+ << n_psp_base << " successfully PSP (" << 1.*n_psp/n_psp_base << " trials/PSP)" << std::endl;
+
+ std::cout << "All processes passed." << std::endl;
+ return EXIT_SUCCESS;
+}
diff --git a/FixedOrderGen/t/W_nj_classify.cc b/FixedOrderGen/t/W_nj_classify.cc
new file mode 100644
index 0000000..2da7126
--- /dev/null
+++ b/FixedOrderGen/t/W_nj_classify.cc
@@ -0,0 +1,179 @@
+// check that the PSP generates the all W+jet subleading processes
+
+#ifdef NDEBUG
+#undef NDEBUG
+#endif
+
+#include <algorithm>
+
+#include "JetParameters.hh"
+#include "ParticleProperties.hh"
+#include "PhaseSpacePoint.hh"
+#include "Process.hh"
+#include "Subleading.hh"
+
+#include "HEJ/Event.hh"
+#include "HEJ/Mixmax.hh"
+#include "HEJ/PDF.hh"
+#include "HEJ/utility.hh"
+
+using namespace HEJFOG;
+using namespace HEJ;
+
+namespace {
+ void print_psp(PhaseSpacePoint const & psp){
+ std::cerr << "Process:\n"
+ << psp.incoming()[0].type << " + "<< psp.incoming()[1].type << " -> ";
+ for(auto const & out: psp.outgoing()){
+ std::cerr << out.type << " ";
+ }
+ std::cerr << "\n";
+ }
+ void bail_out(PhaseSpacePoint const & psp, std::string msg){
+ print_psp(psp);
+ throw std::logic_error{msg};
+ }
+}
+
+int main(){
+ constexpr size_t n_psp_base = 10375;
+ const JetParameters jet_para{
+ fastjet::JetDefinition(fastjet::JetAlgorithm::antikt_algorithm, 0.4), 30, 5, 30};
+ PDF pdf(11000, pid::proton, pid::proton);
+ constexpr double E_cms = 13000.;
+ constexpr double subl_change = 0.8;
+ const ParticlesPropMap boson_prop{
+ {pid::Wp, {91.1876, 2.085, {Decay{ {pid::e_bar, pid::nu_e}, 1.}} }},
+ {pid::Wm, {91.1876, 2.085, {Decay{ {pid::e, pid::nu_e_bar}, 1.}} }}
+ };
+ HEJ::Mixmax ran{};
+
+ auto subl_channels = Subleading::all;
+ std::vector<event_type::EventType> allowed_types{event_type::FKL,
+ event_type::unob, event_type::unof, event_type::qqxexb, event_type::qqxexf};
+
+ std::cout << "Wp3j" << std::endl;
+ // Wp3j
+ Process proc {{pid::proton,pid::proton}, 3, pid::Wp};
+ size_t n_psp = n_psp_base;
+ std::unordered_map<event_type::EventType, size_t> type_counter;
+ for( size_t i = 0; i<n_psp; ++i){
+ const PhaseSpacePoint psp{proc,jet_para,pdf,E_cms, subl_change,subl_channels,
+ boson_prop, ran};
+ if(psp.status()==good){
+ const Event ev{ to_EventData(psp).cluster(jet_para.def, jet_para.min_pt) };
+ ++type_counter[ev.type()];
+ if( std::find(allowed_types.cbegin(), allowed_types.cend(), ev.type())
+ == allowed_types.cend()) {
+ bail_out(psp, "Found not allowed event of type "
+ +std::string(event_type::names[ev.type()]));
+ }
+ } else { // bad process -> try again
+ ++n_psp;
+ }
+ }
+ std::cout << "Wp+3j: Took " << n_psp << " to generate "
+ << n_psp_base << " successfully PSP (" << 1.*n_psp/n_psp_base << " trials/PSP)" << std::endl;
+ std::cout << "States by classification:\n";
+ for(auto const & entry: type_counter){
+ const double fraction = static_cast<double>(entry.second)/n_psp_base;
+ const int percent = std::round(100*fraction);
+ std::cout << std::left << std::setw(25)
+ << (event_type::names[entry.first] + std::string(":"))
+ << entry.second << " (" << percent << "%)\n";
+
+ }
+ for(auto const & t: allowed_types){
+ if(type_counter[t] < 0.05 * n_psp_base){
+ std::cerr << "Less than 5% of the events are of type " << event_type::names[t] << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ // Wm3j - only uno
+ proc = Process{{pid::proton,pid::proton}, 3, pid::Wm};
+ n_psp = n_psp_base;
+
+ subl_channels = Subleading::uno;
+ allowed_types = {event_type::FKL, event_type::unob, event_type::unof};
+ type_counter.clear();
+
+ for( size_t i = 0; i<n_psp; ++i){
+ const PhaseSpacePoint psp{proc,jet_para,pdf,E_cms, subl_change,subl_channels,
+ boson_prop, ran};
+ if(psp.status()==good){
+ const Event ev{ to_EventData(psp).cluster(jet_para.def, jet_para.min_pt) };
+ ++type_counter[ev.type()];
+ if( std::find(allowed_types.cbegin(), allowed_types.cend(), ev.type())
+ == allowed_types.cend()) {
+ bail_out(psp, "Found not allowed event of type "
+ +std::string(event_type::names[ev.type()]));
+ }
+ } else { // bad process -> try again
+ ++n_psp;
+ }
+ }
+ std::cout << "Wm+3j (only uno): Took " << n_psp << " to generate "
+ << n_psp_base << " successfully PSP (" << 1.*n_psp/n_psp_base << " trials/PSP)" << std::endl;
+ std::cout << "States by classification:\n";
+ for(auto const & entry: type_counter){
+ const double fraction = static_cast<double>(entry.second)/n_psp_base;
+ const int percent = std::round(100*fraction);
+ std::cout << std::left << std::setw(25)
+ << (event_type::names[entry.first] + std::string(":"))
+ << entry.second << " (" << percent << "%)\n";
+
+ }
+ for(auto const & t: allowed_types){
+ if(type_counter[t] < 0.05 * n_psp_base){
+ std::cerr << "Less than 5% of the events are of type " << event_type::names[t] << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ // Wm4j
+ proc = Process{{pid::proton,pid::proton}, 4, pid::Wm};
+ n_psp = n_psp_base;
+
+ subl_channels = Subleading::all;
+ allowed_types = {event_type::FKL,
+ event_type::unob, event_type::unof, event_type::qqxexb, event_type::qqxexf,
+ event_type::qqxmid};
+ type_counter.clear();
+
+ for( size_t i = 0; i<n_psp; ++i){
+ const PhaseSpacePoint psp{proc,jet_para,pdf,E_cms, subl_change,subl_channels,
+ boson_prop, ran};
+ if(psp.status()==good){
+ const Event ev{ to_EventData(psp).cluster(jet_para.def, jet_para.min_pt)};
+ ++type_counter[ev.type()];
+ if( std::find(allowed_types.cbegin(), allowed_types.cend(), ev.type())
+ == allowed_types.cend()) {
+ bail_out(psp, "Found not allowed event of type "
+ +std::string(event_type::names[ev.type()]));
+ }
+ } else { // bad process -> try again
+ ++n_psp;
+ }
+ }
+ std::cout << "Wm+4j: Took " << n_psp << " to generate "
+ << n_psp_base << " successfully PSP (" << 1.*n_psp/n_psp_base << " trials/PSP)" << std::endl;
+ std::cout << "States by classification:\n";
+ for(auto const & entry: type_counter){
+ const double fraction = static_cast<double>(entry.second)/n_psp_base;
+ const int percent = std::round(100*fraction);
+ std::cout << std::left << std::setw(25)
+ << (event_type::names[entry.first] + std::string(":"))
+ << entry.second << " (" << percent << "%)\n";
+
+ }
+ for(auto const & t: allowed_types){
+ if(type_counter[t] < 0.03 * n_psp_base){
+ std::cerr << "Less than 3% of the events are of type " << event_type::names[t] << std::endl;
+ return EXIT_FAILURE;
+ }
+ }
+
+ std::cout << "All processes passed." << std::endl;
+ return EXIT_SUCCESS;
+}
diff --git a/config.yml b/config.yml
index 8288cea..bb93dad 100644
--- a/config.yml
+++ b/config.yml
@@ -1,89 +1,97 @@
# number of attempted resummation phase space points for each input event
trials: 10
min extparton pt: 30 # minimum transverse momentum of extremal partons
# maximum soft transverse momentum fraction in extremal jets
#
# max ext soft pt fraction: 0.1
resummation jets: # resummation jet properties
min pt: 35 # minimum jet transverse momentum
algorithm: antikt # jet clustering algorithm
R: 0.4 # jet R parameter
fixed order jets: # properties of input jets
min pt: 30
# by default, algorithm and R are like for resummation jets
# treatment of he various event classes
# the supported settings are: reweight, keep, discard
# non-HEJ events cannot be reweighted
FKL: reweight
unordered: keep
+qqx: keep
non-HEJ: keep
# central scale choice or choices
#
# scales: [125, max jet pperp, H_T/2, 2*jet invariant mass, m_j1j2]
scales: 91.188
# factors by which the central scales should be multiplied
# renormalisation and factorisation scales are varied independently
#
# scale factors: [0.5, 0.7071, 1, 1.41421, 2]
# maximum ratio between renormalisation and factorisation scale
#
# max scale ratio: 2.0001
# import scale setting functions
#
# import scales:
# lib_my_scales.so: [scale0,scale1]
log correction: false # whether or not to include higher order logs
# event output files
#
# the supported formats are
# - Les Houches (suffix .lhe)
# - HepMC (suffix .hepmc3)
# TODO: - ROOT ntuples (suffix .root)
#
# An output file's format is deduced either automatically from the suffix
# or from an explicit specification, e.g.
# - Les Houches: outfile
event output:
- HEJ.lhe
# - HEJ_events.hepmc
# to use a rivet analysis
#
# analysis:
# rivet: MC_XS # rivet analysis name
# output: HEJ # name of the yoda files, ".yoda" and scale suffix will be added
#
# to use a custom analysis
#
# analysis:
# plugin: /path/to/libmyanalysis.so
# my analysis parameter: some value
# selection of random number generator and seed
# the choices are
# - mixmax (seed is an integer)
# - ranlux64 (seed is a filename containing parameters)
random generator:
name: mixmax
# seed: 1
# parameters for Higgs-gluon couplings
# this requires compilation with qcdloop
#
# Higgs coupling:
# use impact factors: false
# mt: 174
# include bottom: true
# mb: 4.7
+
+## ---------------------------------------------------------------------- ##
+## The following settings are only intended for advances users. ##
+## Please DO NOT SET them unless you know exactly what you are doing! ##
+## ---------------------------------------------------------------------- ##
+#
+# regulator parameter: 0.2 # The regulator lambda for the subtraction terms
diff --git a/doc/developer_manual/developer_manual.tex b/doc/developer_manual/developer_manual.tex
index 8fafed2..6c83b9a 100644
--- a/doc/developer_manual/developer_manual.tex
+++ b/doc/developer_manual/developer_manual.tex
@@ -1,1535 +1,1537 @@
\documentclass[a4paper,11pt]{article}
\usepackage{fourier}
\usepackage[T1]{fontenc}
\usepackage{microtype}
\usepackage{geometry}
\usepackage{enumitem}
\setlist[description]{leftmargin=\parindent,labelindent=\parindent}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage[utf8x]{inputenc}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage{todonotes}
\usepackage{listings}
\usepackage{xspace}
\usepackage{tikz}
\usepackage{subcaption}
\usetikzlibrary{arrows.meta}
\usetikzlibrary{shapes}
\usetikzlibrary{calc}
\usepackage[colorlinks,linkcolor={blue!50!black}]{hyperref}
\graphicspath{{build/figures/}{figures/}}
\emergencystretch \hsize
\newcommand{\HEJ}{{\tt HEJ}\xspace}
\newcommand{\HIGHEJ}{\emph{High Energy Jets}\xspace}
\newcommand{\cmake}{\href{https://cmake.org/}{cmake}\xspace}
\newcommand{\html}{\href{https://www.w3.org/html/}{html}\xspace}
\newcommand{\YAML}{\href{http://yaml.org/}{YAML}\xspace}
\newcommand{\QCDloop}{\href{https://github.com/scarrazza/qcdloop}{QCDloop}\xspace}
\newcommand{\as}{\alpha_s}
\DeclareRobustCommand{\mathgraphics}[1]{\vcenter{\hbox{\includegraphics{#1}}}}
\def\spa#1.#2{\left\langle#1\,#2\right\rangle}
\def\spb#1.#2{\left[#1\,#2\right]} \def\spaa#1.#2.#3{\langle\mskip-1mu{#1} |
#2 | {#3}\mskip-1mu\rangle} \def\spbb#1.#2.#3{[\mskip-1mu{#1} | #2 |
{#3}\mskip-1mu]} \def\spab#1.#2.#3{\langle\mskip-1mu{#1} | #2 |
{#3}\mskip-1mu\rangle} \def\spba#1.#2.#3{\langle\mskip-1mu{#1}^+ | #2 |
{#3}^+\mskip-1mu\rangle} \def\spav#1.#2.#3{\|\mskip-1mu{#1} | #2 |
{#3}\mskip-1mu\|^2} \def\jc#1.#2.#3{j^{#1}_{#2#3}}
\definecolor{darkgreen}{rgb}{0,0.4,0}
\lstset{ %
backgroundcolor=\color{lightgray}, % choose the background color; you must add \usepackage{color} or \usepackage{xcolor}
basicstyle=\footnotesize\usefont{T1}{DejaVuSansMono-TLF}{m}{n}, % the size of the fonts that are used for the code
breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace
breaklines=false, % sets automatic line breaking
captionpos=t, % sets the caption-position to bottom
commentstyle=\color{red}, % comment style
deletekeywords={...}, % if you want to delete keywords from the given language
escapeinside={\%*}{*)}, % if you want to add LaTeX within your code
extendedchars=true, % lets you use non-ASCII characters; for 8-bits encodings only, does not work with UTF-8
frame=false, % adds a frame around the code
keepspaces=true, % keeps spaces in text, useful for keeping indentation of code (possibly needs columns=flexible)
keywordstyle=\color{blue}, % keyword style
otherkeywords={}, % if you want to add more keywords to the set
numbers=none, % where to put the line-numbers; possible values are (none, left, right)
numbersep=5pt, % how far the line-numbers are from the code
rulecolor=\color{black}, % if not set, the frame-color may be changed on line-breaks within not-black text (e.g. comments (green here))
showspaces=false, % show spaces everywhere adding particular underscores; it overrides 'showstringspaces'
showstringspaces=false, % underline spaces within strings only
showtabs=false, % show tabs within strings adding particular underscores
stepnumber=2, % the step between two line-numbers. If it's 1, each line will be numbered
stringstyle=\color{gray}, % string literal style
tabsize=2, % sets default tabsize to 2 spaces
title=\lstname,
emph={},
emphstyle=\color{darkgreen}
}
\begin{document}
\tikzstyle{mynode}=[rectangle split,rectangle split parts=2, draw,rectangle split part fill={lightgray, none}]
\title{HEJ 2 developer manual}
\author{}
\maketitle
\tableofcontents
\newpage
\section{Overview}
\label{sec:overview}
HEJ 2 is a C++ program and library implementing an algorithm to
apply \HIGHEJ resummation~\cite{Andersen:2008ue,Andersen:2008gc} to
pre-generated fixed-order events. This document is intended to give an
overview over the concepts and structure of this implementation.
\subsection{Project structure}
\label{sec:project}
HEJ 2 is developed under the \href{https://git-scm.com/}{git}
version control system. The main repository is on the IPPP
\href{https://gitlab.com/}{gitlab} server under
\url{https://gitlab.dur.scotgrid.ac.uk/hej/hej}. To get a local
copy, get an account on the gitlab server and use
\begin{lstlisting}[language=sh,caption={}]
git clone git@gitlab.dur.scotgrid.ac.uk:hej/hej.git
\end{lstlisting}
This should create a directory \texttt{hej} with the following
contents:
\begin{description}
\item[doc:] Contains additional documentation, see section~\ref{sec:doc}.
\item[include:] Contains the C++ header files.
\item[src:] Contains the C++ source files.
\item[t:] Contains the source code for the automated tests.
\item[CMakeLists.txt:] Configuration file for the \cmake build
system. See section~\ref{sec:cmake}.
\item[cmake:] Auxiliary files for \cmake. This includes modules for
finding installed software in \texttt{cmake/Modules} and templates for
code generation during the build process in \texttt{cmake/Templates}.
\item[config.yml:] Sample configuration file for running HEJ 2.
\item[FixedOrderGen:] Contains the code for the fixed-order generator,
see section~\ref{sec:HEJFOG}.
\end{description}
In the following all paths are given relative to the
\texttt{hej} directory.
\subsection{Documentation}
\label{sec:doc}
The \texttt{doc} directory contains user documentation in
\texttt{doc/sphinx} and the configuration to generate source code
documentation in \texttt{doc/doxygen}.
The user documentation explains how to install and run HEJ 2. The
format is
\href{http://docutils.sourceforge.net/rst.html}{reStructuredText}, which
is mostly human-readable. Other formats, like \html, can be generated with the
\href{http://www.sphinx-doc.org/en/master/}{sphinx} generator with
\begin{lstlisting}[language=sh,caption={}]
make html
\end{lstlisting}
To document the source code we use
\href{https://www.stack.nl/~dimitri/doxygen/}{doxygen}. To generate
\html documentation, use the command
\begin{lstlisting}[language=sh,caption={}]
doxygen Doxyfile
\end{lstlisting}
in the \texttt{doc/doxygen} directory.
\subsection{Build system}
\label{sec:cmake}
For the most part, HEJ 2 is a library providing classes and
functions that can be used to add resummation to fixed-order events. In
addition, there is a relatively small executable program leveraging this
library to read in events from an input file and produce resummation
events. Both the library and the program are built and installed with
the help of \cmake.
Debug information can be turned on by using
\begin{lstlisting}[language=sh,caption={}]
cmake base/directory -DCMAKE_BUILD_TYPE=Debug
make install
\end{lstlisting}
This facilitates the use of debuggers like \href{https://www.gnu.org/software/gdb/}{gdb}.
The main \cmake configuration file is \texttt{CMakeLists.txt}. It defines the
compiler flags, software prerequisites, header and source files used to
build HEJ 2, and the automated tests.
\texttt{cmake/Modules} contains module files that help with the
detection of the software prerequisites and \texttt{cmake/Templates}
template files for the automatic generation of header and
source files. For example, this allows to only keep the version
information in one central location (\texttt{CMakeLists.txt}) and
automatically generate a header file from the template \texttt{Version.hh.in} to propagate this to the C++ code.
\subsection{General coding guidelines}
\label{sec:notes}
The goal is to make the HEJ 2 code well-structured and
readable. Here are a number of guidelines to this end.
\begin{description}
\item[Observe the boy scout rule.] Always leave the code cleaner
than how you found it. Ugly hacks can be useful for testing, but
shouldn't make their way into the main branch.
\item[Ask if something is unclear.] Often there is a good reason why
code is written the way it is. Sometimes that reason is only obvious to
the original author (use \lstinline!git blame! to find them), in which
case they should be poked to add a comment. Sometimes there is no good
reason, but nobody has had the time to come up with something better,
yet. In some places the code might just be bad.
\item[Don't break tests.] There are a number of tests in the \texttt{t}
directory, which can be run with \lstinline!make test!. Ideally, all
tests should run successfully in each git revision. If your latest
commit broke a test and you haven't pushed to the central repository
yet, you can fix it with \lstinline!git commit --amend!. If an earlier
local commit broke a test, you can use \lstinline!git rebase -i! if
you feel confident. Additionally each \lstinline!git push! is also
automatically tested via the GitLab CI (see appendix~\ref{sec:gitlabCI}).
\item[Test your new code.] When you add some new functionality, also add an
automated test. This can be useful even if you don't know the
``correct'' result because it prevents the code from changing its behaviour
silently in the future. \href{http://www.valgrind.org/}{valgrind} is a
very useful tool to detect potential memory leaks.
\item[Stick to the coding style.] It is somewhat easier to read code
that has a uniform coding and indentation style. We don't have a
strict style, but it helps if your code looks similar to what is
already there.
\end{description}
\section{Program flow}
\label{sec:flow}
A run of the HEJ 2 program has three stages: initialisation,
event processing, and cleanup. The following sections outline these
stages and their relations to the various classes and functions in the
code. Unless denoted otherwise, all classes and functions are part of
the \lstinline!HEJ! namespace. The code for the HEJ 2 program is
in \texttt{src/bin/HEJ.cc}, all other code comprises the HEJ 2
library. Classes and free functions are usually implemented in header
and source files with a corresponding name, i.e. the code for
\lstinline!MyClass! can usually be found in
\texttt{include/HEJ/MyClass.hh} and \texttt{src/MyClass.cc}.
\subsection{Initialisation}
\label{sec:init}
The first step is to load and parse the \YAML configuration file. The
entry point for this is the \lstinline!load_config! function and the
related code can be found in \texttt{include/HEJ/YAMLreader.hh},
\texttt{include/HEJ/config.hh} and the corresponding \texttt{.cc} files
in the \texttt{src} directory. The implementation is based on the
\href{https://github.com/jbeder/yaml-cpp}{yaml-cpp} library.
The \lstinline!load_config! function returns a \lstinline!Config! object
containing all settings. To detect potential mistakes as early as
possible, we throw an exception whenever one of the following errors
occurs:
\begin{itemize}
\item There is an unknown option in the \YAML file.
\item A setting is invalid, for example a string is given where a number
would be expected.
\item An option value is not set.
\end{itemize}
The third rule is sometimes relaxed for ``advanced'' settings with an
obvious default, like for importing custom scales or analyses.
The information stored in the \lstinline!Config! object is then used to
initialise various objects required for the event processing stage
described in section~\ref{sec:processing}. First, the
\lstinline!get_analysis! function creates an object that inherits from
the \lstinline!Analysis! interface.\footnote{In the context of C++ the
proper technical expression is ``pure abstract class''.} Using an
interface allows us to decide the concrete type of the analysis at run
time instead of having to make a compile-time decision. Depending on the
settings, \lstinline!get_analysis! creates either a user-defined
analysis loaded from an external library (see the user documentation
\url{https://hej.web.cern.ch/HEJ/doc/current/user/}) or the default \lstinline!EmptyAnalysis!, which does
nothing.
Together with a number of further objects, whose roles are described in
section~\ref{sec:processing}, we also initialise the global random
number generator. We again use an interface to defer deciding the
concrete type until the program is actually run. Currently, we support the
\href{https://mixmax.hepforge.org/}{MIXMAX}
(\texttt{include/HEJ/Mixmax.hh}) and Ranlux64
(\texttt{include/HEJ/Ranlux64.hh}) random number generators, both are provided
by \href{http://proj-clhep.web.cern.ch/}{CLHEP}.
We also set up a \lstinline!LHEF::Reader! object (see
\href{http://home.thep.lu.se/~leif/LHEF/}{\texttt{include/LHEF/LHEF.h}}) for
reading events from a file in the Les
Houches event file format~\cite{Alwall:2006yp}. A small wrapper around
the
\href{https://www.boost.org/doc/libs/1_67_0/libs/iostreams/doc/index.html}{boost
iostreams} library allows us to also read event files compressed with
\href{https://www.gnu.org/software/gzip/}{gzip}. The wrapper code is in
\texttt{include/HEJ/stream.hh} and the \texttt{src/stream.cc}.
\subsection{Event processing}
\label{sec:processing}
In the second stage events are continously read from the event
file. After jet clustering, a number of corresponding resummation events
are generated for each input event and fed into the analysis and a
number of output files. The roles of various classes and functions are
illustrated in the following flow chart:
\begin{center}
\begin{tikzpicture}[node distance=2cm and 5mm]
\node (reader) [mynode]
{\lstinline!LHEF::Reader::readEvent!\nodepart{second}{read event}};
\node
(data) [mynode,below=of reader]
{\lstinline!Event::EventData! constructor\nodepart{second}{convert to \HEJ object}};
\node
(cluster) [mynode,below=of data]
{\lstinline!Event::EventData::cluster!\nodepart{second}{cluster jets \&
classify \lstinline!EventType!}};
\node
(resum) [mynode,below=of cluster]
{\lstinline!EventReweighter::reweight!\nodepart{second}{perform resummation}};
\node
(cut) [mynode,below=of resum]
{\lstinline!Analysis::pass_cuts!\nodepart{second}{apply cuts}};
\node
(fill) [mynode,below left=of cut]
{\lstinline!Analysis::fill!\nodepart{second}{analyse event}};
\node
(write) [mynode,below right=of cut]
{\lstinline!CombinedEventWriter::write!\nodepart{second}{write out event}};
\node
(control) [below=of cut] {};
\draw[-{Latex[length=3mm, width=1.5mm]}]
(reader.south) -- node[left] {\lstinline!LHEF::HEPEUP!} (data.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(data.south) -- node[left] {\lstinline!Event::EventData!} (cluster.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(cluster.south) -- node[left] {\lstinline!Event!} (resum.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(resum.south) -- (cut.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(resum.south)+(7mm, 0cm)$) -- ($(cut.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(resum.south)-(7mm, 0cm)$) -- node[left] {\lstinline!Event!} ($(cut.north)-(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(cut.south)-(3mm,0mm)$) .. controls ($(control)-(3mm,0mm)$) ..node[left] {\lstinline!Event!} (fill.east);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(cut.south)-(3mm,0mm)$) .. controls ($(control)-(3mm,0mm)$) .. (write.west);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(cut.south)+(3mm,0mm)$) .. controls ($(control)+(3mm,0mm)$) .. (fill.east);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(cut.south)+(3mm,0mm)$) .. controls ($(control)+(3mm,0mm)$) ..node[right] {\lstinline!Event!} (write.west);
\end{tikzpicture}
\end{center}
\lstinline!EventData! is an intermediate container, its members are completely
accessible. In contrast after jet clustering and classification the phase space
inside \lstinline!Event! can not be changed any more
(\href{https://wikipedia.org/wiki/Builder_pattern}{Builder design pattern}). The
resummation is performed by the \lstinline!EventReweighter! class, which is
described in more detail in section~\ref{sec:resum}. The
\lstinline!CombinedEventWriter! writes events to zero or more output files. To
this end, it contains a number of objects implementing the
\lstinline!EventWriter! interface. These event writers typically write the
events to a file in a given format. We currently have the
\lstinline!LesHouchesWriter! for event files in the Les Houches Event File
format and the \lstinline!HepMCWriter! for the
\href{https://hepmc.web.cern.ch/hepmc/}{HepMC} format (Version 2 and 3).
\subsection{Resummation}
\label{sec:resum}
In the \lstinline!EventReweighter::reweight! member function, we first
classify the input fixed-order event (FKL, unordered, non-HEJ, \dots)
and decide according to the user settings whether to discard, keep, or
resum the event. If we perform resummation for the given event, we
generate a number of trial \lstinline!PhaseSpacePoint! objects. Phase
space generation is discussed in more detail in
section~\ref{sec:pspgen}. We then perform jet clustering according to
the settings for the resummation jets on each
\lstinline!PhaseSpacePoint!, update the factorisation and
renormalisation scale in the resulting \lstinline!Event! and reweight it
according to the ratio of pdf factors and \HEJ matrix elements between
resummation and original fixed-order event:
\begin{center}
\begin{tikzpicture}[node distance=1.5cm and 5mm]
\node (in) {};
\node (treat) [diamond,draw,below=of in,minimum size=3.5cm,
label={[anchor=west, inner sep=8pt]west:discard},
label={[anchor=east, inner sep=14pt]east:keep},
label={[anchor=south, inner sep=20pt]south:reweight}
] {};
\draw (treat.north west) -- (treat.south east);
\draw (treat.north east) -- (treat.south west);
\node
(psp) [mynode,below=of treat]
{\lstinline!PhaseSpacePoint! constructor};
\node
(cluster) [mynode,below=of psp]
{\lstinline!Event::EventData::cluster!\nodepart{second}{cluster jets}};
\node
(colour) [mynode,below=of cluster]
{\lstinline!Event::generate_colours()!\nodepart{second}{generate particle colour}};
\node
(gen_scales) [mynode,below=of colour]
{\lstinline!ScaleGenerator::operator()!\nodepart{second}{update scales}};
\node
(rescale) [mynode,below=of gen_scales]
{\lstinline!PDF::pdfpt!,
\lstinline!MatrixElement!\nodepart{second}{reweight}};
\node (out) [below of=rescale] {};
\draw[-{Latex[length=3mm, width=1.5mm]}]
(in.south) -- node[left] {\lstinline!Event!} (treat.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(treat.south) -- node[left] {\lstinline!Event!} (psp.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(psp.south) -- (cluster.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(psp.south)+(7mm, 0cm)$) -- ($(cluster.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(psp.south)-(7mm, 0cm)$) -- node[left]
{\lstinline!PhaseSpacePoint!} ($(cluster.north)-(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(cluster.south) -- (colour.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(cluster.south)+(7mm, 0cm)$) -- ($(colour.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(cluster.south)-(7mm, 0cm)$) -- node[left]
{\lstinline!Event!} ($(colour.north)-(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(colour.south) -- (gen_scales.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(colour.south)+(7mm, 0cm)$) -- ($(gen_scales.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(colour.south)-(7mm, 0cm)$) -- node[left]
{\lstinline!Event!} ($(gen_scales.north)-(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(gen_scales.south) -- (rescale.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(gen_scales.south)+(7mm, 0cm)$) -- ($(rescale.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(gen_scales.south)-(7mm, 0cm)$) -- node[left]
{\lstinline!Event!} ($(rescale.north)-(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
(rescale.south) -- (out.north);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(rescale.south)+(7mm, 0cm)$) -- ($(out.north)+(7mm, 0cm)$);
\draw[-{Latex[length=3mm, width=1.5mm]}]
($(rescale.south)-(7mm, 0cm)$) -- node[left]
{\lstinline!Event!} ($(out.north)-(7mm, 0cm)$);
\node (helper) at ($(treat.east) + (15mm,0cm)$) {};
\draw[-{Latex[length=3mm, width=1.5mm]}]
(treat.east) -- ($(treat.east) + (15mm,0cm)$)
-- node[left] {\lstinline!Event!} (helper |- gen_scales.east) -- (gen_scales.east)
;
\end{tikzpicture}
\end{center}
\subsection{Phase space point generation}
\label{sec:pspgen}
The resummed and matched \HEJ cross section for pure jet production of
FKL configurations is given by (cf. eq. (3) of~\cite{Andersen:2018tnm})
\begin{align}
\label{eq:resumdijetFKLmatched2}
% \begin{split}
\sigma&_{2j}^\mathrm{resum, match}=\sum_{f_1, f_2}\ \sum_m
\prod_{j=1}^m\left(
\int_{p_{j\perp}^B=0}^{p_{j\perp}^B=\infty}
\frac{\mathrm{d}^2\mathbf{p}_{j\perp}^B}{(2\pi)^3}\ \int
\frac{\mathrm{d} y_j^B}{2} \right) \
(2\pi)^4\ \delta^{(2)}\!\!\left(\sum_{k=1}^{m}
\mathbf{p}_{k\perp}^B\right)\nonumber\\
&\times\ x_a^B\ f_{a, f_1}(x_a^B, Q_a^B)\ x_b^B\ f_{b, f_2}(x_b^B, Q_b^B)\
\frac{\overline{\left|\mathcal{M}_\text{LO}^{f_1f_2\to f_1g\cdots
gf_2}\big(\big\{p^B_j\big\}\big)\right|}^2}{(\hat {s}^B)^2}\nonumber\\
& \times (2\pi)^{-4+3m}\ 2^m \nonumber\\
&\times\ \sum_{n=2}^\infty\
\int_{p_{1\perp}=p_{\perp,\mathrm{min}} }^{p_{1\perp}=\infty}
\frac{\mathrm{d}^2\mathbf{p}_{1\perp}}{(2\pi)^3}\
\int_{p_{n\perp}=p_{\perp,\mathrm{min}}}^{p_{n\perp}=\infty}
\frac{\mathrm{d}^2\mathbf{p}_{n\perp}}{(2\pi)^3}\
\prod_{i=2}^{n-1}\int_{p_{i\perp}=\lambda}^{p_{i\perp}=\infty}
\frac{\mathrm{d}^2\mathbf{p}_{i\perp}}{(2\pi)^3}\ (2\pi)^4\ \delta^{(2)}\!\!\left(\sum_{k=1}^n
\mathbf{p}_{k\perp}\right )\\
&\times \ \mathbf{T}_y \prod_{i=1}^n
\left(\int \frac{\mathrm{d} y_i}{2}\right)\
\mathcal{O}_{mj}^e\
\left(\prod_{l=1}^{m-1}\delta^{(2)}(\mathbf{p}_{\mathcal{J}_{l}\perp}^B -
\mathbf{j}_{l\perp})\right)\
\left(\prod_{l=1}^m\delta(y^B_{\mathcal{J}_l}-y_{\mathcal{J}_l})\right)
\ \mathcal{O}_{2j}(\{p_i\})\nonumber\\
&\times \frac{(\hat{s}^B)^2}{\hat{s}^2}\ \frac{x_a f_{a,f_1}(x_a, Q_a)\ x_b f_{b,f_2}(x_b, Q_b)}{x_a^B\ f_{a,f_1}(x_a^B, Q_a^B)\ x_b^B\ f_{b,f_2}(x_b^B, Q_b^B)}\ \frac{\overline{\left|\mathcal{M}_{\mathrm{HEJ}}^{f_1 f_2\to f_1 g\cdots
gf_2}(\{ p_i\})\right|}^2}{\overline{\left|\mathcal{M}_\text{LO, HEJ}^{f_1f_2\to f_1g\cdots
gf_2}\big(\big\{p^B_j\big\}\big)\right|}^{2}} \,.\nonumber
% \end{split}
\end{align}
The first two lines correspond to the generation of the fixed-order
input events with incoming partons $f_1, f_2$ and outgoing momenta
$p_j^B$, where $\mathbf{p}_{j\perp}^B$ and $y_j^B$ denote the respective
transverse momentum and rapidity. Note that, at leading order, these
coincide with the fixed-order jet momenta $p_{\mathcal{J}_j}^B$.
$f_{a,f_1}(x_a, Q_a),f_{b,f_2}(x_b, Q_b)$ are the pdf factors for the incoming partons with
momentum fractions $x_a$ and $x_b$. The square of the partonic
centre-of-mass energy is denoted by $\hat{s}^B$ and
$\mathcal{M}_\text{LO}^{f_1f_2\to f_1g\cdots gf_2}$ is the
leading-order matrix element.
The third line is a factor accounting for the different multiplicities
between fixed-order and resummation events. Lines four and five are
the integration over the resummation phase space described in this
section. $p_i$ are the momenta of the outgoing partons in resummation
phase space. $\mathbf{T}_y$ denotes rapidity
ordering and $\mathcal{O}_{mj}^e$ projects out the exclusive $m$-jet
component. The relation between resummation and fixed-order momenta is
fixed by the $\delta$ functions. The first sets each transverse fixed-order jet
momentum to some function $\mathbf{j_{l\perp}}$ of the resummation
momenta. The exact form is described in section~\ref{sec:ptj_res}. The second
$\delta$ forces the rapidities of resummation and fixed-order jets to be
the same. Finally, the last line is the reweighting of pdf and matrix
element factors already shown in section~\ref{sec:resum}.
There are two kinds of cut-off in the integration over the resummation
partons. $\lambda$ is a technical cut-off connected to the cancellation
of infrared divergencies between real and virtual corrections. Its
numerical value is set in
\texttt{include/HEJ/Constants.h}. $p_{\perp,\mathrm{min}}$ regulates
and \emph{uncancelled} divergence in the extremal parton momenta. Its
size is set by the user configuration \url{https://hej.web.cern.ch/HEJ/doc/current/user/HEJ.html#settings}.
It is straightforward to generalise eq.~(\ref{eq:resumdijetFKLmatched2})
to unordered configurations and processes with additional colourless
emissions, for example a Higgs or electroweak boson. In the latter case only
the fixed-order integration and the matrix elements change.
\subsubsection{Gluon Multiplicity}
\label{sec:psp_ng}
The first step in evaluating the resummation phase space in
eq.~(\ref{eq:resumdijetFKLmatched2}) is to randomly pick terms in the
sum over the number of emissions. This sampling of the gluon
multiplicity is done in the \lstinline!PhaseSpacePoint::sample_ng!
function in \texttt{src/PhaseSpacePoint.cc}.
The typical number of extra emissions depends strongly on the rapidity
span of the underlying fixed-order event. Let us, for example, consider
a fixed-order FKL-type multi-jet configuration with rapidities
$y_{j_f},\,y_{j_b}$ of the most forward and backward jets,
respectively. By eq.~(\ref{eq:resumdijetFKLmatched2}), the jet
multiplicity and the rapidity of each jet are conserved when adding
resummation. This implies that additional hard radiation is restricted
to rapidities $y$ within a region $y_{j_b} \lesssim y \lesssim
y_{j_f}$. Within \HEJ, we require the most forward and most backward
emissions to be hard \todo{specify how hard} in order to avoid divergences, so this constraint
in fact applies to \emph{all} additional radiation.
To simplify the remaining discussion, let us remove the FKL rapidity
ordering
\begin{equation}
\label{eq:remove_y_order}
\mathbf{T}_y \prod_{i=1}^n\int \frac{\mathrm{d}y_i}{2} =
\frac{1}{n!}\prod_{i=1}^n\int
\frac{\mathrm{d}y_i}{2}\,,
\end{equation}
where all rapidity integrals now cover a region which is approximately
bounded by $y_{j_b}$ and $y_{j_f}$. Each of the $m$ jets has to contain at least
one parton; selecting random emissions we can rewrite the phase space
integrals as
\begin{equation}
\label{eq:select_jets}
\frac{1}{n!}\prod_{i=1}^n\int [\mathrm{d}p_i] =
\left(\prod_{i=1}^{m}\int [\mathrm{d}p_i]\ {\cal J}_i(p_i)\right)
\frac{1}{n_g!}\prod_{i=m+1}^{m+n_g}\int [\mathrm{d}p_i]
\end{equation}
with jet selection functions
\begin{equation}
\label{eq:def_jet_selection}
{\cal J}_i(p) =
\begin{cases}
1 &p\text{ clustered into jet }i\\
0 & \text{otherwise}
\end{cases}
\end{equation}
and $n_g \equiv n - m$. Here and in the following we use the short-hand
notation $[\mathrm{d}p_i]$ to denote the phase-space measure for parton
$i$. As is evident from eq.~\eqref{eq:select_jets}, adding an extra emission
$n_g+1$ introduces a suppression factor $\tfrac{1}{n_g+1}$. However, the
additional phase space integral also results in an enhancement proportional
to $\Delta y_{j_f j_b} = y_{j_f} - y_{j_b}$. This is a result of the
rapidity-independence of the MRK limit of the integrand, consisting of the
matrix elements divided by the flux factor. Indeed, we observe that the
typical number of gluon emissions is to a good approximation proportional to
the rapidity separation and the phase space integral is dominated by events
with $n_g \approx \Delta y_{j_f j_b}$.
For the actual phase space sampling, we assume a Poisson distribution
and extract the mean number of gluon emissions in different rapidity
bins and fit the results to a linear function in $\Delta y_{j_f j_b}$,
finding a coefficient of $0.975$ for the inclusive production of a Higgs
boson with two jets. Here are the observed and fitted average gluon
multiplicities as a function of $\Delta y_{j_f j_b}$:
\begin{center}
\includegraphics[width=.75\textwidth]{ng_mean}
\end{center}
As shown for two rapidity slices the assumption of a Poisson
distribution is also a good approximation:
\begin{center}
\includegraphics[width=.49\textwidth]{{ng_1.5}.pdf}\hfill
\includegraphics[width=.49\textwidth]{{ng_5.5}.pdf}
\end{center}
\subsubsection{Number of Gluons inside Jets}
\label{sec:psp_ng_jet}
For each of the $n_g$ gluon emissions we can split the phase-space
integral into a (disconnected) region inside the jets and a remainder:
\begin{equation}
\label{eq:psp_split}
\int [\mathrm{d}p_i] = \int [\mathrm{d}p_i]\,
\theta\bigg(\sum_{j=1}^{m}{\cal J}_j(p_i)\bigg) + \int [\mathrm{d}p_i]\,
\bigg[1-\theta\bigg(\sum_{j=1}^{m}{\cal J}_j(p_i)\bigg)\bigg]\,.
\end{equation}
The next step is to decide how many of the gluons will form part of a
jet. This is done in the \lstinline!PhaseSpacePoint::sample_ng_jets!
function.
We choose an importance sampling which is flat in the plane
spanned by the azimuthal angle $\phi$ and the rapidity $y$. This is
observed in BFKL and valid in the limit of Multi-Regge-Kinematics
(MRK). Furthermore, we assume anti-$k_t$ jets, which cover an area of
$\pi R^2$.
In principle, the total accessible area in the $y$-$\phi$ plane is given
by $2\pi \Delta y_{fb}$, where $\Delta y_{fb}\geq \Delta y_{j_f j_b}$ is
the a priori unknown rapidity separation between the most forward and
backward partons. In most cases the extremal jets consist of single
partons, so that $\Delta y_{fb} = \Delta y_{j_f j_b}$. For the less common
case of two partons forming a jet we observe a maximum distance of $R$
between the constituents and the jet centre. In rare cases jets have
more than two constituents. Empirically, they are always within a
distance of $\tfrac{5}{3}R$ to the centre of the jet, so
$\Delta y_{fb} \leq \Delta y_{j_f j_b} + \tfrac{10}{3} R$. In practice, the
extremal partons are required to carry a large fraction of the jet
transverse momentum and will therefore be much closer to the jet axis.
In summary, for sufficiently large rapidity separations we can use the
approximation $\Delta y_{fb} \approx \Delta y_{j_f j_b}$. This scenario
is depicted here:
\begin{center}
\includegraphics[width=0.5\linewidth]{ps_large_y}
\end{center}
If there is no overlap between jets, the probability $p_{\cal J, >}$ for
an extra gluon to end up inside a jet is then given by
\begin{equation}
\label{eq:p_J_large}
p_{\cal J, >} = \frac{(m - 1)\*R^2}{2\Delta y_{j_f j_b}}\,.
\end{equation}
For a very small rapidity separation, eq.~\eqref{eq:p_J_large}
obviously overestimates the true probability. The maximum phase space
covered by jets in the limit of a vanishing rapidity distance between
all partons is $2mR \Delta y_{fb}$:
\begin{center}
\includegraphics[width=0.5\linewidth]{ps_small_y}
\end{center}
We therefore estimate the probability for a parton to end up inside a jet as
\begin{equation}
\label{eq:p_J}
p_{\cal J} = \min\bigg(\frac{(m - 1)\*R^2}{2\Delta y_{j_f j_b}}, \frac{mR}{\pi}\bigg)\,.
\end{equation}
Here we compare this estimate with the actually observed
fraction of additional emissions into jets as a function of the rapidity
separation:
\begin{center}
\includegraphics[width=0.75\linewidth]{pJ}
\end{center}
\subsubsection{Gluons outside Jets}
\label{sec:gluons_nonjet}
Using our estimate for the probability of a gluon to be a jet
constituent, we choose a number $n_{g,{\cal J}}$ of gluons inside
jets, which also fixes the number $n_g - n_{g,{\cal J}}$ of gluons
outside jets. As explained later on, we need to generate the momenta of
the gluons outside jets first. This is done in
\lstinline!PhaseSpacePoint::gen_non_jet!.
The azimuthal angle $\phi$ is generated flat within $0\leq \phi \leq 2
\pi$. The allowed rapidity interval is set by the most forward and
backward partons, which are necessarily inside jets. Since these parton
rapidities are not known at this point, we also have to postpone the
rapidity generation for the gluons outside jets. For the scalar
transverse momentum $p_\perp = |\mathbf{p}_\perp|$ of a gluon outside
jets we use the parametrisation
\begin{equation}
\label{eq:p_nonjet}
p_\perp = \lambda + \tilde{p}_\perp\*\tan(\tau\*r)\,, \qquad
\tau = \arctan\bigg(\frac{p_{\perp{\cal J}_\text{min}} - \lambda}{\tilde{p}_\perp}\bigg)\,.
\end{equation}
For $r \in [0,1)$, $p_\perp$ is always less than the minimum momentum
$p_{\perp{\cal J}_\text{min}}$ required for a jet. $\tilde{p}_\perp$ is
a free parameter, a good empirical value is $\tilde{p}_\perp = [1.3 +
0.2\*(n_g - n_{g,\cal J})]\,$GeV
\subsubsection{Resummation jet momenta}
\label{sec:ptj_res}
On the one hand, each jet momentum is given by the sum of its
constituent momenta. On the other hand, the resummation jet momenta are
fixed by the constraints in line five of the master
equation~\eqref{eq:resumdijetFKLmatched2}. We therefore have to
calculate the resummation jet momenta from these constraints before
generating the momenta of the gluons inside jets. This is done in
\lstinline!PhaseSpacePoint::reshuffle! and in the free
\lstinline!resummation_jet_momenta! function (declared in \texttt{resummation\_jet.hh}).
The resummation jet momenta are determined by the $\delta$ functions in
line five of eq.~(\ref{eq:resumdijetFKLmatched2}). The rapidities are
fixed to the rapidities of the jets in the input fixed-order events, so
that the FKL ordering is guaranteed to be preserved.
In traditional \HEJ reshuffling the transverse momentum are given through
\begin{equation}
\label{eq:ptreassign_old}
\mathbf{p}^B_{\mathcal{J}_{l\perp}} = \mathbf{j}_{l\perp} \equiv \mathbf{p}_{\mathcal{J}_{l}\perp}
+ \mathbf{q}_\perp \,\frac{|\mathbf{p}_{\mathcal{J}_{l}\perp}|}{P_\perp},
\end{equation}
where $\mathbf{q}_\perp = \sum_{j=1}^n \mathbf{p}_{i\perp}
\bigg[1-\theta\bigg(\sum_{j=1}^{m}{\cal J}_j(p_i)\bigg)\bigg] $ is the
total transverse momentum of all partons \emph{outside} jets and
$P_\perp = \sum_{j=1}^m |\mathbf{p}_{\mathcal{J}_{j}\perp}|$. Since the
total transverse momentum of an event vanishes, we can also use
$\mathbf{q}_\perp = - \sum_{j=1}^m
\mathbf{p}_{\mathcal{J}_{j}\perp}$. Eq.~(\ref{eq:ptreassign}) is a
non-linear system of equations in the resummation jet momenta
$\mathbf{p}_{\mathcal{J}_{l}\perp}$. Hence we would have to solve
\begin{equation}
\label{eq:ptreassign_eq}
\mathbf{p}_{\mathcal{J}_{l}\perp}=\mathbf{j}^B_{l\perp} \equiv\mathbf{j}_{l\perp}^{-1}
\left(\mathbf{p}^B_{\mathcal{J}_{l\perp}}\right)
\end{equation}
numerically.
Since solving such a system is computationally expensive, we instead
change the reshuffling around to be linear in the resummation jet
momenta. Hence~\eqref{eq:ptreassign_eq} gets replaces by
\begin{equation}
\label{eq:ptreassign}
\mathbf{p}_{\mathcal{J}_{l\perp}} = \mathbf{j}^B_{l\perp} \equiv \mathbf{p}^B_{\mathcal{J}_{l}\perp}
- \mathbf{q}_\perp \,\frac{|\mathbf{p}^B_{\mathcal{J}_{l}\perp}|}{P^B_\perp},
\end{equation}
which is linear in the resummation momentum. Consequently the equivalent
of~\eqref{eq:ptreassign_old} is non-linear in the Born momentum. However
the exact form of~\eqref{eq:ptreassign_old} is not relevant for the resummation.
Both methods have been tested for two and three jets with the \textsc{rivet}
standard analysis \texttt{MC\_JETS}. They didn't show any differences even
after $10^9$ events.
The reshuffling relation~\eqref{eq:ptreassign} allows the transverse
momenta $p^B_{\mathcal{J}_{l\perp}}$ of the fixed-order jets to be
somewhat below the minimum transverse momentum of resummation jets. It
is crucial that this difference does not become too large, as the
fixed-order cross section diverges for vanishing transverse momenta. In
the production of a Higgs boson with resummation jets above $30\,$GeV we observe
that the contribution from fixed-order events with jets softer than
about $20\,$GeV can be safely neglected. This is shown in the following
plot of the differential cross section over the transverse momentum of
the softest fixed-order jet:
\begin{center}
\includegraphics[width=.75\textwidth]{ptBMin}
\end{center}
Finally, we have to account for the fact that the reshuffling
relation~\eqref{eq:ptreassign} is non-linear in the Born momenta. To
arrive at the master formula~\eqref{eq:resumdijetFKLmatched2} for the
cross section, we have introduced unity in the form of an integral over
the Born momenta with $\delta$ functions in the integrand, that is
\begin{equation}
\label{eq:delta_intro}
1 = \int_{p_{j\perp}^B=0}^{p_{j\perp}^B=\infty}
\mathrm{d}^2\mathbf{p}_{j\perp}^B\delta^{(2)}(\mathbf{p}_{\mathcal{J}_{j\perp}}^B -
\mathbf{j}_{j\perp})\,.
\end{equation}
If the arguments of the $\delta$ functions are not linear in the Born
momenta, we have to compensate with additional Jacobians as
factors. Explicitly, for the reshuffling relation~\eqref{eq:ptreassign}
we have
\begin{equation}
\label{eq:delta_rewrite}
\prod_{l=1}^m \delta^{(2)}(\mathbf{p}_{\mathcal{J}_{l\perp}}^B -
\mathbf{j}_{l\perp}) = \Delta \prod_{l=1}^m \delta^{(2)}(\mathbf{p}_{\mathcal{J}_{l\perp}} -
\mathbf{j}_{l\perp}^B)\,,
\end{equation}
where $\mathbf{j}_{l\perp}^B$ is given by~\eqref{eq:ptreassign_eq} and only
depends on the Born momenta. We have extended the product to run to $m$
instead of $m-1$ by eliminating the last $\delta$ function
$\delta^{(2)}\!\!\left(\sum_{k=1}^n \mathbf{p}_{k\perp}\right )$.
The Jacobian $\Delta$ is the determinant of a $2m \times 2m$ matrix with $l, l' = 1,\dots,m$
and $X, X' = x,y$.
\begin{equation}
\label{eq:jacobian}
\Delta = \left|\frac{\partial\,\mathbf{j}^B_{l'\perp}}{\partial\, \mathbf{p}^B_{{\cal J}_l \perp}} \right|
= \left| \delta_{l l'} \delta_{X X'} - \frac{q_X\, p^B_{{\cal
J}_{l'}X'}}{\left|\mathbf{p}^B_{{\cal J}_{l'} \perp}\right| P^B_\perp}\left(\delta_{l l'}
- \frac{\left|\mathbf{p}^B_{{\cal J}_l \perp}\right|}{P^B_\perp}\right)\right|\,.
\end{equation}
The determinant is calculated in \lstinline!resummation_jet_weight!,
again coming from the \texttt{resummation\_jet.hh} header.
Having to introduce this Jacobian is not a disadvantage specific to the new
reshuffling. If we instead use the old reshuffling
relation~\eqref{eq:ptreassign_old} we \emph{also} have to introduce a
similar Jacobian since we actually want to integrate over the
resummation phase space and need to transform the argument of the
$\delta$ function to be linear in the resummation momenta for this.
\subsubsection{Gluons inside Jets}
\label{sec:gluons_jet}
After the steps outlined in section~\ref{sec:psp_ng_jet}, we have a
total number of $m + n_{g,{\cal J}}$ constituents. In
\lstinline!PhaseSpacePoint::distribute_jet_partons! we distribute them
randomly among the jets such that each jet has at least one
constituent. We then generate their momenta in
\lstinline!PhaseSpacePoint::split! using the \lstinline!Splitter! class.
The phase space integral for a jet ${\cal J}$ is given by
\begin{equation}
\label{eq:ps_jetparton} \prod_{i\text{ in }{\cal J}} \bigg(\int
\mathrm{d}\mathbf{p}_{i\perp}\ \int \mathrm{d} y_i
\bigg)\delta^{(2)}\Big(\sum_{i\text{ in }{\cal J}} \mathbf{p}_{i\perp} -
\mathbf{j}_{\perp}^B\Big)\delta(y_{\mathcal{J}}-y^B_{\mathcal{J}})\,.
\end{equation}
For jets with a single constituent, the parton momentum is obiously equal to the
jet momentum. In the case of two constituents, we observe that the
partons are always inside the jet cone with radius $R$ and often very
close to the jet centre. The following plots show the typical relative
distance $\Delta R/R$ for this scenario:
\begin{center}
\includegraphics[width=0.45\linewidth]{dR_2}
\includegraphics[width=0.45\linewidth]{dR_2_small}
\end{center}
According to this preference for small values of $\Delta R$, we
parametrise the $\Delta R$ integrals as
\begin{equation}
\label{eq:dR_sampling}
\frac{\Delta R}{R} =
\begin{cases}
0.25\,x_R & x_R < 0.4 \\
1.5\,x_R - 0.5 & x_R \geq 0.4
\end{cases}\,.
\end{equation}
Next, we generate $\Theta_1 \equiv \Theta$ and use the constraint $\Theta_2 = \Theta
\pm \pi$. The transverse momentum of the first parton is then given by
\begin{equation}
\label{eq:delta_constraints}
p_{1\perp} =
\frac{p_{\mathcal{J} y} - \tan(\phi_2) p_{\mathcal{J} x}}{\sin(\phi_1)
- \tan(\phi_2)\cos(\phi_1)}\,.
\end{equation}
We get $p_{2\perp}$ by exchanging $1 \leftrightarrow 2$ in the
indices. To obtain the Jacobian of the transformation, we start from the
single jet phase space eq.~(\ref{eq:ps_jetparton}) with the rapidity
delta function already rewritten to be linear in the rapidity of the
last parton, i.e.
\begin{equation}
\label{eq:jet_2p}
\prod_{i=1,2} \bigg(\int
\mathrm{d}\mathbf{p}_{i\perp}\ \int \mathrm{d} y_i
\bigg)\delta^{(2)}\Big(\mathbf{p}_{1\perp} + \mathbf{p}_{2\perp} -
\mathbf{j}_{\perp}^B\Big)\delta(y_2- \dots)\,.
\end{equation}
The integral over the second parton momentum is now trivial; we can just replace
the integral over $y_2$ with the equivalent constraint
\begin{equation}
\label{eq:R2}
\int \mathrm{d}R_2 \ \delta\bigg(R_2 - \bigg[\phi_{\cal J} - \arctan
\bigg(\frac{p_{{\cal J}y} - p_{1y}}{p_{{\cal J}x} -
p_{1x}}\bigg)\bigg]/\cos \Theta\bigg) \,.
\end{equation}
In order to fix the integral over $p_{1\perp}$ instead, we rewrite this
$\delta$ function. This introduces the Jacobian
\begin{equation}
\label{eq:jac_pt1}
\bigg|\frac{\partial p_{1\perp}}{\partial R_2} \bigg| =
\frac{\cos(\Theta)\mathbf{p}_{2\perp}^2}{p_{{\cal J}\perp}\sin(\phi_{\cal J}-\phi_1)}\,.
\end{equation}
The final form of the integral over the two parton momenta is then
\begin{equation}
\label{eq:ps_jet_2p}
\int \mathrm{d}R_1\ R_1 \int \mathrm{d}R_2 \int \mathrm{d}x_\Theta\ 2\pi \int
\mathrm{d}p_{1\perp}\ p_{1\perp} \int \mathrm{d}p_{2\perp}
\ \bigg|\frac{\partial p_{1\perp}}{\partial R_2} \bigg|\delta(p_{1\perp}
-\dots) \delta(p_{2\perp} - \dots)\,.
\end{equation}
As is evident from section~\ref{sec:psp_ng_jet}, jets with three or more
constituents are rare and an efficient phase-space sampling is less
important. For such jets, we exploit the observation that partons with a
distance larger than $R_{\text{max}} = \tfrac{5}{3} R$ to
the jet centre are never clustered into the jet. Assuming $N$
constituents, we generate all components
for the first $N-1$ partons and fix the remaining parton with the
$\delta$-functional. In order to end up inside the jet, we use the
parametrisation
\begin{align}
\label{eq:ps_jet_param}
\phi_i ={}& \phi_{\cal J} + \Delta \phi_i\,, & \Delta \phi_i ={}& \Delta
R_i
\cos(\Theta_i)\,, \\
y_i ={}& y_{\cal J} + \Delta y_i\,, & \Delta y_i ={}& \Delta
R_i
\sin(\Theta_i)\,,
\end{align}
and generate $\Theta_i$ and $\Delta R_i$ randomly with $\Delta R_i \leq
R_{\text{max}}$ and the empiric value $R_{\text{max}} = 5\*R/3$. We can
then write the phase space integral for a single parton as $(p_\perp = |\mathbf{p}_\perp|)$
\begin{equation}
\label{eq:ps_jetparton_x}
\int \mathrm{d}\mathbf{p}_{\perp}\ \int
\mathrm{d} y \approx \int_{\Box} \mathrm{d}x_{\perp}
\mathrm{d}x_{ R}
\mathrm{d}x_{\theta}\
2\*\pi\,\*R_{\text{max}}^2\,\*x_{R}\,\*p_{\perp}\,\*(p_{\perp,\text{max}}
- p_{\perp,\text{min}})
\end{equation}
with
\begin{align}
\label{eq:ps_jetparton_parameters}
\Delta \phi ={}& R_{\text{max}}\*x_{R}\*\cos(2\*\pi\*x_\theta)\,,&
\Delta y ={}& R_{\text{max}}\*x_{R}\*\sin(2\*\pi\*x_\theta)\,, \\
p_{\perp} ={}& (p_{\perp,\text{max}} - p_{\perp,\text{min}})\*x_\perp +
p_{\perp,\text{min}}\,.
\end{align}
$p_{\perp,\text{max}}$ is determined from the requirement that the total
contribution from the first $n-1$ partons --- i.e. the projection onto the
jet $p_{\perp}$ axis --- must never exceed the jet $p_\perp$. This gives
\todo{This bound is too high}
\begin{equation}
\label{eq:pt_max}
p_{i\perp,\text{max}} = \frac{p_{{\cal J}\perp} - \sum_{j<i} p_{j\perp}
\cos \Delta
\phi_j}{\cos \Delta
\phi_i}\,.
\end{equation}
The $x$ and $y$ components of the last parton follow immediately from
the first $\delta$ function. The last rapidity is fixed by the condition that
the jet rapidity is kept fixed by the reshuffling, i.e.
\begin{equation}
\label{eq:yJ_delta}
y^B_{\cal J} = y_{\cal J} = \frac 1 2 \ln \frac{\sum_{i=1}^n E_i+ p_{iz}}{\sum_{i=1}^n E_i - p_{iz}}\,.
\end{equation}
With $E_n \pm p_{nz} = p_{n\perp}\exp(\pm y_n)$ this can be rewritten to
\begin{equation}
\label{eq:yn_quad_eq}
\exp(2y_{\cal J}) = \frac{\sum_{i=1}^{n-1} E_i+ p_{iz}+p_{n\perp} \exp(y_n)}{\sum_{i=1}^{n-1} E_i - p_{iz}+p_{n\perp} \exp(-y_n)}\,,
\end{equation}
which is a quadratic equation in $\exp(y_n)$. The physical solution is
\begin{align}
\label{eq:yn}
y_n ={}& \log\Big(-b + \sqrt{b^2 + \exp(2y_{\cal J})}\,\Big)\,,\\
b ={}& \bigg(\sum_{i=1}^{n-1} E_i + p_{iz} - \exp(2y_{\cal J})
\sum_{i=1}^{n-1} E_i - p_{iz}\bigg)/(2 p_{n\perp})\,.
\end{align}
\todo{what's wrong with the following?} To eliminate the remaining rapidity
integral, we transform the $\delta$ function to be linear in the
rapidity $y$ of the last parton. The corresponding Jacobian is
\begin{equation}
\label{eq:jacobian_y}
\bigg|\frac{\partial y_{\cal J}}{\partial y_n}\bigg|^{-1} = 2 \bigg( \frac{E_n +
p_{nz}}{E_{\cal J} + p_{{\cal J}z}} + \frac{E_n - p_{nz}}{E_{\cal J} -
p_{{\cal J}z}}\bigg)^{-1}\,.
\end{equation}
Finally, we check that all designated constituents are actually
clustered into the considered jet.
\subsubsection{Final steps}
\label{sec:final}
Knowing the rapidity span covered by the extremal partons, we can now
generate the rapdities for the partons outside jets. We perform jet
clustering on all partons and check in
\lstinline!PhaseSpacePoint::jets_ok! that all the following criteria are
fulfilled:
\begin{itemize}
\item The number of resummation jets must match the number of
fixed-order jets.
\item No partons designated to be outside jets may end up inside jets.
\item All other outgoing partons \emph{must} end up inside jets.
\item The extremal (in rapidity) partons must be inside the extremal
jets. If there is, for example, an unordered forward emission, the
most forward parton must end up inside the most forward jet and the
next parton must end up inside second jet.
\item The rapidities of fixed-order and resummation jets must match.
\end{itemize}
After this, we adjust the phase-space normalisation according to the
third line of eq.~(\ref{eq:resumdijetFKLmatched2}), determine the
flavours of the outgoing partons, and adopt any additional colourless
bosons from the fixed-order input event. Finally, we use momentum
conservation to reconstruct the momenta of the incoming partons.
\subsection{Colour connection}
\label{sec:Colour}
\begin{figure}
\input{src/ColourConnect.tex}
\caption{Left: Non-crossing colour flow dominating in the MRK limit. The
crossing of the colour line connecting to particle 2 can be resolved by
writing particle 2 on the left. Right: A colour flow with a (manifest)
colour-crossing. The crossing can only be resolved if one breaks the
rapidities order, e.g. switching particles 2 and 3. From~\cite{Andersen:2017sht}.}
\label{fig:Colour_crossing}
\end{figure}
After the phase space for the resummation event is generated, we can construct
the colour for each particle. To generate the colour flow one has to call
\lstinline!Event::generate_colours! on any \HEJ configuration. For non-\HEJ
event we do not change the colour, and assume it is provided by the user (e.g.
through the LHE file input). The colour connection is done in the large $N_c$
(infinite number of colour) limit with leading colour in
MRK~\cite{Andersen:2008ue, Andersen:2017sht}. The idea is to allow only
$t$-channel colour exchange, without any crossing colour lines. For example the
colour crossing in the colour connection on the left of
figure~\ref{fig:Colour_crossing} can be resolved by switching \textit{particle
2} to the left.
We can write down the colour connections by following the colour flow from
\textit{gluon a} to \textit{gluon b} and back to \textit{gluon a}, e.g.
figure~\ref{fig:Colour_gleft} corresponds to $a123ba$. In such an expression any
valid, non-crossing colour flow will connect all external legs while respecting
the rapidity ordering. Thus configurations like the left of
figure~\ref{fig:Colour_crossing} are allowed ($a134b2a$), but the right of the
same figures breaks the rapidity ordering between 2 and 3 ($a1324ba$). Note that
connections between $b$ and $a$ are in inverse order, e.g. $ab321a$ corresponds to~\ref{fig:Colour_gright} ($a123ba$) just with colour and anti-colour swapped.
\begin{figure}
\centering
\subcaptionbox{$a123ba$\label{fig:Colour_gright}}{
\includegraphics[height=0.25\textwidth]{figures/colour_gright.jpg}}
\subcaptionbox{$a13b2a$\label{fig:Colour_gleft}}{
\includegraphics[height=0.25\textwidth]{figures/colour_gleft.jpg}}
\subcaptionbox{$a\_123ba$\label{fig:Colour_qx}}{
\includegraphics[height=0.25\textwidth]{figures/colour_qx.jpg}}
\subcaptionbox{$a\_23b1a$\label{fig:Colour_uno}}{
\includegraphics[height=0.25\textwidth]{figures/colour_uno.jpg}}
\subcaptionbox{$a14b3\_2a$\label{fig:Colour_qqx}}{
\includegraphics[height=0.25\textwidth]{figures/colour_centralqqx.jpg}}
\caption{Different colour non-crossing colour connections. Both incoming
particles are drawn at the top or bottom and the outgoing left or right.
The Feynman diagram is shown in black and the colour flow in blue.}
%TODO Maybe make these plots nicer (in Latex/asy)
\end{figure}
If we replace two gluons with a quark, (anti-)quark pair we break one of the
colour connections. Still the basic concept from before holds, we just have to
treat the connection between two (anti-)quarks like an unmovable (anti-)colour.
We denote such a connection by a underscore (e.g. $1\_a$). For example the
equivalent of~\ref{fig:Colour_gright} ($a123ba$) with an incoming antiquark
is~\ref{fig:Colour_qx} ($a\_123ba$). As said this also holds for other
subleading configurations like unordered emission~\ref{fig:Colour_uno} or
central quark-antiquark pairs~\ref{fig:Colour_qqx} \footnote{Obviously this can
not be guaranteed for non-\HEJ configurations, e.g. $qQ\to Qq$ requires a
$u$-channel exchange.}.
Some rapidity ordering can have multiple possible colour connections,
e.g.~\ref{fig:Colour_gright} and~\ref{fig:Colour_gleft}. This is always the case
if a gluon radiates off a gluon line. In that case we randomly connect the gluon
to either the colour or anti-colour. Thus in the generation we keep track
whether we are on a quark or gluon line, and act accordingly.
\subsection{The matrix element }
\label{sec:ME}
The derivation of the \HEJ matrix element is explained in some detail
in~\cite{Andersen:2017kfc}, where also results for leading and
subleading matrix elements for pure multijet production and production
of a Higgs boson with at least two associated jets are listed. Matrix
elements for $W$ and $Z/\gamma^*$ production together with jets are
given in~\cite{Andersen:2012gk,Andersen:2016vkp}, but not yet included.
The matrix elements are implemented in the \lstinline!MatrixElement!
class. To discuss the structure, let us consider the squared matrix
element for FKL multijet production with $n$ final-state partons:
\begin{align}
\label{eq:ME}
\begin{split}
\overline{\left|\mathcal{M}_\text{HEJ}^{f_1 f_2 \to f_1
g\cdots g f_2}\right|}^2 = \ &\frac {(4\pi\alpha_s)^n} {4\ (N_c^2-1)}
\cdot\ \textcolor{blue}{\frac {K_{f_1}(p_1^-, p_a^-)} {t_1}\ \cdot\ \frac{K_{f_2}(p_n^+, p_b^+)}{t_{n-1}}\ \cdot\ \left\|S_{f_1 f_2\to f_1 f_2}\right\|^2}\\
& \cdot \prod_{i=1}^{n-2} \textcolor{gray}{\left( \frac{-C_A}{t_it_{i+1}}\
V^\mu(q_i,q_{i+1})V_\mu(q_i,q_{i+1}) \right)}\\
& \cdot \prod_{j=1}^{n-1} \textcolor{red}{\exp\left[\omega^0(q_{j\perp})(y_{j+1}-y_j)\right]}.
\end{split}
\end{align}
The structure and momentum assignment of the unsquared matrix element is
as illustrated here:
\begin{center}
\includegraphics{HEJ_amplitude}
\end{center}
The square
-of the complete matrix element as given in eq.~(\ref{eq:ME}) is
+of the complete matrix element as given in eq.~\eqref{eq:ME} is
calculated by \lstinline!MatrixElement::operator()!. The \textcolor{red}{last line} of
eq.~\eqref{eq:ME} constitutes the all-order virtual correction,
implemented in
\lstinline!MatrixElement::virtual_corrections!.
$\omega^0$ is the
\textit{regularised Regge trajectory}
\begin{equation}
\label{eq:omega_0}
\omega^0(q_\perp) = - C_A \frac{\alpha_s}{\pi} \log \left(\frac{q_\perp^2}{\lambda^2}\right)\,,
\end{equation}
where $\lambda$ is the slicing parameter limiting the softness of real
-gluon emissions, cf. eq.~(\ref{eq:resumdijetFKLmatched2}).
+gluon emissions, cf. eq.~\eqref{eq:resumdijetFKLmatched2}. $\lambda$ can be
+changed at runtime by setting \lstinline!regulator parameter! in
+\lstinline!conifg.yml!.
The remaining parts, which correspond to the square of the leading-order
HEJ matrix element $\overline{\left|\mathcal{M}_\text{LO,
HEJ}^{f_1f_2\to f_1g\cdots
gf_2}\big(\big\{p^B_j\big\}\big)\right|}^{2}$, are computed in
\lstinline!MatrixElement::tree!. We can further factor off the
scale-dependent ``parametric'' part
\lstinline!MatrixElement::tree_param! containing all factors of the
strong coupling $4\pi\alpha_s$. Using this function saves some CPU time
when adjusting the renormalisation scale, see
section~\ref{sec:resum}. The remaining ``kinematic'' factors are
calculated in \lstinline!MatrixElement::kin!.
\subsubsection{Matrix elements for Higgs plus dijet}
\label{sec:ME_h_jets}
In the production of a Higgs boson together with jets the parametric
parts and the virtual corrections only require minor changes in the
respective functions. However, in the ``kinematic'' parts we have to
distinguish between several cases, which is done in
\lstinline!MatrixElement::tree_kin_Higgs!. The Higgs boson can be
\emph{central}, i.e. inside the rapidity range spanned by the extremal
partons (\lstinline!MatrixElement::tree_kin_Higgs_central!) or
\emph{peripheral} and outside this range
(\lstinline!MatrixElement::tree_kin_Higgs_first! or
\lstinline!MatrixElement::tree_kin_Higgs_last!). In case there is also
an unordered gluon emission the matrix element is already suppressed by one
logarithm $\log(s/t)$. Therefore at NLL the Higgs boson can only be emitted
centrally\footnote{In principle emitting a Higgs boson \textit{on the other
side} of the unordered gluon is possible by contracting an unordered and
external Higgs current. Obviously this would not cover all possible
configurations, e.g. $qQ\to HgqQ$ requires contraction of the standard $Q\to Q$
current with an (unknown) $q\to Hgq$ one.}.
If a Higgs boson with momentum $p_H$ is emitted centrally, after parton
$j$ in rapidity, the matrix element reads
\begin{equation}
\label{eq:ME_h_jets_central}
\begin{split}
\overline{\left|\mathcal{M}_\text{HEJ}^{f_1 f_2 \to f_1 g\cdot H
\cdot g f_2}\right|}^2 = \ &\frac {\alpha_s^2 (4\pi\alpha_s)^n} {4\ (N_c^2-1)}
\cdot\ \textcolor{blue}{\frac {K_{f_1}(p_1^-, p_a^-)} {t_1}\
\cdot\ \frac{1}{t_j t_{j+1}} \cdot\ \frac{K_{f_2}(p_n^+, p_b^+)}{t_{n}}\ \cdot\ \left\|S_{f_1
f_2\to f_1 H f_2}\right\|^2}\\
& \cdot \prod_{\substack{i=1\\i \neq j}}^{n-1} \textcolor{gray}{\left( \frac{-C_A}{t_it_{i+1}}\
V^\mu(q_i,q_{i+1})V_\mu(q_i,q_{i+1}) \right)}\\
& \cdot \textcolor{red}{\prod_{i=1}^{n-1}
\exp\left[\omega^0(q_{i\perp})\Delta y_i\right]}
\end{split}
\end{equation}
with the momentum definitions
\begin{center}
\includegraphics{HEJ_central_Higgs_amplitude}
\end{center}
$q_i$ is the $i$th $t$-channel momentum and $\Delta y_i$ the rapidity
gap between outgoing \emph{particles} (not partons) $i$ and $i+1$ in
rapidity ordering.
For \emph{peripheral} emission in the backward direction
(\lstinline!MatrixElement::tree_kin_Higgs_first!) we first check whether
the most backward parton is a gluon or an (anti-)quark. In the latter
case the leading contribution to the matrix element arises through
emission off the $t$-channel gluons and we can use the same formula
eq.~(\ref{eq:ME_h_jets_central}) as for central emission. If the most
backward parton is a gluon, the square of the matrix element can be
written as
\begin{equation}
\label{eq:ME_h_jets_peripheral}
\begin{split}
\overline{\left|\mathcal{M}_\text{HEJ}^{g f_2 \to H g\cdot g f_2}\right|}^2 = \ &\frac {\alpha_s^2 (4\pi\alpha_s)^n} {\textcolor{blue}{4\ (N_c^2-1)}}
\textcolor{blue}{\cdot\ K_{H}\
\frac{K_{f_2}(p_n^+, p_b^+)}{t_{n-1}}\ \cdot\ \left\|S_{g
f_2\to H g f_2}\right\|^2}\\
& \cdot \prod_{\substack{i=1}}^{n-2} \textcolor{gray}{\left( \frac{-C_A}{t_it_{i+1}}\
V^\mu(q_i,q_{i+1})V_\mu(q_i,q_{i+1}) \right)}\\
& \cdot \textcolor{red}{\prod_{i=1}^{n-1}
\exp\left[\omega^0(q_{i\perp}) (y_{i+1} - y_i)\right]}
\end{split}
\end{equation}
with the momenta as follows:
\begin{center}
\includegraphics{HEJ_peripheral_Higgs_amplitude}
\end{center}
The \textcolor{blue}{blue part} is implemented in
\lstinline!MatrixElement::MH2_forwardH!. All other building blocks are
already available.\todo{Impact factors} The actual current contraction
is calculated in \lstinline!MH2gq_outsideH! inside
\lstinline!currents.cc!, which corresponds to $\tfrac{16 \pi^2}{t_1} \left\|S_{g
f_2\to H g f_2}\right\|^2$.\todo{Fix this insane normalisation}
The forward emission of a Higgs boson is completely analogous. We can
use the same function \lstinline!MatrixElement::MH2_forwardH!, swapping
$p_1 \leftrightarrow p_n,\,p_a \leftrightarrow p_b$.
\subsubsection{FKL ladder and Lipatov vertices}
\label{sec:FKL_ladder}
The ``FKL ladder'' is the product
\begin{equation}
\label{eq:FKL_ladder}
\prod_{i=1}^{n-2} \left( \frac{-C_A}{t_it_{i+1}}\
V^\mu(q_i,q_{i+1})V_\mu(q_i,q_{i+1}) \right)
\end{equation}
appearing in the square of the matrix element for $n$ parton production,
cf. eq.~(\ref{eq:ME}), and implemented in
\lstinline!MatrixElement::FKL_ladder_weight!. The Lipatov vertex contraction
$V^\mu(q_i,q_{i+1})V_\mu(q_i,q_{i+1})$ is implemented \lstinline!C2Lipatovots!.
It is given by \todo{equation} \todo{mention difference between the two versions
of \lstinline!C2Lipatovots!, maybe even get rid of one}.
\subsubsection{Currents}
\label{sec:currents}
The current factors $\frac{K_{f_1}K_{f_2}}{t_1 t_{n-1}}\left\|S_{f_1
f_2\to f_1 f_2}\right\|^2$ and their extensions for unordered and Higgs
boson emissions are implemented in the \lstinline!jM2!$\dots$ functions
of \texttt{src/currents.cc}. \todo{Only $\|S\|^2$ should be in currents}
\footnote{The current implementation for
Higgs production in \texttt{src/currents.cc} includes the $1/4$ factor
inside $S$, opposing to~\eqref{eq:ME}. Thus the overall normalisation is
unaffected.} The ``colour acceleration multiplier'' (CAM) $K_{f}$
for a parton $f\in\{g,q,\bar{q}\}$ is defined as
\begin{align}
\label{eq:K_g}
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}\\
\label{eq:K_q}
K_q(p_1^-, p_a^-) ={}&K_{\bar{q}}(p_1^-, p_a^-) = C_F\,.
\end{align}
The Higgs current CAM used in eq.~(\ref{eq:ME_h_jets_peripheral}) is
\begin{equation}
\label{eq:K_H}
K_H = C_A\,.
\end{equation}
The current contractions are given by\todo{check all this
carefully!}
\begin{align}
\label{eq:S}
\left\|S_{f_1 f_2\to f_1 f_2}\right\|^2 ={}& \sum_{\substack{\lambda_a =
+,-\\\lambda_b = +,-}} \left|j^{\lambda_a}_\mu(p_1, p_a)\
j^{\lambda_b\,\mu}(p_n, p_b)\right|^2 = 2\sum_{\lambda =
+,-} \left|j^{-}_\mu(p_1, p_a)\ j^{\lambda\,\mu}(p_n, p_b)\right|^2\,,\\
\left\|S_{f_1 f_2\to f_1 H f_2}\right\|^2 ={}& \sum_{\substack{\lambda_a =
+,-\\\lambda_b = +,-}} \left|j^{\lambda_a}_\mu(p_1, p_a)V_H^{\mu\nu}(q_j, q_{j+1})\
j^{\lambda_b}_\nu(p_n, p_b)\right|^2\,,\\
\left\|S_{g f_2 \to H g f_2}\right\|^2 ={}& \sum_{
\substack{
\lambda_{a} = +,-\\
\lambda_{1} =+,-\\
\lambda_{b} = +,-
}}
\left|j^{\lambda_a\lambda_1}_{H\,\mu}(p_1, p_a, p_H)\ j^{\lambda_b\,\mu}(p_n, p_b)\right|^2\,.
\end{align}
The ``basic'' currents $j$ are independent of the parton flavour and read
\begin{equation}
\label{eq:j}
j^\pm_\mu(p, q) = u^{\pm,\dagger}(p)\ \sigma^\pm_\mu\ u^{\pm}(q)\,,
\end{equation}
where $\sigma_\mu^\pm = (1, \pm \sigma_i)$ and $\sigma_i$ are the Pauli
matrices
\begin{equation}
\label{eq:Pauli_matrices}
\sigma_1 =
\begin{pmatrix}
0 & 1\\ 1 & 0
\end{pmatrix}
\,,
\qquad \sigma_2 =
\begin{pmatrix}
0 & -i\\ i & 0
\end{pmatrix}
\,,
\qquad \sigma_3 =
\begin{pmatrix}
1 & 0\\ 0 & -1
\end{pmatrix}
\,.
\end{equation}
The two-component chiral spinors are given by
\begin{align}
\label{eq:u_plus}
u^+(p)={}& \left(\sqrt{p^+}, \sqrt{p^-} \hat{p}_\perp \right) \,,\\
\label{eq:u_minus}
u^-(p)={}& \left(\sqrt{p^-} \hat{p}^*_\perp, -\sqrt{p^+}\right)\,,
\end{align}
with $p^\pm = E\pm p_z,\, \hat{p}_\perp = \tfrac{p_\perp}{|p_\perp|},\,
p_\perp = p_x + i p_y$. The spinors for vanishing transverse momentum
are obtained by replacing $\hat{p_\perp} \to -1$.
Explicitly, the currents read
\begin{align}
\label{eq:j-_explicit}
j^-_\mu(p, q) ={}&
\begin{pmatrix}
\sqrt{p^+\,q^+} + \sqrt{p^-\,q^-} \hat{p}_{\perp} \hat{q}_{\perp}^*\\
\sqrt{p^-\,q^+}\, \hat{p}_{\perp} + \sqrt{p^+\,q^-}\,\hat{q}_{\perp}^*\\
-i \sqrt{p^-\,q^+}\, \hat{p}_{\perp} + i \sqrt{p^+\,q^-}\, \hat{q}_{\perp}^*\\
\sqrt{p^+\,q^+} - \sqrt{p^-\,q^-}\, \hat{p}_{\perp}\, \hat{q}_{\perp}^*
\end{pmatrix}\\
j^+_\mu(p, q) ={}&\big(j^-_\mu(p, q)\big)^*
\end{align}
If $q= p_{\text{in}}$ is the momentum of an incoming parton, we have
$\hat{p}_{\text{in} \perp} = -1$ and either $p_{\text{in}}^+ = 0$ or
$p_{\text{in}}^- = 0$. The current simplifies further:\todo{Helicities flipped w.r.t code}
\begin{align}
\label{eq:j_explicit}
j^-_\mu(p_{\text{out}}, p_{\text{in}}) ={}&
\begin{pmatrix}
\sqrt{p_{\text{in}}^+\,p_{\text{out}}^+}\\
\sqrt{p_{\text{in}}^+\,p_{\text{out}}^-} \ \hat{p}_{\text{out}\,\perp}\\
-i\,j^-_1\\
j^-_0
\end{pmatrix}
& p_{\text{in}\,z} > 0\,,\\
j^-_\mu(p_{\text{out}}, p_{\text{in}}) ={}&
\begin{pmatrix}
-\sqrt{p_{\text{in}}^-\,p_{\text{out}}^{-\phantom{+}}} \ \hat{p}_{\text{out}\,\perp}\\
- \sqrt{p_{\text{in}}^-\,p_{\text{out}}^+}\\
i\,j^-_1\\
-j^-_0
\end{pmatrix} & p_{\text{in}\,z} < 0\,.
\end{align}
\section{The fixed-order generator}
\label{sec:HEJFOG}
Even at leading order, standard fixed-order generators can only generate
events with a limited number of final-state particles within reasonable
CPU time. The purpose of the fixed-order generator is to supplement this
with high-multiplicity input events according to the first two lines of
eq.~\eqref{eq:resumdijetFKLmatched2} with the \HEJ approximation
$\mathcal{M}_\text{LO, HEJ}^{f_1f_2\to f_1g\cdots gf_2}$ instead of the
full fixed-order matrix element $\mathcal{M}_\text{LO}^{f_1f_2\to
f_1g\cdots gf_2}$. Its usage is described in the user
documentation \url{https://hej.web.cern.ch/HEJ/doc/current/user/HEJFOG.html}.
\subsection{File structure}
\label{sec:HEJFOG_structure}
The code for the fixed-order generator is in the \texttt{FixedOrderGen}
directory, which contains the following:
\begin{description}
\item[include:] Contains the C++ header files.
\item[src:] Contains the C++ source files.
\item[t:] Contains the source code for the automated tests.
\item[CMakeLists.txt:] Configuration file for the \cmake build system.
\item[configFO.yml:] Sample configuration file for the fixed-order generator.
\end{description}
The code is generally in the \lstinline!HEJFOG! namespace. Functions and
classes \lstinline!MyClass! are usually declared in
\texttt{include/MyClass.hh} and implemented in \texttt{src/MyClass.cc}.
\subsection{Program flow}
\label{sec:prog_flow}
A single run of the fixed-order generator consists of three or four
stages.
First, we perform initialisation similar to HEJ 2, see
section~\ref{sec:init}. Since there is a lot of overlap we frequently
reuse classes and functions from HEJ 2, i.e. from the
\lstinline!HEJ! namespace. The code for parsing the configuration file
is in \texttt{include/config.hh} and implemented in
\texttt{src/config.cc}.
If partial unweighting is requested in the user settings \url{https://hej.web.cern.ch/HEJ/doc/current/user/HEJFOG.html#settings},
the initialisation is followed by a calibration phase. We use a
\lstinline!EventGenerator! to produce a number of trial
events. We use these to calibrate the \lstinline!Unweighter! in
its constructor and produce a first batch of partially unweighted
events. This also allows us to estimate our unweighting efficiency.
In the next step, we continue to generate events and potentially
unweight them. Once the user-defined target number of events is reached,
we adjust their weights according to the number of required trials. As
in HEJ 2 (see section~\ref{sec:processing}), we pass the final
events to a \lstinline!HEJ::Analysis! and a
\lstinline!HEJ::CombinedEventWriter!.
\subsection{Event generation}
\label{sec:evgen}
Event generation is performed by the
\lstinline!EventGenerator::gen_event! member function. We begin by generating a
\lstinline!PhaseSpacePoint!. This is not to be confused with
the resummation phase space points represented by
\lstinline!HEJ::PhaseSpacePoint!! After jet clustering, we compute the
leading-order matrix element (see section~\ref{sec:ME}) and pdf factors.
The phase space point generation is performed in the
\lstinline!PhaseSpacePoint! constructor. We first construct the
user-defined number of $n_p$ partons (by default gluons) in
\lstinline!PhaseSpacePoint::gen_LO_partons!. We use flat sampling in
rapidity and azimuthal angle. For the scalar transverse momenta, we
distinguish between two cases. By default, they are generated based on a
random variable $x_{p_\perp}$ according to
\begin{equation}
\label{eq:pt_sampling}
p_\perp = p_{\perp,\text{min}} +
\begin{cases}
p_{\perp,\text{par}}
\tan\left(
x_{p_\perp}
\arctan\left(
\frac{p_{\perp,\text{max}} - p_{\perp,\text{min}}}{p_{\perp,\text{par}}}
\right)
\right)
& y < y_\text{cut}
\\
- \tilde{p}_{\perp,\text{par}}\log\left(1 - x_{p_\perp}\left[1 -
\exp\left(\frac{p_{\perp,\text{min}} -
p_{\perp,\text{max}}}{\tilde{p}_{\perp,\text{par}}}\right)\right]\right)
& y \geq y_\text{cut}
\end{cases}\,,
\end{equation}
where $p_{\perp,\text{min}}$ is the minimum jet transverse momentum,
$p_{\perp,\text{max}}$ is the maximum transverse parton momentum,
tentatively set to the beam energy, and $y_\text{cut}$, $p_{\perp,\text{par}}$
and $\tilde{p}_{\perp,\text{par}}$ are generation parameters set to
heuristically determined values of
\begin{align}
y_\text{cut}&=3,\\
p_{\perp,\text{par}}&=p_{\perp,\min}+\frac{n_p}{5}, \\
\tilde{p}_{\perp,\text{par}}&=\frac{p_{\perp,\text{par}}}{1 +
5(y-y_\text{cut})}.
\end{align}
The problem with this generation is that the transverse momenta peak at
the minimum transverse momentum required for fixed-order jets. However,
if we use the generated events as input for \HEJ resummation, events
with such soft transverse momenta hardly contribute, see
section~\ref{sec:ptj_res}. To generate efficient input for resummation,
there is the user option \texttt{peak pt}, which specifies the
dominant transverse momentum for resummation jets. If this option is
set, most jets will be generated as above, but with
$p_{\perp,\text{min}}$ set to the peak transverse momentum $p_{\perp,
\text{peak}}$. In addition, there is a small chance of around $2\%$ to
generate softer jets. The heuristic ansatz for the transverse momentum
distribution in the ``soft'' region is
\begin{equation}
\label{FO_pt_soft}
\frac{\partial \sigma}{\partial p_\perp} \propto e^{n_p\frac{p_\perp- p_{\perp,
\text{peak}}}{\bar{p}_\perp}}\,,
\end{equation}
where $n_p$ is the number of partons and $\bar{p}_\perp \approx
4\,$GeV. To achieve this distribution, we use
\begin{equation}
\label{eq:FO_pt_soft_sampling}
p_\perp = p_{\perp, \text{peak}} + \bar{p}_\perp \frac{\log x_{p_\perp}}{n_p}
\end{equation}
and discard the phase space point if the parton is too soft, i.e. below the threshold for
fixed-order jets.
After ensuring that all partons form separate jets, we generate any
potential colourless emissions. We then determine the incoming momenta
and flavours in \lstinline!PhaseSpacePoint::reconstruct_incoming! and
adjust the outgoing flavours to ensure an FKL configuration. Finally, we
may reassign outgoing flavours to generate suppressed (for example
unordered) configurations.
\subsection{Unweighting}
\label{sec:unweight}
Straightforward event generation tends to produce many events with small
weights. Those events have a negligible contribution to the final
observables, but can take up considerable storage space and CPU time in
later processing stages. This problem can be addressed by unweighting.
For naive unweighting, one would determine the maximum weight
$w_\text{max}$ of all events, discard each event with weight $w$ with a
probability $p=w/w_\text{max}$, and set the weights of all remaining
events to $w_\text{max}$. The downside to this procedure is that it also
eliminates a sizeable fraction of events with moderate weight, so that
the statistical convergence deteriorates.
To ameliorate this problem, we perform unweighting only for events with
sufficiently small weights. This is done by the
\lstinline!Unweighter! class. In the constructor we estimate the
mean and width of the weight-weight distribution from a sample of
events. We use these estimates to determine the maximum weight below
which unweighting is performed. The actual unweighting is the done in
the \lstinline!Unweighter::unweight! function.
\input{currents}
\appendix
\section{Continuous Integration}
\label{sec:gitlabCI}
GitLab provides ways to directly test code via \textit{Continuous integrations}.
The CI is controlled by \texttt{.gitlab-ci.yml}. For all options for the YAML
file see \href{https://docs.gitlab.com/ee/ci/yaml/}{docs.gitlab.com/ee/ci/yaml/}.
GitLab also provides a small tool to check that YAML syntax is correct under
\lstinline!CI/CD > Pipelines > CI Lint! or
\href{https://gitlab.dur.scotgrid.ac.uk/hej/HEJ/-/ci/lint}{gitlab.dur.scotgrid.ac.uk/hej/HEJ/-/ci/lint}.
Currently the CI is configured to trigger a \textit{Pipeline} on each
\lstinline!git push!. The corresponding \textit{GitLab runners} are configured
under \lstinline!CI/CD Settings>Runners! in the GitLab UI. All runners use a
\href{https://www.docker.com/}{docker} image as virtual environments\footnote{To
use only Docker runners set the \lstinline!docker! tag in
\texttt{.gitlab-ci.yml}.}. The specific docker images maintained separately. If
you add a new dependences, please also provide a docker image for the CI. The
goal to be able to test \HEJ with all possible configurations.
Each pipeline contains multiple stages (see \lstinline!stages! in
\texttt{.gitlab-ci.yml}) which are executed in order from top to bottom.
Additionally each stage contains multiple jobs. For example the stage
\textit{build} contains the jobs \lstinline!build:basic!,
\lstinline!build:qcdloop!, \lstinline!build:rivet!, etc., which compile \HEJ for
different environments and dependences, by using different in the Docker images.
Jobs staring with an dot are ignored by the Runner, e.g. \lstinline!.HEJ_build!
is only used as a template but never executed directly. Only after all jobs of
the previous stage was executed without any error the next stage will start.
To pass information between one stage and the next we use \lstinline!artifacts!.
The runner will automatically load all artifacts form all
\lstinline!dependencies! for each job\footnote{If no dependencies are defined
\textit{all} artifacts from all previous jobs are downloaded. Thus please
specify an empty dependence if you do not want to load any artifacts.}. For
example the compiled \HEJ code from \lstinline!build:basic! gets loaded in
\lstinline!test:basic! and \lstinline!FOG:build:basic!, without recompiling \HEJ
again. Additionally artifacts can be downloaded from the GitLab web page, which
could be handy for debugging.
The actual commands are given in the \lstinline!before_script!,
\lstinline!script! and \lstinline!after_script!
\footnote{\lstinline!after_script! is always executed} sections, and are
standard Linux shell commands (dependent on the docker image). Any failed
command, i.e. returning not zero, stops the job and making the pipeline fail
entirely. Most tests are just running \lstinline!make test! or are based on it.
Thus, to emphasise it again, write tests for your code in \lstinline!cmake!. The
CI is only intended to make automated testing in different environments easier.
\bibliographystyle{JHEP}
\bibliography{biblio}
\end{document}
diff --git a/doc/sphinx/HEJ.rst b/doc/sphinx/HEJ.rst
index 83df36f..d130a0a 100644
--- a/doc/sphinx/HEJ.rst
+++ b/doc/sphinx/HEJ.rst
@@ -1,289 +1,302 @@
.. _`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>`_. 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
..
- *TODO* 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. 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 boson plus
jets production.
.. _`non-HEJ`:
**non-HEJ**
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 an overall factor,
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.hepmc` or :code:`HepMC: file`: The HepMC format.
.. _`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, see :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 569295e..bd0eddc 100644
--- a/doc/sphinx/HEJFOG.rst
+++ b/doc/sphinx/HEJFOG.rst
@@ -1,292 +1,301 @@
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`
At most one of the outgoing particles can be a boson, the rest has to be
partonic. At the moment only the Higgs boson :code:`h` is supported. All
other outgoing particles are jets. Multiple jets can be grouped together, so
:code:`p p => h j j` is the same as :code:`p p => h 2j`. There have to be at
least two jets. Further decays of the boson can be added through the
:ref:`particle properties<particle properties: particle: decays>`.
.. _`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 FKL
- configurations and thus subleading in the high-energy
- limit. Currently only unordered emissions are implemented, and only
- for Higgs boson plus multijet processes. 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
+ 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 parameter to select the production of specific channels that
- are subleading in the high-energy limit. Only has an effect if
- :code:`subleading fraction` is non-zero. Currently three values are
- supported:
-
- - :code:`all`: All subleading channels are allowed. This is the default.
- - :code:`none`: No subleading contribution, only FKL configurations
- are allowed. This is equivalent to :code:`subleading fraction: 0`.
- - :code:`unordered`: Unordered emission are allowed.
-
- Unordered emission are any rapidity ordering where exactly one
- gluon is emitted outside the FKL rapidity ordering. 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.
+ 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.
+ - :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.
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.
.. _`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/Constants.hh b/include/HEJ/Constants.hh
index bce7476..4568911 100644
--- a/include/HEJ/Constants.hh
+++ b/include/HEJ/Constants.hh
@@ -1,34 +1,39 @@
/** \file
* \brief Header file defining all global constants used for HEJ
*
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#pragma once
namespace HEJ{
/// @name QCD parameters
//@{
constexpr double N_C = 3.; //!< number of Colours
constexpr double C_A = N_C; //!< \f$C_A\f$
constexpr double C_F = (N_C*N_C - 1.)/(2.*N_C); //!< \f$C_F\f$
constexpr double t_f = 0.5; //!< \f$t_f\f$
constexpr double n_f = 5.; //!< number light flavours
constexpr double beta0 = 11./3.*C_A - 4./3.*t_f*n_f; //!< \f$\beta_0\f$
//@}
/// @name QFT parameters
//@{
constexpr double vev = 246.2196508; //!< Higgs vacuum expectation value in GeV
-//@}
+ constexpr double gw = 0.653233;
+ constexpr double MW = 80.419; // The W mass in GeV/c^2
+ constexpr double GammaW = 2.0476; // the W width in GeV/c^2
+
+ //@}
/// @name Generation Parameters
//@{
- constexpr double CLAMBDA = 0.2; //!< Scale for virtual correction, \f$\lambda\f$ cf. eq. (20) in \cite Andersen:2011hs
- constexpr double CMINPT = CLAMBDA; //!< minimal \f$p_t\f$ of all partons
+ //! Default scale for virtual correction, \f$\lambda\f$ cf. eq. (20) in \cite Andersen:2011hs
+ constexpr double CLAMBDA = 0.2;
+ constexpr double CMINPT = 0.2; //!< minimal \f$p_t\f$ of all partons
//@}
/// @name Conventional Parameters
//@{
//! Value of first colour for colour dressing, according to LHE convention \cite Boos:2001cv
constexpr int COLOUR_OFFSET = 501;
//@}
}
diff --git a/include/HEJ/LesHouchesWriter.hh b/include/HEJ/LesHouchesWriter.hh
index 604c21e..7d23e79 100644
--- a/include/HEJ/LesHouchesWriter.hh
+++ b/include/HEJ/LesHouchesWriter.hh
@@ -1,60 +1,61 @@
/** \file
* \brief Contains the writer for LesHouches output
*
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#pragma once
#include <fstream>
#include <memory>
#include <string>
#include "LHEF/LHEF.h"
#include "HEJ/EventWriter.hh"
namespace HEJ{
class Event;
//! Class for writing events to a file in the Les Houches Event File format
class LesHouchesWriter : public EventWriter{
public:
//! Constructor
/**
* @param file Name of output file
* @param heprup General process information
*/
LesHouchesWriter(std::string const & file, LHEF::HEPRUP heprup);
LesHouchesWriter(LesHouchesWriter const & other) = delete;
LesHouchesWriter & operator=(LesHouchesWriter const & other) = delete;
- // TODO: in principle, this class should be movable
- // but that somehow(?) breaks the write member function
+ /** @TODO in principle, this class should be movable
+ * but that somehow(?) breaks the write member function
+ */
LesHouchesWriter(LesHouchesWriter && other) = delete;
LesHouchesWriter & operator=(LesHouchesWriter && other) = delete;
~LesHouchesWriter() override;
//! Write an event to the file specified in the constructor
void write(Event const & ev) override;
private:
void write_init(){
writer_->init();
}
void rewrite_init();
LHEF::HEPRUP & heprup(){
return writer_->heprup;
}
LHEF::HEPEUP & hepeup(){
return writer_->hepeup;
}
std::fstream out_;
std::unique_ptr<LHEF::Writer> writer_;
};
}
diff --git a/include/HEJ/MatrixElement.hh b/include/HEJ/MatrixElement.hh
index b83c4c3..cfcd15f 100644
--- a/include/HEJ/MatrixElement.hh
+++ b/include/HEJ/MatrixElement.hh
@@ -1,183 +1,191 @@
/** \file
* \brief Contains the MatrixElement Class
*
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#pragma once
#include <functional>
#include <vector>
#include "fastjet/PseudoJet.hh"
#include "HEJ/PDG_codes.hh"
#include "HEJ/Parameters.hh"
#include "HEJ/config.hh"
namespace CLHEP {
class HepLorentzVector;
}
namespace HEJ{
class Event;
class Particle;
//! Class to calculate the squares of matrix elements
class MatrixElement{
public:
/** \brief MatrixElement Constructor
* @param alpha_s Function taking the renormalisation scale
* and returning the strong coupling constant
* @param conf General matrix element settings
*/
MatrixElement(
std::function<double (double)> alpha_s,
MatrixElementConfig conf
);
/**
* \brief squares of regulated HEJ matrix elements
* @param event The event for which to calculate matrix elements
* @returns The squares of HEJ matrix elements including virtual corrections
*
* This function returns one value for the central parameter choice
* and one additional value for each entry in \ref Event.variations().
* See eq. (22) in \cite Andersen:2011hs for the definition of the squared
* matrix element.
*
* \internal Relation to standard HEJ Met2: MatrixElement = Met2*shat^2/(pdfta*pdftb)
*/
Weights operator()(Event const & event) const;
//! Squares of HEJ tree-level matrix elements
/**
* @param event The event for which to calculate matrix elements
* @returns The squares of HEJ matrix elements without virtual corrections
*
* cf. eq. (22) in \cite Andersen:2011hs
*/
Weights tree(Event const & event) const;
/**
* \brief Virtual corrections to matrix element squares
* @param event The event for which to calculate matrix elements
* @returns The virtual corrections to the squares of the matrix elements
*
* The all order virtual corrections to LL in the MRK limit is
* given by replacing 1/t in the scattering amplitude according to the
* lipatov ansatz.
*
* cf. second-to-last line of eq. (22) in \cite Andersen:2011hs
* note that indices are off by one, i.e. out[0].p corresponds to p_1
*/
Weights virtual_corrections(Event const & event) const;
/**
* \brief Scale-dependent part of tree-level matrix element squares
* @param event The event for which to calculate matrix elements
* @returns The scale-dependent part of the squares of the
* tree-level matrix elements
*
* The tree-level matrix elements factorises into a renormalisation-scale
* dependent part, given by the strong coupling to some power, and a
* scale-independent remainder. This function only returns the former parts
* for the central scale choice and all \ref Event.variations().
*
* @see tree, tree_kin
*/
Weights tree_param(
Event const & event
) const;
/**
* \brief Kinematic part of tree-level matrix element squares
* @param event The event for which to calculate matrix elements
* @returns The kinematic part of the squares of the
* tree-level matrix elements
*
* The tree-level matrix elements factorises into a renormalisation-scale
* dependent part, given by the strong coupling to some power, and a
* scale-independent remainder. This function only returns the latter part.
* Since it does not depend on the parameter variations, only a single value
* is returned.
*
* @see tree, tree_param
*/
double tree_kin(Event const & event) const;
private:
double tree_param(
Event const & event,
double mur
) const;
+ double virtual_corrections_W(
+ Event const & event,
+ double mur,
+ Particle const & WBoson
+ ) const;
double virtual_corrections(
Event const & event,
double mur
) const;
//! \internal cf. last line of eq. (22) in \cite Andersen:2011hs
double omega0(
double alpha_s, double mur,
- fastjet::PseudoJet const & q_j, double lambda
+ fastjet::PseudoJet const & q_j
) const;
double tree_kin_jets(
Event const & ev
) const;
+ double tree_kin_W(
+ Event const & ev
+ ) const;
double tree_kin_Higgs(
Event const & ev
) const;
double tree_kin_Higgs_first(
Event const & ev
) const;
double tree_kin_Higgs_last(
Event const & ev
) const;
/**
* \internal
* \brief Higgs inbetween extremal partons.
*
* Note that in the case of unordered emission, the Higgs is *always*
* treated as if in between the extremal (FKL) partons, even if its
* rapidity is outside the extremal parton rapidities
*/
double tree_kin_Higgs_between(
Event const & ev
) const;
double tree_param_partons(
double alpha_s, double mur,
std::vector<Particle> const & partons
) const;
std::vector<int> in_extremal_jet_indices(
std::vector<fastjet::PseudoJet> const & partons
) const;
std::vector<Particle> tag_extremal_jet_partons(
Event const & ev
) const;
double MH2_forwardH(
CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
pid::ParticleID type2,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
CLHEP::HepLorentzVector pH,
double t1, double t2
) const;
std::function<double (double)> alpha_s_;
MatrixElementConfig param_;
};
}
diff --git a/include/HEJ/PDG_codes.hh b/include/HEJ/PDG_codes.hh
index a942130..cf3ca3a 100644
--- a/include/HEJ/PDG_codes.hh
+++ b/include/HEJ/PDG_codes.hh
@@ -1,132 +1,143 @@
/** \file PDG_codes.hh
* \brief Contains the Particle IDs of all relevant SM particles.
*
* Large enumeration included which has multiple entries for potential
* alternative names of different particles. There are also functions
* which can be used to determine if a particle is a parton or if
* it is a non-gluon boson.
*
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#pragma once
#include <string>
namespace HEJ {
//! particle ids according to PDG
namespace pid {
//! The possible particle identities. We use PDG IDs as standard.
enum ParticleID{
d = 1, /*!< Down Quark */
down = d, /*!< Down Quark */
u = 2, /*!< Up Quark */
up = u, /*!< Up Quark */
s = 3, /*!< Strange Quark */
strange = s, /*!< Strange Quark */
c = 4, /*!< Charm Quark */
charm = c, /*!< Charm Quark */
b = 5, /*!< Bottom Quark */
bottom = b, /*!< Bottom Quark */
t = 6, /*!< Top Quark */
top = t, /*!< Top Quark */
e = 11, /*!< Electron */
electron = e, /*!< Electron */
nu_e = 12, /*!< Electron Neutrino */
electron_neutrino = nu_e, /*!< Electron neutrino */
mu = 13, /*!< Muon */
muon = mu, /*!< Muon */
nu_mu = 14, /*!< Muon Neutrino */
muon_neutrino = nu_mu, /*!< Muon Neutrino */
tau = 15, /*!< Tau */
nu_tau = 16, /*!< Tau Neutrino */
tau_neutrino = nu_tau, /*!< Tau Neutrino */
d_bar = -d, /*!< Anti-Down Quark */
u_bar = -u, /*!< Anti-Up quark */
s_bar = -s, /*!< Anti-Strange Quark */
c_bar = -c, /*!< Anti-Charm Quark */
b_bar = -b, /*!< Anti-Bottom Quark */
t_bar = -t, /*!< Anti-Top Quark */
e_bar = -e, /*!< Positron */
positron = e_bar, /*!< Positron */
nu_e_bar = -nu_e, /*!< Anti-Electron Neutrino */
mu_bar = -mu, /*!< Anti-Muon */
nu_mu_bar = -nu_mu, /*!< Anti-Muon Neutrino */
tau_bar = -tau, /*!< Anti-Tau */
nu_tau_bar = -nu_tau, /*!< Anti-Tau Neutrino */
gluon = 21, /*!< Gluon */
g = gluon, /*!< Gluon */
photon = 22, /*!< Photon */
gamma = photon, /*!< Photon */
Z = 23, /*!< Z Boson */
Wp = 24, /*!< W- Boson */
Wm = -Wp, /*!< W+ Boson */
h = 25, /*!< Higgs Boson */
Higgs = h, /*!< Higgs Boson */
higgs = h, /*!< Higgs Boson */
p = 2212, /*!< Proton */
proton = p, /*!< Proton */
p_bar = -p, /*!< Anti-Proton */
};
}
using ParticleID = pid::ParticleID;
//! Convert a particle name to the corresponding PDG particle ID
ParticleID to_ParticleID(std::string const & name);
/**
* \brief Function to determine if particle is a parton
* @param p PDG ID of particle
* @returns true if the particle is a parton, false otherwise
*/
inline
constexpr bool is_parton(ParticleID p){
return p == pid::gluon || std::abs(p) <= pid::top;
}
/**
* \brief Function to determine if particle is a quark
* @param id PDG ID of particle
* @returns true if the particle is a qaurk, false otherwise
*/
inline
constexpr bool is_quark(ParticleID id){
return (id >= pid::down && id <= pid::top);
}
/**
* \brief Function to determine if particle is a antiquark
* @param id PDG ID of particle
* @returns true if the particle is an antiquark, false otherwise
*/
inline
constexpr bool is_antiquark(ParticleID id){
return (id <= pid::d_bar && id >= pid::t_bar);
}
/**
* \brief Function to determine if particle is a (anti-)quark
* @param id PDG ID of particle
* @returns true if the particle is a quark or antiquark, false otherwise
*/
inline
constexpr bool is_anyquark(ParticleID id){
return (id && id >= pid::t_bar && id <= pid::t);
}
/**
* \brief function to determine if the particle is a photon, W, Z, or Higgs boson
* @param id PDG ID of particle
* @returns true if the partice is a A,W,Z, or H, false otherwise
*/
inline
constexpr bool is_AWZH_boson(ParticleID id){
return id == pid::Wm || (id >= pid::photon && id <= pid::Higgs);
}
+ /**
+ * \brief function to determine if the particle is a photon, W or Z
+ * @param id PDG ID of particle
+ * @returns true if the partice is a A,W,Z, or H, false otherwise
+ */
+ inline
+ constexpr bool is_AWZ_boson(ParticleID id){
+ return id == pid::Wm || (id >= pid::photon && id <= pid::Wp);
+ }
+
+
}
diff --git a/include/HEJ/Particle.hh b/include/HEJ/Particle.hh
index 67af9db..c6f321c 100644
--- a/include/HEJ/Particle.hh
+++ b/include/HEJ/Particle.hh
@@ -1,143 +1,148 @@
/**
* \file Particle.hh
* \brief Contains the particle struct
*
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#pragma once
#include <utility>
#include "fastjet/PseudoJet.hh"
#include "HEJ/optional.hh"
#include "HEJ/PDG_codes.hh"
namespace HEJ {
using Colour = std::pair<int,int>;
//! Class representing a particle
struct Particle {
//! particle type
ParticleID type;
//! particle momentum
fastjet::PseudoJet p;
//! (optional) colour & anti-colour
optional<Colour> colour;
//! get rapidity
double rapidity() const{
return p.rapidity();
}
//! get transverse momentum
double perp() const{
return p.perp();
}
//! get momentum in x direction
double px() const{
return p.px();
}
//! get momentum in y direction
double py() const{
return p.py();
}
//! get momentum in z direction
double pz() const{
return p.pz();
}
//! get energy
double E() const{
return p.E();
}
//! get mass
double m() const{
return p.m();
}
};
//! Functor to compare rapidities
/**
* This can be used whenever a rapidity comparison function is needed,
* for example in many standard library functions.
*
* @see pz_less
*/
struct rapidity_less{
template<class FourVector>
bool operator()(FourVector const & p1, FourVector const & p2){
return p1.rapidity() < p2.rapidity();
}
};
//! Functor to compare momenta in z direction
/**
* This can be used whenever a pz comparison function is needed,
* for example in many standard library functions.
*
* @see rapidity_less
*/
struct pz_less{
template<class FourVector>
bool operator()(FourVector const & p1, FourVector const & p2){
return p1.pz() < p2.pz();
}
};
//! Convert a vector of Particles to a vector of particle momenta
inline
std::vector<fastjet::PseudoJet> to_PseudoJet(
std::vector<Particle> const & v
){
std::vector<fastjet::PseudoJet> result;
for(auto && sp: v) result.emplace_back(sp.p);
return result;
}
//! Check if a particle is a parton, i.e. quark, antiquark, or gluon
inline
bool is_parton(Particle const & p){
return is_parton(p.type);
}
//! Check if a particle is a quark
inline
bool is_quark(Particle const & p){
return is_quark(p.type);
}
//! Check if a particle is an anti-quark
inline
bool is_antiquark(Particle const & p){
return is_antiquark(p.type);
}
//! Check if a particle is a quark or anit-quark
inline
bool is_anyquark(Particle const & p){
return is_anyquark(p.type);
}
+ //! Check if a particle is a photon, W or Z boson
+ inline bool is_AWZ_boson(Particle const & particle){
+ return is_AWZ_boson(particle.type);
+ }
+
//! Check if a particle is a photon, W, Z, or Higgs boson
inline bool is_AWZH_boson(Particle const & particle){
return is_AWZH_boson(particle.type);
}
//! Extract all partons from a vector of particles
inline
std::vector<Particle> filter_partons(
std::vector<Particle> const & v
){
std::vector<Particle> result;
result.reserve(v.size());
std::copy_if(
begin(v), end(v), std::back_inserter(result),
[](Particle const & p){ return is_parton(p); }
);
return result;
}
}
diff --git a/include/HEJ/PhaseSpacePoint.hh b/include/HEJ/PhaseSpacePoint.hh
index f8b0ec9..6189932 100644
--- a/include/HEJ/PhaseSpacePoint.hh
+++ b/include/HEJ/PhaseSpacePoint.hh
@@ -1,154 +1,155 @@
/** \file
* \brief Contains the PhaseSpacePoint Class
*
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#pragma once
#include <array>
#include <functional>
#include <unordered_map>
#include <vector>
#include "HEJ/config.hh"
#include "HEJ/Particle.hh"
#include "HEJ/RNG.hh"
namespace HEJ{
class Event;
//! A point in resummation phase space
class PhaseSpacePoint{
public:
//! Default PhaseSpacePoint Constructor
PhaseSpacePoint() = default;
//! PhaseSpacePoint Constructor
/**
* @param ev Clustered Jet Event
* @param conf Configuration parameters
* @param ran Random number generator
*/
PhaseSpacePoint(
Event const & ev,
PhaseSpacePointConfig conf,
RNG & ran
);
//! Get phase space point weight
double weight() const{
return weight_;
}
//! Access incoming particles
std::array<Particle, 2> const & incoming() const{
return incoming_;
}
//! Access outgoing particles
std::vector<Particle> const & outgoing() const{
return outgoing_;
}
//! Particle decays
/**
* The key in the returned map corresponds to the index in the
* vector returned by outgoing()
*/
std::unordered_map<size_t, std::vector<Particle>> const & decays() const{
return decays_;
}
static constexpr int ng_max = 1000; //< maximum number of extra gluons
private:
std::vector<fastjet::PseudoJet> cluster_jets(
std::vector<fastjet::PseudoJet> const & partons
) const;
bool pass_resummation_cuts(
std::vector<fastjet::PseudoJet> const & jets
) const;
bool pass_extremal_cuts(
fastjet::PseudoJet const & ext_parton,
fastjet::PseudoJet const & jet
) const;
int sample_ng(std::vector<fastjet::PseudoJet> const & Born_jets);
int sample_ng_jets(int ng, std::vector<fastjet::PseudoJet> const & Born_jets);
double probability_in_jet(
std::vector<fastjet::PseudoJet> const & Born_jets
) const;
std::vector<fastjet::PseudoJet> gen_non_jet(
int ng_non_jet,
double ptmin, double ptmax
);
void rescale_rapidities(
std::vector<fastjet::PseudoJet> & partons,
double ymin, double ymax
);
std::vector<fastjet::PseudoJet> reshuffle(
std::vector<fastjet::PseudoJet> const & Born_jets,
fastjet::PseudoJet const & q
);
bool jets_ok(
std::vector<fastjet::PseudoJet> const & Born_jets,
std::vector<fastjet::PseudoJet> const & partons
) const;
void reconstruct_incoming(std::array<Particle, 2> const & Born_incoming);
double phase_space_normalisation(
int num_Born_jets,
int num_res_partons
) const;
std::vector<fastjet::PseudoJet> split(
std::vector<fastjet::PseudoJet> const & jets, int ng_jets
);
std::vector<int> distribute_jet_partons(
int ng_jets, std::vector<fastjet::PseudoJet> const & jets
);
std::vector<fastjet::PseudoJet> split(
std::vector<fastjet::PseudoJet> const & jets,
std::vector<int> const & np_in_jet
);
bool split_preserved_jets(
std::vector<fastjet::PseudoJet> const & jets,
std::vector<fastjet::PseudoJet> const & jet_partons
) const;
template<class Particle>
Particle const & most_backward_FKL(
std::vector<Particle> const & partons
) const;
template<class Particle>
Particle const & most_forward_FKL(
std::vector<Particle> const & partons
) const;
template<class Particle>
Particle & most_backward_FKL(std::vector<Particle> & partons) const;
template<class Particle>
Particle & most_forward_FKL(std::vector<Particle> & partons) const;
bool extremal_ok(
std::vector<fastjet::PseudoJet> const & partons
) const;
+ void label_qqx(Event const & event);
void copy_AWZH_boson_from(Event const & event);
bool momentum_conserved() const;
- bool unob_, unof_;
+ bool unob_, unof_, qqxb_, qqxf_, qqxmid_;
double weight_;
PhaseSpacePointConfig param_;
std::array<Particle, 2> incoming_;
std::vector<Particle> outgoing_;
//! \internal Particle decays in the format {outgoing index, decay products}
std::unordered_map<size_t, std::vector<Particle>> decays_;
std::reference_wrapper<HEJ::RNG> ran_;
};
}
diff --git a/include/HEJ/Tensor.hh b/include/HEJ/Tensor.hh
new file mode 100644
index 0000000..b02ae30
--- /dev/null
+++ b/include/HEJ/Tensor.hh
@@ -0,0 +1,201 @@
+/** \file
+ * \brief Tensor Template Class declaration.
+ *
+ * This file contains the declaration of the Tensor Template class. This
+ * is used to calculate some of the more complex currents within the
+ * W+Jets implementation particularly.
+ */
+
+#pragma once
+#include <array>
+
+///@TODO remove function implementation from header
+///@TODO put in some namespace
+template <unsigned int N, unsigned int D>
+class Tensor{
+public:
+
+ //Constructor
+ Tensor();
+ Tensor(COM x);
+
+ //Destructor
+ virtual ~Tensor();
+
+ int rank(){
+ return N;
+ }
+
+ int dim(){
+ return D;
+ }
+
+ int len(){
+ return size;
+ }
+
+ COM at(int i){
+ return components[i];
+ }
+ COM at(int i, int j) {
+ return components[D*i +j];
+ }
+ COM at(int i, int j, int k) {
+ return components[D*(D*i + j)+ k];
+ }
+ COM at(int i,int j, int k,int l) {
+ return components[D*(D*(D*i +j) + k) + l];
+ }
+ COM at(int i,int j, int k,int l, int m){
+ return components[D*(D*(D*(D*i + j) + k) + l) + m];
+ }
+
+ bool isSet(){
+ if(components.size()==0)
+ return false;
+ else
+ return true;
+ }
+
+ void Fill(COM x){
+ components=x;
+ }
+
+ //Set component indexed by i,j,k,l,m
+ void Set(int i,COM x){
+ components[i] = x;
+ }
+ void Set(int i, int j, COM x) {
+ components[D*i +j] = x;
+ }
+ void Set(int i, int j, int k, COM x) {
+ components[D*(D*i + j)+ k] = x;
+ }
+ void Set(int i,int j, int k,int l,COM x) {
+ components[D*(D*(D*i +j) + k) + l] = x;
+ }
+ void Set(int i,int j, int k,int l, int m, COM x){
+ components[D*(D*(D*(D*i + j) + k) + l) + m] = x;
+ }
+
+ Tensor<N,D> operator*(const double x){
+ Tensor<N,D> newT;
+ newT.components=components*COM(x,0);
+ return newT;
+ }
+ Tensor<N,D> operator*(const COM x){
+ Tensor<N,D> newT;
+ newT.components=components*x;
+ return newT;
+ }
+ Tensor<N,D> operator/(const double x){
+ Tensor<N,D> newT;
+ newT.components=components/COM(x,0);
+ return newT;
+ }
+ Tensor<N,D> operator/(const COM x){
+ Tensor<N,D> newT;
+ newT.components=components/x;
+ return newT;
+ }
+ Tensor<N,D> operator+(const Tensor<N,D> T2){
+ Tensor<N,D> newT;
+ newT.components=components+T2.components;
+ return newT;
+ }
+ Tensor<N,D> operator-(const Tensor<N,D> T2){
+ Tensor<N,D> newT;
+ newT.components=components-T2.components;
+ return newT;
+ }
+ void operator+=(const Tensor<N,D> T2){
+ components = components+T2.components;
+ }
+ void operator-=(const Tensor<N,D> T2){
+ components=components-T2.components;
+ }
+
+ Tensor<N+1,D> rightprod(const Tensor<1,D> T2){
+ Tensor<N+1,D> newT;
+ for(int i=0; i<size;i++){
+ for(unsigned int j=0;j<D;j++){
+ newT.components[i*D+j]=components[i]*T2.components[j];
+ }
+ }
+ return newT;
+ }
+
+ Tensor<N+1,D> leftprod(const Tensor<1,D> T2){
+ Tensor<N+1,D> newT;
+ for(unsigned int j=0;j<D;j++){
+ for(int i=0; i<size;i++){
+ newT.components[j*size+i]=components[i]*T2.components[j];
+ }
+ }
+ return newT;
+ }
+
+ //T^(mu1...mk..mN)T2_(muk) contract kth index, where k member of [1,N]
+ Tensor<N-1,D> contract(const Tensor<1,D> T2, int k){
+ Tensor<N-1,D> newT;
+ for(int j=0; j<newT.len(); j++){
+ COM temp;
+ int itemp = pow(D,(N-k));
+ for (unsigned int i=0; i<D; i++){
+ int index = D*itemp*floor(j/itemp) + itemp*i +j%(itemp);
+ temp+=components[index]*T2.components[i]*sign(i);
+ }
+ newT.components[j]=temp;
+ }
+ return newT;
+ }
+
+ std::valarray<COM> components;
+
+private:
+
+ int size;
+ COM sign(unsigned int i){
+ if(i==0)
+ return 1.;
+ else
+ return -1.;
+ }
+
+};
+
+template <unsigned int N, unsigned int D> Tensor<N,D>::Tensor()
+{
+ size = pow(D,N);
+ components.resize(size);
+}
+template <unsigned int N, unsigned int D> Tensor<N,D>::Tensor(COM x) {
+ size = pow(D,N);
+ components.resize(size, x);
+}
+template <unsigned int N, unsigned int D> Tensor<N,D>::~Tensor() {}
+
+// Tensor Functions:
+// Tensor<1,4> Sigma(int i, int j, bool hel);
+// Tensor<2,4> Metric();
+// int tensor2listindex(std::array<int,5> indexlist);
+// int tensor2listindex(std::array<int,3> indexlist);
+// void perms41(int same4, int diff, std::vector<std::array<int,5>> * perms);
+// void perms32(int same3, int diff, std::vector<std::array<int,5>> * perms);
+// void perms311(int same3, int diff1, int diff2, std::vector<std::array<int,5>> * perms);
+// void perms221(int same2a, int same2b, int diff, std::vector<std::array<int,5>> * perms);
+// void perms2111(int same2, int diff1,int diff2,int diff3, std::vector<std::array<int,5>> * perms);
+// void perms21(int same, int diff, std::vector<std::array<int,3>> * perms);
+// void perms111(int diff1, int diff2, int diff3, std::vector<std::array<int,3>> * perms);
+
+Tensor<2,4> Metric();
+Tensor<1,4> TCurrent(CLHEP::HepLorentzVector p1, bool h1,
+ CLHEP::HepLorentzVector p2, bool h2);
+Tensor<3,4> T3Current(CLHEP::HepLorentzVector p1, bool h1,
+ CLHEP::HepLorentzVector p2, bool h2);
+Tensor<5,4> T5Current(CLHEP::HepLorentzVector p1, bool h1,
+ CLHEP::HepLorentzVector p2, bool h2);
+Tensor<1,4> Construct1Tensor(CCurrent j);
+Tensor<1,4> Construct1Tensor(CLHEP::HepLorentzVector p);
+Tensor<1,4> eps(CLHEP::HepLorentzVector k, CLHEP::HepLorentzVector ref, bool pol);
+bool init_sigma_index();
diff --git a/include/HEJ/config.hh b/include/HEJ/config.hh
index 2b9d9f6..51f973c 100644
--- a/include/HEJ/config.hh
+++ b/include/HEJ/config.hh
@@ -1,175 +1,191 @@
/** \file
* \brief HEJ 2 configuration parameters
*
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#pragma once
#include <string>
#include "fastjet/JetDefinition.hh"
#include "yaml-cpp/yaml.h"
+#include "HEJ/Constants.hh"
#include "HEJ/event_types.hh"
#include "HEJ/HiggsCouplingSettings.hh"
#include "HEJ/optional.hh"
#include "HEJ/output_formats.hh"
#include "HEJ/ScaleFunction.hh"
namespace HEJ{
//! Jet parameters
struct JetParameters{
fastjet::JetDefinition def; /**< Jet Definition */
double min_pt; /**< Minimum Jet Transverse Momentum */
};
//! Settings for scale variation
struct ScaleConfig{
//! Base scale choices
std::vector<ScaleFunction> base;
//! Factors for multiplicative scale variation
std::vector<double> factors;
//! Maximum ratio between renormalisation and factorisation scale
double max_ratio;
};
//! Settings for random number generator
struct RNGConfig {
//! Random number generator name
std::string name;
//! Optional initial seed
optional<std::string> seed;
};
/**! Possible treatments for fixed-order input events.
*
* The program will decide on how to treat an event based on
* the value of this enumeration.
*/
enum class EventTreatment{
reweight, /**< Perform resummation */
keep, /**< Keep the event */
discard, /**< Discard the event */
};
//! Container to store the treatments for various event types
using EventTreatMap = std::map<event_type::EventType, EventTreatment>;
/**! Input parameters.
*
* This struct handles stores all configuration parameters
* needed in a HEJ 2 run.
*
* \internal To add a new option:
* 1. Add a member to the Config struct.
* 2. Inside "src/YAMLreader.cc":
* - Add the option name to the "supported" Node in
* get_supported_options.
* - Initialise the new Config member in to_Config.
* The functions set_from_yaml (for mandatory options) and
* set_from_yaml_if_defined (non-mandatory) may be helpful.
* 3. Add a new entry (with short description) to config.yaml
* 4. Update the user documentation in "doc/Sphinx/"
*/
struct Config {
//! Parameters for scale variation
ScaleConfig scales;
//! Resummation jet properties
JetParameters resummation_jets;
//! Fixed-order jet properties
JetParameters fixed_order_jets;
//! Minimum transverse momentum for extremal partons
double min_extparton_pt;
//! Maximum transverse momentum fraction from soft radiation in extremal jets
double max_ext_soft_pt_fraction;
+ //! The regulator lambda for the subtraction terms
+ double regulator_lambda = CLAMBDA;
//! Number of resummation configurations to generate per fixed-order event
int trials;
//! Whether to include the logarithmic correction from \f$\alpha_s\f$ running
bool log_correction;
//! Event output files names and formats
std::vector<OutputFile> output;
//! Parameters for random number generation
RNGConfig rng;
//! Map to decide what to do for different event types
EventTreatMap treat;
//! Parameters for custom analyses
YAML::Node analysis_parameters;
//! Settings for effective Higgs-gluon coupling
HiggsCouplingSettings Higgs_coupling;
};
//! Configuration options for the PhaseSpacePoint class
struct PhaseSpacePointConfig {
//! Properties of resummation jets
JetParameters jet_param;
//! Minimum transverse momentum for extremal partons
double min_extparton_pt;
//! Maximum transverse momentum fraction from soft radiation in extremal jets
double max_ext_soft_pt_fraction;
};
//! Configuration options for the MatrixElement class
struct MatrixElementConfig {
+ MatrixElementConfig() = default;
+ MatrixElementConfig(
+ bool log_correction,
+ HiggsCouplingSettings Higgs_coupling,
+ double regulator_lambda = CLAMBDA
+ ):
+ log_correction(log_correction),
+ Higgs_coupling(Higgs_coupling),
+ regulator_lambda(regulator_lambda)
+ {}
+
//! Whether to include the logarithmic correction from \f$\alpha_s\f$ running
bool log_correction;
//! Settings for effective Higgs-gluon coupling
HiggsCouplingSettings Higgs_coupling;
+ //! The regulator lambda for the subtraction terms
+ double regulator_lambda = CLAMBDA;
};
//! Configuration options for the EventReweighter class
struct EventReweighterConfig {
//! Settings for phase space point generation
PhaseSpacePointConfig psp_config;
//! Settings for matrix element calculation
MatrixElementConfig ME_config;
//! Properties of resummation jets
JetParameters jet_param;
//! Treatment of the various event types
EventTreatMap treat;
};
/**! Extract PhaseSpacePointConfig from Config
*
* \internal We do not provide a PhaseSpacePointConfig constructor from Config
* so that PhaseSpacePointConfig remains an aggregate.
* This faciliates writing client code (e.g. the HEJ fixed-order generator)
* that creates a PhaseSpacePointConfig *without* a Config object.
*
* @see to_MatrixElementConfig, to_EventReweighterConfig
*/
inline
PhaseSpacePointConfig to_PhaseSpacePointConfig(Config const & conf) {
return {
conf.resummation_jets,
conf.min_extparton_pt,
conf.max_ext_soft_pt_fraction
};
}
/**! Extract MatrixElementConfig from Config
*
* @see to_PhaseSpacePointConfig, to_EventReweighterConfig
*/
inline
MatrixElementConfig to_MatrixElementConfig(Config const & conf) {
- return {conf.log_correction, conf.Higgs_coupling};
+ return {conf.log_correction, conf.Higgs_coupling, conf.regulator_lambda};
}
/**! Extract EventReweighterConfig from Config
*
* @see to_PhaseSpacePointConfig, to_MatrixElementConfig
*/
inline
EventReweighterConfig to_EventReweighterConfig(Config const & conf) {
return {
to_PhaseSpacePointConfig(conf),
to_MatrixElementConfig(conf),
conf.resummation_jets, conf.treat
};
}
} // namespace HEJ
diff --git a/include/HEJ/currents.hh b/include/HEJ/currents.hh
index b7316a7..fb2ffaf 100644
--- a/include/HEJ/currents.hh
+++ b/include/HEJ/currents.hh
@@ -1,875 +1,1333 @@
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// This source code is Copyright (2012) of //
// Jeppe R. Andersen and Jennifer M. Smillie //
// and is distributed under the //
// Gnu Public License version 2 //
// http://www.gnu.org/licenses/gpl-2.0.html //
// You are allowed to distribute and alter the //
// source under the conditions of the GPLv2 //
// as long as this copyright notice //
// is unaltered and distributed with the source //
// Any use should comply with the //
// MCNET GUIDELINES //
// for Event Generator Authors and Users //
// as distributed with this source code //
//////////////////////////////////////////////////
//////////////////////////////////////////////////
/** \file
* \brief Functions computing the square of current contractions.
*
* This file contains all the necessary functions to compute the current
* contractions for all valid HEJ processes. PJETS, H+JETS and W+JETS along with
* some unordered counterparts.
+ *
+ * @TODO add a namespace
*/
#pragma once
#include <complex>
+#include <vector>
+#include <valarray>
+#include <limits>
+
#include <ostream>
#include <CLHEP/Vector/LorentzVector.h>
typedef std::complex<double> COM;
typedef COM current[4];
typedef CLHEP::HepLorentzVector HLV;
//! Square of qQ->qenuQ W+Jets Scattering Current
/**
* @param p1out Momentum of final state quark
* @param pe Momentum of final state electron
* @param pnu Momentum of final state Neutrino
* @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->qenuQ Scattering
*
* This returns the square of the current contractions in qQ->qenuQ scattering
* with an emission of a W Boson.
*/
double jMWqQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
//! Square of qbarQ->qbarenuQ W+Jets Scattering Current
/**
* @param p1out Momentum of final state anti-quark
* @param pe Momentum of final state electron
* @param pnu Momentum of final state Neutrino
* @param p1in Momentum of initial state anti-quark
* @param p2out Momentum of final state quark
* @param p2in Momentum of intial state quark
* @returns Square of the current contractions for qbarQ->qbarenuQ Scattering
*
* This returns the square of the current contractions in qbarQ->qbarenuQ scattering
* with an emission of a W Boson.
*/
double jMWqbarQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
//! Square of qQbar->qenuQbar W+Jets Scattering Current
/**
* @param p1out Momentum of final state quark
* @param pe Momentum of final state electron
* @param pnu Momentum of final state Neutrino
* @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->qenuQbar Scattering
*
* This returns the square of the current contractions in qQbar->qenuQbar scattering
* with an emission of a W Boson.
*/
double jMWqQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
//! Square of qbarQbar->qbarenuQbar W+Jets Scattering Current
/**
* @param p1out Momentum of final state anti-quark
* @param pe Momentum of final state electron
* @param pnu Momentum of final state Neutrino
* @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->qbarenuQbar Scattering
*
* This returns the square of the current contractions in qbarQbar->qbarenuQbar scattering
* with an emission of a W Boson.
*/
double jMWqbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
//! Square of qg->qenug W+Jets Scattering Current
/**
* @param p1out Momentum of final state quark
* @param pe Momentum of final state electron
* @param pnu Momentum of final state Neutrino
* @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->qenug Scattering
*
* This returns the square of the current contractions in qg->qenug scattering
* with an emission of a W Boson.
*/
double jMWqg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
//! Square of qbarg->qbarenug W+Jets Scattering Current
/**
* @param p1out Momentum of final state anti-quark
* @param pe Momentum of final state electron
* @param pnu Momentum of final state Neutrino
* @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->qbarenug Scattering
*
* This returns the square of the current contractions in qbarg->qbarenug scattering
* with an emission of a W Boson.
*/
double jMWqbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe,
CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+// W+Jets Unordered Functions
+
+//! qQg Wjets Unordered backwards opposite leg to W
+/**
+ * @param p1out Momentum of final state quark a
+ * @param pe Momentum of final state electron
+ * @param pnu Momentum of final state Neutrino
+ * @param p1in Momentum of initial state quark a
+ * @param p2out Momentum of final state quark b
+ * @param p2in Momentum of intial state quark b
+ * @param pg Momentum of final state unordered gluon
+ * @returns Square of the current contractions for qQ->qQg Scattering
+ *
+ * This returns the square of the current contractions in qQg->qQg scattering
+ * with an emission of a W Boson.
+ */
+double junobMWqQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg);
+
+//! qbarQg Wjets Unordered backwards opposite leg to W
+/**
+ * @param p1out Momentum of final state anti-quark a
+ * @param pe Momentum of final state electron
+ * @param pnu Momentum of final state Neutrino
+ * @param p1in Momentum of initial state anti-quark a
+ * @param p2out Momentum of final state quark b
+ * @param p2in Momentum of intial state quark b
+ * @param pg Momentum of final state unordered gluon
+ * @returns Square of the current contractions for qbarQ->qbarQg Scattering
+ *
+ * This returns the square of the current contractions in qbarQg->qbarQg scattering
+ * with an emission of a W Boson.
+ */
+double junobMWqbarQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg);
+
+
+
+//! qQbarg Wjets Unordered backwards opposite leg to W
+/**
+ * @param p1out Momentum of final state quark a
+ * @param pe Momentum of final state electron
+ * @param pnu Momentum of final state Neutrino
+ * @param p1in Momentum of initial state quark a
+ * @param p2out Momentum of final state anti-quark b
+ * @param p2in Momentum of intial state anti-quark b
+ * @param pg Momentum of final state unordered gluon
+ * @returns Square of the current contractions for qQbar->qQbarg Scattering
+ *
+ * This returns the square of the current contractions in qQbarg->qQbarg scattering
+ * with an emission of a W Boson.
+ */
+double junobMWqQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg);
+
+//! qbarQbarg Wjets Unordered backwards opposite leg to W
+/**
+ * @param p1out Momentum of final state anti-quark a
+ * @param pe Momentum of final state electron
+ * @param pnu Momentum of final state Neutrino
+ * @param p1in Momentum of initial state anti-quark a
+ * @param p2out Momentum of final state anti-quark b
+ * @param p2in Momentum of intial state anti-quark b
+ * @param pg Momentum of final state unordered gluon
+ * @returns Square of the current contractions for qbarQbar->qbarQbarg Scattering
+ *
+ * This returns the square of the current contractions in qbarQbarg->qbarQbarg scattering
+ * with an emission of a W Boson.
+ */
+double junobMWqbarQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg);
+
+
+//!Wjets Unordered forwards opposite leg to W
+/**
+ * @param pg Momentum of final state unordered gluon
+ * @param p1out Momentum of final state quark a
+ * @param pe Momentum of final state electron
+ * @param pnu Momentum of final state Neutrino
+ * @param p1in Momentum of initial state quark a
+ * @param p2out Momentum of final state quark b
+ * @param p2in Momentum of intial state quark b
+ * @returns Square of the current contractions for qQ->gqQ Scattering
+ *
+ * This returns the square of the current contractions in qQg->gqQ scattering
+ * with an emission of a W Boson.
+ */
+double junofMWgqQ (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in);
+
+//!Wjets Unordered forwards opposite leg to W
+/**
+ * @param pg Momentum of final state unordered gluon
+ * @param p1out Momentum of final state anti-quark a
+ * @param pe Momentum of final state electron
+ * @param pnu Momentum of final state Neutrino
+ * @param p1in Momentum of initial state anti-quark a
+ * @param p2out Momentum of final state quark b
+ * @param p2in Momentum of intial state quark b
+ * @returns Square of the current contractions for qbarQ->gqbarQ Scattering
+ *
+ * This returns the square of the current contractions in qbarQg->gqbarQ scattering
+ * with an emission of a W Boson.
+ */
+double junofMWgqbarQ (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in);
+
+//!Wjets Unordered forwards opposite leg to W
+/**
+ * @param pg Momentum of final state unordered gluon
+ * @param p1out Momentum of final state quark a
+ * @param pe Momentum of final state electron
+ * @param pnu Momentum of final state Neutrino
+ * @param p1in Momentum of initial state quark a
+ * @param p2out Momentum of final state anti-quark b
+ * @param p2in Momentum of intial state anti-quark b
+ * @returns Square of the current contractions for qQbar->gqQbar Scattering
+ *
+ * This returns the square of the current contractions in qQbarg->gqQbar scattering
+ * with an emission of a W Boson.
+ */
+double junofMWgqQbar (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in);
+
+//!Wjets Unordered forwards opposite leg to W
+/**
+ * @param pg Momentum of final state unordered gluon
+ * @param p1out Momentum of final state anti-quark a
+ * @param pe Momentum of final state electron
+ * @param pnu Momentum of final state Neutrino
+ * @param p1in Momentum of initial state anti-quark a
+ * @param p2out Momentum of final state anti-quark b
+ * @param p2in Momentum of intial state anti-quark b
+ * @returns Square of the current contractions for qbarQbar->gqbarQbar Scattering
+ *
+ * This returns the square of the current contractions in qbarQbarg->gqbarQbar scattering
+ * with an emission of a W Boson.
+ */
+double junofMWgqbarQbar (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in);
+
+//!W+uno same leg
+/**
+ * @param pg Momentum of final state unordered gluon
+ * @param p1out Momentum of final state quark a
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param p1in Momentum of initial state quark a
+ * @param p2out Momentum of final state quark b
+ * @param p2in Momentum of intial state quark b
+ * @returns Square of the current contractions for qQ->qQg Scattering
+ *
+ * This returns the square of the current contractions in gqQ->gqQ scattering
+ * with an emission of a W Boson.
+ */
+double jM2WunogqQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+
+//! @TODO What does this function do? Crossed contribution is Exqqx..?
+/**
+ * @param pg Momentum of final state unordered gluon
+ * @param p1out Momentum of final state quark a
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param p1in Momentum of initial state quark a
+ * @param p2out Momentum of final state quark b
+ * @param p2in Momentum of intial state quark b
+ * @returns Square of the current contractions for qQ->gqQ Scattering
+ *
+ * This returns the square of the current contractions in gqQ->gqQ scattering
+ * with an emission of a W Boson.
+ */
+double jM2WunogqQ_crossqQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+
+//! W+uno same leg. quark anti-quark
+/**
+ * @param pg Momentum of final state unordered gluon
+ * @param p1out Momentum of final state quark a
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param p1in Momentum of initial state quark a
+ * @param p2out Momentum of final state anti-quark b
+ * @param p2in Momentum of intial state anti-quark b
+ * @returns Square of the current contractions for qQbar->gqQbar Scattering
+ *
+ * This returns the square of the current contractions in gqQbar->gqQbar scattering
+ * with an emission of a W Boson. (Unordered Same Leg)
+ */
+double jM2WunogqQbar(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+
+//! W+uno same leg. quark gluon
+/**
+ * @param pg Momentum of final state unordered gluon
+ * @param p1out Momentum of final state quark a
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param p1in Momentum of initial state quark a
+ * @param p2out Momentum of final state gluon b
+ * @param p2in Momentum of intial state gluon b
+ * @returns Square of the current contractions for qg->gqg Scattering
+ *
+ * This returns the square of the current contractions in qg->gqg scattering
+ * with an emission of a W Boson.
+ */
+double jM2Wunogqg(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+
+//! W+uno same leg. anti-quark quark
+/**
+ * @param pg Momentum of final state unordered gluon
+ * @param p1out Momentum of final state anti-quark a
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param p1in Momentum of initial state anti-quark a
+ * @param p2out Momentum of final state quark b
+ * @param p2in Momentum of intial state quark b
+ * @returns Square of the current contractions for qbarQ->gqbarQ Scattering
+ *
+ * This returns the square of the current contractions in qbarQ->gqbarQ scattering
+ * with an emission of a W Boson.
+ */
+double jM2WunogqbarQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+
+//! W+uno same leg. anti-quark anti-quark
+/**
+ * @param pg Momentum of final state unordered gluon
+ * @param p1out Momentum of final state anti-quark a
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param p1in Momentum of initial state anti-quark a
+ * @param p2out Momentum of final state anti-quark b
+ * @param p2in Momentum of intial state anti-quark b
+ * @returns Square of the current contractions for qbarQbar->gqbarQbar Scattering
+ *
+ * This returns the square of the current contractions in gqbarQbar->qbarQbar scattering
+ * with an emission of a W Boson.
+ */
+double jM2WunogqbarQbar(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+
+//! W+uno same leg. anti-quark gluon
+/**
+ * @param pg Momentum of final state unordered gluon
+ * @param p1out Momentum of final state anti-quark a
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param p1in Momentum of initial state anti-quark a
+ * @param p2out Momentum of final state gluon b
+ * @param p2in Momentum of intial state gluon b
+ * @returns Square of the current contractions for ->gqbarg Scattering
+ *
+ * This returns the square of the current contractions in qbarg->gqbarg scattering
+ * with an emission of a W Boson.
+ */
+double jM2Wunogqbarg(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+
+//W+Jets qqxExtremal
+//! W+Extremal qqx. qxqQ
+/**
+ * @param pgin Momentum of initial state gluon
+ * @param pqout Momentum of final state quark a
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param pqbarout Momentum of final state anti-quark a
+ * @param p2out Momentum of initial state anti-quark b
+ * @param p2in Momentum of final state gluon b
+ * @returns Square of the current contractions for ->qbarqQ Scattering
+ *
+ * Calculates the square of the current contractions with extremal qqbar pair
+ * production. This is calculated through the use of crossing symmetry.
+ */
+double jM2WgQtoqbarqQ(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqbarout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+
+//W+Jets qqxExtremal
+//! W+Extremal qqx. qqxQ
+/**
+ * @param pgin Momentum of initial state gluon
+ * @param pqout Momentum of final state quark a
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param pqbarout Momentum of final state anti-quark a
+ * @param p2out Momentum of initial state anti-quark b
+ * @param p2in Momentum of final state gluon b
+ * @returns Square of the current contractions for ->qqbarQ Scattering
+ *
+ * Calculates the square of the current contractions with extremal qqbar pair
+ * production. This is calculated through the use of crossing symmetry.
+ */
+double jM2WgQtoqqbarQ(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqbarout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+
+//W+Jets qqxExtremal
+//! W+Extremal qqx. gg->qxqg
+/**
+ * @param pgin Momentum of initial state gluon
+ * @param pqout Momentum of final state quark a
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param pqbarout Momentum of final state anti-quark a
+ * @param p2out Momentum of initial state gluon b
+ * @param p2in Momentum of final state gluon b
+ * @returns Square of the current contractions for gg->qbarqg Scattering
+ *
+ * Calculates the square of the current contractions with extremal qqbar pair
+ * production. This is calculated through the use of crossing symmetry.
+ */
+double jM2Wggtoqbarqg(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqbarout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+
+//W+Jets qqxExtremal
+//! W+Extremal qqx. gg->qqxg
+/**
+ * @param pgin Momentum of initial state gluon
+ * @param pqout Momentum of final state quark a
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param pqbarout Momentum of final state anti-quark a
+ * @param p2out Momentum of initial state gluon a
+ * @param p2in Momentum of final state gluon b
+ * @returns Square of the current contractions for gg->qqbarg Scattering
+ *
+ * Calculates the square of the current contractions with extremal qqbar pair
+ * production. This is calculated through the use of crossing symmetry.
+ */
+double jM2Wggtoqqbarg(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqbarout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
+
+//W+Jets qqxExtremal, W emission from opposite leg
+//! W+Extremal qqx. gg->qqxg. qqx on forwards leg, W emission backwards leg.
+/**
+ * @param pa Momentum of initial state (anti-)quark
+ * @param pb Momentum of initial state gluon
+ * @param p1 Momentum of final state (anti-)quark (after W emission)
+ * @param p2 Momentum of final state anti-quark
+ * @param p3 Momentum of final state quark
+ * @param plbar Momentum of final state anti-lepton
+ * @param pl Momentum of final state lepton
+ * @param aqlinepa Is opposite extremal leg to qqx a quark or antiquark line
+ * @returns Square of the current contractions for gq->qqbarqW Scattering
+ *
+ * Calculates the square of the current contractions with extremal qqbar pair
+ * production. This is calculated via current contraction of existing currents.
+ * Assumes qqx split from forwards leg, W emission from backwards leg.
+ * Switch input (pa<->pb, p1<->pn) if calculating forwards qqx.
+ */
+double jM2WgqtoQQqW(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p3,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, bool aqlinepa);
+
+//! W+Jets qqxCentral. qqx W emission.
+/**
+ * @param pa Momentum of initial state particle a
+ * @param pb Momentum of initial state particle b
+ * @param pl Momentum of final state lepton
+ * @param plbar Momentum of final state anti-lepton
+ * @param partons Vector of outgoing parton momenta
+ * @param aqlinepa Bool: True= pa is anti-quark
+ * @param aqlinepb Bool: True= pb is anti-quark
+ * @param qqxmarker Bool: Ordering of the qqbar pair produced (qqx vs qxq)
+ * @param nabove Number of lipatov vertices "above" qqbar pair
+ * @param nbelow Number of lipatov vertices "below" qqbar pair
+ * @returns Square of the current contractions for qq>qQQbarWq Scattering
+ *
+ * Calculates the square of the current contractions with extremal qqbar pair
+ * production. This is calculated through the use of crossing symmetry.
+ */
+double jM2WqqtoqQQq(HLV pa, HLV pb,HLV pl,HLV plbar, std::vector<HLV> partons, bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove);
+//emission from backwards leg
+
+//! W+Jets qqxCentral. W emission from backwards leg.
+/**
+ * @param ka HLV: Momentum of initial state particle a
+ * @param kb HLV: Momentum of initial state particle b
+ * @param pl HLV: Momentum of final state lepton
+ * @param plbar HLV: Momentum of final state anti-lepton
+ * @param partons Vector(HLV): outgoing parton momenta
+ * @param aqlinepa Bool: True= pa is anti-quark
+ * @param aqlinepb Bool: True= pb is anti-quark
+ * @param qqxmarker Bool: Ordering of the qqbar pair produced (qqx vs qxq)
+ * @param nabove Int: Number of lipatov vertices "above" qqbar pair
+ * @param nbelow Int: Number of lipatov vertices "below" qqbar pair
+ * @param forwards Bool: Swap to emission off front leg TODO:remove so args can be const
+ * @returns Square of the current contractions for qq>qQQbarWq Scattering
+ *
+ * Calculates the square of the current contractions with extremal qqbar pair
+ * production. This is calculated through the use of crossing symmetry.
+ */
+double jM2WqqtoqQQqW(HLV ka, HLV kb,HLV pl,HLV plbar, std::vector<HLV> partons, bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove, int nbelow, bool forwards); //Doing
+
+
+
//! 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
*
* This returns the square of the current contractions in qQ->qQ Pure Jet Scattering.
*/
double jM2qQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector 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
*
* This returns the square of the current contractions in qQbar->qQbar Pure Jet Scattering.
* Note this can be used for qbarQ->qbarQ Scattering by inputting arguments appropriately.
*/
double jM2qQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector 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
*
* This returns the square of the current contractions in qbarQbar->qbarQbar Pure Jet Scattering.
*/
double jM2qbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector 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
*
* This returns the square of the current contractions in qg->qg Pure Jet Scattering.
* Note this can be used for gq->gq Scattering by inputting arguments appropriately.
*/
double jM2qg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector 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
*
* This returns the square of the current contractions in qbarg->qbarg Pure Jet Scattering.
* Note this can be used for gqbar->gqbar Scattering by inputting arguments appropriately.
*/
double jM2qbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector 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
*
* This returns the square of the current contractions in gg->gg Pure Jet Scattering.
*/
double jM2gg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in);
//! Square of gg->gg Higgs+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
* @param q1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for gg->gg Scattering
*
* This returns the square of the current contractions in gg->gg Higgs+Jet Scattering.
*
* g~p1 g~p2
* should be called with q1 meant to be contracted with p2 in first part of vertex
* (i.e. if g is backward, q1 is forward)
*/
double MH2gg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of gq->gq Higgs+Jets Scattering Current with Higgs before Gluon
/**
* @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
* @param pH Momentum of Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contraction
*
*/
double MH2gq_outsideH(CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
CLHEP::HepLorentzVector pH,
double mt,
bool include_bottom, double mb);
//! Square of qg->qg Higgs+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
* @param q1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qg->qg Scattering
*
* This returns the square of the current contractions in qg->qg Higgs+Jet Scattering.
*
* q~p1 g~p2 (i.e. ALWAYS p1 for quark, p2 for gluon)
* should be called with q1 meant to be contracted with p2 in first part of vertex
* (i.e. if g is backward, q1 is forward)
*/
double MH2qg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qbarg->qbarg Higgs+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
* @param q1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qbarg->qbarg Scattering
*
* This returns the square of the current contractions in qbarg->qbarg Higgs+Jet Scattering.
*
* qbar~p1 g~p2 (i.e. ALWAYS p1 for anti-quark, p2 for gluon)
* should be called with q1 meant to be contracted with p2 in first part of vertex
* (i.e. if g is backward, q1 is forward)
*/
double MH2qbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qQ->qQ Higgs+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
* @param q1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qQ->qQ Scattering
*
* This returns the square of the current contractions in qQ->qQ Higgs+Jet Scattering.
*
* q~p1 Q~p2 (i.e. ALWAYS p1 for quark, p2 for quark)
* should be called with q1 meant to be contracted with p2 in first part of vertex
* (i.e. if Q is backward, q1 is forward)
*/
double MH2qQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qQbar->qQbar Higgs+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
* @param q1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qQ->qQ Scattering
*
* This returns the square of the current contractions in qQbar->qQbar Higgs+Jet Scattering.
*
* q~p1 Qbar~p2 (i.e. ALWAYS p1 for quark, p2 for anti-quark)
* should be called with q1 meant to be contracted with p2 in first part of vertex
* (i.e. if Qbar is backward, q1 is forward)
*/
double MH2qQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qbarQ->qbarQ Higgs+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 quark
* @param p2in Momentum of intial state quark
* @param q1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qbarQ->qbarQ Scattering
*
* This returns the square of the current contractions in qbarQ->qbarQ Higgs+Jet Scattering.
*
* qbar~p1 Q~p2 (i.e. ALWAYS p1 for anti-quark, p2 for quark)
* should be called with q1 meant to be contracted with p2 in first part of vertex
* (i.e. if Q is backward, q1 is forward)
*/
double MH2qbarQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qbarQbar->qbarQbar Higgs+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
* @param q1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qbarQbar->qbarQbar Scattering
*
* This returns the square of the current contractions in qbarQbar->qbarQbar Higgs+Jet Scattering.
*
* qbar~p1 Qbar~p2 (i.e. ALWAYS p1 for anti-quark, p2 for anti-quark)
* should be called with q1 meant to be contracted with p2 in first part of vertex
* (i.e. if Qbar is backward, q1 is forward)
*/
double MH2qbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
// Unordered f
//! Square of qQ->gqQ Higgs+Jets Unordered f Scattering Current
/**
* @param pg Momentum of unordered gluon
* @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
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qQ->gqQ Scattering
*
* This returns the square of the current contractions in qQ->gqQ Higgs+Jet Scattering.
*
* This construction is taking rapidity order: pg > p1out >> p2out
*/
double jM2unogqHQ (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qQbar->gqQbar Higgs+Jets Unordered f Scattering Current
/**
* @param pg Momentum of unordered gluon
* @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
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qQbar->gqQbar Scattering
*
* This returns the square of the current contractions in qQbar->gqQbar Higgs+Jet Scattering.
*
* This construction is taking rapidity order: pg > p1out >> p2out
*/
double jM2unogqHQbar (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qbarQ->gqbarQ Higgs+Jets Unordered f Scattering Current
/**
* @param pg Momentum of unordered gluon
* @param p1out Momentum of final state anti-quark
* @param p1in Momentum of initial state anti-quark
* @param p2out Momentum of final state quark
* @param p2in Momentum of intial state quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qbarQ->gqbarQ Scattering
*
* This returns the square of the current contractions in qbarQ->gqbarQ Higgs+Jet Scattering.
*
* This construction is taking rapidity order: pg > p1out >> p2out
*/
double jM2unogqbarHQ (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qbarQbar->gqbarQbar Higgs+Jets Unordered f Scattering Current
/**
* @param pg Momentum of unordered gluon
* @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
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qbarQbar->gqbarQbar Scattering
*
* This returns the square of the current contractions in qbarQbar->gqbarQbar Higgs+Jet Scattering.
*
* This construction is taking rapidity order: pg > p1out >> p2out
*/
double jM2unogqbarHQbar (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qg->gqg Higgs+Jets Unordered f Scattering Current
/**
* @param pg Momentum of unordered gluon
* @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
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qg->gqg Scattering
*
* This returns the square of the current contractions in qg->gqg Higgs+Jet Scattering.
*
* This construction is taking rapidity order: pg > p1out >> p2out
*/
double jM2unogqHg (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qbarg->gqbarg Higgs+Jets Unordered f Scattering Current
/**
* @param pg Momentum of unordered gluon
* @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
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qbarg->gbarg Scattering
*
* This returns the square of the current contractions in qbarg->gqbarg Higgs+Jet Scattering.
*
* This construction is taking rapidity order: pg > p1out >> p2out
*/
double jM2unogqbarHg (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,
CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//Unordered b
//! Square of qbarQ->qbarQg Higgs+Jets Unordered b Scattering Current
/**
* @param p1out Momentum of final state anti-quark
* @param p1in Momentum of initial state anti-quark
* @param pg Momentum of unordered b gluon
* @param p2out Momentum of final state quark
* @param p2in Momentum of intial state quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qbarQ->qbarQg Scattering
*
* This returns the square of the current contractions in qbarQ->qbarQg Higgs+Jet Scattering.
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double jM2unobqbarHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qQ->qQg Higgs+Jets Unordered b Scattering Current
/**
* @param p1out Momentum of final state quark
* @param p1in Momentum of initial state quark
* @param pg Momentum of unordered b gluon
* @param p2out Momentum of final state quark
* @param p2in Momentum of intial state quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qQ->qQg Scattering
*
* This returns the square of the current contractions in qQ->qQg Higgs+Jet Scattering.
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double jM2unobqHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qQbar->qQbarg Higgs+Jets Unordered b Scattering Current
/**
* @param p1out Momentum of final state quark
* @param p1in Momentum of initial state quark
* @param pg Momentum of unordered b gluon
* @param p2out Momentum of final state anti-quark
* @param p2in Momentum of intial state anti-quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qQbar->qQbarg Scattering
*
* This returns the square of the current contractions in qQbar->qQbarg Higgs+Jet Scattering.
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double jM2unobqHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of qbarQbar->qbarQbarg Higgs+Jets Unordered b Scattering Current
/**
* @param p1out Momentum of final state anti-quark
* @param p1in Momentum of initial state anti-quark
* @param pg Momentum of unordered b gluon
* @param p2out Momentum of final state anti-quark
* @param p2in Momentum of intial state anti-quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for qbarQbar->qbarQbarg Scattering
*
* This returns the square of the current contractions in qbarQbar->qbarQbarg Higgs+Jet Scattering.
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double jM2unobqbarHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of gQbar->gQbarg Higgs+Jets Unordered b Scattering Current
/**
* @param p1out Momentum of final state gluon
* @param p1in Momentum of initial state gluon
* @param pg Momentum of unordered b gluon
* @param p2out Momentum of final state anti-quark
* @param p2in Momentum of intial state anti-quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for gQbar->gQbarg Scattering
*
* This returns the square of the current contractions in gQbar->gQbarg Higgs+Jet Scattering.
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double jM2unobgHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
//! Square of gQ->gQg Higgs+Jets Unordered b Scattering Current
/**
* @param p1out Momentum of final state gluon
* @param p1in Momentum of initial state gluon
* @param pg Momentum of unordered b gluon
* @param p2out Momentum of final state quark
* @param p2in Momentum of intial state quark
* @param qH1 Momentum of t-channel propagator before Higgs
* @param qH2 Momentum of t-channel propagator after Higgs
* @param mt Top quark mass
* @param include_bottom Specifies whether bottom corrections are included
* @param mb Bottom quark mass
* @returns Square of the current contractions for gQ->gQg Scattering
*
* This returns the square of the current contractions in gQ->gQg Higgs+Jet Scattering.
*
* This construction is taking rapidity order: p1out >> p2out > pg
*/
double jM2unobgHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out,
CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1,
CLHEP::HepLorentzVector qH2,
double mt,
bool include_bottom, double mb);
// impact factors for Higgs + jet
//! Implements Eq. (4.22) in hep-ph/0301013 with modifications to incoming plus momenta
/**
* @param p2 Momentum of Particle 2
* @param p1 Momentum of Particle 1
* @param pH Momentum of Higgs
* @returns Value of Eq. (4.22) in Hep-ph/0301013 with modifications
*
* This gives the impact factor. First it determines first whether this is the case
* p1p\sim php>>p3p or the opposite
*/
double C2gHgm(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1,
CLHEP::HepLorentzVector pH);
//! Implements Eq. (4.23) in hep-ph/0301013 with modifications to incoming plus momenta
/**
* @param p2 Momentum of Particle 2
* @param p1 Momentum of Particle 1
* @param pH Momentum of Higgs
* @returns Value of Eq. (4.23) in Hep-ph/0301013
*
* This gives the impact factor. First it determines first whether this is the case
* p1p\sim php>>p3p or the opposite
*/
double C2gHgp(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1,
CLHEP::HepLorentzVector pH);
//! Implements Eq. (4.22) in hep-ph/0301013
/**
* @param p2 Momentum of Particle 2
* @param p1 Momentum of Particle 1
* @param pH Momentum of Higgs
* @returns Value of Eq. (4.22) in Hep-ph/0301013
*
* This gives the impact factor. First it determines first whether this is the case
* p1p\sim php>>p3p or the opposite
*/
double C2qHqm(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1,
CLHEP::HepLorentzVector pH);
/** \class CCurrent currents.hh "include/HEJ/currents.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 CLHEP::HepLorentzVector 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(CLHEP::HepLorentzVector p1);
COM dot(CCurrent p1);
COM c0,c1,c2,c3;
private:
};
/* 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 <outgoing state | mu | incoming state>
+/**
+ * These functions are a mess. There are many more defined in the source file than declared in the
+ * header - and the arguments are mislabelled in some cases. Need to investigate.
+ */
+//! @TODO remove
+[[deprecated("Use joi instead")]]
+void j (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin, bool helin,current &cur);
+
+//! Current <incoming state | mu | outgoing state>
+/**
+ * These functions are a mess. There are many more defined in the source file than declared in the
+ * header - and the arguments are mislabelled in some cases. Need to investigate.
+ */
+void jio(HLV pin, bool helin, HLV pout, bool helout, current &cur);
+
+//! Current <outgoing state | mu | outgoing state>
+/**
+ * These functions are a mess. There are many more defined in the source file than declared in the
+ * header - and the arguments are mislabelled in some cases. Need to investigate.
+ */
+void joo(HLV pi, bool heli, HLV pj, bool helj, current &cur);
+
+//! Current <outgoing state | mu | incoming state>
+/**
+ * These functions are a mess. There are many more defined in the source file than declared in the
+ * header - and the arguments are mislabelled in some cases. Need to investigate.
+ */
+void joi(HLV pout, bool helout, HLV pin, bool helin, current &cur);
+
//! Current <outgoing state | mu | incoming state>
/**
* These functions are a mess. There are many more defined in the source file than declared in the
* header - and the arguments are mislabelled in some cases. Need to investigate.
*/
//! @TODO remove
[[deprecated("Use joi instead")]]
CCurrent j (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin, bool helin);
//! Current <outgoing state | mu | incoming state>
/**
* These functions are a mess. There are many more defined in the source file than declared in the
* header - and the arguments are mislabelled in some cases. Need to investigate.
*/
CCurrent joi (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin, bool helin);
//! Current <incoming state | mu | outgoing state>
/**
* These functions are a mess. There are many more defined in the source file than declared in the
* header - and the arguments are mislabelled in some cases. Need to investigate.
*/
CCurrent jio (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin, bool helin);
//! Current <outgoing state | mu | outgoing state>
/**
* These functions are a mess. There are many more defined in the source file than declared in the
* header - and the arguments are mislabelled in some cases. Need to investigate.
*/
CCurrent joo (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin, bool helin);
-/* // Coupling values */
-/* const double stw2 = 0.2222; */
-/* const double ctw = sqrt(1.0 - stw2); */
-/* const double gs = 1.217716; */
-/* const double gw = 0.653232911; */
-/* const double Zem = (-1.0 / 2.0 + stw2) / ctw; */
-/* const double Zep = stw2 / ctw; */
-/* const double Zum = ( 1.0 / 2.0 - 2.0 * stw2 / 3.0) / ctw; */
-/* const double Zup = - 2.0 * stw2 / 3.0 / ctw; */
-/* const double Zdm = (-1.0 / 2.0 + 1.0 / 3.0 * stw2) / ctw; */
-/* const double Zdp = stw2 / 3.0 / ctw; */
-/* const double RWeak = -pow(gw, 2.0); */
-/* const double Strong = pow(gs, 4.0); */
-/* const double ee = pow(gw, 2.0) * stw2; */
-
-
-/* std::vector <double> jMZqQ (HLV, HLV, HLV, HLV, HLV, HLV, std::vector <double>, std::vector < std::vector <double> >, int, int, bool, bool); */
-/* std::vector <double> jMZqg (HLV, HLV, HLV, HLV, HLV, HLV, std::vector <double>, std::vector < std::vector <double> >, int, int, bool, bool); */
-/* void jZ (HLV, HLV, HLV, HLV, bool, bool, current); */
-/* void jZbar (HLV, HLV, HLV, HLV, bool, bool, current); */
-/* COM PZ(double); */
-/* double Zq (int, bool); */
-/* double Gq (int); */
+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(CLHEP::HepLorentzVector const & pout, CLHEP::HepLorentzVector const & pin);
diff --git a/include/HEJ/event_types.hh b/include/HEJ/event_types.hh
index df60728..ac85fd6 100644
--- a/include/HEJ/event_types.hh
+++ b/include/HEJ/event_types.hh
@@ -1,65 +1,82 @@
/** \file
* \brief Define different types of events.
*
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#pragma once
#include "HEJ/utility.hh"
namespace HEJ{
//! Namespace for event types
namespace event_type{
//! Possible event types
enum EventType: size_t{
FKL, /**< FKL-type event */
unordered_backward, /**< event with unordered backward emission */
unordered_forward, /**< event with unordered forward emission */
+ extremal_qqxb, /**< event with a backward extremal qqbar */
+ extremal_qqxf, /**< event with a forward extremal qqbar */
+ central_qqx, /**< event with a central qqbar */
nonHEJ, /**< event configuration not covered by HEJ */
no_2_jets, /**< event with less than two jets */
bad_final_state, /**< event with an unsupported final state */
unob = unordered_backward,
unof = unordered_forward,
+ qqxexb = extremal_qqxb,
+ qqxexf = extremal_qqxf,
+ qqxmid = central_qqx,
first_type = FKL,
last_type = bad_final_state
};
//! Event type names
/**
* For example, names[FKL] is the string "FKL"
*/
static constexpr auto names = make_array(
"FKL",
"unordered backward",
"unordered forward",
+ "extremal qqbar backward",
+ "extremal qqbar forward",
+ "central qqbar",
"nonHEJ",
"no 2 jets",
"bad final state"
);
//! Returns True for a HEJ \ref event_type::EventType "EventType"
inline
bool is_HEJ(EventType type) {
switch(type) {
case FKL:
case unordered_backward:
case unordered_forward:
+ case extremal_qqxb:
+ case extremal_qqxf:
+ case central_qqx:
return true;
default:
return false;
}
}
//! Returns True for an unordered \ref event_type::EventType "EventType"
inline
bool is_uno(EventType type) {
return type == unordered_backward || type == unordered_forward;
}
+ inline
+ bool is_qqx(EventType type) {
+ return type == extremal_qqxb || type == extremal_qqxf || type == central_qqx;
+ }
+
}
}
diff --git a/include/HEJ/utility.hh b/include/HEJ/utility.hh
index 83f6e4a..9d2d53e 100644
--- a/include/HEJ/utility.hh
+++ b/include/HEJ/utility.hh
@@ -1,105 +1,104 @@
/**
* \file
* \brief Contains various utilities
*
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#pragma once
#include <memory>
#include <boost/core/demangle.hpp>
#include "fastjet/PseudoJet.hh"
namespace HEJ{
//! Create a std::unique_ptr to a T object
/**
* For non-array types this works like std::make_unique,
* which is not available under C++11
*/
template<class T, class... Args>
std::unique_ptr<T> make_unique(Args&&... a){
return std::unique_ptr<T>{new T{std::forward<Args>(a)...}};
}
//! Create an array containing the passed arguments
template<typename T, typename... U>
constexpr
std::array<T, 1 + sizeof...(U)> make_array(T t, U&&... rest){
return {{t, std::forward<U>(rest)...}};
}
inline
std::string join(
std::string const & /* delim */
){
return "";
}
inline
std::string join(
std::string const & /* delim */, std::string const & str
){
return str;
}
//! Join strings with a delimiter
/**
* @param delim Delimiter to be put between consecutive strings
* @param first First string
* @param second Second string
* @param rest Remaining strings
*/
template<typename... Strings>
std::string join(
std::string const & delim,
std::string const & first, std::string const & second,
Strings&&... rest
){
return join(delim, first + delim + second, std::forward<Strings>(rest)...);
}
//! Return the name of the argument's type
template<typename T>
std::string type_string(T&&){
return boost::core::demangle(typeid(T).name());
}
//! Eliminate compiler warnings for unused variables
template<typename... T>
constexpr void ignore(T&&...) {}
//! Check whether two doubles are closer than ep > 0 to each other
inline
bool nearby_ep(double a, double b, double ep){
assert(ep > 0);
return std::abs(a-b) < ep;
}
//! Check whether all components of two PseudoJets are closer than ep to each other
inline
bool nearby_ep(
fastjet::PseudoJet const & pa, fastjet::PseudoJet const & pb,
double ep
){
assert(ep > 0);
for(size_t i = 0; i < 4; ++i){
if(!nearby_ep(pa[i], pb[i], ep)) return false;
}
return true;
}
inline
bool nearby(
fastjet::PseudoJet const & pa, fastjet::PseudoJet const & pb, double const norm = 1.
){
return nearby_ep(pa, pb, 1e-7*norm);
}
-
}
diff --git a/src/Event.cc b/src/Event.cc
index ae2e3df..66ec30f 100644
--- a/src/Event.cc
+++ b/src/Event.cc
@@ -1,487 +1,795 @@
/**
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#include "HEJ/Event.hh"
#include <algorithm>
#include <assert.h>
#include <numeric>
#include <utility>
#include "LHEF/LHEF.h"
#include "fastjet/JetDefinition.hh"
#include "HEJ/Constants.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/PDG_codes.hh"
namespace HEJ{
namespace{
constexpr int status_in = -1;
constexpr int status_decayed = 2;
constexpr int status_out = 1;
/// @name helper functions to determine event type
//@{
/**
* \brief check if final state valid for HEJ
*
* check if there is at most one photon, W, H, Z in the final state
* and all the rest are quarks or gluons
*/
bool final_state_ok(std::vector<Particle> const & outgoing){
bool has_AWZH_boson = false;
for(auto const & out: outgoing){
if(is_AWZH_boson(out.type)){
if(has_AWZH_boson) return false;
has_AWZH_boson = true;
}
else if(! is_parton(out.type)) return false;
}
return true;
}
template<class Iterator>
Iterator remove_AWZH(Iterator begin, Iterator end){
return std::remove_if(
begin, end, [](Particle const & p){return is_AWZH_boson(p);}
);
}
template<class Iterator>
bool valid_outgoing(Iterator begin, Iterator end){
return std::distance(begin, end) >= 2
&& std::is_sorted(begin, end, rapidity_less{})
&& std::count_if(
begin, end, [](Particle const & s){return is_AWZH_boson(s);}
) < 2;
}
- /// @note that this changes the outgoing range!
+ /**
+ * \brief function which determines if type change is consistent with W emission.
+ * @param in incoming Particle
+ * @param out outgoing Particle
+ *
+ * Ensures that change type of quark line is possible by a flavour changing
+ * W emission.
+ */
+ bool is_W_Current(ParticleID in, ParticleID out){
+ if((in==1 && out==2)||(in==2 && out==1)){
+ return true;
+ }
+ else if((in==-1 && out==-2)||(in==-2 && out==-1)){
+ return true;
+ }
+ else if((in==3 && out==4)||(in==4 && out==3)){
+ return true;
+ }
+ else if((in==-3 && out==-4)||(in==-4 && out==-3)){
+ return true;
+ }
+ else{
+ return false;
+ }
+ }
+
+ /**
+ * \brief checks if particle type remains same from incoming to outgoing
+ * @param in incoming Particle
+ * @param out outgoing Particle
+ */
+ bool is_Pure_Current(ParticleID in, ParticleID out){
+ if(abs(in)<=6 || in==21) return (in==out);
+ else return false;
+ }
+
+
+ // @note that this changes the outgoing range!
template<class ConstIterator, class Iterator>
bool is_FKL(
ConstIterator begin_incoming, ConstIterator end_incoming,
Iterator begin_outgoing, Iterator end_outgoing
){
assert(std::distance(begin_incoming, end_incoming) == 2);
assert(std::distance(begin_outgoing, end_outgoing) >= 2);
// One photon, W, H, Z in the final state is allowed.
// Remove it for remaining tests,
end_outgoing = remove_AWZH(begin_outgoing, end_outgoing);
- // Test if this is a standard FKL configuration.
- return
- (begin_incoming->type == begin_outgoing->type)
- && ((end_incoming-1)->type == (end_outgoing-1)->type)
- && std::all_of(
+ if(std::all_of(
begin_outgoing + 1, end_outgoing - 1,
- [](Particle const & p){ return p.type == pid::gluon; }
- );
+ [](Particle const & p){ return p.type == pid::gluon; })
+ ){
+ // Test if this is a standard FKL configuration.
+ if (is_Pure_Current(begin_incoming->type, begin_outgoing->type)
+ && is_Pure_Current((end_incoming-1)->type, (end_outgoing-1)->type)){
+ return true;
+ }
+ }
+ return false;
+ }
+
+ template<class ConstIterator, class Iterator>
+ bool is_W_FKL(
+ ConstIterator begin_incoming, ConstIterator end_incoming,
+ Iterator begin_outgoing, Iterator end_outgoing
+ ){
+ assert(std::distance(begin_incoming, end_incoming) == 2);
+ assert(std::distance(begin_outgoing, end_outgoing) >= 2);
+
+ // One photon, W, H, Z in the final state is allowed.
+ // Remove it for remaining tests,
+ end_outgoing = remove_AWZH(begin_outgoing, end_outgoing);
+
+ if(std::all_of(
+ begin_outgoing + 1, end_outgoing - 1,
+ [](Particle const & p){ return p.type == pid::gluon; })
+ ){
+ // Test if this is a standard FKL configuration.
+ if(is_W_Current(begin_incoming->type, begin_outgoing->type)
+ && is_Pure_Current((end_incoming-1)->type, (end_outgoing-1)->type)){
+ return true;
+ }
+ else if(is_Pure_Current(begin_incoming->type, begin_outgoing->type)
+ && is_W_Current((end_incoming-1)->type, (end_outgoing-1)->type)){
+ return true;
+ }
+ }
+ return false;
}
bool is_FKL(
std::array<Particle, 2> const & incoming,
std::vector<Particle> outgoing
){
assert(std::is_sorted(begin(incoming), end(incoming), pz_less{}));
assert(valid_outgoing(begin(outgoing), end(outgoing)));
- return is_FKL(
+ const auto WEmit = std::find_if(
+ begin(outgoing), end(outgoing),
+ [](Particle const & s){ return abs(s.type) == pid::Wp; }
+ );
+
+ if (WEmit != end(outgoing) && abs(WEmit->type) == pid::Wp){
+ return is_W_FKL(
begin(incoming), end(incoming),
begin(outgoing), end(outgoing)
- );
+ );
+ }
+ else{
+ return is_FKL(
+ begin(incoming), end(incoming),
+ begin(outgoing), end(outgoing)
+ );
+ }
}
bool has_2_jets(Event const & event){
return event.jets().size() >= 2;
}
/**
* \brief Checks whether event is unordered backwards
* @param ev Event
* @returns Is Event Unordered Backwards
*
* - Checks there is more than 3 constuents in the final state
* - Checks there is more than 3 jets
* - Checks the most backwards parton is a gluon
* - Checks the most forwards jet is not a gluon
* - Checks the rest of the event is FKL
* - Checks the second most backwards is not a different boson
* - Checks the unordered gluon actually forms a jet
*/
bool is_unordered_backward(Event const & ev){
auto const & in = ev.incoming();
auto const & out = ev.outgoing();
assert(std::is_sorted(begin(in), end(in), pz_less{}));
assert(valid_outgoing(begin(out), end(out)));
if(out.size() < 3) return false;
if(ev.jets().size() < 3) return false;
if(in.front().type == pid::gluon) return false;
if(out.front().type != pid::gluon) return false;
// When skipping the unordered emission
// the remainder should be a regular FKL event,
// except that the (new) first outgoing particle must not be a A,W,Z,H.
const auto FKL_begin = next(begin(out));
if(is_AWZH_boson(*FKL_begin)) return false;
if(!is_FKL(in, {FKL_begin, end(out)})) return false;
// check that the unordered gluon forms an extra jet
const auto jets = sorted_by_rapidity(ev.jets());
const auto indices = ev.particle_jet_indices({jets.front()});
return indices[0] >= 0 && indices[1] == -1;
}
/**
* \brief Checks for a forward unordered gluon emission
* @param ev Event
* @returns Is the event a forward unordered emission
*
* \see is_unordered_backward
*/
bool is_unordered_forward(Event const & ev){
auto const & in = ev.incoming();
auto const & out = ev.outgoing();
assert(std::is_sorted(begin(in), end(in), pz_less{}));
assert(valid_outgoing(begin(out), end(out)));
if(out.size() < 3) return false;
if(ev.jets().size() < 3) return false;
if(in.back().type == pid::gluon) return false;
if(out.back().type != pid::gluon) return false;
// When skipping the unordered emission
// the remainder should be a regular FKL event,
// except that the (new) last outgoing particle must not be a A,W,Z,H.
const auto FKL_end = prev(end(out));
if(is_AWZH_boson(*prev(FKL_end))) return false;
if(!is_FKL(in, {begin(out), FKL_end})) return false;
// check that the unordered gluon forms an extra jet
const auto jets = sorted_by_rapidity(ev.jets());
const auto indices = ev.particle_jet_indices({jets.back()});
return indices.back() >= 0 && indices[indices.size()-2] == -1;
}
+
+ /**
+ * \brief Checks for a forward extremal qqx
+ * @param ev Event
+ * @returns Is the event a forward extremal qqx event
+ *
+ * Checks there is 3 or more than 3 constituents in the final state
+ * Checks there is 3 or more than 3 jets
+ * Checks most forwards incoming is gluon
+ * Checks most extremal particle is not a Higgs (either direction)
+ * Checks the second most forwards particle is not Higgs boson
+ * Checks the most forwards parton is a either quark or anti-quark.
+ * Checks the second most forwards parton is anti-quark or quark.
+ * Checks the qqbar pair form 2 separate jets.
+ */
+ bool is_Ex_qqxf(Event const & ev){
+ auto const & in = ev.incoming();
+ auto const & out = ev.outgoing();
+ assert(std::is_sorted(begin(in), end(in), pz_less{}));
+ assert(valid_outgoing(begin(out), end(out)));
+
+ int fkl_end=2;
+
+ if(out.size() < 3) return false;
+ if(ev.jets().size() < 3) return false;
+ if(in.back().type != pid::gluon) return false;
+ if(out.back().type == pid::Higgs || out.front().type == pid::Higgs
+ || out.rbegin()[1].type == pid::Higgs) return false;
+
+ // if extremal AWZ
+ if(is_AWZ_boson(out.back())){ // if extremal AWZ
+ fkl_end++;
+ if (is_quark(out.rbegin()[1])){ //if second quark
+ if (!(is_antiquark(out.rbegin()[2]))) return false;// third must be anti-quark
+ }
+ else if (is_antiquark(out.rbegin()[1])){ //if second anti-quark
+ if (!(is_quark(out.rbegin()[2]))) return false;// third must be quark
+ }
+ else return false;
+ }
+ else if (is_quark(out.rbegin()[0])){ //if extremal quark
+ if(is_AWZ_boson(out.rbegin()[1])){ // if second AWZ
+ fkl_end++;
+ if (!(is_antiquark(out.rbegin()[2]))) return false;// third must be anti-quark
+ }
+ else if (!(is_antiquark(out.rbegin()[1]))) return false;// second must be anti-quark
+ }
+ else if (is_antiquark(out.rbegin()[0])){ //if extremal anti-quark
+ if(is_AWZ_boson(out.rbegin()[1])){ // if second AWZ
+ fkl_end++;
+ if (!(is_quark(out.rbegin()[2]))) return false;// third must be quark
+ }
+ else if (!(is_quark(out.rbegin()[1]))) return false;// second must be quark
+ }
+ else return false;
+
+ // When skipping the qqbar
+ // New last outgoing particle must not be a Higgs
+ if (out.rbegin()[fkl_end].type == pid::Higgs) return false;
+
+ const auto jets = fastjet::sorted_by_rapidity(ev.jets());
+ const auto indices = ev.particle_jet_indices({jets});
+
+ // Ensure qqbar pair are in separate jets
+ if(indices[indices.size()-2] != indices[indices.size()-1]-1) return false;
+
+ // Opposite current should be logical to process
+ if (is_AWZ_boson(out.front().type)){
+ return (is_Pure_Current(in.front().type, out[1].type)
+ || is_W_Current(in.front().type,out[1].type));
+ }
+ else
+ return (is_Pure_Current(in.front().type, out[0].type)
+ || is_W_Current(in.front().type,out[0].type));
+ }
+
+ /**
+ * \brief Checks for a backward extremal qqx
+ * @param ev Event
+ * @returns Is the event a backward extremal qqx event
+ *
+ * Checks there is 3 or more than 3 constituents in the final state
+ * Checks there is 3 or more than 3 jets
+ * Checks most backwards incoming is gluon
+ * Checks most extremal particle is not a Higgs (either direction) y
+ * Checks the second most backwards particle is not Higgs boson y
+ * Checks the most backwards parton is a either quark or anti-quark. y
+ * Checks the second most backwards parton is anti-quark or quark. y
+ * Checks the qqbar pair form 2 separate jets.
+ */
+ bool is_Ex_qqxb(Event const & ev){
+ auto const & in = ev.incoming();
+ auto const & out = ev.outgoing();
+ assert(std::is_sorted(begin(in), end(in), pz_less{}));
+ assert(valid_outgoing(begin(out), end(out)));
+
+ int fkl_start=2;
+
+ if(out.size() < 3) return false;
+ if(ev.jets().size() < 3) return false;
+ if(in.front().type != pid::gluon) return false;
+ if(out.back().type == pid::Higgs || out.front().type == pid::Higgs
+ || out[1].type == pid::Higgs) return false;
+
+ if(is_AWZ_boson(out.front())){ // if extremal AWZ
+ fkl_start++;
+ if (is_quark(out[1])){ //if second quark
+ if (!(is_antiquark(out[2]))) return false;// third must be anti-quark
+ }
+ else if (is_antiquark(out[1])){ //if second anti-quark
+ if (!(is_quark(out[2]))) return false;// third must be quark
+ }
+ else return false;
+ }
+ else if (is_quark(out[0])){ // if extremal quark
+ if(is_AWZ_boson(out[1])){ // if second AWZ
+ fkl_start++;
+ if (!(is_antiquark(out[2]))) return false;// third must be anti-quark
+ }
+ else if (!(is_antiquark(out[1]))) return false;// second must be anti-quark
+ }
+ else if (is_antiquark(out[0])){ //if extremal anti-quark
+ if(is_AWZ_boson(out[1])){ // if second AWZ
+ fkl_start++;
+ if (!(is_quark(out[2]))) return false;// third must be quark
+ }
+ else if (!(is_quark(out[1]))) return false;// second must be quark
+ }
+ else return false;
+
+ // When skipping the qqbar
+ // New last outgoing particle must not be a Higgs.
+ if (out[fkl_start].type == pid::Higgs) return false;
+
+ const auto jets = fastjet::sorted_by_rapidity(ev.jets());
+ const auto indices = ev.particle_jet_indices({jets});
+
+ // Ensure qqbar pair form separate jets.
+ if(indices[0] != indices[1]-1) return false;
+
+ // Other current should be logical to process
+ if (is_AWZ_boson(out.back())){
+ return (is_Pure_Current(in.back().type, out.rbegin()[1].type)
+ || is_W_Current(in.back().type,out.rbegin()[1].type));
+ }
+ else
+ return (is_Pure_Current(in.back().type, out.rbegin()[0].type)
+ || is_W_Current(in.back().type, out.rbegin()[0].type));
+ }
+
+
+ /**
+ * \brief Checks for a central qqx
+ * @param ev Event
+ * @returns Is the event a central extremal qqx event
+ *
+ * Checks there is 4 or more than 4 constuents in the final state
+ * Checks there is 4 or more than 4 jets
+ * Checks most extremal particle is not a Higgs (either direction) y
+ * Checks for a central quark in the outgoing states
+ * Checks for adjacent anti-quark parton. (allowing for AWZ boson emission between)
+ * Checks external currents are logically sound.
+ */
+ bool is_Mid_qqx(Event const & ev){
+ auto const & in = ev.incoming();
+ auto const & out = ev.outgoing();
+ assert(std::is_sorted(begin(in), end(in), pz_less{}));
+ assert(valid_outgoing(begin(out), end(out)));
+
+ if(out.size() < 4) return false;
+ if(ev.jets().size() < 4) return false;
+
+ if(out.back().type == pid::Higgs || out.front().type == pid::Higgs)
+ return false;
+
+ size_t start_FKL=0;
+ size_t end_FKL=0;
+
+ if (is_AWZ_boson(out.back())){
+ end_FKL++;
+ }
+ if (is_AWZ_boson(out.front())){
+ start_FKL++;
+ }
+
+ if ((is_Pure_Current(in.back().type,out.rbegin()[end_FKL].type)
+ && is_Pure_Current(in.front().type,out[start_FKL].type))){
+ //nothing to do
+ }
+ else if (is_W_Current(in.back().type,out.rbegin()[end_FKL].type)
+ && is_Pure_Current(in.front().type,out[start_FKL].type)){
+ //nothing to do
+ }
+ else if (!(is_Pure_Current(in.back().type,out.rbegin()[end_FKL].type)
+ && is_W_Current(in.front().type,out[start_FKL].type))){
+ return false;
+ }
+
+ const auto jets = fastjet::sorted_by_rapidity(ev.jets());
+ const auto indices = ev.particle_jet_indices({jets});
+ auto const out_partons = filter_partons(out);
+
+ for (size_t i = 1; i<out_partons.size()-2; i++){
+ if ((is_quark(out_partons[i]) && (is_antiquark(out_partons[i+1])))
+ || (is_antiquark(out_partons[i]) && (is_quark(out_partons[i+1])))){
+ return (indices[i+1] == indices[i]+1 && indices[i] != -1);
+ }
+ }
+ return false;
+ }
+
using event_type::EventType;
EventType classify(Event const & ev){
- if(! final_state_ok(ev.outgoing())) return EventType::bad_final_state;
- if(! has_2_jets(ev)) return EventType::no_2_jets;
- if(is_FKL(ev.incoming(), ev.outgoing())) return EventType::FKL;
- if(is_unordered_backward(ev)){
+ if(! final_state_ok(ev.outgoing()))
+ return EventType::bad_final_state;
+ if(! has_2_jets(ev))
+ return EventType::no_2_jets;
+ if(is_FKL(ev.incoming(), ev.outgoing()))
+ return EventType::FKL;
+ if(is_unordered_backward(ev))
return EventType::unordered_backward;
- }
- if(is_unordered_forward(ev)){
+ if(is_unordered_forward(ev))
return EventType::unordered_forward;
- }
+ if(is_Ex_qqxb(ev))
+ return EventType::extremal_qqxb;
+ if(is_Ex_qqxf(ev))
+ return EventType::extremal_qqxf;
+ if(is_Mid_qqx(ev))
+ return EventType::central_qqx;
return EventType::nonHEJ;
}
//@}
Particle extract_particle(LHEF::HEPEUP const & hepeup, int i){
const ParticleID id = static_cast<ParticleID>(hepeup.IDUP[i]);
const fastjet::PseudoJet momentum{
hepeup.PUP[i][0], hepeup.PUP[i][1],
hepeup.PUP[i][2], hepeup.PUP[i][3]
};
if(is_parton(id))
return Particle{ id, std::move(momentum), hepeup.ICOLUP[i] };
return Particle{ id, std::move(momentum), {} };
}
bool is_decay_product(std::pair<int, int> const & mothers){
if(mothers.first == 0) return false;
return mothers.second == 0 || mothers.first == mothers.second;
}
} // namespace anonymous
Event::EventData::EventData(LHEF::HEPEUP const & hepeup){
parameters.central = EventParameters{
hepeup.scales.mur, hepeup.scales.muf, hepeup.weight()
};
size_t in_idx = 0;
for (int i = 0; i < hepeup.NUP; ++i) {
// skip decay products
// we will add them later on, but we have to ensure that
// the decayed particle is added before
if(is_decay_product(hepeup.MOTHUP[i])) continue;
auto particle = extract_particle(hepeup, i);
// needed to identify mother particles for decay products
particle.p.set_user_index(i+1);
if(hepeup.ISTUP[i] == status_in){
- if(in_idx > incoming.size()) {
- throw std::invalid_argument{
- "Event has too many incoming particles"
- };
- }
- incoming[in_idx++] = std::move(particle);
+ if(in_idx > incoming.size()) {
+ throw std::invalid_argument{
+ "Event has too many incoming particles"
+ };
+ }
+ incoming[in_idx++] = std::move(particle);
}
else outgoing.emplace_back(std::move(particle));
}
// add decay products
for (int i = 0; i < hepeup.NUP; ++i) {
if(!is_decay_product(hepeup.MOTHUP[i])) continue;
const int mother_id = hepeup.MOTHUP[i].first;
const auto mother = std::find_if(
begin(outgoing), end(outgoing),
[mother_id](Particle const & particle){
return particle.p.user_index() == mother_id;
}
);
if(mother == end(outgoing)){
throw std::invalid_argument{"invalid decay product parent"};
}
const int mother_idx = std::distance(begin(outgoing), mother);
assert(mother_idx >= 0);
decays[mother_idx].emplace_back(extract_particle(hepeup, i));
}
}
Event::Event(
UnclusteredEvent const & ev,
fastjet::JetDefinition const & jet_def, double const min_jet_pt
):
Event( Event::EventData{
ev.incoming, ev.outgoing, ev.decays,
Parameters<EventParameters>{ev.central, ev.variations}
}.cluster(jet_def, min_jet_pt) )
{}
//! @TODO remove in HEJ 2.3.0
UnclusteredEvent::UnclusteredEvent(LHEF::HEPEUP const & hepeup){
Event::EventData const evData{hepeup};
incoming = evData.incoming;
outgoing = evData.outgoing;
decays = evData.decays;
central = evData.parameters.central;
variations = evData.parameters.variations;
}
void Event::EventData::sort(){
// sort particles
std::sort(
begin(incoming), end(incoming),
[](Particle o1, Particle o2){return o1.p.pz()<o2.p.pz();}
);
auto old_outgoing = std::move(outgoing);
std::vector<size_t> idx(old_outgoing.size());
std::iota(idx.begin(), idx.end(), 0);
std::sort(idx.begin(), idx.end(), [&old_outgoing](size_t i, size_t j){
return old_outgoing[i].rapidity() < old_outgoing[j].rapidity();
});
outgoing.clear();
outgoing.reserve(old_outgoing.size());
for(size_t i: idx) {
outgoing.emplace_back(std::move(old_outgoing[i]));
}
// find decays again
if(!decays.empty()){
auto old_decays = std::move(decays);
decays.clear();
for(size_t i=0; i<idx.size(); ++i) {
auto decay = old_decays.find(idx[i]);
if(decay != old_decays.end())
decays.emplace(i, std::move(decay->second));
}
assert(old_decays.size() == decays.size());
}
}
Event Event::EventData::cluster(
fastjet::JetDefinition const & jet_def, double const min_jet_pt
){
sort();
Event ev{ std::move(incoming), std::move(outgoing), std::move(decays),
std::move(parameters),
jet_def, min_jet_pt
};
assert(std::is_sorted(begin(ev.outgoing_), end(ev.outgoing_),
rapidity_less{}));
ev.type_ = classify(ev);
return ev;
}
namespace {
void connect_incoming(Particle & in, int & colour, int & anti_colour){
in.colour = std::make_pair(anti_colour, colour);
// gluon
if(in.type == pid::gluon)
return;
if(in.type > 0){
// quark
assert(is_quark(in));
in.colour->second = 0;
colour*=-1;
return;
}
// anti-quark
assert(is_antiquark(in));
in.colour->first = 0;
anti_colour*=-1;
return;
}
}
bool Event::generate_colours(RNG & ran){
// generate only for HEJ events
if(!event_type::is_HEJ(type()))
return false;
assert(std::is_sorted(
begin(outgoing()), end(outgoing()), rapidity_less{}));
assert(incoming()[0].pz() < incoming()[1].pz());
// positive (anti-)colour -> can connect
// negative (anti-)colour -> not available/used up by (anti-)quark
int colour = COLOUR_OFFSET;
int anti_colour = colour+1;
// initialise first
connect_incoming(incoming_[0], colour, anti_colour);
for(auto & part: outgoing_){
assert(colour>0 || anti_colour>0);
if(part.type == ParticleID::gluon){
// gluon
if(colour>0 && anti_colour>0){
// on g line => connect to colour OR anti-colour (random)
if(ran.flat() < 0.5){
part.colour = std::make_pair(colour+2,colour);
colour+=2;
} else {
part.colour = std::make_pair(anti_colour, anti_colour+2);
anti_colour+=2;
}
} else if(colour > 0){
// on q line => connect to available colour
part.colour = std::make_pair(colour+2, colour);
colour+=2;
} else {
assert(colour<0 && anti_colour>0);
// on qx line => connect to available anti-colour
part.colour = std::make_pair(anti_colour, anti_colour+2);
anti_colour+=2;
}
} else if(is_quark(part)) {
// quark
assert(anti_colour>0);
if(colour>0){
// on g line => connect and remove anti-colour
part.colour = std::make_pair(anti_colour, 0);
anti_colour+=2;
anti_colour*=-1;
} else {
// on qx line => new colour
colour*=-1;
part.colour = std::make_pair(colour, 0);
}
} else if(is_antiquark(part)) {
// anti-quark
assert(colour>0);
if(anti_colour>0){
// on g line => connect and remove colour
part.colour = std::make_pair(0, colour);
colour+=2;
colour*=-1;
} else {
// on q line => new anti-colour
anti_colour*=-1;
part.colour = std::make_pair(0, anti_colour);
}
}
// else not a parton
}
// Connect last
connect_incoming(incoming_[1], anti_colour, colour);
return true;
} // generate_colours
std::vector<fastjet::PseudoJet> Event::jets() const{
return cs_.inclusive_jets(min_jet_pt_);
}
+ /**
+ * \brief Returns the invarient mass of the event
+ * @param ev Event
+ * @returns s hat
+ *
+ * Makes use of the FastJet PseudoJet function m2().
+ * Applies this function to the sum of the incoming partons.
+ */
double shat(Event const & ev){
return (ev.incoming()[0].p + ev.incoming()[1].p).m2();
}
LHEF::HEPEUP to_HEPEUP(Event const & event, LHEF::HEPRUP * heprup){
LHEF::HEPEUP result;
result.heprup = heprup;
result.weights = {{event.central().weight, nullptr}};
for(auto const & var: event.variations()){
result.weights.emplace_back(var.weight, nullptr);
}
size_t num_particles = event.incoming().size() + event.outgoing().size();
for(auto const & decay: event.decays()) num_particles += decay.second.size();
result.NUP = num_particles;
// the following entries are pretty much meaningless
result.IDPRUP = event.type()+1; // event ID
result.AQEDUP = 1./128.; // alpha_EW
//result.AQCDUP = 0.118 // alpha_QCD
// end meaningless part
result.XWGTUP = event.central().weight;
result.SCALUP = event.central().muf;
result.scales.muf = event.central().muf;
result.scales.mur = event.central().mur;
result.scales.SCALUP = event.central().muf;
result.pdfinfo.p1 = event.incoming().front().type;
result.pdfinfo.p2 = event.incoming().back().type;
result.pdfinfo.scale = event.central().muf;
result.IDUP.reserve(num_particles); // PID
result.ISTUP.reserve(num_particles); // status (in, out, decay)
result.PUP.reserve(num_particles); // momentum
result.MOTHUP.reserve(num_particles); // index mother particle
result.ICOLUP.reserve(num_particles); // colour
// incoming
for(Particle const & in: event.incoming()){
result.IDUP.emplace_back(in.type);
result.ISTUP.emplace_back(status_in);
result.PUP.push_back({in.p[0], in.p[1], in.p[2], in.p[3], in.p.m()});
result.MOTHUP.emplace_back(0, 0);
assert(in.colour);
result.ICOLUP.emplace_back(*in.colour);
}
// outgoing
for(size_t i = 0; i < event.outgoing().size(); ++i){
Particle const & out = event.outgoing()[i];
result.IDUP.emplace_back(out.type);
const int status = event.decays().count(i)?status_decayed:status_out;
result.ISTUP.emplace_back(status);
result.PUP.push_back({out.p[0], out.p[1], out.p[2], out.p[3], out.p.m()});
result.MOTHUP.emplace_back(1, 2);
if(out.colour)
result.ICOLUP.emplace_back(*out.colour);
else{
assert(is_AWZH_boson(out));
result.ICOLUP.emplace_back(std::make_pair(0,0));
}
}
// decays
for(auto const & decay: event.decays()){
for(auto const out: decay.second){
result.IDUP.emplace_back(out.type);
result.ISTUP.emplace_back(status_out);
result.PUP.push_back({out.p[0], out.p[1], out.p[2], out.p[3], out.p.m()});
const size_t mother_idx = 1 + event.incoming().size() + decay.first;
result.MOTHUP.emplace_back(mother_idx, mother_idx);
result.ICOLUP.emplace_back(0,0);
}
}
assert(result.ICOLUP.size() == num_particles);
static constexpr double unknown_spin = 9.; //per Les Houches accord
result.VTIMUP = std::vector<double>(num_particles, unknown_spin);
result.SPINUP = result.VTIMUP;
return result;
}
}
diff --git a/src/EventReweighter.cc b/src/EventReweighter.cc
index fcda57c..3bca11c 100644
--- a/src/EventReweighter.cc
+++ b/src/EventReweighter.cc
@@ -1,268 +1,309 @@
/**
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#include "HEJ/EventReweighter.hh"
#include <algorithm>
#include <assert.h>
#include <limits>
#include <math.h>
#include <stddef.h>
#include <string>
#include <unordered_map>
#include "fastjet/ClusterSequence.hh"
#include "LHEF/LHEF.h"
#include "HEJ/Event.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/Particle.hh"
#include "HEJ/PDG_codes.hh"
#include "HEJ/PhaseSpacePoint.hh"
namespace HEJ{
using EventType = event_type::EventType;
namespace {
static_assert(
std::numeric_limits<double>::has_quiet_NaN,
"no quiet NaN for double"
);
constexpr double NaN = std::numeric_limits<double>::quiet_NaN();
Event::EventData to_EventData(PhaseSpacePoint const & psp){
Event::EventData result;
result.incoming=psp.incoming();
assert(result.incoming.size() == 2);
result.outgoing=psp.outgoing();
// technically Event::EventData doesn't have to be sorted,
// but PhaseSpacePoint should be anyway
assert(
std::is_sorted(
begin(result.outgoing), end(result.outgoing),
rapidity_less{}
)
);
assert(result.outgoing.size() >= 2);
result.decays = psp.decays();
result.parameters.central = {NaN, NaN, psp.weight()};
return result;
}
} // namespace anonymous
EventReweighter::EventReweighter(
LHEF::HEPRUP const & heprup,
ScaleGenerator scale_gen,
EventReweighterConfig conf,
HEJ::RNG & ran
):
EventReweighter{
HEJ::Beam{
heprup.EBMUP.first,
{{
static_cast<HEJ::ParticleID>(heprup.IDBMUP.first),
static_cast<HEJ::ParticleID>(heprup.IDBMUP.second)
}}
},
heprup.PDFSUP.first,
std::move(scale_gen),
std::move(conf),
ran
}
{
if(heprup.EBMUP.second != E_beam_){
throw std::invalid_argument(
"asymmetric beam: " + std::to_string(E_beam_)
+ " ---> <--- " + std::to_string(heprup.EBMUP.second)
);
};
if(heprup.PDFSUP.second != pdf_.id()){
throw std::invalid_argument(
"conflicting PDF ids: " + std::to_string(pdf_.id())
+ " vs. " + std::to_string(heprup.PDFSUP.second)
);
}
}
EventReweighter::EventReweighter(
Beam beam,
int pdf_id,
ScaleGenerator scale_gen,
EventReweighterConfig conf,
HEJ::RNG & ran
):
param_{std::move(conf)},
E_beam_{beam.E},
pdf_{pdf_id, beam.type.front(), beam.type.back()},
MEt2_{
[this](double mu){ return pdf_.Halphas(mu); },
param_.ME_config
},
scale_gen_(std::move(scale_gen)),
ran_{ran}
{}
PDF const & EventReweighter::pdf() const{
return pdf_;
}
std::vector<Event> EventReweighter::reweight(
Event const & input_ev, int num_events
){
auto res_events = gen_res_events(input_ev, num_events);
if(res_events.empty()) return {};
for(auto & event: res_events) event = scale_gen_(event);
return rescale(input_ev, std::move(res_events));
}
+ /**
+ * \brief main generation/reweighting function:
+ * generate phase space points and divide out Born factors
+ */
std::vector<Event> EventReweighter::gen_res_events(
Event const & ev,
int phase_space_points
){
assert(ev.variations().empty());
switch(param_.treat.at(ev.type())){
case EventTreatment::discard: return {};
case EventTreatment::keep:
if(! jets_pass_resummation_cuts(ev)) return {};
else return {ev};
default:;
}
const double Born_shat = shat(ev);
std::vector<Event> resummation_events;
for(int psp_number = 0; psp_number < phase_space_points; ++psp_number){
PhaseSpacePoint psp{ev, param_.psp_config, ran_};
if(psp.weight() == 0.) continue;
if(psp.incoming()[0].E() > E_beam_ || psp.incoming()[1].E() > E_beam_) continue;
resummation_events.emplace_back(
to_EventData( std::move(psp) ).cluster(
param_.jet_param.def, param_.jet_param.min_pt
)
);
auto & new_event = resummation_events.back();
assert(new_event.type() == ev.type());
new_event.generate_colours(ran_);
assert(new_event.variations().empty());
new_event.central().mur = ev.central().mur;
new_event.central().muf = ev.central().muf;
const double resum_shat = shat(new_event);
new_event.central().weight *= ev.central().weight*Born_shat*Born_shat/
(phase_space_points*resum_shat*resum_shat);
}
return resummation_events;
}
std::vector<Event> EventReweighter::rescale(
Event const & Born_ev,
std::vector<Event> events
) const{
const double Born_pdf = pdf_factors(Born_ev).central;
const double Born_ME = tree_matrix_element(Born_ev);
for(auto & cur_event: events){
const auto pdf = pdf_factors(cur_event);
assert(pdf.variations.size() == cur_event.variations().size());
const auto ME = matrix_elements(cur_event);
assert(ME.variations.size() == cur_event.variations().size());
cur_event.parameters() *= pdf*ME/(Born_pdf*Born_ME);
}
return events;
};
+ /**
+ * \brief Do the Jets pass the resummation Cuts?
+ *
+ * @param ev Event in Question
+ * @returns 0 or 1 depending on if ev passes Jet Cuts
+ */
bool EventReweighter::jets_pass_resummation_cuts(
Event const & ev
) const{
const auto out_as_PseudoJet = to_PseudoJet(filter_partons(ev.outgoing()));
fastjet::ClusterSequence cs{out_as_PseudoJet, param_.jet_param.def};
return cs.inclusive_jets(param_.jet_param.min_pt).size() == ev.jets().size();
}
+ /**
+ * \brief pdf_factors Function
+ *
+ * @param ev Event in Question
+ * @returns Event weights due to PDFs
+ *
+ * Calculates the Central value and the variation due
+ * to the PDF choice made.
+ */
Weights EventReweighter::pdf_factors(Event const & ev) const{
auto const & a = ev.incoming().front();
auto const & b = ev.incoming().back();
const double xa = a.p.e()/E_beam_;
const double xb = b.p.e()/E_beam_;
Weights result;
std::unordered_map<double, double> known_pdf;
result.central =
pdf_.pdfpt(0,xa,ev.central().muf,a.type)*
pdf_.pdfpt(1,xb,ev.central().muf,b.type);
known_pdf.emplace(ev.central().muf, result.central);
result.variations.reserve(ev.variations().size());
for(auto const & ev_param: ev.variations()){
const double muf = ev_param.muf;
auto cur_pdf = known_pdf.find(muf);
if(cur_pdf == known_pdf.end()){
cur_pdf = known_pdf.emplace(
muf,
pdf_.pdfpt(0,xa,muf,a.type)*pdf_.pdfpt(1,xb,muf,b.type)
).first;
}
result.variations.emplace_back(cur_pdf->second);
}
assert(result.variations.size() == ev.variations().size());
return result;
}
+
+
+ /**
+ * \brief matrix_elements Function
+ *
+ * @param ev Event in question
+ * @returns Event Weights due to MatrixElements
+ *
+ * Calculates the Central value and the variation due
+ * to the Matrix Element.
+ */
Weights
EventReweighter::matrix_elements(Event const & ev) const{
assert(param_.treat.count(ev.type()) > 0);
if(param_.treat.find(ev.type())->second == EventTreatment::keep){
return fixed_order_scale_ME(ev);
}
return MEt2_(ev);
}
+ /**
+ * \brief Computes the tree level matrix element
+ *
+ * @param ev Event in Question
+ * @returns HEJ approximation to Tree level Matrix Element
+ *
+ * This computes the HEJ approximation to the tree level FO
+ * Matrix element which is used within the LO weighting process.
+ */
double EventReweighter::tree_matrix_element(Event const & ev) const{
assert(ev.variations().empty());
assert(param_.treat.count(ev.type()) > 0);
if(param_.treat.find(ev.type())->second == EventTreatment::keep){
return fixed_order_scale_ME(ev).central;
}
return MEt2_.tree(ev).central;
}
+ /**
+ * \brief Scale-dependent part of fixed-order matrix element
+ *
+ * @param ev Event in question
+ * @returns Scale variation due to FO-ME.
+ *
+ * This is only called to compute the scale variation for events where
+ * we don't do resummation (e.g. non-FKL).
+ * Since at tree level the scale dependence is just due to alpha_s,
+ * it is enough to return the alpha_s(mur) factors in the matrix element.
+ * The rest drops out in the ratio of (output event ME)/(input event ME),
+ * so we never have to compute it.
+ */
Weights
EventReweighter::fixed_order_scale_ME(Event const & ev) const{
int alpha_s_power = 0;
for(auto const & part: ev.outgoing()){
if(is_parton(part))
++alpha_s_power;
- else {
- switch(part.type){
- case pid::Higgs: {
- alpha_s_power += 2;
- break;
- }
- // TODO
- case pid::Wp:
- case pid::Wm:
- case pid::photon:
- case pid::Z:
- default:
- throw not_implemented("Emission of boson of unsupported type");
- }
+ else if(part.type == pid::Higgs) {
+ alpha_s_power += 2;
}
+ // nothing to do for other uncoloured particles
}
Weights result;
result.central = pow(pdf_.Halphas(ev.central().mur), alpha_s_power);
for(auto const & var: ev.variations()){
result.variations.emplace_back(
pow(pdf_.Halphas(var.mur), alpha_s_power)
);
}
return result;
}
} // namespace HEJ
diff --git a/src/MatrixElement.cc b/src/MatrixElement.cc
index 4c0b62f..ee6ab55 100644
--- a/src/MatrixElement.cc
+++ b/src/MatrixElement.cc
@@ -1,855 +1,1754 @@
/**
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \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/currents.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{
//cf. last line of eq. (22) in \ref Andersen:2011hs
double MatrixElement::omega0(
double alpha_s, double mur,
- fastjet::PseudoJet const & q_j, double lambda
+ 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_HEJ(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_HEJ(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 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){
+
+ // 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){
+ 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, CLAMBDA)*(
+ 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 qav, CLHEP::HepLorentzVector qbv,
CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector 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 qav, CLHEP::HepLorentzVector qbv,
- CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector p2)
- {
+ double C2Lipatovots(
+ CLHEP::HepLorentzVector qav,
+ CLHEP::HepLorentzVector qbv,
+ CLHEP::HepLorentzVector p1,
+ CLHEP::HepLorentzVector p2,
+ double lambda
+ ) {
double kperp=(qav-qbv).perp();
- if (kperp>HEJ::CLAMBDA)
+ if (kperp>lambda)
return C2Lipatov(qav, qbv, p1, p2)/(qav.m2()*qbv.m2());
else {
double Cls=(C2Lipatov(qav, qbv, p1, p2)/(qav.m2()*qbv.m2()));
return Cls-4./(kperp*kperp);
}
}
//! Lipatov vertex
double C2Lipatov(CLHEP::HepLorentzVector qav, CLHEP::HepLorentzVector qbv,
CLHEP::HepLorentzVector pim, CLHEP::HepLorentzVector pip,
CLHEP::HepLorentzVector pom, CLHEP::HepLorentzVector pop) // B
{
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 qav, CLHEP::HepLorentzVector qbv,
- CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb,
- CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector p2)
- {
+ double C2Lipatovots(
+ CLHEP::HepLorentzVector qav,
+ CLHEP::HepLorentzVector qbv,
+ CLHEP::HepLorentzVector pa,
+ CLHEP::HepLorentzVector pb,
+ CLHEP::HepLorentzVector p1,
+ CLHEP::HepLorentzVector p2,
+ double lambda
+ ) {
double kperp=(qav-qbv).perp();
- if (kperp>HEJ::CLAMBDA)
+ if (kperp>lambda)
return C2Lipatov(qav, qbv, pa, pb, p1, p2)/(qav.m2()*qbv.m2());
else {
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 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 jM2gg(pn,pb,p1,pa);
} else if (aptype==21&&bptype!=21) {
if (bptype > 0)
return jM2qg(pn,pb,p1,pa);
else
return jM2qbarg(pn,pb,p1,pa);
}
else if (bptype==21&&aptype!=21) { // ----- || -----
if (aptype > 0)
return jM2qg(p1,pa,pn,pb);
else
return jM2qbarg(p1,pa,pn,pb);
}
else { // they are both quark
if (bptype>0) {
if (aptype>0)
return jM2qQ(pn,pb,p1,pa);
else
return jM2qQbar(pn,pb,p1,pa);
}
else {
if (aptype>0)
return jM2qQbar(p1,pa,pn,pb);
else
return jM2qbarQbar(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 jMWqg(pn,plbar,pl,pb,p1,pa);
+ else
+ return jMWqbarg(pn,plbar,pl,pb,p1,pa);
+ }
+ else if (bptype==21&&aptype!=21) { // ----- || -----
+ if (aptype > 0)
+ return jMWqg(p1,plbar,pl,pa,pn,pb);
+ else
+ return jMWqbarg(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 jMWqQ(pn,plbar,pl,pb,p1,pa);
+ else
+ return jMWqQbar(pn,plbar,pl,pb,p1,pa);
+ }
+ else {
+ if (aptype>0)
+ return jMWqbarQ(pn,plbar,pl,pb,p1,pa);
+ else
+ return jMWqbarQbar(pn,plbar,pl,pb,p1,pa);
+ }
+ }
+ else{ // emission off a, (first argument paout)
+ if (aptype > 0) {
+ if (bptype > 0)
+ return jMWqQ(p1,plbar,pl,pa,pn,pb);
+ else
+ return jMWqQbar(p1,plbar,pl,pa,pn,pb);
+ }
+ else { // a is anti-quark
+ if (bptype > 0)
+ return jMWqbarQ(p1,plbar,pl,pa,pn,pb);
+ else
+ return jMWqbarQbar(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 jM2Wunogqg(pg,p1,plbar,pl,pa,pn,pb);
+ else
+ return jM2Wunogqbarg(pg,p1,plbar,pl,pa,pn,pb);
+ }
+
+ else { // they are both quark
+ if (wc==true) {// emission off b, i.e. b is first current
+ if (bptype>0){
+ if (aptype>0)
+ return junobMWqQg(pn,plbar,pl,pb,p1,pa,pg);
+ else
+ return junobMWqQbarg(pn,plbar,pl,pb,p1,pa,pg);
+ }
+ else{
+ if (aptype>0)
+ return junobMWqbarQg(pn,plbar,pl,pb,p1,pa,pg);
+ else
+ return junobMWqbarQbarg(pn,plbar,pl,pb,p1,pa,pg);
+ }
+ }
+ else {// wc == false, emission off a, i.e. a is first current
+ if (aptype > 0) {
+ if (bptype > 0) //qq
+ return jM2WunogqQ(pg,p1,plbar,pl,pa,pn,pb);
+ else //qqbar
+ return jM2WunogqQbar(pg,p1,plbar,pl,pa,pn,pb);
+ }
+ else { // a is anti-quark
+ if (bptype > 0) //qbarq
+ return jM2WunogqbarQ(pg,p1,plbar,pl,pa,pn,pb);
+ else //qbarqbar
+ return jM2WunogqbarQbar(pg,p1,plbar,pl,pa,pn,pb);
+ }
+ }
+ }
+ }
+
+ /** 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 jM2Wunogqg(pg, pn,plbar, pl, pb, p1, pa);
+ else
+ return jM2Wunogqbarg(pg, pn,plbar, pl, pb, p1, pa);
+ }
+ else { // they are both quark
+ if (wc==true) {// emission off b, i.e. b is first current
+ if (bptype>0){
+ if (aptype>0)
+ return jM2WunogqQ(pg,pn,plbar,pl,pb,p1,pa);
+ else
+ return jM2WunogqQbar(pg,pn,plbar,pl,pb,p1,pa);
+ }
+ else{
+ if (aptype>0)
+ return jM2WunogqbarQ(pg,pn,plbar,pl,pb,p1,pa);
+ else
+ return jM2WunogqbarQbar(pg,pn,plbar,pl,pb,p1,pa);
+ }
+ }
+ else {// wc == false, emission off a, i.e. a is first current
+ if (aptype > 0) {
+ if (bptype > 0) //qq
+ return junofMWgqQ(pg,pn,pb,p1,plbar,pl,pa);
+ else //qqbar
+ return junofMWgqQbar(pg,pn,pb,p1,plbar,pl,pa);
+ }
+ else { // a is anti-quark
+ if (bptype > 0) //qbarq
+ return junofMWgqbarQ(pg,pn,pb,p1,plbar,pl,pa);
+ else //qbarqbar
+ return junofMWgqbarQbar(pg,pn,pb,p1,plbar,pl,pa);
+ }
+ }
+ }
+ }
+
+ /** \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 jM2Wggtoqqbarg(pa, pqbar, plbar, pl, pq, pn,pb)*CFbackward;}
+ else {
+ return jM2Wggtoqbarqg(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!=1){ // W Emitted from backwards qqx
+ if (swapQuarkAntiquark){
+ return jM2WgQtoqqbarQ(pa, pq, plbar, pl, pqbar, pn, pb)*CFbackward;}
+ else{
+ return jM2WgQtoqbarqQ(pa, pq, plbar, pl, pqbar, pn, pb)*CFbackward;}
+ }
+ else { // W Must be emitted from forwards leg.
+ if(bptype > 0){
+ if (swapQuarkAntiquark){
+ return jM2WgqtoQQqW(pb, pa, pn, pqbar, pq, plbar, pl, false)*CFbackward;}
+ else{
+ return jM2WgqtoQQqW(pb, pa, pn, pq, pqbar, plbar, pl, false)*CFbackward;}
+ } else {
+ if (swapQuarkAntiquark){
+ return jM2WgqtoQQqW(pb, pa, pn, pqbar, pq, plbar, pl, true)*CFbackward;}
+ else{
+ return jM2WgqtoQQqW(pb, pa, pn, pq, pqbar, plbar, pl, true)*CFbackward;}
+ }
+ }
+ }
+ else{
+ 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 jM2Wggtoqqbarg(pb, pqbar, plbar, pl, pq, p1,pa)*CFforward;}
+ else {
+ return jM2Wggtoqbarqg(pb, pq, plbar, pl, pqbar, p1,pa)*CFforward;}
+ }
+
+ else if (bptype==21&&aptype!=21) {// b gluon => W emission off a or qqx
+ if (wc==1){ // W Emitted from forwards qqx
+ if (swapQuarkAntiquark){
+ return jM2WgQtoqbarqQ(pb, pq, plbar,pl, pqbar, p1, pa)*CFforward;}
+ else {
+ return jM2WgQtoqqbarQ(pb, pq, plbar,pl, pqbar, p1, pa)*CFforward;}
+ }
+ // W Must be emitted from backwards leg.
+ if (aptype > 0){
+ if (swapQuarkAntiquark){
+ return jM2WgqtoQQqW(pa,pb, p1, pqbar, pq, plbar, pl, false)*CFforward;}
+ else{
+ return jM2WgqtoQQqW(pa,pb, p1, pq, pqbar, plbar, pl, false)*CFforward;}
+ } else
+ {
+ if (swapQuarkAntiquark){
+ return jM2WgqtoQQqW(pa,pb, p1, pqbar, pq, plbar, pl, true)*CFforward;}
+ else{
+ return jM2WgqtoQQqW(pa,pb, p1, pq, pqbar, plbar, pl, true)*CFforward;}
+ }
+ }
+ else{
+ 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> 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 CFforward = (0.5*(3.-1./3.)*(pb.plus()/(partons[partons.size()-1].plus())+(partons[partons.size()-1].plus())/pb.plus())+1./3.)*3./4.;
+ double CFbackward = (0.5*(3.-1./3.)*(pa.minus()/(partons[0].minus())+(partons[0].minus())/pa.minus())+1./3.)*3./4.;
+ double wt=1.;
+
+ if (aptype==21) wt*=CFbackward;
+ if (bptype==21) wt*=CFforward;
+
+ if (aptype <=0 && bptype <=0){ // Both External AntiQuark
+ if (wqq==1){//emission from central qqbar
+ return wt*jM2WqqtoqQQq(pa, pb, pl,plbar, partons,true,true, swapQuarkAntiquark, nabove);
+ }
+ else if (wc==1){//emission from b leg
+ return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons, true,true, swapQuarkAntiquark, nabove, nbelow, true);
+ }
+ else { // emission from a leg
+ return wt*jM2WqqtoqQQqW(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*jM2WqqtoqQQq(pa, pb, pl,plbar, partons, false, true, swapQuarkAntiquark, nabove);
+ }
+ else if (wc==1){//emission from b leg
+ return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons,false,true, swapQuarkAntiquark, nabove, nbelow, true);
+ }
+ else { // emission from a leg
+ return wt*jM2WqqtoqQQqW(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*jM2WqqtoqQQq(pa, pb, pl,plbar, partons, true, false, swapQuarkAntiquark, nabove);
+ }
+ else if (wc==1){//emission from b leg
+ return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons, true, false, swapQuarkAntiquark, nabove, nbelow, true);
+ }
+ else { // emission from a leg
+ return wt*jM2WqqtoqQQqW(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*jM2WqqtoqQQq(pa, pb, pl, plbar, partons, false, false, swapQuarkAntiquark, nabove);}
+ else if (wc==1){//emission from b leg
+ return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons, false, false, swapQuarkAntiquark, nabove, nbelow, true);
+ }
+ else { // emission from a leg
+ return wt*jM2WqqtoqQQqW(pa, pb, pl,plbar, partons, false, false, swapQuarkAntiquark, nabove, nbelow, false);
+ }
+
+ }
+ }
+
/** \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 MH2gg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else if (aptype==21&&bptype!=21) {
if (bptype > 0)
return MH2qg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4./9.;
else
return MH2qbarg(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4./9.;
}
else if (bptype==21&&aptype!=21) {
if (aptype > 0)
return MH2qg(p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb)*4./9.;
else
return MH2qbarg(p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb)*4./9.;
}
else { // they are both quark
if (bptype>0) {
if (aptype>0)
return MH2qQ(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4.*4./(9.*9.);
else
return MH2qQbar(pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb)*4.*4./(9.*9.);
}
else {
if (aptype>0)
return MH2qQbar(p1,pa,pn,pb,-qH,-qHp1,mt,include_bottom,mb)*4.*4./(9.*9.);
else
return MH2qbarQbar(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 jM2unogqHg(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return jM2unogqbarHg(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
}
else { // they are both quark
if (bptype>0) {
if (aptype>0)
return jM2unogqHQ(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return jM2unogqHQbar(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
}
else {
if (aptype>0)
return jM2unogqbarHQ(punof,pn,pb,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return jM2unogqbarHQbar(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 jM2unobgHQg(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return jM2unobgHQbarg(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
}
else { // they are both quark
if (aptype>0) {
if (bptype>0)
return jM2unobqHQg(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return jM2unobqbarHQg(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
}
else {
if (bptype>0)
return jM2unobqHQbarg(pn,pb,punob,p1,pa,-qHp1,-qH,mt,include_bottom,mb);
else
return jM2unobqbarHQbarg(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_HEJ(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);
}
- // TODO
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
+ 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)*C_A;
+ wt *= C2Lipatovots(qip1, qi, pa, pb, lambda)*C_A;
} else{
- wt *= C2Lipatovots(qip1, qi, pa, pb, p1, pn)*C_A;
+ 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
- if(ev.type() == event_type::unob){
+ // 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){
+ 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;
}
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");
}
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
+ 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]);
+
+ auto begin_ladder = begin(partons) + 1;
+ auto end_ladder = end(partons) - 1;
+
+ bool wc = true;
+ auto q0 = pa - p1;
+ if (aptype!=partons[0].type) { //leg a emits w
+ wc = false;
+ 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]);
+
+ auto begin_ladder = begin(partons) + 2;
+ auto end_ladder = end(partons) - 1;
+
+ bool wc = true;
+ auto q0 = pa - p1 -pg;
+ if (aptype!=partons[1].type) { //leg a emits w
+ wc = false;
+ 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]);
+
+ auto begin_ladder = begin(partons) + 1;
+ auto end_ladder = end(partons) - 2;
+
+ bool wc = true;
+ auto q0 = pa - p1;
+ if (aptype!=partons[0].type) { //leg a emits w
+ wc = false;
+ 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]);
+
+ auto begin_ladder = begin(partons) + 2;
+ auto end_ladder = end(partons) - 1;
+
+ bool wc = true;
+ auto q0 = pa - pq - pqbar;
+ if (partons[1].type!=partons[0].type) { //leg a emits w
+ wc = false;
+ 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]);
+
+ auto begin_ladder = begin(partons) + 1;
+ auto end_ladder = end(partons) - 2;
+
+ bool wc = true;
+ auto q0 = pa - p1;
+ if (aptype!=partons[0].type) { //leg a emits w
+ wc = false;
+ 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;
+ }
+
+ auto begin_ladder = begin(partons) + 1;
+ auto end_ladder_1 = (backmidquark);
+ auto begin_ladder_2 = (backmidquark+2);
+ auto end_ladder = end(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 currents.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 p1out, CLHEP::HepLorentzVector p1in,
ParticleID type2,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
CLHEP::HepLorentzVector 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*MH2gq_outsideH(
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
+ 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
+ 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
+ q0, pa, pb, p1, pn,
+ param_.regulator_lambda
)*FKL_ladder_weight(
first_after_Higgs, end_ladder,
- qH - pH, pa, pb, p1, pn
+ qH - pH, pa, pb, p1, pn,
+ param_.regulator_lambda
);
return current_factor*C_A*C_A/(N_C*N_C-1.)*ladder_factor;
}
double MatrixElement::tree_param_partons(
double alpha_s, double mur,
std::vector<Particle> const & partons
) const{
const double gs2 = 4.*M_PI*alpha_s;
double wt = std::pow(gs2, partons.size());
if(param_.log_correction){
// use alpha_s(q_perp), evolved to mur
assert(partons.size() >= 2);
for(size_t i = 1; i < partons.size()-1; ++i){
wt *= 1 + alpha_s/(2*M_PI)*beta0*log(mur/partons[i].p.perp());
}
}
return wt;
}
- double MatrixElement::tree_param(
- Event const & ev,
- double mur
- ) const{
- assert(is_HEJ(ev.type()));
-
- const auto & out = ev.outgoing();
- const double alpha_s = alpha_s_(mur);
- auto AWZH_boson = std::find_if(
- begin(out), end(out),
- [](auto const & p){return is_AWZH_boson(p);}
- );
- double AWZH_coupling = 1.;
- if(AWZH_boson != end(out)){
+ 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: {
- AWZH_coupling = alpha_s*alpha_s;
- break;
- }
- // TODO
+ 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");
}
}
- if(ev.type() == event_type::unob){
+ }
+
+ double MatrixElement::tree_param(
+ Event const & ev,
+ double mur
+ ) const{
+ assert(is_HEJ(ev.type()));
+
+ const auto & out = ev.outgoing();
+ const double alpha_s = alpha_s_(mur);
+ const double AWZH_coupling = get_AWZH_coupling(ev, alpha_s);
+ if(ev.type() == event_type::unob || ev.type() == event_type::qqxexb){
return AWZH_coupling*4*M_PI*alpha_s*tree_param_partons(
alpha_s, mur, filter_partons({begin(out) + 1, end(out)})
);
}
- if(ev.type() == event_type::unof){
+ if(ev.type() == event_type::unof || ev.type() == event_type::qqxexf){
return AWZH_coupling*4*M_PI*alpha_s*tree_param_partons(
alpha_s, mur, filter_partons({begin(out), end(out) - 1})
);
}
return AWZH_coupling*tree_param_partons(alpha_s, mur, filter_partons(out));
}
} // namespace HEJ
diff --git a/src/PhaseSpacePoint.cc b/src/PhaseSpacePoint.cc
index db08408..9ea93fa 100644
--- a/src/PhaseSpacePoint.cc
+++ b/src/PhaseSpacePoint.cc
@@ -1,548 +1,631 @@
/**
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#include "HEJ/PhaseSpacePoint.hh"
#include <algorithm>
#include <assert.h>
#include <numeric>
#include <random>
#include "fastjet/ClusterSequence.hh"
#include "HEJ/Constants.hh"
#include "HEJ/Event.hh"
#include "HEJ/JetSplitter.hh"
#include "HEJ/kinematics.hh"
#include "HEJ/resummation_jet.hh"
#include "HEJ/utility.hh"
#include "HEJ/PDG_codes.hh"
#include "HEJ/event_types.hh"
namespace HEJ{
namespace {
constexpr int max_jet_user_idx = PhaseSpacePoint::ng_max;
bool is_nonjet_parton(fastjet::PseudoJet const & parton){
assert(parton.user_index() != -1);
return parton.user_index() > max_jet_user_idx;
}
bool is_jet_parton(fastjet::PseudoJet const & parton){
assert(parton.user_index() != -1);
return parton.user_index() <= max_jet_user_idx;
}
// user indices for partons with extremal rapidity
+ constexpr int qqxb_idx = -7;
+ constexpr int qqxf_idx = -6;
constexpr int unob_idx = -5;
constexpr int unof_idx = -4;
constexpr int backward_FKL_idx = -3;
constexpr int forward_FKL_idx = -2;
}
namespace {
double estimate_ng_mean(std::vector<fastjet::PseudoJet> const & Born_jets){
const double delta_y =
Born_jets.back().rapidity() - Born_jets.front().rapidity();
assert(delta_y > 0);
// Formula derived from fit in arXiv:1805.04446 (see Fig. 2)
return 0.975052*delta_y;
}
}
std::vector<fastjet::PseudoJet> PhaseSpacePoint::cluster_jets(
std::vector<fastjet::PseudoJet> const & partons
) const{
fastjet::ClusterSequence cs(partons, param_.jet_param.def);
return cs.inclusive_jets(param_.jet_param.min_pt);
}
bool PhaseSpacePoint::pass_resummation_cuts(
std::vector<fastjet::PseudoJet> const & jets
) const{
return cluster_jets(jets).size() == jets.size();
}
int PhaseSpacePoint::sample_ng(std::vector<fastjet::PseudoJet> const & Born_jets){
const double ng_mean = estimate_ng_mean(Born_jets);
std::poisson_distribution<int> dist(ng_mean);
const int ng = dist(ran_.get());
assert(ng >= 0);
assert(ng < ng_max);
weight_ *= std::tgamma(ng + 1)*std::exp(ng_mean)*std::pow(ng_mean, -ng);
return ng;
}
void PhaseSpacePoint::copy_AWZH_boson_from(Event const & event){
auto const & from = event.outgoing();
const auto AWZH_boson = std::find_if(
begin(from), end(from),
[](Particle const & p){ return is_AWZH_boson(p); }
);
if(AWZH_boson == end(from)) return;
auto insertion_point = std::lower_bound(
begin(outgoing_), end(outgoing_), *AWZH_boson, rapidity_less{}
);
outgoing_.insert(insertion_point, *AWZH_boson);
// copy decay products
const int idx = std::distance(begin(from), AWZH_boson);
assert(idx >= 0);
const auto decay_it = event.decays().find(idx);
if(decay_it != end(event.decays())){
const int new_idx = std::distance(begin(outgoing_), insertion_point);
assert(new_idx >= 0);
assert(outgoing_[new_idx].type == AWZH_boson->type);
decays_.emplace(new_idx, decay_it->second);
}
assert(std::is_sorted(begin(outgoing_), end(outgoing_), rapidity_less{}));
}
+
+ //! \brief relabels qqx-pair with its PDG IDs.
+ //*@param ev Born Event
+ //
+ // This function will label the qqx pair in a qqx event back to
+ // their original types from the input event.
+ void PhaseSpacePoint::label_qqx(Event const & event){
+ auto const & bornout = event.outgoing();
+ const auto backquark = std::find_if(
+ begin(bornout) + 1 - ((qqxb_)?1:0), end(bornout) - 1 + ((qqxf_)?1:0) ,
+ [](Particle const & s){ return (is_anyquark(s.type)); }
+ );
+ if(backquark == end(bornout) || (backquark+1)->type==pid::gluon) weight_= 0;
+
+ auto quark1type = backquark->type;
+ auto quark2type = (backquark+1)->type;
+
+ if(is_AWZ_boson((backquark+1)->type)) quark2type = (backquark+2)->type;
+
+ if( !((is_quark(quark1type) && is_antiquark(quark2type))
+ && !(is_quark(quark2type) && is_antiquark(quark1type)))
+ ){
+ weight_=0;
+ }
+
+ auto partons = to_PseudoJet(filter_partons(outgoing_));
+ fastjet::ClusterSequence cs(partons, event.jet_def());
+ const auto jets = fastjet::sorted_by_rapidity(cs.inclusive_jets(event.min_jet_pt()));
+
+ const auto indices = cs.particle_jet_indices({jets});
+ assert(partons.size() == indices.size());
+
+ int qpart=-1;
+ // Find Parton in res event closest to most backward qqx jet in born
+ for (size_t i=0; i<indices.size(); i++) {
+ if( (indices[i] != -1) && (indices[i]==indices[i+1]-1)
+ && nearby_ep(backquark->rapidity(), partons[i].rapidity(), 0.1)){
+ qpart=i;
+ outgoing_.at(qpart).type = quark1type;
+ outgoing_.at(qpart+1).type = quark2type;
+ break;
+ }
+ }
+
+ if(qpart==-1) weight_=0;
+ assert(std::is_sorted(begin(outgoing_), end(outgoing_), rapidity_less{}));
+ }
+
PhaseSpacePoint::PhaseSpacePoint(
Event const & ev, PhaseSpacePointConfig conf, HEJ::RNG & ran
):
unob_{ev.type() == event_type::unob},
unof_{ev.type() == event_type::unof},
+ qqxb_{ev.type() == event_type::qqxexb},
+ qqxf_{ev.type() == event_type::qqxexf},
+ qqxmid_{ev.type() == event_type::qqxmid},
param_{std::move(conf)},
ran_{ran}
{
weight_ = 1;
const auto Born_jets = sorted_by_rapidity(ev.jets());
const int ng = sample_ng(Born_jets);
weight_ /= std::tgamma(ng + 1);
const int ng_jets = sample_ng_jets(ng, Born_jets);
std::vector<fastjet::PseudoJet> out_partons = gen_non_jet(
ng - ng_jets, CMINPT, param_.jet_param.min_pt
);
- {
+
const auto qperp = std::accumulate(
begin(out_partons), end(out_partons),
fastjet::PseudoJet{}
);
const auto jets = reshuffle(Born_jets, qperp);
if(weight_ == 0.) return;
if(! pass_resummation_cuts(jets)){
weight_ = 0.;
return;
}
std::vector<fastjet::PseudoJet> jet_partons = split(jets, ng_jets);
if(weight_ == 0.) return;
rescale_rapidities(
out_partons,
most_backward_FKL(jet_partons).rapidity(),
most_forward_FKL(jet_partons).rapidity()
);
if(! cluster_jets(out_partons).empty()){
weight_ = 0.;
return;
}
std::sort(begin(out_partons), end(out_partons), rapidity_less{});
assert(
std::is_sorted(begin(jet_partons), end(jet_partons), rapidity_less{})
);
const auto first_jet_parton = out_partons.insert(
end(out_partons), begin(jet_partons), end(jet_partons)
);
std::inplace_merge(
begin(out_partons), first_jet_parton, end(out_partons), rapidity_less{}
);
- }
+
if(! jets_ok(Born_jets, out_partons)){
weight_ = 0.;
return;
}
weight_ *= phase_space_normalisation(Born_jets.size(), out_partons.size());
outgoing_.reserve(out_partons.size() + 1); // one slot for possible A, W, Z, H
for(auto & p: out_partons){
outgoing_.emplace_back(Particle{pid::gluon, std::move(p), {}});
}
- most_backward_FKL(outgoing_).type = ev.incoming().front().type;
- most_forward_FKL(outgoing_).type = ev.incoming().back().type;
+
+ const auto WEmit = std::find_if(
+ begin(ev.outgoing()), end(ev.outgoing()),
+ [](Particle const & s){ return abs(s.type) == pid::Wp; }
+ );
+
+ if (WEmit != end(ev.outgoing())){
+ if(!qqxb_)
+ outgoing_[unob_].type = filter_partons(ev.outgoing())[unob_].type;
+ if(!qqxf_)
+ outgoing_.rbegin()[unof_].type = filter_partons(ev.outgoing()).rbegin()[unof_].type;
+ }
+ else{
+ most_backward_FKL(outgoing_).type = ev.incoming().front().type;
+ most_forward_FKL(outgoing_).type = ev.incoming().back().type;
+ }
+
+ if(qqxmid_||qqxb_||qqxf_){
+ label_qqx(ev);
+ }
copy_AWZH_boson_from(ev);
assert(!outgoing_.empty());
+
reconstruct_incoming(ev.incoming());
}
std::vector<fastjet::PseudoJet> PhaseSpacePoint::gen_non_jet(
int count, double ptmin, double ptmax
){
// heuristic parameters for pt sampling
const double ptpar = 1.3 + count/5.;
const double temp1 = atan((ptmax - ptmin)/ptpar);
std::vector<fastjet::PseudoJet> partons(count);
for(size_t i = 0; i < (size_t) count; ++i){
const double r1 = ran_.get().flat();
const double pt = ptmin + ptpar*tan(r1*temp1);
const double temp2 = cos(r1*temp1);
const double phi = 2*M_PI*ran_.get().flat();
weight_ *= 2.0*M_PI*pt*ptpar*temp1/(temp2*temp2);
// we don't know the allowed rapidity span yet,
// set a random value to be rescaled later on
const double y = ran_.get().flat();
partons[i].reset_PtYPhiM(pt, y, phi);
// Set user index higher than any jet-parton index
// in order to assert that these are not inside jets
partons[i].set_user_index(i + 1 + ng_max);
assert(ptmin-1e-5 <= partons[i].pt() && partons[i].pt() <= ptmax+1e-5);
}
assert(std::all_of(partons.cbegin(), partons.cend(), is_nonjet_parton));
return partons;
}
void PhaseSpacePoint::rescale_rapidities(
std::vector<fastjet::PseudoJet> & partons,
double ymin, double ymax
){
constexpr double ep = 1e-7;
for(auto & parton: partons){
assert(0 <= parton.rapidity() && parton.rapidity() <= 1);
const double dy = ymax - ymin - 2*ep;
const double y = ymin + ep + dy*parton.rapidity();
parton.reset_momentum_PtYPhiM(parton.pt(), y, parton.phi());
weight_ *= dy;
assert(ymin <= parton.rapidity() && parton.rapidity() <= ymax);
}
}
namespace {
template<typename T, typename... Rest>
auto min(T const & a, T const & b, Rest&&... r) {
using std::min;
return min(a, min(b, std::forward<Rest>(r)...));
}
}
double PhaseSpacePoint::probability_in_jet(
std::vector<fastjet::PseudoJet> const & Born_jets
) const{
assert(std::is_sorted(begin(Born_jets), end(Born_jets), rapidity_less{}));
assert(Born_jets.size() >= 2);
const double dy =
Born_jets.back().rapidity() - Born_jets.front().rapidity();
const double R = param_.jet_param.def.R();
const int njets = Born_jets.size();
const double p_J_y_large = (njets-1)*R*R/(2.*dy);
const double p_J_y0 = njets*R/M_PI;
return min(p_J_y_large, p_J_y0, 1.);
}
int PhaseSpacePoint::sample_ng_jets(
int ng, std::vector<fastjet::PseudoJet> const & Born_jets
){
const double p_J = probability_in_jet(Born_jets);
std::binomial_distribution<> bin_dist(ng, p_J);
const int ng_J = bin_dist(ran_.get());
weight_ *= std::pow(p_J, -ng_J)*std::pow(1 - p_J, ng_J - ng);
return ng_J;
}
std::vector<fastjet::PseudoJet> PhaseSpacePoint::reshuffle(
std::vector<fastjet::PseudoJet> const & Born_jets,
fastjet::PseudoJet const & q
){
if(q == fastjet::PseudoJet{0, 0, 0, 0}) return Born_jets;
const auto jets = resummation_jet_momenta(Born_jets, q);
if(jets.empty()){
weight_ = 0;
return {};
}
// additional Jacobian to ensure Born integration over delta gives 1
weight_ *= resummation_jet_weight(Born_jets, q);
return jets;
}
std::vector<int> PhaseSpacePoint::distribute_jet_partons(
int ng_jets, std::vector<fastjet::PseudoJet> const & jets
){
size_t first_valid_jet = 0;
size_t num_valid_jets = jets.size();
const double R_eff = 5./3.*param_.jet_param.def.R();
// if there is an unordered jet too far away from the FKL jets
// then extra gluon constituents of the unordered jet would
// violate the FKL rapidity ordering
- if(unob_ && jets[0].delta_R(jets[1]) > R_eff){
+ if((unob_||qqxb_) && jets[0].delta_R(jets[1]) > R_eff){
++first_valid_jet;
--num_valid_jets;
}
- else if(unof_ && jets[jets.size()-1].delta_R(jets[jets.size()-2]) > R_eff){
+ else if((unof_||qqxf_) && jets[jets.size()-1].delta_R(jets[jets.size()-2]) > R_eff){
--num_valid_jets;
}
std::vector<int> np(jets.size(), 1);
for(int i = 0; i < ng_jets; ++i){
++np[first_valid_jet + ran_.get().flat() * num_valid_jets];
}
weight_ *= std::pow(num_valid_jets, ng_jets);
return np;
}
#ifndef NDEBUG
namespace{
bool tagged_FKL_backward(
std::vector<fastjet::PseudoJet> const & jet_partons
){
return std::find_if(
begin(jet_partons), end(jet_partons),
[](fastjet::PseudoJet const & p){
return p.user_index() == backward_FKL_idx;
}
) != end(jet_partons);
}
bool tagged_FKL_forward(
std::vector<fastjet::PseudoJet> const & jet_partons
){
// the most forward FKL parton is most likely near the end of jet_partons;
// start search from there
return std::find_if(
jet_partons.rbegin(), jet_partons.rend(),
[](fastjet::PseudoJet const & p){
return p.user_index() == forward_FKL_idx;
}
) != jet_partons.rend();
}
bool tagged_FKL_extremal(
std::vector<fastjet::PseudoJet> const & jet_partons
){
return tagged_FKL_backward(jet_partons) && tagged_FKL_forward(jet_partons);
}
} // namespace anonymous
#endif
std::vector<fastjet::PseudoJet> PhaseSpacePoint::split(
std::vector<fastjet::PseudoJet> const & jets,
int ng_jets
){
return split(jets, distribute_jet_partons(ng_jets, jets));
}
bool PhaseSpacePoint::pass_extremal_cuts(
fastjet::PseudoJet const & ext_parton,
fastjet::PseudoJet const & jet
) const{
if(ext_parton.pt() < param_.min_extparton_pt) return false;
return (ext_parton - jet).pt()/jet.pt() < param_.max_ext_soft_pt_fraction;
}
std::vector<fastjet::PseudoJet> PhaseSpacePoint::split(
std::vector<fastjet::PseudoJet> const & jets,
std::vector<int> const & np
){
assert(! jets.empty());
assert(jets.size() == np.size());
assert(pass_resummation_cuts(jets));
- const size_t most_backward_FKL_idx = 0 + unob_;
- const size_t most_forward_FKL_idx = jets.size() - 1 - unof_;
+ const size_t most_backward_FKL_idx = 0 + unob_ + qqxb_;
+ const size_t most_forward_FKL_idx = jets.size() - 1 - unof_ - qqxf_;
const auto & jet = param_.jet_param;
const JetSplitter jet_splitter{jet.def, jet.min_pt, ran_};
std::vector<fastjet::PseudoJet> jet_partons;
// randomly distribute jet gluons among jets
for(size_t i = 0; i < jets.size(); ++i){
auto split_res = jet_splitter.split(jets[i], np[i]);
weight_ *= split_res.weight;
if(weight_ == 0) return {};
assert(
std::all_of(
begin(split_res.constituents), end(split_res.constituents),
is_jet_parton
)
);
const auto first_new_parton = jet_partons.insert(
end(jet_partons),
begin(split_res.constituents), end(split_res.constituents)
);
// mark uno and extremal FKL emissions here so we can check
// their position once all emissions are generated
auto extremal = end(jet_partons);
- if((unob_ && i == 0) || i == most_backward_FKL_idx){
- // unordered or FKL backward emission
+ if (i == most_backward_FKL_idx){ //FKL backward emission
extremal = std::min_element(
first_new_parton, end(jet_partons), rapidity_less{}
);
- extremal->set_user_index(
- (i == most_backward_FKL_idx)?backward_FKL_idx:unob_idx
+ extremal->set_user_index(backward_FKL_idx);
+ }
+ else if(((unob_ || qqxb_) && i == 0)){
+ // unordered/qqxb
+ extremal = std::min_element(
+ first_new_parton, end(jet_partons), rapidity_less{}
);
+ extremal->set_user_index((unob_)?unob_idx:qqxb_idx);
}
- else if((unof_ && i == jets.size() - 1) || i == most_forward_FKL_idx){
- // unordered or FKL forward emission
+
+ else if (i == most_forward_FKL_idx){
extremal = std::max_element(
first_new_parton, end(jet_partons), rapidity_less{}
);
- extremal->set_user_index(
- (i == most_forward_FKL_idx)?forward_FKL_idx:unof_idx
+ extremal->set_user_index(forward_FKL_idx);
+ }
+ else if(((unof_ || qqxf_) && i == jets.size() - 1)){
+ // unordered/qqxf
+ extremal = std::max_element(
+ first_new_parton, end(jet_partons), rapidity_less{}
);
+ extremal->set_user_index((unof_)?unof_idx:qqxf_idx);
}
if(
extremal != end(jet_partons)
&& !pass_extremal_cuts(*extremal, jets[i])
){
weight_ = 0;
return {};
}
}
assert(tagged_FKL_extremal(jet_partons));
std::sort(begin(jet_partons), end(jet_partons), rapidity_less{});
if(
!extremal_ok(jet_partons)
|| !split_preserved_jets(jets, jet_partons)
){
weight_ = 0.;
return {};
}
return jet_partons;
}
bool PhaseSpacePoint::extremal_ok(
std::vector<fastjet::PseudoJet> const & partons
) const{
assert(std::is_sorted(begin(partons), end(partons), rapidity_less{}));
if(unob_ && partons.front().user_index() != unob_idx) return false;
if(unof_ && partons.back().user_index() != unof_idx) return false;
+ if(qqxb_ && partons.front().user_index() != qqxb_idx) return false;
+ if(qqxf_ && partons.back().user_index() != qqxf_idx) return false;
return
most_backward_FKL(partons).user_index() == backward_FKL_idx
&& most_forward_FKL(partons).user_index() == forward_FKL_idx;
}
bool PhaseSpacePoint::split_preserved_jets(
std::vector<fastjet::PseudoJet> const & jets,
std::vector<fastjet::PseudoJet> const & jet_partons
) const{
assert(std::is_sorted(begin(jets), end(jets), rapidity_less{}));
const auto split_jets = sorted_by_rapidity(cluster_jets(jet_partons));
// this can happen if two overlapping jets
// are both split into more than one parton
if(split_jets.size() != jets.size()) return false;
for(size_t i = 0; i < split_jets.size(); ++i){
// this can happen if there are two overlapping jets
// and a parton is assigned to the "wrong" jet
if(!nearby_ep(jets[i].rapidity(), split_jets[i].rapidity(), 1e-2)){
return false;
}
}
return true;
}
template<class Particle>
Particle const & PhaseSpacePoint::most_backward_FKL(
std::vector<Particle> const & partons
) const{
- return partons[0 + unob_];
+ return partons[0 + unob_ + qqxb_];
}
template<class Particle>
Particle const & PhaseSpacePoint::most_forward_FKL(
std::vector<Particle> const & partons
) const{
- const size_t idx = partons.size() - 1 - unof_;
+ const size_t idx = partons.size() - 1 - unof_ - qqxf_;
assert(idx < partons.size());
return partons[idx];
}
template<class Particle>
Particle & PhaseSpacePoint::most_backward_FKL(
std::vector<Particle> & partons
) const{
- return partons[0 + unob_];
+ return partons[0 + unob_ + qqxb_];
}
template<class Particle>
Particle & PhaseSpacePoint::most_forward_FKL(
std::vector<Particle> & partons
) const{
- const size_t idx = partons.size() - 1 - unof_;
+ const size_t idx = partons.size() - 1 - unof_ - qqxf_;
assert(idx < partons.size());
return partons[idx];
}
namespace {
bool contains_idx(
fastjet::PseudoJet const & jet, fastjet::PseudoJet const & parton
){
auto const & constituents = jet.constituents();
const int idx = parton.user_index();
return std::find_if(
begin(constituents), end(constituents),
[idx](fastjet::PseudoJet const & con){return con.user_index() == idx;}
) != end(constituents);
}
}
/**
* final jet test:
* - number of jets must match Born kinematics
* - no partons designated as nonjet may end up inside jets
* - all other outgoing partons *must* end up inside jets
* - the extremal (in rapidity) partons must be inside the extremal jets
* - rapidities must be the same (by construction)
*/
bool PhaseSpacePoint::jets_ok(
std::vector<fastjet::PseudoJet> const & Born_jets,
std::vector<fastjet::PseudoJet> const & partons
) const{
fastjet::ClusterSequence cs(partons, param_.jet_param.def);
const auto jets = sorted_by_rapidity(cs.inclusive_jets(param_.jet_param.min_pt));
if(jets.size() != Born_jets.size()) return false;
int in_jet = 0;
for(size_t i = 0; i < jets.size(); ++i){
assert(jets[i].has_constituents());
for(auto && parton: jets[i].constituents()){
if(is_nonjet_parton(parton)) return false;
}
in_jet += jets[i].constituents().size();
}
const int expect_in_jet = std::count_if(
partons.cbegin(), partons.cend(), is_jet_parton
);
if(in_jet != expect_in_jet) return false;
// note that PseudoJet::contains does not work here
if(! (
contains_idx(most_backward_FKL(jets), most_backward_FKL(partons))
&& contains_idx(most_forward_FKL(jets), most_forward_FKL(partons))
)) return false;
if(unob_ && !contains_idx(jets.front(), partons.front())) return false;
if(unof_ && !contains_idx(jets.back(), partons.back())) return false;
for(size_t i = 0; i < jets.size(); ++i){
assert(nearby_ep(jets[i].rapidity(), Born_jets[i].rapidity(), 1e-2));
}
return true;
}
void PhaseSpacePoint::reconstruct_incoming(
std::array<Particle, 2> const & Born_incoming
){
std::tie(incoming_[0].p, incoming_[1].p) = incoming_momenta(outgoing_);
for(size_t i = 0; i < incoming_.size(); ++i){
incoming_[i].type = Born_incoming[i].type;
}
assert(momentum_conserved());
}
double PhaseSpacePoint::phase_space_normalisation(
int num_Born_jets, int num_out_partons
) const{
return pow(16*pow(M_PI,3), num_Born_jets - num_out_partons);
}
bool PhaseSpacePoint::momentum_conserved() const{
fastjet::PseudoJet diff;
for(auto const & in: incoming()) diff += in.p;
const double norm = diff.E();
for(auto const & out: outgoing()) diff -= out.p;
return nearby(diff, fastjet::PseudoJet{}, norm);
}
} //namespace HEJ
diff --git a/src/Tensor.cc b/src/Tensor.cc
new file mode 100644
index 0000000..0fba3bb
--- /dev/null
+++ b/src/Tensor.cc
@@ -0,0 +1,790 @@
+#include "HEJ/currents.hh"
+#include "HEJ/Tensor.hh"
+
+#include <array>
+
+#include <iostream>
+
+namespace{
+// Tensor Template definitions
+ short int sigma_index5[1024];
+ short int sigma_index3[64];
+ std::valarray<COM> permfactor5;
+ std::valarray<COM> permfactor3;
+ short int helfactor5[2][1024];
+ short int helfactor3[2][64];
+
+ // 2D sigma matrices
+ const COM sigma0[2][2] = { {1.,0.}, {0., 1.} };
+ const COM sigma1[2][2] = { {0.,1.}, {1., 0.} };
+ const COM sigma2[2][2] = { {0,-1.*COM(0,1)}, {1.*COM(0,1), 0.} };
+ const COM sigma3[2][2] = { {1.,0.}, {0., -1.} };
+
+ Tensor<1,4> Sigma(int i, int j, bool hel){
+ Tensor<1,4> newT;
+ if(hel){
+ newT.components[0]=sigma0[i][j];
+ newT.components[1]=sigma1[i][j];
+ newT.components[2]=sigma2[i][j];
+ newT.components[3]=sigma3[i][j];
+ } else {
+ newT.components[0]= sigma0[i][j];
+ newT.components[1]=-sigma1[i][j];
+ newT.components[2]=-sigma2[i][j];
+ newT.components[3]=-sigma3[i][j];
+ }
+ return newT;
+ }
+
+ // map from a list of 5 tensor lorentz indices onto a single index 0<=i<1024
+ // in 4 dimensional spacetime
+
+ int tensor2listindex(std::array<int,5> indexlist){
+ int mu=indexlist[0];
+ int nu=indexlist[1];
+ int sigma=indexlist[2];
+ int tau=indexlist[3];
+ int rho=indexlist[4];
+ int myindex;
+
+ myindex = 256*mu+64*nu+16*sigma+4*tau+rho;
+
+ if(myindex<0||myindex>1023){
+ std::cerr<<"bad index in tensor2listindex "<<std::endl;
+ return 1024;
+ }
+ return myindex;
+ }
+
+ // map from a list of 3 tensor lorentz indices onto a single index 0<=i<64 in
+ // 4 dimensional spacetime
+ int tensor2listindex(std::array<int,3> indexlist){
+ int mu=indexlist[0];
+ int nu=indexlist[1];
+ int sigma=indexlist[2];
+ int myindex;
+
+ myindex = 16*mu+4*nu+sigma;
+
+ if(myindex<0||myindex>64){
+ std::cerr<<"bad index in tensor2listindex "<<std::endl;
+ return 64;
+ }
+ return myindex;
+ }
+
+ // generate all unique perms of vectors {a,a,a,a,b}, return in perms
+ // set_permfactor is a bool which encodes the anticommutation relations of the
+ // sigma matrices namely if we have sigma0, set_permfactor= false because it
+ // commutes with all others otherwise we need to assign a minus sign to odd
+ // permutations, set in permfactor
+ // note, inital perm is always even
+ void perms41(int same4, int diff, std::vector<std::array<int,5>> & perms){
+ bool set_permfactor(true);
+ if(same4==0||diff==0)
+ set_permfactor=false;
+
+ for(int diffpos=0;diffpos<5;diffpos++){
+ std::array<int,5> tempvec={same4,same4,same4,same4,same4};
+ tempvec[diffpos]=diff;
+ perms.push_back(tempvec);
+ if(set_permfactor){
+ if(diffpos%2==1)
+ permfactor5[tensor2listindex(tempvec)]=-1.;
+ }
+ }
+ }
+
+ // generate all unique perms of vectors {a,a,a,b,b}, return in perms
+ // note, inital perm is always even
+ void perms32(int same3, int diff, std::vector<std::array<int,5>> & perms){
+ bool set_permfactor(true);
+ if(same3==0||diff==0)
+ set_permfactor=false;
+
+ for(int diffpos1=0;diffpos1<5;diffpos1++){
+ for(int diffpos2=diffpos1+1;diffpos2<5;diffpos2++){
+ std::array<int,5> tempvec={same3,same3,same3,same3,same3};
+ tempvec[diffpos1]=diff;
+ tempvec[diffpos2]=diff;
+ perms.push_back(tempvec);
+ if(set_permfactor){
+ if((diffpos2-diffpos1)%2==0)
+ permfactor5[tensor2listindex(tempvec)]=-1.;
+ }
+ }
+ }
+ }
+
+ // generate all unique perms of vectors {a,a,a,b,c}, return in perms
+ // we have two bools since there are three distinct type of sigma matrices to
+ // permute, so need to test if the 3xrepeated = sigma0 or if one of the
+ // singles is sigma0
+ // if diff1/diff2 are distinct, flipping them results in a change of perm,
+ // otherwise it'll be symmetric under flip -> encode this in set_permfactor2
+ // as long as diff2!=0 can ensure inital perm is even
+ // if diff2=0 then it is not possible to ensure inital perm even -> encode in
+ // bool signflip
+ void perms311(int same3, int diff1, int diff2,
+ std::vector<std::array<int,5>> & perms
+ ){
+ bool set_permfactor2(true);
+ bool same0(false);
+ bool diff0(false);
+ bool signflip(false); // if true, inital perm is odd
+
+ if(same3==0) // is the repeated matrix sigma0?
+ same0 = true;
+ else if(diff2==0){ // is one of the single matrices sigma0
+ diff0=true;
+ if((diff1%3-same3)!=-1)
+ signflip=true;
+ } else if(diff1==0){
+ std::cerr<<"Note, only first and last argument may be zero"<<std::endl;
+ return;
+ }
+
+ // possible outcomes: tt, ft, tf
+
+ for(int diffpos1=0;diffpos1<5;diffpos1++){
+ for(int diffpos2=diffpos1+1;diffpos2<5;diffpos2++){
+ std::array<int,5> tempvec={same3,same3,same3,same3,same3};
+ tempvec[diffpos1]=diff1;
+ tempvec[diffpos2]=diff2;
+ perms.push_back(tempvec);
+
+ if(!same0 && !diff0){
+ // full antisymmetric under exchange of same3,diff1,diff2
+ if((diffpos2-diffpos1)%2==0){
+ permfactor5[tensor2listindex(tempvec)]=-1.*COM(0,1); // odd perm
+ // if this perm is odd, swapping diff1<->diff2 automatically even
+ set_permfactor2=false;
+ } else {
+ permfactor5[tensor2listindex(tempvec)]=COM(0,1); // even perm
+ // if this perm is even, swapping diff1<->diff2 automatically odd
+ set_permfactor2=true;
+ }
+ } else if(diff0){// one of the single matrices is sigma0
+ if(signflip){ // initial config is odd!
+ if(diffpos1%2==1){
+ permfactor5[tensor2listindex(tempvec)]=COM(0,1); // even perm
+ // initally symmetric under diff1<->diff2 =>
+ // if this perm is even, automatically even for first diffpos2
+ set_permfactor2=false;
+ } else {
+ permfactor5[tensor2listindex(tempvec)]=-1.*COM(0,1); // odd perm
+ // initally symmetric under diff1<->diff2 =>
+ // if this perm is odd, automatically odd for first diffpos2
+ set_permfactor2=true;
+ }
+ } else {// diff0=true, initial config is even
+ if(diffpos1%2==1){
+ permfactor5[tensor2listindex(tempvec)]=-1.*COM(0,1); // odd perm
+ // initally symmetric under diff1<->diff2 =>
+ // if this perm is odd, automatically odd for first diffpos2
+ set_permfactor2=true;
+ } else {
+ permfactor5[tensor2listindex(tempvec)]=COM(0,1); // even perm
+ // initally symmetric under diff1<->diff2 =>
+ // if this perm is even, automatically even for first diffpos2
+ set_permfactor2=false;
+ }
+ }
+ if((diffpos2-diffpos1-1)%2==1)
+ set_permfactor2=!set_permfactor2; // change to account for diffpos2
+ } else if(same0){
+ // the repeated matrix is sigma0
+ // => only relative positions of diff1, diff2 matter.
+ // always even before flip because diff1pos<diff2pos
+ permfactor5[tensor2listindex(tempvec)]=COM(0,1);
+ // if this perm is odd, swapping diff1<->diff2 automatically odd
+ set_permfactor2=true;
+ }
+
+ tempvec[diffpos1]=diff2;
+ tempvec[diffpos2]=diff1;
+ perms.push_back(tempvec);
+
+ if(set_permfactor2)
+ permfactor5[tensor2listindex(tempvec)]=-1.*COM(0,1);
+ else
+ permfactor5[tensor2listindex(tempvec)]=COM(0,1);
+
+ }
+ }
+ } // end perms311
+
+ // generate all unique perms of vectors {a,a,b,b,c}, return in perms
+ void perms221(int same2a, int same2b, int diff,
+ std::vector<std::array<int,5>> & perms
+ ){
+ bool set_permfactor1(true);
+ bool set_permfactor2(true);
+ if(same2b==0){
+ std::cerr<<"second entry in perms221() shouldn't be zero" <<std::endl;
+ return;
+ } else if(same2a==0)
+ set_permfactor1=false;
+ else if(diff==0)
+ set_permfactor2=false;
+
+ for(int samepos=0;samepos<5;samepos++){
+ int permcount = 0;
+ for(int samepos2=samepos+1;samepos2<5;samepos2++){
+ for(int diffpos=0;diffpos<5;diffpos++){
+ if(diffpos==samepos||diffpos==samepos2) continue;
+
+ std::array<int,5> tempvec={same2a,same2a,same2a,same2a,same2a};
+ tempvec[samepos]=same2b;
+ tempvec[samepos2]=same2b;
+ tempvec[diffpos]=diff;
+ perms.push_back(tempvec);
+
+ if(set_permfactor1){
+ if(set_permfactor2){// full anti-symmetry
+ if(permcount%2==1)
+ permfactor5[tensor2listindex(tempvec)]=-1.;
+ } else { // diff is sigma0
+ if( ((samepos2-samepos-1)%3>0)
+ && (abs(abs(samepos2-diffpos)-abs(samepos-diffpos))%3>0) )
+ permfactor5[tensor2listindex(tempvec)]=-1.;
+ }
+ } else { // same2a is sigma0
+ if((diffpos>samepos) && (diffpos<samepos2))
+ permfactor5[tensor2listindex(tempvec)]=-1.;
+ }
+ permcount++;
+ }
+ }
+ }
+ }
+
+ // generate all unique perms of vectors {a,a,b,b,c}, return in perms
+ // there must be a sigma zero if we have 4 different matrices in string
+ // bool is true if sigma0 is the repeated matrix
+ void perms2111(int same2, int diff1,int diff2,int diff3,
+ std::vector<std::array<int,5>> & perms
+ ){
+ bool twozero(false);
+ if(same2==0)
+ twozero=true;
+ else if (diff1!=0){
+ std::cerr<<"One of first or second argurments must be a zero"<<std::endl;
+ return;
+ } else if(diff2==0|| diff3==0){
+ std::cerr<<"Only first and second arguments may be a zero."<<std::endl;
+ return;
+ }
+
+ int permcount = 0;
+
+ for(int diffpos1=0;diffpos1<5;diffpos1++){
+ for(int diffpos2=0;diffpos2<5;diffpos2++){
+ if(diffpos2==diffpos1) continue;
+ for(int diffpos3=0;diffpos3<5;diffpos3++){
+ if(diffpos3==diffpos2||diffpos3==diffpos1) continue;
+
+ std::array<int,5> tempvec={same2,same2,same2,same2,same2};
+ tempvec[diffpos1]=diff1;
+ tempvec[diffpos2]=diff2;
+ tempvec[diffpos3]=diff3;
+ perms.push_back(tempvec);
+
+ if(twozero){// don't care about exact positions of singles, just order
+ if(diffpos2>diffpos3 && diffpos3>diffpos1)
+ permfactor5[tensor2listindex(tempvec)]=-1.*COM(0,1);// odd
+ else if(diffpos1>diffpos2 && diffpos2>diffpos3)
+ permfactor5[tensor2listindex(tempvec)]=-1.*COM(0,1);// odd
+ else if(diffpos3>diffpos1 && diffpos1>diffpos2)
+ permfactor5[tensor2listindex(tempvec)]=-1.*COM(0,1);// odd
+ else
+ permfactor5[tensor2listindex(tempvec)]=COM(0,1);// evwn
+ } else {
+ if(permcount%2==1)
+ permfactor5[tensor2listindex(tempvec)]=-1.*COM(0,1);
+ else
+ permfactor5[tensor2listindex(tempvec)]=COM(0,1);
+ }
+ permcount++;
+ }
+ }
+ }
+ }
+
+ void perms21(int same, int diff, std::vector<std::array<int,3>> & perms){
+
+ bool set_permfactor(true);
+ if(same==0||diff==0)
+ set_permfactor=false;
+
+ for(int diffpos=0; diffpos<3;diffpos++){
+ std::array<int,3> tempvec={same,same,same};
+ tempvec[diffpos]=diff;
+ perms.push_back(tempvec);
+ if(set_permfactor && diffpos==1)
+ permfactor3[tensor2listindex(tempvec)]=-1.;
+ }
+ }
+
+ void perms111(int diff1, int diff2, int diff3,
+ std::vector<std::array<int,3>> & perms
+ ){
+ bool sig_zero(false);
+ if(diff1==0)
+ sig_zero=true;
+ else if(diff2==0||diff3==0){
+ std::cerr<<"Only first argument may be a zero."<<std::endl;
+ return;
+ }
+ int permcount=0;
+ for(int pos1=0;pos1<3;pos1++){
+ for(int pos2=pos1+1;pos2<3;pos2++){
+ std::array<int,3> tempvec={diff1,diff1,diff1};
+ tempvec[pos1]=diff2;
+ tempvec[pos2]=diff3;
+ perms.push_back(tempvec);
+ if(sig_zero){
+ permfactor3[tensor2listindex(tempvec)]=1.*COM(0,1); // even
+ } else if(permcount%2==1){
+ permfactor3[tensor2listindex(tempvec)]=-1.*COM(0,1); // odd
+ } else {
+ permfactor3[tensor2listindex(tempvec)]=1.*COM(0,1); // even
+ }
+
+ tempvec[pos1]=diff3;
+ tempvec[pos2]=diff2;
+ perms.push_back(tempvec);
+
+ if(sig_zero){
+ permfactor3[tensor2listindex(tempvec)]=-1.*COM(0,1); // odd
+ } else if(permcount%2==1){
+ permfactor3[tensor2listindex(tempvec)]=1.*COM(0,1); // even
+ } else {
+ permfactor3[tensor2listindex(tempvec)]=-1.*COM(0,1); // odd
+ }
+ permcount++;
+ }
+ }
+ }
+
+ void SpinorO(CLHEP::HepLorentzVector p, bool hel, COM *sp){
+ // sp is pointer to COM sp[2]
+ COM pplus = p.e() +p.z();
+ COM pminus = p.e() -p.z();
+ COM sqpp= sqrt(pplus);
+ COM sqpm= sqrt(pminus);
+ COM pperp = p.x() + COM(0,1)*p.y();
+
+ // if hel=+
+ if(hel){
+ sp[0] = sqpp;
+ sp[1] = sqpm*pperp/abs(pperp);
+ } else {
+ sp[0] = sqpm*conj(pperp)/abs(pperp);
+ sp[1] = -sqpp;
+ }
+ }
+
+ void SpinorIp(COM sqpp, bool hel, COM *sp){
+ // if hel=+
+ if(hel){
+ sp[0] = sqpp;
+ sp[1] = 0.;
+ } else {
+ sp[0] = 0.;
+ sp[1] = -sqpp;
+ }
+ }
+
+ void SpinorIm(COM sqpm, bool hel, COM *sp){
+ // if hel=+
+ if(hel){
+ sp[0] = 0;
+ sp[1] = -sqpm;
+ } else {
+ sp[0] = -sqpm;
+ sp[1] = 0.;
+ }
+ }
+
+ void Spinor(CLHEP::HepLorentzVector p, bool hel, COM *sp){
+ COM pplus = p.e() +p.z();
+ COM pminus = p.e() -p.z();
+
+ // If incoming along +ve z
+ if (pminus==0.){
+ COM sqpp= sqrt(pplus);
+ SpinorIp(sqpp,hel,sp);
+ }
+ // If incoming along -ve z
+ else if(pplus==0.){
+ COM sqpm= sqrt(pminus);
+ SpinorIm(sqpm,hel,sp);
+ }
+ // Outgoing
+ else {
+ SpinorO(p,hel,sp);
+ }
+ }
+} // anonymous namespace
+
+Tensor<2,4> Metric(){
+ Tensor<2,4> g(0.);
+ g.Set(0,0, 1.);
+ g.Set(1,1, -1.);
+ g.Set(2,2, -1.);
+ g.Set(3,3, -1.);
+ return g;
+}
+
+// <1|mu|2>
+Tensor<1,4> TCurrent(CLHEP::HepLorentzVector p1, bool h1,
+ CLHEP::HepLorentzVector p2, bool h2
+){
+ COM sp1[2];
+ COM sp2[2];
+ Tensor<1,4> newT(0.);
+
+ CLHEP::HepLorentzVector p1new{ p1.e()<0?-p1:p1 };
+ CLHEP::HepLorentzVector p2new{ p2.e()<0?-p2:p2 };
+
+ if(h1!=h2){
+ return newT;
+ }
+
+ Spinor(p1new, h1, sp1);
+ Spinor(p2new, h2, sp2);
+
+ for(int i=0;i<2;i++){
+ for(int j=0; j<2; j++){
+ newT+=(Sigma(i,j,h2)*sp2[j])*conj(sp1[i]);
+ }
+ }
+ return newT;
+}
+// <1|mu nu sigma|2>
+Tensor<3,4> T3Current(CLHEP::HepLorentzVector p1, bool h1,
+ CLHEP::HepLorentzVector p2, bool h2
+){
+
+ COM sp1[2];
+ COM sp2[2];
+
+ Tensor<3,4> newT(0.);
+
+ CLHEP::HepLorentzVector p1new{ p1.e()<0?-p1:p1 };
+ CLHEP::HepLorentzVector p2new{ p2.e()<0?-p2:p2 };
+
+ if(h1!=h2){
+ return newT;
+ }
+
+ Spinor(p1new, h1, sp1);
+ Spinor(p2new, h2, sp2);
+
+ COM current[4];
+
+ for(int i=0; i<2;i++){
+ for(int j=0; j<2;j++){
+ current[0]+=conj(sp1[i])*sigma0[i][j]*sp2[j];
+ current[1]+=conj(sp1[i])*sigma1[i][j]*sp2[j];
+ current[2]+=conj(sp1[i])*sigma2[i][j]*sp2[j];
+ current[3]+=conj(sp1[i])*sigma3[i][j]*sp2[j];
+ }
+ }
+
+ for( int itensor=0; itensor<newT.len(); itensor++ ){
+ double hfact = double( helfactor3[h2][itensor] );
+ newT.components[itensor] = current[sigma_index3[itensor]] * hfact
+ * permfactor3[itensor];
+ }
+
+ return newT;
+}
+
+// <1|mu nu sigma tau rho|2>
+Tensor<5,4> T5Current(CLHEP::HepLorentzVector p1, bool h1,
+ CLHEP::HepLorentzVector p2, bool h2
+){
+
+ COM sp1[2];
+ COM sp2[2];
+
+ Tensor<5,4> newT(0.);
+
+ CLHEP::HepLorentzVector p1new{ p1.e()<0?-p1:p1 };
+ CLHEP::HepLorentzVector p2new{ p2.e()<0?-p2:p2 };
+
+ if(h1!=h2){
+ return newT;
+ }
+
+ Spinor(p1new, h1, sp1);
+ Spinor(p2new, h2, sp2);
+
+ COM current[4];
+
+ for(int i=0; i<2;i++){
+ for(int j=0; j<2;j++){
+ current[0]+=conj(sp1[i])*sigma0[i][j]*sp2[j];
+ current[1]+=conj(sp1[i])*sigma1[i][j]*sp2[j];
+ current[2]+=conj(sp1[i])*sigma2[i][j]*sp2[j];
+ current[3]+=conj(sp1[i])*sigma3[i][j]*sp2[j];
+ }
+ }
+
+ for(int itensor=0;itensor<newT.len();itensor++){
+ double hfact = double(helfactor5[h2][itensor]);
+ newT.components[itensor] = current[sigma_index5[itensor]] * hfact
+ * permfactor5[itensor];
+ }
+
+ return newT;
+}
+
+Tensor<1,4> Construct1Tensor(CCurrent j){
+ Tensor<1,4> newT;
+ newT.components={j.c0,j.c1,j.c2,j.c3};
+ return newT;
+}
+
+Tensor<1,4> Construct1Tensor(CLHEP::HepLorentzVector p){
+ Tensor<1,4> newT;
+ newT.components={p.e(),p.x(),p.y(),p.z()};
+ return newT;
+}
+
+Tensor<1,4> eps(CLHEP::HepLorentzVector k, CLHEP::HepLorentzVector ref, bool pol){
+
+ Tensor<1,4> polvec;
+ COM spk[2];
+ COM spr[2];
+ COM denom;
+
+ CLHEP::HepLorentzVector knew{ k.e()<0?-k:k };
+
+ Spinor(knew, pol, spk);
+ Spinor(ref, !pol, spr);
+ denom = pow(-1.,pol)*sqrt(2)*(conj(spr[0])*spk[0] + conj(spr[1])*spk[1]);
+ polvec = TCurrent(ref,!pol,knew,!pol)/denom;
+
+ return polvec;
+}
+
+// slow function! - but only need to evaluate once.
+bool init_sigma_index(){
+
+ // initialize permfactor(3) to list of ones (change to minus one for each odd
+ // permutation and multiply by i for all permutations in perms2111, perms311,
+ // perms111)
+ permfactor5.resize(1024,1.);
+ permfactor3.resize(64,1.);
+
+ // first set sigma_index (5)
+ std::vector<std::array<int,5>> sigma0indices;
+ std::vector<std::array<int,5>> sigma1indices;
+ std::vector<std::array<int,5>> sigma2indices;
+ std::vector<std::array<int,5>> sigma3indices;
+
+ // need to generate all possible permuations of {i,j,k,l,m}
+ // where each index can be {0,1,2,3,4}
+ // 1024 possibilities
+
+ // perms with 5 same
+ sigma0indices.push_back({0,0,0,0,0});
+ sigma1indices.push_back({1,1,1,1,1});
+ sigma2indices.push_back({2,2,2,2,2});
+ sigma3indices.push_back({3,3,3,3,3});
+
+ // perms with 4 same
+ perms41(1,0,sigma0indices);
+ perms41(2,0,sigma0indices);
+ perms41(3,0,sigma0indices);
+ perms41(0,1,sigma1indices);
+ perms41(2,1,sigma1indices);
+ perms41(3,1,sigma1indices);
+ perms41(0,2,sigma2indices);
+ perms41(1,2,sigma2indices);
+ perms41(3,2,sigma2indices);
+ perms41(0,3,sigma3indices);
+ perms41(1,3,sigma3indices);
+ perms41(2,3,sigma3indices);
+
+ // perms with 3 same, 2 same
+ perms32(0,1,sigma0indices);
+ perms32(0,2,sigma0indices);
+ perms32(0,3,sigma0indices);
+ perms32(1,0,sigma1indices);
+ perms32(1,2,sigma1indices);
+ perms32(1,3,sigma1indices);
+ perms32(2,0,sigma2indices);
+ perms32(2,1,sigma2indices);
+ perms32(2,3,sigma2indices);
+ perms32(3,0,sigma3indices);
+ perms32(3,1,sigma3indices);
+ perms32(3,2,sigma3indices);
+
+ // perms with 3 same, 2 different
+ perms311(1,2,3,sigma0indices);
+ perms311(2,3,1,sigma0indices);
+ perms311(3,1,2,sigma0indices);
+ perms311(0,2,3,sigma1indices);
+ perms311(2,3,0,sigma1indices);
+ perms311(3,2,0,sigma1indices);
+ perms311(0,3,1,sigma2indices);
+ perms311(1,3,0,sigma2indices);
+ perms311(3,1,0,sigma2indices);
+ perms311(0,1,2,sigma3indices);
+ perms311(1,2,0,sigma3indices);
+ perms311(2,1,0,sigma3indices);
+
+ perms221(1,2,0,sigma0indices);
+ perms221(1,3,0,sigma0indices);
+ perms221(2,3,0,sigma0indices);
+ perms221(0,2,1,sigma1indices);
+ perms221(0,3,1,sigma1indices);
+ perms221(2,3,1,sigma1indices);
+ perms221(0,1,2,sigma2indices);
+ perms221(0,3,2,sigma2indices);
+ perms221(1,3,2,sigma2indices);
+ perms221(0,1,3,sigma3indices);
+ perms221(0,2,3,sigma3indices);
+ perms221(1,2,3,sigma3indices);
+
+ perms2111(0,1,2,3,sigma0indices);
+ perms2111(1,0,2,3,sigma1indices);
+ perms2111(2,0,3,1,sigma2indices);
+ perms2111(3,0,1,2,sigma3indices);
+
+ if(sigma0indices.size()!=256){
+ std::cerr<<"sigma_index not set: ";
+ std::cerr<<"sigma0indices has "<< sigma0indices.size() << " components" << std::endl;
+ return false;
+ } else if(sigma1indices.size()!=256){
+ std::cerr<<"sigma_index not set: ";
+ std::cerr<<"sigma1indices has "<< sigma0indices.size() << " components" << std::endl;
+ return false;
+ } else if(sigma2indices.size()!=256){
+ std::cerr<<"sigma_index not set: ";
+ std::cerr<<"sigma2indices has "<< sigma0indices.size() << " components" << std::endl;
+ return false;
+ } else if(sigma3indices.size()!=256){
+ std::cerr<<"sigma_index not set: ";
+ std::cerr<<"sigma3indices has "<< sigma0indices.size() << " components" << std::endl;
+ return false;
+ }
+
+ for(int i=0;i<256;i++){
+ // map each unique set of tensor indices to its position in a list
+ int index0 = tensor2listindex(sigma0indices.at(i));
+ int index1 = tensor2listindex(sigma1indices.at(i));
+ int index2 = tensor2listindex(sigma2indices.at(i));
+ int index3 = tensor2listindex(sigma3indices.at(i));
+ sigma_index5[index0]=0;
+ sigma_index5[index1]=1;
+ sigma_index5[index2]=2;
+ sigma_index5[index3]=3;
+
+ short int sign[4]={1,-1,-1,-1};
+ // plus->true->1
+ helfactor5[1][index0] = sign[sigma0indices.at(i)[1]]
+ * sign[sigma0indices.at(i)[3]];
+ helfactor5[1][index1] = sign[sigma1indices.at(i)[1]]
+ * sign[sigma1indices.at(i)[3]];
+ helfactor5[1][index2] = sign[sigma2indices.at(i)[1]]
+ * sign[sigma2indices.at(i)[3]];
+ helfactor5[1][index3] = sign[sigma3indices.at(i)[1]]
+ * sign[sigma3indices.at(i)[3]];
+ // minus->false->0
+ helfactor5[0][index0] = sign[sigma0indices.at(i)[0]]
+ * sign[sigma0indices.at(i)[2]]
+ * sign[sigma0indices.at(i)[4]];
+ helfactor5[0][index1] = sign[sigma1indices.at(i)[0]]
+ * sign[sigma1indices.at(i)[2]]
+ * sign[sigma1indices.at(i)[4]];
+ helfactor5[0][index2] = sign[sigma2indices.at(i)[0]]
+ * sign[sigma2indices.at(i)[2]]
+ * sign[sigma2indices.at(i)[4]];
+ helfactor5[0][index3] = sign[sigma3indices.at(i)[0]]
+ * sign[sigma3indices.at(i)[2]]
+ * sign[sigma3indices.at(i)[4]];
+ }
+
+ // now set sigma_index3
+ std::vector<std::array<int,3>> sigma0indices3;
+ std::vector<std::array<int,3>> sigma1indices3;
+ std::vector<std::array<int,3>> sigma2indices3;
+ std::vector<std::array<int,3>> sigma3indices3;
+
+ // perms with 3 same
+ sigma0indices3.push_back({0,0,0});
+ sigma1indices3.push_back({1,1,1});
+ sigma2indices3.push_back({2,2,2});
+ sigma3indices3.push_back({3,3,3});
+
+ // 2 same
+ perms21(1,0,sigma0indices3);
+ perms21(2,0,sigma0indices3);
+ perms21(3,0,sigma0indices3);
+ perms21(0,1,sigma1indices3);
+ perms21(2,1,sigma1indices3);
+ perms21(3,1,sigma1indices3);
+ perms21(0,2,sigma2indices3);
+ perms21(1,2,sigma2indices3);
+ perms21(3,2,sigma2indices3);
+ perms21(0,3,sigma3indices3);
+ perms21(1,3,sigma3indices3);
+ perms21(2,3,sigma3indices3);
+
+ // none same
+ perms111(1,2,3,sigma0indices3);
+ perms111(0,2,3,sigma1indices3);
+ perms111(0,3,1,sigma2indices3);
+ perms111(0,1,2,sigma3indices3);
+
+ if(sigma0indices3.size()!=16){
+ std::cerr<<"sigma_index3 not set: ";
+ std::cerr<<"sigma0indices3 has "<< sigma0indices3.size() << " components" << std::endl;
+ return false;
+ } else if(sigma1indices3.size()!=16){
+ std::cerr<<"sigma_index3 not set: ";
+ std::cerr<<"sigma1indices3 has "<< sigma0indices3.size() << " components" << std::endl;
+ return false;
+ } else if(sigma2indices3.size()!=16){
+ std::cerr<<"sigma_index3 not set: ";
+ std::cerr<<"sigma2indices3 has "<< sigma0indices3.size() << " components" << std::endl;
+ return false;
+ } else if(sigma3indices3.size()!=16){
+ std::cerr<<"sigma_index3 not set: ";
+ std::cerr<<"sigma3indices3 has "<< sigma0indices3.size() << " components" << std::endl;
+ return false;
+ }
+
+ for(int i=0;i<16;i++){
+ int index0 = tensor2listindex(sigma0indices3.at(i));
+ int index1 = tensor2listindex(sigma1indices3.at(i));
+ int index2 = tensor2listindex(sigma2indices3.at(i));
+ int index3 = tensor2listindex(sigma3indices3.at(i));
+ sigma_index3[index0]=0;
+ sigma_index3[index1]=1;
+ sigma_index3[index2]=2;
+ sigma_index3[index3]=3;
+
+ short int sign[4]={1,-1,-1,-1};
+ // plus->true->1
+ helfactor3[1][index0] = sign[sigma0indices3.at(i)[1]];
+ helfactor3[1][index1] = sign[sigma1indices3.at(i)[1]];
+ helfactor3[1][index2] = sign[sigma2indices3.at(i)[1]];
+ helfactor3[1][index3] = sign[sigma3indices3.at(i)[1]];
+ // minus->false->0
+ helfactor3[0][index0] = sign[sigma0indices3.at(i)[0]]
+ * sign[sigma0indices3.at(i)[2]];
+ helfactor3[0][index1] = sign[sigma1indices3.at(i)[0]]
+ * sign[sigma1indices3.at(i)[2]];
+ helfactor3[0][index2] = sign[sigma2indices3.at(i)[0]]
+ * sign[sigma2indices3.at(i)[2]];
+ helfactor3[0][index3] = sign[sigma3indices3.at(i)[0]]
+ * sign[sigma3indices3.at(i)[2]];
+ }
+ return true;
+} // end init_sigma_index
diff --git a/src/Wjets.cc b/src/Wjets.cc
new file mode 100644
index 0000000..cf5ae44
--- /dev/null
+++ b/src/Wjets.cc
@@ -0,0 +1,2067 @@
+#include "HEJ/currents.hh"
+#include "HEJ/utility.hh"
+#include "HEJ/Tensor.hh"
+#include "HEJ/Constants.hh"
+
+#include <array>
+
+#include <iostream>
+
+
+
+namespace { // Helper Functions
+ // FKL W Helper Functions
+ void jW (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe, bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin, bool helin, current cur)
+ {
+ // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
+ // Need to swap e and nu for events with W- --> e- nubar!
+ if (helin==helout && hele==helnu) {
+ CLHEP::HepLorentzVector qa=pout+pe+pnu;
+ CLHEP::HepLorentzVector qb=pin-pe-pnu;
+ double ta(qa.m2()),tb(qb.m2());
+
+ current t65,vout,vin,temp2,temp3,temp5;
+ joo(pnu,helnu,pe,hele,t65);
+ vout[0]=pout.e();
+ vout[1]=pout.x();
+ vout[2]=pout.y();
+ vout[3]=pout.z();
+ vin[0]=pin.e();
+ vin[1]=pin.x();
+ vin[2]=pin.y();
+ vin[3]=pin.z();
+
+ COM brac615=cdot(t65,vout);
+ COM brac645=cdot(t65,vin);
+
+ // prod1565 and prod6465 are zero for Ws (not Zs)!!
+ // noalias(temp)=prod(trans(CurrentOutOut(pout,helout,pnu,helout)),metric);
+ joo(pout,helout,pnu,helout,temp2);
+ // noalias(temp2)=prod(temp,ctemp);
+ COM prod1665=cdot(temp2,t65);
+ // noalias(temp)=prod(trans(Current(pe,helin,pin,helin)),metric);
+ // noalias(temp2)=prod(temp,ctemp);
+ joi(pe,helin,pin,helin,temp3);
+ COM prod5465=cdot(temp3,t65);
+ // noalias(temp)=prod(trans(Current(pnu,helin,pin,helin)),metric);
+ // noalias(temp2)=prod(temp,ctemp);
+
+ joo(pout,helout,pe,helout,temp2);
+ joi(pnu,helnu,pin,helin,temp3);
+ joi(pout,helout,pin,helin,temp5);
+
+ current term1,term2,term3,sum;
+ cmult(2.*brac615/ta+2.*brac645/tb,temp5,term1);
+ cmult(prod1665/ta,temp3,term2);
+ cmult(-prod5465/tb,temp2,term3);
+
+ // cur=((2.*brac615*Current(pout,helout,pin,helin)+prod1565*Current(pe,helin,pin,helin)+prod1665*Current(pnu,helin,pin,helin))/ta + (2.*brac645*Current(pout,helout,pin,helin)-prod5465*CurrentOutOut(pout,helout,pe,helout)-prod6465*CurrentOutOut(pout,helout,pnu,helout))/tb);
+ // cur=((2.*brac615*temp5+prod1565*temp3+prod1665*temp4)/ta + (2.*brac645*temp5-prod5465*temp1-prod6465*temp2)/tb);
+ cadd(term1,term2,term3,sum);
+ // std::cout<<"sum: ("<<sum[0]<<","<<sum[1]<<","<<sum[2]<<","<<sum[3]<<")\n";
+ cur[0]=sum[0];
+ cur[1]=sum[1];
+ cur[2]=sum[2];
+ cur[3]=sum[3];
+ }
+ }
+
+ void jWbar (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe, bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin, bool helin, current cur)
+ {
+ // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
+ // Need to swap e and nu for events with W- --> e- nubar!
+ if (helin==helout && hele==helnu) {
+ CLHEP::HepLorentzVector qa=pout+pe+pnu;
+ CLHEP::HepLorentzVector qb=pin-pe-pnu;
+ double ta(qa.m2()),tb(qb.m2());
+
+ current t65,vout,vin,temp2,temp3,temp5;
+ joo(pnu,helnu,pe,hele,t65);
+ vout[0]=pout.e();
+ vout[1]=pout.x();
+ vout[2]=pout.y();
+ vout[3]=pout.z();
+ vin[0]=pin.e();
+ vin[1]=pin.x();
+ vin[2]=pin.y();
+ vin[3]=pin.z();
+
+ COM brac615=cdot(t65,vout);
+ COM brac645=cdot(t65,vin);
+
+ // prod1565 and prod6465 are zero for Ws (not Zs)!!
+ joo(pe,helout,pout,helout,temp2); // temp2 is <5|alpha|1>
+ COM prod5165=cdot(temp2,t65);
+ jio(pin,helin,pnu,helin,temp3); // temp3 is <4|alpha|6>
+ COM prod4665=cdot(temp3,t65);
+
+ joo(pnu,helout,pout,helout,temp2); // temp2 is now <6|mu|1>
+ jio(pin,helin,pe,helin,temp3); // temp3 is now <4|mu|5>
+ jio(pin,helin,pout,helout,temp5); // temp5 is <4|mu|1>
+
+ current term1,term2,term3,sum;
+ cmult(-2.*brac615/ta-2.*brac645/tb,temp5,term1);
+ cmult(-prod5165/ta,temp3,term2);
+ cmult(prod4665/tb,temp2,term3);
+
+ // cur=((2.*brac615*Current(pout,helout,pin,helin)+prod1565*Current(pe,helin,pin,helin)+prod1665*Current(pnu,helin,pin,helin))/ta + (2.*brac645*Current(pout,helout,pin,helin)-prod5465*CurrentOutOut(pout,helout,pe,helout)-prod6465*CurrentOutOut(pout,helout,pnu,helout))/tb);
+ // cur=((2.*brac615*temp5+prod1565*temp3+prod1665*temp4)/ta + (2.*brac645*temp5-prod5465*temp1-prod6465*temp2)/tb);
+ cadd(term1,term2,term3,sum);
+ // std::cout<<"term1: ("<<temp5[0]<<" "<<temp5[1]<<" "<<temp5[2]<<" "<<temp5[3]<<")"<<std::endl;
+ // std::cout<<"sum: ("<<sum[0]<<","<<sum[1]<<","<<sum[2]<<","<<sum[3]<<")\n";
+ cur[0]=sum[0];
+ cur[1]=sum[1];
+ cur[2]=sum[2];
+ cur[3]=sum[3];
+ }
+ }
+
+ double WProp (const CLHEP::HepLorentzVector & plbar, const CLHEP::HepLorentzVector & pl){
+ COM propW = COM(0.,-1.)/((pl+plbar).m2() -HEJ::MW*HEJ::MW + COM(0.,1.)*HEJ::MW*HEJ::GammaW);
+ double PropFactor=(propW*conj(propW)).real();
+ return PropFactor;
+ }
+
+CCurrent jW (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe, bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin, bool helin)
+{
+
+ COM cur[4];
+
+ cur[0]=0.;
+ cur[1]=0.;
+ cur[2]=0.;
+ cur[3]=0.;
+ CCurrent sum(0.,0.,0.,0.);
+
+ // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
+ // Need to swap e and nu for events with W- --> e- nubar!
+ if (helin==helout && hele==helnu) {
+ CLHEP::HepLorentzVector qa=pout+pe+pnu;
+ CLHEP::HepLorentzVector qb=pin-pe-pnu;
+ double ta(qa.m2()),tb(qb.m2());
+
+ CCurrent temp2,temp3,temp5;
+ CCurrent t65 = joo(pnu,helnu,pe,hele);
+ CCurrent vout(pout.e(),pout.x(),pout.y(),pout.z());
+ CCurrent vin(pin.e(),pin.x(),pin.y(),pin.z());
+
+ COM brac615=t65.dot(vout);
+ COM brac645=t65.dot(vin);
+
+
+ // prod1565 and prod6465 are zero for Ws (not Zs)!!
+ temp2 = joo(pout,helout,pnu,helout);
+ COM prod1665=temp2.dot(t65);
+ temp3 = joi(pe,helin,pin,helin);
+ COM prod5465=temp3.dot(t65);
+
+ temp2=joo(pout,helout,pe,helout);
+ temp3=joi(pnu,helnu,pin,helin);
+ temp5=joi(pout,helout,pin,helin);
+
+ CCurrent term1,term2,term3;
+ term1=(2.*brac615/ta+2.*brac645/tb)*temp5;
+ term2=(prod1665/ta)*temp3;
+ term3=(-prod5465/tb)*temp2;
+
+ sum=term1+term2+term3;
+ }
+
+ return sum;
+}
+
+CCurrent jWbar (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe, bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin, bool helin)
+{
+
+ COM cur[4];
+
+ cur[0]=0.;
+ cur[1]=0.;
+ cur[2]=0.;
+ cur[3]=0.;
+ CCurrent sum(0.,0.,0.,0.);
+
+ // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
+ // Need to swap e and nu for events with W- --> e- nubar!
+ if (helin==helout && hele==helnu) {
+ CLHEP::HepLorentzVector qa=pout+pe+pnu;
+ CLHEP::HepLorentzVector qb=pin-pe-pnu;
+ double ta(qa.m2()),tb(qb.m2());
+
+ CCurrent temp2,temp3,temp5;
+ CCurrent t65 = joo(pnu,helnu,pe,hele);
+ CCurrent vout(pout.e(),pout.x(),pout.y(),pout.z());
+ CCurrent vin(pin.e(),pin.x(),pin.y(),pin.z());
+
+ COM brac615=t65.dot(vout);
+ COM brac645=t65.dot(vin);
+
+ // prod1565 and prod6465 are zero for Ws (not Zs)!!
+ temp2 = joo(pe,helout,pout,helout); // temp2 is <5|alpha|1>
+ COM prod5165=temp2.dot(t65);
+ temp3 = jio(pin,helin,pnu,helin); // temp3 is <4|alpha|6>
+ COM prod4665=temp3.dot(t65);
+
+ temp2=joo(pnu,helout,pout,helout); // temp2 is now <6|mu|1>
+ temp3=jio(pin,helin,pe,helin); // temp3 is now <4|mu|5>
+ temp5=jio(pin,helin,pout,helout); // temp5 is <4|mu|1>
+
+ CCurrent term1,term2,term3;
+ term1 =(-2.*brac615/ta-2.*brac645/tb)*temp5;
+ term2 =(-prod5165/ta)*temp3;
+ term3 =(prod4665/tb)*temp2;
+
+ sum = term1 + term2 + term3;
+ }
+
+ return sum;
+}
+
+
+ // Extremal quark current with W emission. Using Tensor class rather than CCurrent
+ Tensor <1,4> jW(HLV pin, HLV pout, HLV plbar, HLV pl, bool aqline){
+ // Build the external quark line W Emmision
+ Tensor<1,4> ABCurr = TCurrent(pl, false, plbar, false);
+ Tensor<1,4> Tp4W = Construct1Tensor((pout+pl+plbar));//p4+pw
+ Tensor<1,4> TpbW = Construct1Tensor((pin-pl-plbar));//pb-pw
+
+ Tensor<3,4> J4bBlank;
+ if (aqline){
+ J4bBlank = T3Current(pin,false,pout,false);
+ }
+ else{
+ J4bBlank = T3Current(pout,false,pin,false);
+ }
+ double t4AB = (pout+pl+plbar).m2();
+ double tbAB = (pin-pl-plbar).m2();
+
+ Tensor<2,4> J4b1 = (J4bBlank.contract(Tp4W,2))/t4AB;
+ Tensor<2,4> J4b2 = (J4bBlank.contract(TpbW,2))/tbAB;
+
+ Tensor<2,4> T4bmMom(0.);
+
+ if (aqline){
+ for(int mu=0; mu<4;mu++){
+ for(int nu=0;nu<4;nu++){
+ T4bmMom.Set(mu,nu, (J4b1.at(nu,mu) + J4b2.at(mu,nu))*(COM(0,-1)));
+ }
+ }
+ }
+ else{
+ for(int mu=0; mu<4;mu++){
+ for(int nu=0;nu<4;nu++){
+ T4bmMom.Set(nu,mu, (J4b1.at(nu,mu) + J4b2.at(mu,nu))*(COM(0,1)));
+ }
+ }
+ }
+ Tensor<1,4> T4bm = T4bmMom.contract(ABCurr,1);
+
+ return T4bm;
+ }
+
+
+
+ // Relevant W+Jets Unordered Contribution Helper Functions
+ // W+Jets Uno
+ double jM2Wuno(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1,CLHEP::HepLorentzVector plbar, CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pa, bool h1, CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector pb, bool h2, bool pol)
+ {
+ static bool is_sigma_index_set(false);
+
+ if(!is_sigma_index_set){
+ //std::cout<<"Setting sigma_index...." << std::endl;
+ if(init_sigma_index())
+ is_sigma_index_set = true;
+ else
+ return 0.;
+ }
+
+ CLHEP::HepLorentzVector pW = pl+plbar;
+ CLHEP::HepLorentzVector q1g=pa-pW-p1-pg;
+ CLHEP::HepLorentzVector q1 = pa-p1-pW;
+ CLHEP::HepLorentzVector q2 = p2-pb;
+
+ const double taW = (pa-pW).m2();
+ const double taW1 = (pa-pW-p1).m2();
+ const double tb2 = (pb-p2).m2();
+ const double tb2g = (pb-p2-pg).m2();
+ const double s1W = (p1+pW).m2();
+ const double s1gW = (p1+pW+pg).m2();
+ const double s1g = (p1+pg).m2();
+ const double tag = (pa-pg).m2();
+ const double taWg = (pa-pW-pg).m2();
+
+ //use p1 as ref vec in pol tensor
+ Tensor<1,4> epsg = eps(pg,p2,pol);
+ Tensor<1,4> epsW = TCurrent(pl,false,plbar,false);
+ Tensor<1,4> j2b = TCurrent(p2,h2,pb,h2);
+
+ Tensor<1,4> Tq1q2 = Construct1Tensor((q1+q2)/taW1 + (pb/pb.dot(pg)
+ + p2/p2.dot(pg)) * tb2/(2*tb2g));
+ Tensor<1,4> Tq1g = Construct1Tensor((-pg-q1))/taW1;
+ Tensor<1,4> Tq2g = Construct1Tensor((pg-q2));
+ Tensor<1,4> TqaW = Construct1Tensor((pa-pW));//pa-pw
+ Tensor<1,4> Tqag = Construct1Tensor((pa-pg));
+ Tensor<1,4> TqaWg = Construct1Tensor((pa-pg-pW));
+ Tensor<1,4> Tp1g = Construct1Tensor((p1+pg));
+ Tensor<1,4> Tp1W = Construct1Tensor((p1+pW));//p1+pw
+ Tensor<1,4> Tp1gW = Construct1Tensor((p1+pg+pW));//p1+pw+pg
+
+ Tensor<2,4> g=Metric();
+
+ Tensor<3,4> J31a = T3Current(p1, h1, pa, h1);
+ Tensor<2,4> J2_qaW =J31a.contract(TqaW/taW, 2);
+ Tensor<2,4> J2_p1W =J31a.contract(Tp1W/s1W, 2);
+ Tensor<3,4> L1a =J2_qaW.leftprod(Tq1q2);
+ Tensor<3,4> L1b =J2_p1W.leftprod(Tq1q2);
+ Tensor<3,4> L2a = J2_qaW.leftprod(Tq1g);
+ Tensor<3,4> L2b = J2_p1W.leftprod(Tq1g);
+ Tensor<3,4> L3 = (g.rightprod(J2_qaW.contract(Tq2g,1)+J2_p1W.contract(Tq2g,2)))/taW1;
+ Tensor<3,4> L(0.);
+
+ Tensor<5,4> J51a = T5Current(p1, h1, pa, h1);
+
+ Tensor<4,4> J_qaW = J51a.contract(TqaW,4);
+ Tensor<4,4> J_qag = J51a.contract(Tqag,4);
+ Tensor<4,4> J_p1gW = J51a.contract(Tp1gW,4);
+
+ Tensor<3,4> U1a = J_qaW.contract(Tp1g,2);
+ Tensor<3,4> U1b = J_p1gW.contract(Tp1g,2);
+ Tensor<3,4> U1c = J_p1gW.contract(Tp1W,2);
+ Tensor<3,4> U1(0.);
+
+ Tensor<3,4> U2a = J_qaW.contract(TqaWg,2);
+ Tensor<3,4> U2b = J_qag.contract(TqaWg,2);
+ Tensor<3,4> U2c = J_qag.contract(Tp1W,2);
+ Tensor<3,4> U2(0.);
+
+ for(int nu=0; nu<4;nu++){
+ for(int mu=0;mu<4;mu++){
+ for(int rho=0;rho<4;rho++){
+ L.Set(nu, mu, rho, L1a.at(nu,mu,rho) + L1b.at(nu,rho,mu)
+ + L2a.at(mu,nu,rho) + L2b.at(mu,rho,nu) + L3.at(mu,nu,rho));
+ U1.Set(nu, mu, rho, U1a.at(nu, mu, rho) / (s1g*taW)
+ + U1b.at(nu,rho,mu) / (s1g*s1gW) + U1c.at(rho,nu,mu) / (s1W*s1gW));
+ U2.Set(nu,mu,rho,U2a.at(mu,nu,rho) / (taWg*taW)
+ + U2b.at(mu,rho,nu) / (taWg*tag) + U2c.at(rho,mu,nu) / (s1W*tag));
+ }
+ }
+ }
+
+ COM X = ((((U1-L).contract(epsW,3)).contract(j2b,2)).contract(epsg,1)).at(0);
+ COM Y = ((((U2+L).contract(epsW,3)).contract(j2b,2)).contract(epsg,1)).at(0);
+
+ double amp = HEJ::C_A*HEJ::C_F*HEJ::C_F/2.*(norm(X)+norm(Y)) - HEJ::C_F/2.*(X*conj(Y)).real();
+
+ double t1 = q1g.m2();
+ double t2 = q2.m2();
+
+ double WPropfact = WProp(plbar, pl);
+
+ //Divide by WProp
+ amp*=WPropfact;
+
+ //Divide by t-channels
+ amp/=(t1*t2);
+
+ //Average over initial states
+ amp/=(4.*HEJ::C_A*HEJ::C_A);
+
+ return amp;
+ }
+
+
+
+ // Relevant Wqqx Helper Functions.
+ //g->qxqlxl (Calculates gluon to qqx Current. See JV_\mu in WSubleading Notes)
+ Tensor <1,4> gtqqxW(CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar,CLHEP::HepLorentzVector pl,CLHEP::HepLorentzVector plbar){
+
+ double s2AB=(pl+plbar+pq).m2();
+ double s3AB=(pl+plbar+pqbar).m2();
+
+ Tensor<1,4> Tpq = Construct1Tensor(pq);
+ Tensor<1,4> Tpqbar = Construct1Tensor(pqbar);
+ Tensor<1,4> TAB = Construct1Tensor(pl+plbar);
+
+ // Define llx current.
+ Tensor<1,4> ABCur = TCurrent(pl, false, plbar, false);
+
+ //blank 3 Gamma Current
+ Tensor<3,4> JV23 = T3Current(pq,false,pqbar,false);
+
+ // Components of g->qqW before W Contraction
+ Tensor<2,4> JV1 = JV23.contract((Tpq + TAB),2)/(s2AB);
+ Tensor<2,4> JV2 = JV23.contract((Tpqbar + TAB),2)/(s3AB);
+
+ // g->qqW Current. Note Minus between terms due to momentum flow.
+ // Also note: (-I)^2 from W vert. (I) from Quark prop.
+ Tensor<1,4> JVCur = (JV1.contract(ABCur,1) - JV2.contract(ABCur,2))*COM(0.,-1.);
+
+ return JVCur;
+ }
+
+ // Helper Functions Calculate the Crossed Contribution
+ Tensor <2,4> MCrossW(CLHEP::HepLorentzVector pa,CLHEP::HepLorentzVector p1,CLHEP::HepLorentzVector pb,CLHEP::HepLorentzVector p4, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar,CLHEP::HepLorentzVector pl,CLHEP::HepLorentzVector plbar, std::vector<HLV> partons, int nabove){
+
+ // Useful propagator factors
+ double s2AB=(pl+plbar+pq).m2();
+ double s3AB=(pl+plbar+pqbar).m2();
+
+ CLHEP::HepLorentzVector q1, q3;
+ q1=pa;
+ for(int i=0; i<nabove+1;i++){
+ q1=q1-partons.at(i);
+ }
+ q3 = q1 - pq - pqbar - pl - plbar;
+
+ double tcro1=(q3+pq).m2();
+ double tcro2=(q1-pqbar).m2();
+
+ Tensor<1,4> Tp1 = Construct1Tensor(p1);
+ Tensor<1,4> Tp4 = Construct1Tensor(p4);
+ Tensor<1,4> Tpa = Construct1Tensor(pa);
+ Tensor<1,4> Tpb = Construct1Tensor(pb);
+ Tensor<1,4> Tpq = Construct1Tensor(pq);
+ Tensor<1,4> Tpqbar = Construct1Tensor(pqbar);
+ Tensor<1,4> TAB = Construct1Tensor(pl+plbar);
+ Tensor<1,4> Tq1 = Construct1Tensor(q1);
+ Tensor<1,4> Tq3 = Construct1Tensor(q3);
+ Tensor<2,4> g=Metric();
+
+ // Define llx current.
+ Tensor<1,4> ABCur = TCurrent(pl, false, plbar,false);
+
+ //Blank 5 gamma Current
+ Tensor<5,4> J523 = T5Current(pq,false,pqbar,false);
+
+ // 4 gamma currents (with 1 contraction already).
+ Tensor<4,4> J_q3q = J523.contract((Tq3+Tpq),2);
+ Tensor<4,4> J_2AB = J523.contract((Tpq+TAB),2);
+
+ // Components of Crossed Vertex Contribution
+ Tensor<3,4> Xcro1 = J_q3q.contract((Tpqbar + TAB),3);
+ Tensor<3,4> Xcro2 = J_q3q.contract((Tq1-Tpqbar),3);
+ Tensor<3,4> Xcro3 = J_2AB.contract((Tq1-Tpqbar),3);
+
+ // Term Denominators Taken Care of at this stage
+ Tensor<2,4> Xcro1Cont = Xcro1.contract(ABCur,3)/(tcro1*s3AB);
+ Tensor<2,4> Xcro2Cont = Xcro2.contract(ABCur,2)/(tcro1*tcro2);
+ Tensor<2,4> Xcro3Cont = Xcro3.contract(ABCur,1)/(s2AB*tcro2);
+
+ //Initialise the Crossed Vertex Object
+ Tensor<2,4> Xcro(0.);
+
+ for(int mu=0; mu<4;mu++){
+ for(int nu=0;nu<4;nu++){
+ Xcro.Set(mu,nu, -(-Xcro1Cont.at(nu,mu)+Xcro2Cont.at(nu,mu)+Xcro3Cont.at(nu,mu)));
+ }
+ }
+
+
+ return Xcro;
+ }
+
+ // Helper Functions Calculate the Uncrossed Contribution
+ Tensor <2,4> MUncrossW(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p4, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar,CLHEP::HepLorentzVector pl,CLHEP::HepLorentzVector plbar, std::vector<HLV> partons, int nabove){
+
+ double s2AB=(pl+plbar+pq).m2();
+ double s3AB=(pl+plbar+pqbar).m2();
+
+ CLHEP::HepLorentzVector q1, q3;
+ q1=pa;
+ for(int i=0; i<nabove+1;i++){
+ q1=q1-partons.at(i);
+ }
+ q3 = q1 - pl - plbar - pq - pqbar;
+ double tunc1 = (q1-pq).m2();
+ double tunc2 = (q3+pqbar).m2();
+
+ Tensor<1,4> Tp1 = Construct1Tensor(p1);
+ Tensor<1,4> Tp4 = Construct1Tensor(p4);
+ Tensor<1,4> Tpa = Construct1Tensor(pa);
+ Tensor<1,4> Tpb = Construct1Tensor(pb);
+ Tensor<1,4> Tpq = Construct1Tensor(pq);
+ Tensor<1,4> Tpqbar = Construct1Tensor(pqbar);
+ Tensor<1,4> TAB = Construct1Tensor(pl+plbar);
+ Tensor<1,4> Tq1 = Construct1Tensor(q1);
+ Tensor<1,4> Tq3 = Construct1Tensor(q3);
+ Tensor<2,4> g=Metric();
+
+
+ // Define llx current.
+ Tensor<1,4> ABCur = TCurrent(pl, false, plbar, false);
+
+ //Blank 5 gamma Current
+ Tensor<5,4> J523 = T5Current(pq,false,pqbar,false);
+
+ // 4 gamma currents (with 1 contraction already).
+ Tensor<4,4> J_2AB = J523.contract((Tpq+TAB),2);
+ Tensor<4,4> J_q1q = J523.contract((Tq1-Tpq),2);
+
+ // 2 Contractions taken care of.
+ Tensor<3,4> Xunc1 = J_2AB.contract((Tq3+Tpqbar),3);
+ Tensor<3,4> Xunc2 = J_q1q.contract((Tq3+Tpqbar),3);
+ Tensor<3,4> Xunc3 = J_q1q.contract((Tpqbar+TAB),3);
+
+ // Term Denominators Taken Care of at this stage
+ Tensor<2,4> Xunc1Cont = Xunc1.contract(ABCur,1)/(s2AB*tunc2);
+ Tensor<2,4> Xunc2Cont = Xunc2.contract(ABCur,2)/(tunc1*tunc2);
+ Tensor<2,4> Xunc3Cont = Xunc3.contract(ABCur,3)/(tunc1*s3AB);
+
+ //Initialise the Uncrossed Vertex Object
+ Tensor<2,4> Xunc(0.);
+
+ for(int mu=0; mu<4;mu++){
+ for(int nu=0;nu<4;nu++){
+ Xunc.Set(mu,nu,-(- Xunc1Cont.at(mu,nu)+Xunc2Cont.at(mu,nu) +Xunc3Cont.at(mu,nu)));
+ }
+ }
+
+ return Xunc;
+ }
+
+
+ // Helper Functions Calculate the g->qqxW (Eikonal) Contributions
+ Tensor <2,4> MSymW(CLHEP::HepLorentzVector pa,CLHEP::HepLorentzVector p1,CLHEP::HepLorentzVector pb,CLHEP::HepLorentzVector p4, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar,CLHEP::HepLorentzVector pl,CLHEP::HepLorentzVector plbar, std::vector<HLV> partons, int nabove){
+
+ double sa2=(pa+pq).m2();
+ double s12=(p1+pq).m2();
+ double sa3=(pa+pqbar).m2();
+ double s13=(p1+pqbar).m2();
+ double saA=(pa+pl).m2();
+ double s1A=(p1+pl).m2();
+ double saB=(pa+plbar).m2();
+ double s1B=(p1+plbar).m2();
+ double sb2=(pb+pq).m2();
+ double s42=(p4+pq).m2();
+ double sb3=(pb+pqbar).m2();
+ double s43=(p4+pqbar).m2();
+ double sbA=(pb+pl).m2();
+ double s4A=(p4+pl).m2();
+ double sbB=(pb+plbar).m2();
+ double s4B=(p4+plbar).m2();
+ double s23AB=(pl+plbar+pq+pqbar).m2();
+
+ CLHEP::HepLorentzVector q1,q3;
+ q1=pa;
+ for(int i=0;i<nabove+1;i++){
+ q1-=partons.at(i);
+ }
+ q3=q1-pq-pqbar-plbar-pl;
+ double t1 = (q1).m2();
+ double t3 = (q3).m2();
+
+ //Define Tensors to be used
+ Tensor<1,4> Tp1 = Construct1Tensor(p1);
+ Tensor<1,4> Tp4 = Construct1Tensor(p4);
+ Tensor<1,4> Tpa = Construct1Tensor(pa);
+ Tensor<1,4> Tpb = Construct1Tensor(pb);
+ Tensor<1,4> Tpq = Construct1Tensor(pq);
+ Tensor<1,4> Tpqbar = Construct1Tensor(pqbar);
+ Tensor<1,4> TAB = Construct1Tensor(pl+plbar);
+ Tensor<1,4> Tq1 = Construct1Tensor(q1);
+ Tensor<1,4> Tq3 = Construct1Tensor(q3);
+ Tensor<2,4> g=Metric();
+
+ // g->qqW Current (Factors of sqrt2 dealt with in this function.)
+ Tensor<1,4> JV = gtqqxW(pq,pqbar,pl,plbar);
+
+ // 1a gluon emisson Contribution
+ Tensor<3,4> X1a = g.rightprod(Tp1*(t1/(s12+s13+s1A+s1B)) + Tpa*(t1/(sa2+sa3+saA+saB)));
+ Tensor<2,4> X1aCont = X1a.contract(JV,3);
+
+ //4b gluon emission Contribution
+ Tensor<3,4> X4b = g.rightprod(Tp4*(t3/(s42+s43+s4A+s4B)) + Tpb*(t3/(sb2+sb3+sbA+sbB)));
+ Tensor<2,4> X4bCont = X4b.contract(JV,3);
+
+ //Set up each term of 3G diagram.
+ Tensor<3,4> X3g1 = g.leftprod(Tq1+Tpq+Tpqbar+TAB);
+ Tensor<3,4> X3g2 = g.leftprod(Tq3-Tpq-Tpqbar-TAB);
+ Tensor<3,4> X3g3 = g.leftprod((Tq1+Tq3));
+
+ // Note the contraction of indices changes term by term
+ Tensor<2,4> X3g1Cont = X3g1.contract(JV,3);
+ Tensor<2,4> X3g2Cont = X3g2.contract(JV,2);
+ Tensor<2,4> X3g3Cont = X3g3.contract(JV,1);
+
+ // XSym is an amalgamation of x1a, X4b and X3g. Makes sense from a colour factor point of view.
+ Tensor<2,4>Xsym(0.);
+
+ for(int mu=0; mu<4;mu++){
+ for(int nu=0;nu<4;nu++){
+ Xsym.Set(mu,nu, (X3g1Cont.at(nu,mu) + X3g2Cont.at(mu,nu) - X3g3Cont.at(nu,mu))
+ + (X1aCont.at(mu,nu) - X4bCont.at(mu,nu)) );
+ }
+ }
+ return Xsym/s23AB;
+ }
+
+ Tensor <2,4> MCross(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar, std::vector<HLV> partons, bool hq, int nabove){
+
+ CLHEP::HepLorentzVector q1;
+ q1=pa;
+ for(int i=0;i<nabove+1;i++){
+ q1-=partons.at(i);
+ }
+
+ double t2=(q1-pqbar).m2();
+
+ Tensor<1,4> Tq1 = Construct1Tensor(q1-pqbar);
+
+ //Blank 3 gamma Current
+ Tensor<3,4> J323 = T3Current(pq,hq,pqbar,hq);
+
+ // 2 gamma current (with 1 contraction already).
+ Tensor<2,4> XCroCont = J323.contract((Tq1),2)/(t2);
+
+ //Initialise the Crossed Vertex
+ Tensor<2,4> Xcro(0.);
+
+ for(int mu=0; mu<4;mu++){
+ for(int nu=0;nu<4;nu++){
+ Xcro.Set(mu,nu, (XCroCont.at(nu,mu)));
+ }
+ }
+
+ return Xcro;
+ }
+
+
+ // Helper Functions Calculate the Uncrossed Contribution
+ Tensor <2,4> MUncross(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar, std::vector<HLV> partons, bool hq, int nabove){
+
+ CLHEP::HepLorentzVector q1;
+ q1=pa;
+ for(int i=0;i<nabove+1;i++){
+ q1-=partons.at(i);
+ }
+ double t2 = (q1-pq).m2();
+
+ Tensor<1,4> Tq1 = Construct1Tensor(q1-pq);
+
+ //Blank 3 gamma Current
+ Tensor<3,4> J323 = T3Current(pq,hq,pqbar,hq);
+
+ // 2 gamma currents (with 1 contraction already).
+ Tensor<2,4> XUncCont = J323.contract((Tq1),2)/t2;
+
+ //Initialise the Uncrossed Vertex
+ Tensor<2,4> Xunc(0.);
+
+ for(int mu=0; mu<4;mu++){
+ for(int nu=0;nu<4;nu++){
+ Xunc.Set(mu,nu,-(XUncCont.at(mu,nu)));
+ }
+ }
+
+ return Xunc;
+ }
+
+
+ // Helper Functions Calculate the Eikonal Contributions
+ Tensor <2,4> MSym(CLHEP::HepLorentzVector pa,CLHEP::HepLorentzVector p1,CLHEP::HepLorentzVector pb,CLHEP::HepLorentzVector p4, CLHEP::HepLorentzVector pq,CLHEP::HepLorentzVector pqbar, std::vector<HLV> partons, bool hq, int nabove){
+
+ CLHEP::HepLorentzVector q1, q3;
+ q1=pa;
+ for(int i=0;i<nabove+1;i++){
+ q1-=partons.at(i);
+ }
+ q3 = q1-pq-pqbar;
+ double t1 = (q1).m2();
+ double t3 = (q3).m2();
+
+ double s23 = (pq+pqbar).m2();
+ double sa2 = (pa+pq).m2();
+ double sa3 = (pa+pqbar).m2();
+ double s12 = (p1+pq).m2();
+ double s13 = (p1+pqbar).m2();
+ double sb2 = (pb+pq).m2();
+ double sb3 = (pb+pqbar).m2();
+ double s42 = (p4+pq).m2();
+ double s43 = (p4+pqbar).m2();
+
+ //Define Tensors to be used
+ Tensor<1,4> Tp1 = Construct1Tensor(p1);
+ Tensor<1,4> Tp4 = Construct1Tensor(p4);
+ Tensor<1,4> Tpa = Construct1Tensor(pa);
+ Tensor<1,4> Tpb = Construct1Tensor(pb);
+ Tensor<1,4> Tpq = Construct1Tensor(pq);
+ Tensor<1,4> Tpqbar = Construct1Tensor(pqbar);
+ Tensor<1,4> Tq1 = Construct1Tensor(q1);
+ Tensor<1,4> Tq3 = Construct1Tensor(q3);
+ Tensor<2,4> g=Metric();
+
+ Tensor<1,4> qqxCur = TCurrent(pq, hq, pqbar, hq);
+
+ // // 1a gluon emisson Contribution
+ Tensor<3,4> X1a = g.rightprod(Tp1*(t1/(s12+s13))+Tpa*(t1/(sa2+sa3)));
+ Tensor<2,4> X1aCont = X1a.contract(qqxCur,3);
+
+ // //4b gluon emission Contribution
+ Tensor<3,4> X4b = g.rightprod(Tp4*(t3/(s42+s43)) + Tpb*(t3/(sb2+sb3)));
+ Tensor<2,4> X4bCont = X4b.contract(qqxCur,3);
+
+ // New Formulation Corresponding to New Analytics
+ Tensor<3,4> X3g1 = g.leftprod(Tq1+Tpq+Tpqbar);
+ Tensor<3,4> X3g2 = g.leftprod(Tq3-Tpq-Tpqbar);
+ Tensor<3,4> X3g3 = g.leftprod((Tq1+Tq3));
+
+ // Note the contraction of indices changes term by term
+ Tensor<2,4> X3g1Cont = X3g1.contract(qqxCur,3);
+ Tensor<2,4> X3g2Cont = X3g2.contract(qqxCur,2);
+ Tensor<2,4> X3g3Cont = X3g3.contract(qqxCur,1);
+
+ Tensor<2,4>Xsym(0.);
+
+ for(int mu=0; mu<4;mu++){
+ for(int nu=0;nu<4;nu++){
+ Xsym.Set(mu, nu, COM(0,1) * ( (X3g1Cont.at(nu,mu) + X3g2Cont.at(mu,nu)
+ - X3g3Cont.at(nu,mu)) + (X1aCont.at(mu,nu) - X4bCont.at(mu,nu)) ) );
+ }
+ }
+ return Xsym/s23;
+ }
+} // Anonymous Namespace helper functions
+
+// W+Jets FKL Contributions
+double jMWqQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ current mj1m,mj2p,mj2m;
+ CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out);
+
+ jW(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
+ joi(p2out,true,p2in,true,mj2p);
+ joi(p2out,false,p2in,false,mj2m);
+
+ COM Mmp=cdot(mj1m,mj2p);
+
+ // mj1m.mj2m
+ COM Mmm=cdot(mj1m,mj2m);
+
+ // sum of spinor strings ||^2
+ double a2Mmp=abs2(Mmp);
+ double a2Mmm=abs2(Mmm);
+
+ double WPropfact = WProp(pe, pnu);
+
+ // Division by colour and Helicity average (Nc2-1)(4)
+ // Multiply by Cf^2
+ return HEJ::C_F*HEJ::C_F*WPropfact*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2()*(HEJ::N_C*HEJ::N_C - 1)*4);
+
+}
+
+double jMWqQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ current mj1m,mj2p,mj2m;
+ CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out);
+
+ jW(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
+ jio(p2in,true,p2out,true,mj2p);
+ jio(p2in,false,p2out,false,mj2m);
+
+ COM Mmp=cdot(mj1m,mj2p);
+
+ // mj1m.mj2m
+ COM Mmm=cdot(mj1m,mj2m);
+
+ // sum of spinor strings ||^2
+ double a2Mmp=abs2(Mmp);
+ double a2Mmm=abs2(Mmm);
+
+ double WPropfact = WProp(pe, pnu);
+
+ // Division by colour and Helicity average (Nc2-1)(4)
+ // Multiply by Cf^2
+ return HEJ::C_F*HEJ::C_F*WPropfact*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2()*(HEJ::N_C*HEJ::N_C - 1)*4);
+
+}
+
+double jMWqbarQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ current mj1m,mj2p,mj2m;
+ CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out);
+
+ jWbar(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
+ joi(p2out,true,p2in,true,mj2p);
+ joi(p2out,false,p2in,false,mj2m);
+
+ COM Mmp=cdot(mj1m,mj2p);
+
+ // mj1m.mj2m
+ COM Mmm=cdot(mj1m,mj2m);
+
+ // sum of spinor strings ||^2
+ double a2Mmp=abs2(Mmp);
+ double a2Mmm=abs2(Mmm);
+
+ double WPropfact = WProp(pe, pnu);
+
+ // Division by colour and Helicity average (Nc2-1)(4)
+ // Multiply by Cf^2
+ return HEJ::C_F*HEJ::C_F*WPropfact*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2()*(HEJ::N_C*HEJ::N_C - 1)*4);
+
+}
+
+double jMWqbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ current mj1m,mj2p,mj2m;
+ CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out);
+
+ jWbar(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
+ jio(p2in,true,p2out,true,mj2p);
+ jio(p2in,false,p2out,false,mj2m);
+
+ COM Mmp=cdot(mj1m,mj2p);
+
+ // mj1m.mj2m
+ COM Mmm=cdot(mj1m,mj2m);
+
+ // sum of spinor strings ||^2
+ double a2Mmp=abs2(Mmp);
+ double a2Mmm=abs2(Mmm);
+
+ double WPropfact = WProp(pe, pnu);
+
+ // Division by colour and Helicity average (Nc2-1)(4)
+ // Multiply by Cf^2
+ return HEJ::C_F*HEJ::C_F*WPropfact*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2()*(HEJ::N_C*HEJ::N_C - 1)*4);
+
+}
+
+double jMWqg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+// Calculates the square of the current contractions for qg->qenug scattering
+// p1: quark
+// p2: gluon
+{
+ CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out);
+ current mj1m,mj2p,mj2m;
+
+ jW(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
+
+ joi(p2out,true,p2in,true,mj2p);
+ joi(p2out,false,p2in,false,mj2m);
+
+ // mj1m.mj2p
+ COM Mmp=cdot(mj1m,mj2p);
+
+ // mj1m.mj2m
+ COM Mmm=cdot(mj1m,mj2m);
+
+ const double K = K_g(p2out, p2in);
+
+ // sum of spinor strings ||^2
+ double a2Mmp=abs2(Mmp);
+ double a2Mmm=abs2(Mmm);
+ double sst = K/HEJ::C_A*(a2Mmp+a2Mmm);
+
+ double WPropfact = WProp(pe, pnu);
+
+ // Division by colour and Helicity average (Nc2-1)(4)
+ // Multiply by Cf*Ca=4
+ return HEJ::C_F*HEJ::C_A*WPropfact*sst/(q1.m2()*q2.m2()*(HEJ::N_C*HEJ::N_C - 1)*4);
+
+}
+
+double jMWqbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+// Calculates the square of the current contractions for qg->qenug scattering
+// p1: quark
+// p2: gluon
+{
+ CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out);
+ current mj1m,mj2p,mj2m;
+
+ jWbar(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
+
+ joi(p2out,true,p2in,true,mj2p);
+ joi(p2out,false,p2in,false,mj2m);
+
+ // mj1m.mj2p
+ COM Mmp=cdot(mj1m,mj2p);
+
+ // mj1m.mj2m
+ COM Mmm=cdot(mj1m,mj2m);
+
+ const double K = K_g(p2out, p2in);
+
+ // sum of spinor strings ||^2
+ double a2Mmp=abs2(Mmp);
+ double a2Mmm=abs2(Mmm);
+ double sst = K/HEJ::C_A*(a2Mmp+a2Mmm);
+
+ double WPropfact = WProp(pe, pnu);
+
+ // Division by colour and Helicity average (Nc2-1)(4)
+ // Multiply by Cf*Ca=4
+ return HEJ::C_F*HEJ::C_A*WPropfact*sst/(q1.m2()*q2.m2()*(HEJ::N_C*HEJ::N_C - 1)*4);
+
+}
+
+
+// W+Jets Unordered Contributions
+//qQ->qQWg_unob
+double junobMWqQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ CCurrent mj1m,mj2p,mj2m;
+ CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);
+ CLHEP::HepLorentzVector q3=-(p2in-p2out);
+
+ mj1m=jW(p1out,false,pe,false,pnu,false,p1in,false);
+ mj2p=joi(p2out,true,p2in,true);
+ mj2m=joi(p2out,false,p2in,false);
+
+
+ // Dot products of these which occur again and again
+ COM MWmp=mj1m.dot(mj2p); // And now for the Higgs ones
+ COM MWmm=mj1m.dot(mj2m);
+
+ CCurrent jgbm,jgbp,j2gm,j2gp;
+ j2gp=joo(p2out,true,pg,true);
+ j2gm=joo(p2out,false,pg,false);
+ jgbp=joi(pg,true,p2in,true);
+ jgbm=joi(pg,false,p2in,false);
+
+ CCurrent qsum(q2+q3);
+
+ CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
+ CCurrent p2o(p2out);
+ CCurrent p2i(p2in);
+
+
+ Lmm=((-1.)*qsum*(MWmm) + (-2.*mj1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmm/2.))/q3.m2();
+ Lmp=((-1.)*qsum*(MWmp) + (-2.*mj1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmp/2.))/q3.m2();
+
+ U1mm=(jgbm.dot(mj1m)*j2gm+2.*p2o*MWmm)/(p2out+pg).m2();
+ U1mp=(jgbp.dot(mj1m)*j2gp+2.*p2o*MWmp)/(p2out+pg).m2();
+
+ U2mm=((-1.)*j2gm.dot(mj1m)*jgbm+2.*p2i*MWmm)/(p2in-pg).m2();
+ U2mp=((-1.)*j2gp.dot(mj1m)*jgbp+2.*p2i*MWmp)/(p2in-pg).m2();
+
+
+ double amm,amp;
+
+ amm=HEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mm+U2mm);
+ amp=HEJ::C_F*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mp+U2mp);
+
+ double ampsq=-(amm+amp);
+ //Divide by WProp
+ double WPropfact = WProp(pe, pnu);
+ ampsq*=WPropfact;
+
+
+ // Now add the t-channels
+ double th=q2.m2()*q1.m2();
+ ampsq/=th;
+ ampsq/=16.;
+
+
+ return ampsq;
+
+
+}
+
+//qQbar->qQbarWg_unob
+double junobMWqQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ CCurrent mj1m,mj2p,mj2m;
+ CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);
+ CLHEP::HepLorentzVector q3=-(p2in-p2out);
+
+ mj1m=jW(p1out,false,pe,false,pnu,false,p1in,false);
+ mj2p=jio(p2in,true,p2out,true);
+ mj2m=jio(p2in,false,p2out,false);
+
+
+ // Dot products of these which occur again and again
+ COM MWmp=mj1m.dot(mj2p); // And now for the Higgs ones
+ COM MWmm=mj1m.dot(mj2m);
+
+ CCurrent jgbm,jgbp,j2gm,j2gp;
+ j2gp=joo(pg,true,p2out,true);
+ j2gm=joo(pg,false,p2out,false);
+ jgbp=jio(p2in,true,pg,true);
+ jgbm=jio(p2in,false,pg,false);
+
+ CCurrent qsum(q2+q3);
+
+ CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
+ CCurrent p2o(p2out);
+ CCurrent p2i(p2in);
+
+
+ Lmm=((-1.)*qsum*(MWmm) + (-2.*mj1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmm/2.))/q3.m2();
+ Lmp=((-1.)*qsum*(MWmp) + (-2.*mj1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmp/2.))/q3.m2();
+
+ U1mm=(jgbm.dot(mj1m)*j2gm+2.*p2o*MWmm)/(p2out+pg).m2();
+ U1mp=(jgbp.dot(mj1m)*j2gp+2.*p2o*MWmp)/(p2out+pg).m2();
+
+ U2mm=((-1.)*j2gm.dot(mj1m)*jgbm+2.*p2i*MWmm)/(p2in-pg).m2();
+ U2mp=((-1.)*j2gp.dot(mj1m)*jgbp+2.*p2i*MWmp)/(p2in-pg).m2();
+
+ double amm,amp;
+
+ amm=HEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mm+U2mm);
+ amp=HEJ::C_F*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mp+U2mp);
+
+ double ampsq=-(amm+amp);
+ //Divide by WProp
+ double WPropfact = WProp(pe, pnu);
+ ampsq*=WPropfact;
+
+ // Now add the t-channels
+ double th=q2.m2()*q1.m2();
+ ampsq/=th;
+ ampsq/=16.;
+
+
+ return ampsq;
+
+
+}
+
+//qbarQ->qbarQWg_unob
+double junobMWqbarQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ CCurrent mj1m,mj2p,mj2m;
+ CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);
+ CLHEP::HepLorentzVector q3=-(p2in-p2out);
+
+ mj1m=jWbar(p1out,false,pe,false,pnu,false,p1in,false);
+ mj2p=joi(p2out,true,p2in,true);
+ mj2m=joi(p2out,false,p2in,false);
+
+
+ // Dot products of these which occur again and again
+ COM MWmp=mj1m.dot(mj2p); // And now for the Higgs ones
+ COM MWmm=mj1m.dot(mj2m);
+
+ CCurrent jgbm,jgbp,j2gm,j2gp;
+ j2gp=joo(p2out,true,pg,true);
+ j2gm=joo(p2out,false,pg,false);
+ jgbp=joi(pg,true,p2in,true);
+ jgbm=joi(pg,false,p2in,false);
+
+ CCurrent qsum(q2+q3);
+
+ CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
+ CCurrent p2o(p2out);
+ CCurrent p2i(p2in);
+
+
+ Lmm=((-1.)*qsum*(MWmm) + (-2.*mj1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmm/2.))/q3.m2();
+ Lmp=((-1.)*qsum*(MWmp) + (-2.*mj1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmp/2.))/q3.m2();
+
+ U1mm=(jgbm.dot(mj1m)*j2gm+2.*p2o*MWmm)/(p2out+pg).m2();
+ U1mp=(jgbp.dot(mj1m)*j2gp+2.*p2o*MWmp)/(p2out+pg).m2();
+
+ U2mm=((-1.)*j2gm.dot(mj1m)*jgbm+2.*p2i*MWmm)/(p2in-pg).m2();
+ U2mp=((-1.)*j2gp.dot(mj1m)*jgbp+2.*p2i*MWmp)/(p2in-pg).m2();
+
+
+ double amm,amp;
+
+ amm=HEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mm+U2mm);
+ amp=HEJ::C_F*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mp+U2mp);
+
+ double ampsq=-(amm+amp);
+ //Divide by WProp
+ double WPropfact = WProp(pe, pnu);
+ ampsq*=WPropfact;
+
+ // Now add the t-channels
+ double th=q2.m2()*q1.m2();
+ ampsq/=th;
+ ampsq/=16.;
+
+ return ampsq;
+
+
+}
+
+//qbarQbar->qbarQbarWg_unob
+double junobMWqbarQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pg)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ CCurrent mj1m,mj2p,mj2m;
+ CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out-pg);
+ CLHEP::HepLorentzVector q3=-(p2in-p2out);
+
+ mj1m=jWbar(p1out,false,pe,false,pnu,false,p1in,false);
+ mj2p=jio(p2in,true,p2out,true);
+ mj2m=jio(p2in,false,p2out,false);
+
+
+ // Dot products of these which occur again and again
+ COM MWmp=mj1m.dot(mj2p); // And now for the Higgs ones
+ COM MWmm=mj1m.dot(mj2m);
+
+ CCurrent jgbm,jgbp,j2gm,j2gp;
+ j2gp=joo(pg,true,p2out,true);
+ j2gm=joo(pg,false,p2out,false);
+ jgbp=jio(p2in,true,pg,true);
+ jgbm=jio(p2in,false,pg,false);
+
+ CCurrent qsum(q2+q3);
+
+ CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
+ CCurrent p2o(p2out);
+ CCurrent p2i(p2in);
+
+
+ Lmm=((-1.)*qsum*(MWmm) + (-2.*mj1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmm/2.))/q3.m2();
+ Lmp=((-1.)*qsum*(MWmp) + (-2.*mj1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mj1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MWmp/2.))/q3.m2();
+
+ U1mm=(jgbm.dot(mj1m)*j2gm+2.*p2o*MWmm)/(p2out+pg).m2();
+ U1mp=(jgbp.dot(mj1m)*j2gp+2.*p2o*MWmp)/(p2out+pg).m2();
+
+ U2mm=((-1.)*j2gm.dot(mj1m)*jgbm+2.*p2i*MWmm)/(p2in-pg).m2();
+ U2mp=((-1.)*j2gp.dot(mj1m)*jgbp+2.*p2i*MWmp)/(p2in-pg).m2();
+
+
+ double amm,amp;
+
+ amm=HEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mm+U2mm);
+ amp=HEJ::C_F*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mp+U2mp);
+
+ double ampsq=-(amm+amp);
+ //Divide by WProp
+ double WPropfact = WProp(pe, pnu);
+ ampsq*=WPropfact;
+
+ // Now add the t-channels
+ double th=q2.m2()*q1.m2();
+ ampsq/=th;
+ ampsq/=16.;
+
+ return ampsq;
+
+
+}
+
+////////////////////////////////////////////////////////////////////
+//qQ->qQWg_unof
+double junofMWgqQ (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ CCurrent mj2m,mj1p,mj1m;
+ CLHEP::HepLorentzVector q1=p1in-p1out;
+ CLHEP::HepLorentzVector qg=p1in-p1out-pg;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out-pe-pnu);
+
+ mj2m=jW(p2out,false,pe,false,pnu,false,p2in,false);
+ mj1p=joi(p1out,true,p1in,true);
+ mj1m=joi(p1out,false,p1in,false);
+
+
+ // Dot products of these which occur again and again
+ COM MWpm=mj1p.dot(mj2m); // And now for the Higgs ones
+ COM MWmm=mj1m.dot(mj2m);
+
+ CCurrent jgam,jgap,j2gm,j2gp;
+ j2gp=joo(p1out,true,pg,true);
+ j2gm=joo(p1out,false,pg,false);
+ jgap=joi(pg,true,p1in,true);
+ jgam=joi(pg,false,p1in,false);
+
+ CCurrent qsum(q1+qg);
+
+ CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
+ CCurrent p1o(p1out);
+ CCurrent p1i(p1in);
+
+ Lmm=(qsum*(MWmm) + (-2.*mj2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWmm/2.))/q1.m2();
+ Lpm=(qsum*(MWpm) + (-2.*mj2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWpm/2.))/q1.m2();
+
+
+ U1mm=(jgam.dot(mj2m)*j2gm+2.*p1o*MWmm)/(p1out+pg).m2();
+ U1pm=(jgap.dot(mj2m)*j2gp+2.*p1o*MWpm)/(p1out+pg).m2();
+
+ U2mm=((-1.)*j2gm.dot(mj2m)*jgam+2.*p1i*MWmm)/(p1in-pg).m2();
+ U2pm=((-1.)*j2gp.dot(mj2m)*jgap+2.*p1i*MWpm)/(p1in-pg).m2();
+
+ double amm,apm;
+ amm=HEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mm+U2mm);
+ apm=HEJ::C_F*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1pm+U2pm);
+
+ double ampsq=-(apm+amm);
+ //Divide by WProp
+ double WPropfact = WProp(pe, pnu);
+ ampsq*=WPropfact;
+
+ // Now add the t-channels
+ double th=q2.m2()*qg.m2();
+ ampsq/=th;
+ ampsq/=16.;
+
+ return ampsq;
+
+
+}
+
+//qQbar->qQbarWg_unof
+double junofMWgqQbar (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ CCurrent mj2m,mj1p,mj1m;
+ CLHEP::HepLorentzVector q1=p1in-p1out;
+ CLHEP::HepLorentzVector qg=p1in-p1out-pg;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out-pe-pnu);
+
+ mj2m=jWbar(p2out,false,pe,false,pnu,false,p2in,false);
+ mj1p=joi(p1out,true,p1in,true);
+ mj1m=joi(p1out,false,p1in,false);
+
+
+ // Dot products of these which occur again and again
+ COM MWpm=mj1p.dot(mj2m); // And now for the Higgs ones
+ COM MWmm=mj1m.dot(mj2m);
+
+ CCurrent jgam,jgap,j2gm,j2gp;
+ j2gp=joo(p1out,true,pg,true);
+ j2gm=joo(p1out,false,pg,false);
+ jgap=joi(pg,true,p1in,true);
+ jgam=joi(pg,false,p1in,false);
+
+ CCurrent qsum(q1+qg);
+
+ CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
+ CCurrent p1o(p1out);
+ CCurrent p1i(p1in);
+
+ Lmm=(qsum*(MWmm) + (-2.*mj2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWmm/2.))/q1.m2();
+ Lpm=(qsum*(MWpm) + (-2.*mj2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWpm/2.))/q1.m2();
+
+
+ U1mm=(jgam.dot(mj2m)*j2gm+2.*p1o*MWmm)/(p1out+pg).m2();
+ U1pm=(jgap.dot(mj2m)*j2gp+2.*p1o*MWpm)/(p1out+pg).m2();
+
+ U2mm=((-1.)*j2gm.dot(mj2m)*jgam+2.*p1i*MWmm)/(p1in-pg).m2();
+ U2pm=((-1.)*j2gp.dot(mj2m)*jgap+2.*p1i*MWpm)/(p1in-pg).m2();
+
+ double amm,apm;
+
+ amm=HEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mm+U2mm);
+ apm=HEJ::C_F*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1pm+U2pm);
+
+ double ampsq=-(apm+amm);
+ //Divide by WProp
+ double WPropfact = WProp(pe, pnu);
+ ampsq*=WPropfact;
+
+ // Now add the t-channels
+ double th=q2.m2()*qg.m2();
+ ampsq/=th;
+ ampsq/=16.;
+
+ return ampsq;
+}
+
+//qbarQ->qbarQWg_unof
+double junofMWgqbarQ (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ CCurrent mj2m,mj1p,mj1m;
+ CLHEP::HepLorentzVector q1=p1in-p1out;
+ CLHEP::HepLorentzVector qg=p1in-p1out-pg;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out-pe-pnu);
+
+ mj2m=jW(p2out,false,pe,false,pnu,false,p2in,false);
+ mj1p=jio(p1in,true,p1out,true);
+ mj1m=jio(p1in,false,p1out,false);
+
+
+ // Dot products of these which occur again and again
+ COM MWpm=mj1p.dot(mj2m); // And now for the Higgs ones
+ COM MWmm=mj1m.dot(mj2m);
+
+ CCurrent jgam,jgap,j2gm,j2gp;
+ j2gp=joo(pg,true,p1out,true);
+ j2gm=joo(pg,false,p1out,false);
+ jgap=jio(p1in,true,pg,true);
+ jgam=jio(p1in,false,pg,false);
+
+ CCurrent qsum(q1+qg);
+
+ CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
+ CCurrent p1o(p1out);
+ CCurrent p1i(p1in);
+
+ Lmm=(qsum*(MWmm) + (-2.*mj2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWmm/2.))/q1.m2();
+ Lpm=(qsum*(MWpm) + (-2.*mj2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWpm/2.))/q1.m2();
+
+
+ U1mm=(jgam.dot(mj2m)*j2gm+2.*p1o*MWmm)/(p1out+pg).m2();
+ U1pm=(jgap.dot(mj2m)*j2gp+2.*p1o*MWpm)/(p1out+pg).m2();
+
+ U2mm=((-1.)*j2gm.dot(mj2m)*jgam+2.*p1i*MWmm)/(p1in-pg).m2();
+ U2pm=((-1.)*j2gp.dot(mj2m)*jgap+2.*p1i*MWpm)/(p1in-pg).m2();
+
+ double amm,apm;
+ amm=HEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mm+U2mm);
+ apm=HEJ::C_F*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1pm+U2pm);
+
+ double ampsq=-(apm+amm);
+ //Divide by WProp
+ double WPropfact = WProp(pe, pnu);
+ ampsq*=WPropfact;
+
+ // Now add the t-channels
+ double th=q2.m2()*qg.m2();
+ ampsq/=th;
+ ampsq/=16.;
+
+ return ampsq;
+
+
+}
+
+//qbarQbar->qbarQbarWg_unof
+double junofMWgqbarQbar (CLHEP::HepLorentzVector pg,CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu, CLHEP::HepLorentzVector p2in)
+// Calculates the square of the current contractions for qQ->qenuQ scattering
+// p1: quark (with W emittance)
+// p2: Quark
+{
+ CCurrent mj2m,mj1p,mj1m;
+ CLHEP::HepLorentzVector q1=p1in-p1out;
+ CLHEP::HepLorentzVector qg=p1in-p1out-pg;
+ CLHEP::HepLorentzVector q2=-(p2in-p2out-pe-pnu);
+
+ mj2m=jWbar(p2out,false,pe,false,pnu,false,p2in,false);
+ mj1p=jio(p1in,true,p1out,true);
+ mj1m=jio(p1in,false,p1out,false);
+
+
+ // Dot products of these which occur again and again
+ COM MWpm=mj1p.dot(mj2m); // And now for the Higgs ones
+ COM MWmm=mj1m.dot(mj2m);
+
+ CCurrent jgam,jgap,j2gm,j2gp;
+ j2gp=joo(pg,true,p1out,true);
+ j2gm=joo(pg,false,p1out,false);
+ jgap=jio(p1in,true,pg,true);
+ jgam=jio(p1in,false,pg,false);
+
+ CCurrent qsum(q1+qg);
+
+ CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
+ CCurrent p1o(p1out);
+ CCurrent p1i(p1in);
+
+ Lmm=(qsum*(MWmm) + (-2.*mj2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWmm/2.))/q1.m2();
+ Lpm=(qsum*(MWpm) + (-2.*mj2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mj2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MWpm/2.))/q1.m2();
+
+ U1mm=(jgam.dot(mj2m)*j2gm+2.*p1o*MWmm)/(p1out+pg).m2();
+ U1pm=(jgap.dot(mj2m)*j2gp+2.*p1o*MWpm)/(p1out+pg).m2();
+
+ U2mm=((-1.)*j2gm.dot(mj2m)*jgam+2.*p1i*MWmm)/(p1in-pg).m2();
+ U2pm=((-1.)*j2gp.dot(mj2m)*jgap+2.*p1i*MWpm)/(p1in-pg).m2();
+
+ double amm,apm;
+
+ amm=HEJ::C_F*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1mm+U2mm);
+ apm=HEJ::C_F*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*HEJ::C_F*HEJ::C_F/3.*vabs2(U1pm+U2pm);
+
+
+
+ double ampsq=-(apm+amm);
+ //Divide by WProp
+ double WPropfact = WProp(pe, pnu);
+ ampsq*=WPropfact;
+
+
+ // Now add the t-channels
+ double th=q2.m2()*qg.m2();
+ ampsq/=th;
+ ampsq/=16.;
+ return ampsq;
+
+
+}
+
+
+
+///TODO make this comment more visible
+/// Naming scheme jM2-Wuno-g-({q/qbar}{Q/Qbar/g})
+///TODO Spit naming for more complicated functions?
+/// e.g. jM2WqqtoqQQq -> jM2_Wqq_to_qQQq
+double jM2WunogqQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+{
+ //COM temp;
+ double ME2mpp=0.;
+ double ME2mpm=0.;
+ double ME2mmp=0.;
+ double ME2mmm=0.;
+ double ME2;
+
+ ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,true);
+ ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,false);
+ ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,true);
+ ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,false);
+
+ //Helicity sum
+ ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
+
+ return ME2;
+
+}
+
+//same as function above but actually obtaining the antiquark line by crossing symmetry, where p1out and p1in are expected to be negative.
+//should give same result as jM2WunogqbarQ below (verified)
+double jM2WunogqQ_crossqQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+{
+ //COM temp;
+ double ME2mpp=0.;
+ double ME2mpm=0.;
+ double ME2mmp=0.;
+ double ME2mmm=0.;
+ double ME2;
+
+ ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,true);
+ ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,false);
+ ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,true);
+ ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,false);
+
+ //Helicity sum
+ ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
+
+ return ME2;
+
+}
+
+double jM2WunogqQbar(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+{
+ //COM temp;
+ double ME2mpp=0.;
+ double ME2mpm=0.;
+ double ME2mmp=0.;
+ double ME2mmm=0.;
+ double ME2;
+
+ ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,true);
+ ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,false);
+ ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,true);
+ ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,false);
+
+ //Helicity sum
+ ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
+
+ return ME2;
+
+}
+
+double jM2Wunogqg(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+{
+ //COM temp;
+ double ME2mpp=0.;
+ double ME2mpm=0.;
+ double ME2mmp=0.;
+ double ME2mmm=0.;
+ double ME2;
+
+ ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,true);
+ ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,true,false);
+ ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,true);
+ ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,false,p2out,p2in,false,false);
+
+ //Helicity sum
+ ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
+
+ double ratio; // p2-/pb- in the notes
+ if (p2in.pz()>0.) // if the gluon is the positive
+ ratio=p2out.plus()/p2in.plus();
+ else // the gluon is the negative
+ ratio=p2out.minus()/p2in.minus();
+
+ double cam = ( (HEJ::C_A - 1/HEJ::C_A)*(ratio + 1./ratio)/2. + 1/HEJ::C_A)/HEJ::C_F;
+ ME2*=cam;
+
+ return ME2;
+
+}
+
+double jM2WunogqbarQ(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+{
+ //COM temp;
+ double ME2mpp=0.;
+ double ME2mpm=0.;
+ double ME2mmp=0.;
+ double ME2mmm=0.;
+ double ME2;
+
+ ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,true);
+ ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,false);
+ ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,true);
+ ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,false);
+
+ //Helicity sum
+ ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
+
+ return ME2;
+
+}
+
+double jM2WunogqbarQbar(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+{
+ //COM temp;
+ double ME2mpp=0.;
+ double ME2mpm=0.;
+ double ME2mmp=0.;
+ double ME2mmm=0.;
+ double ME2;
+
+ ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,true);
+ ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,false);
+ ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,true);
+ ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,false);
+
+ //Helicity sum
+ ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
+
+ return ME2;
+
+}
+
+double jM2Wunogqbarg(CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+{
+ //COM temp;
+ double ME2mpp=0.;
+ double ME2mpm=0.;
+ double ME2mmp=0.;
+ double ME2mmm=0.;
+ double ME2;
+
+ ME2mpp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,true);
+ ME2mpm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,true,false);
+ ME2mmp = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,true);
+ ME2mmm = jM2Wuno(pg, p1out,plbar,pl,p1in,true,p2out,p2in,false,false);
+
+ //Helicity sum
+ ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
+
+ double ratio; // p2-/pb- in the notes
+ if (p2in.pz()>0.) // if the gluon is the positive
+ ratio=p2out.plus()/p2in.plus();
+ else // the gluon is the negative
+ ratio=p2out.minus()/p2in.minus();
+
+ double cam = ( (HEJ::C_A - 1/HEJ::C_A)*(ratio + 1./ratio)/2. + 1/HEJ::C_A)/HEJ::C_F;
+ ME2*=cam;
+
+ return ME2;
+
+}
+
+
+// W+Jets qqxExtremal
+// W+Jets qqxExtremal Currents - wqq emission
+double jM2WgQtoqbarqQ(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqbarout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+{
+ //COM temp;
+ double ME2mpp=0.;
+ double ME2mpm=0.;
+ double ME2mmp=0.;
+ double ME2mmm=0.;
+ double ME2;
+
+ ME2mpp = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,true,true);
+ ME2mpm = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,true,false);
+ ME2mmp = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,false,true);
+ ME2mmm = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,false,false);
+
+ //Helicity sum
+ ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
+
+ //Correct colour averaging
+ ME2*=(3.0/8.0);
+
+ return ME2;
+
+}
+
+double jM2WgQtoqqbarQ(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqbarout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in){
+
+ //COM temp;
+ double ME2mpp=0.;
+ double ME2mpm=0.;
+ double ME2mmp=0.;
+ double ME2mmm=0.;
+ double ME2;
+
+ ME2mpp = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,true,true);
+ ME2mpm = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,true,false);
+ ME2mmp = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,false,true);
+ ME2mmm = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,false,false);
+
+ //Helicity sum
+ ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
+
+ //Correct colour averaging
+ ME2*=(3.0/8.0);
+
+ return ME2;
+
+}
+
+
+double jM2Wggtoqbarqg(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqbarout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
+{
+ //COM temp;
+ double ME2mpp=0.;
+ double ME2mpm=0.;
+ double ME2mmp=0.;
+ double ME2mmm=0.;
+ double ME2;
+
+ ME2mpp = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,true,true);
+ ME2mpm = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,true,false);
+ ME2mmp = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,false,true);
+ ME2mmm = jM2Wuno(-pgin, pqout,plbar,pl,-pqbarout,false,p2out,p2in,false,false);
+
+ //Helicity sum
+ ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
+
+ double ratio; // p2-/pb- in the notes
+ if (p2in.pz()>0.) // if the gluon is the positive
+ ratio=p2out.plus()/p2in.plus();
+ else // the gluon is the negative
+ ratio=p2out.minus()/p2in.minus();
+
+ double cam = ( (HEJ::C_A - 1/HEJ::C_A)*(ratio + 1./ratio)/2. + 1/HEJ::C_A)/HEJ::C_F;
+ ME2*=cam;
+
+ //Correct colour averaging
+ ME2*=(3.0/8.0);
+
+ return ME2;
+}
+
+double jM2Wggtoqqbarg(CLHEP::HepLorentzVector pgin, CLHEP::HepLorentzVector pqbarout,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector pqout, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in){
+
+ //COM temp;
+ double ME2mpp=0.;
+ double ME2mpm=0.;
+ double ME2mmp=0.;
+ double ME2mmm=0.;
+ double ME2;
+
+ ME2mpp = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,true,true);
+ ME2mpm = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,true,false);
+ ME2mmp = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,false,true);
+ ME2mmm = jM2Wuno(-pgin, pqbarout,plbar,pl,-pqout,true,p2out,p2in,false,false);
+
+ //Helicity sum
+ ME2 = ME2mpp + ME2mpm + ME2mmp + ME2mmm;
+
+ double ratio; // p2-/pb- in the notes
+ if (p2in.pz()>0.) // if the gluon is the positive
+ ratio=p2out.plus()/p2in.plus();
+ else // the gluon is the negative
+ ratio=p2out.minus()/p2in.minus();
+
+ double cam = ( (HEJ::C_A - 1/HEJ::C_A)*(ratio + 1./ratio)/2. + 1/HEJ::C_A)/HEJ::C_F;
+ ME2*=cam;
+
+ //Correct colour averaging
+ ME2*=(3.0/8.0);
+
+ return ME2;
+
+}
+
+
+namespace {
+//Function to calculate Term 1 in Equation 3.23 in James Cockburn's Thesis.
+ Tensor<1,4> qggm1(CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p3, bool hel2, bool helg, CLHEP::HepLorentzVector refmom){
+
+ double t1 = (p3-pb)*(p3-pb);
+ Tensor<1,4> Tp3 = Construct1Tensor((p3));//p3
+ Tensor<1,4> Tpb = Construct1Tensor((pb));//pb
+ // Gauge choice in polarisation tensor. (see JC's Thesis)
+ Tensor<1,4> epsg = eps(pb, refmom, helg);
+ Tensor<3,4> qqCurBlank = T3Current(p2,hel2,p3,hel2);
+ Tensor<2,4> qqCur = qqCurBlank.contract(Tp3-Tpb,2);
+ Tensor<1,4> gqqCur = qqCur.contract(epsg,2)/t1;
+
+ return gqqCur*(-1);
+}
+
+//Function to calculate Term 2 in Equation 3.23 in James Cockburn's Thesis.
+ Tensor<1,4> qggm2(CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p3, bool hel2, bool helg, CLHEP::HepLorentzVector refmom){
+
+ double t1 = (p2-pb)*(p2-pb);
+ Tensor<1,4> Tp2 = Construct1Tensor((p2));//p2
+ Tensor<1,4> Tpb = Construct1Tensor((pb));//pb
+ // Gauge choice in polarisation tensor. (see JC's Thesis)
+ Tensor<1,4> epsg = eps(pb,refmom, helg);
+ Tensor<3,4> qqCurBlank = T3Current(p2,hel2,p3,hel2);
+ Tensor<2,4> qqCur = qqCurBlank.contract(Tp2-Tpb,2);
+ Tensor<1,4> gqqCur = qqCur.contract(epsg,1)/t1;
+
+ return gqqCur;
+}
+
+//Function to calculate Term 3 in Equation 3.23 in James Cockburn's Thesis.
+ Tensor<1,4> qggm3(CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p3, bool hel2, bool helg, CLHEP::HepLorentzVector refmom){
+
+ double s23 = (p2+p3)*(p2+p3);
+ Tensor<1,4> Tp2 = Construct1Tensor((p2));//p2
+ Tensor<1,4> Tp3 = Construct1Tensor((p3));//p3
+ Tensor<1,4> Tpb = Construct1Tensor((pb));//pb
+ // Gauge choice in polarisation tensor. (see JC's Thesis)
+ Tensor<1,4> epsg = eps(pb, refmom, helg);
+ Tensor<2,4> g=Metric();
+ Tensor<3,4> qqCurBlank1 = g.leftprod(Tp2+Tp3)/s23;
+ Tensor<3,4> qqCurBlank2 = g.leftprod(Tpb)/s23;
+ Tensor<1,4> Cur23 = TCurrent(p2,hel2, p3,hel2);
+
+ Tensor<2,4> qqCur1 = qqCurBlank1.contract(Cur23,3);
+ Tensor<2,4> qqCur2 = qqCurBlank2.contract(Cur23,3);
+ Tensor<2,4> qqCur3 = qqCurBlank2.contract(Cur23,1);
+
+ Tensor<1,4> gqqCur = (qqCur1.contract(epsg,1)
+ - qqCur2.contract(epsg,2)
+ + qqCur3.contract(epsg,1))*2*COM(0,1);
+ return gqqCur;
+}
+}
+
+// no wqq emission
+double jM2WgqtoQQqW(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p3,CLHEP::HepLorentzVector plbar,CLHEP::HepLorentzVector pl, bool aqlinepa){
+
+ static bool is_sigma_index_set(false);
+ if(!is_sigma_index_set){
+ if(init_sigma_index())
+ is_sigma_index_set = true;
+ else
+ return 0.;}
+
+ // 2 independent helicity choices (complex conjugation related).
+ Tensor<1,4> TMmmm1 = qggm1(pb,p2,p3,false,false, pa);
+ Tensor<1,4> TMmmm2 = qggm2(pb,p2,p3,false,false, pa);
+ Tensor<1,4> TMmmm3 = qggm3(pb,p2,p3,false,false, pa);
+ Tensor<1,4> TMpmm1 = qggm1(pb,p2,p3,false,true, pa);
+ Tensor<1,4> TMpmm2 = qggm2(pb,p2,p3,false,true, pa);
+ Tensor<1,4> TMpmm3 = qggm3(pb,p2,p3,false,true, pa);
+
+ // Build the external quark line W Emmision
+ Tensor<1,4> cur1a = jW(pa,p1,plbar,pl, aqlinepa);
+
+ //Contract with the qqxCurrent.
+ COM Mmmm1 = TMmmm1.contract(cur1a,1).at(0);
+ COM Mmmm2 = TMmmm2.contract(cur1a,1).at(0);
+ COM Mmmm3 = TMmmm3.contract(cur1a,1).at(0);
+ COM Mpmm1 = TMpmm1.contract(cur1a,1).at(0);
+ COM Mpmm2 = TMpmm2.contract(cur1a,1).at(0);
+ COM Mpmm3 = TMpmm3.contract(cur1a,1).at(0);
+
+ //Colour factors:
+ COM cm1m1,cm2m2,cm3m3,cm1m2,cm1m3,cm2m3;
+ cm1m1=8./3.;
+ cm2m2=8./3.;
+ cm3m3=6.;
+ cm1m2 =-1./3.;
+ cm1m3 = -3.*COM(0.,1.);
+ cm2m3 = 3.*COM(0.,1.);
+
+ //Sqaure and sum for each helicity config:
+ double Mmmm = real(cm1m1*pow(abs(Mmmm1),2)+cm2m2*pow(abs(Mmmm2),2)+cm3m3*pow(abs(Mmmm3),2)+2.*real(cm1m2*Mmmm1*conj(Mmmm2))+2.*real(cm1m3*Mmmm1*conj(Mmmm3))+2.*real(cm2m3*Mmmm2*conj(Mmmm3)));
+ double Mpmm = real(cm1m1*pow(abs(Mpmm1),2)+cm2m2*pow(abs(Mpmm2),2)+cm3m3*pow(abs(Mpmm3),2)+2.*real(cm1m2*Mpmm1*conj(Mpmm2))+2.*real(cm1m3*Mpmm1*conj(Mpmm3))+2.*real(cm2m3*Mpmm2*conj(Mpmm3)));
+
+ // Divide by WProp
+ double WPropfact = WProp(plbar, pl);
+
+ return (2*WPropfact*(Mmmm+Mpmm)/24./4.)/(pa-p1-pl-plbar).m2()/(p2+p3-pb).m2();
+}
+
+
+// W+Jets qqxCentral
+double jM2WqqtoqQQq(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb,CLHEP::HepLorentzVector pl, CLHEP::HepLorentzVector plbar, std::vector<HLV> partons, bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove)
+{
+
+ static bool is_sigma_index_set(false);
+ if(!is_sigma_index_set){
+ if(init_sigma_index())
+ is_sigma_index_set = true;
+ else
+ return 0.;}
+
+ HLV pq, pqbar, p1, p4;
+ if (qqxmarker){
+ pqbar = partons[nabove+1];
+ pq = partons[nabove+2];}
+ else{
+ pq = partons[nabove+1];
+ pqbar = partons[nabove+2];}
+
+ p1 = partons.front();
+ p4 = partons.back();
+
+ Tensor<1,4> T1am, T4bm, T1ap, T4bp;
+ if(!(aqlinepa)){
+ T1ap = TCurrent(p1, true, pa, true);
+ T1am = TCurrent(p1, false, pa, false);}
+ else if(aqlinepa){
+ T1ap = TCurrent(pa, true, p1, true);
+ T1am = TCurrent(pa, false, p1, false);}
+ if(!(aqlinepb)){
+ T4bp = TCurrent(p4, true, pb, true);
+ T4bm = TCurrent(p4, false, pb, false);}
+ else if(aqlinepb){
+ T4bp = TCurrent(pb, true, p4, true);
+ T4bm = TCurrent(pb, false, p4, false);}
+
+ // Calculate the 3 separate contributions to the effective vertex
+ Tensor<2,4> Xunc = MUncrossW(pa, p1, pb, p4, pq, pqbar, pl, plbar, partons, nabove);
+ Tensor<2,4> Xcro = MCrossW( pa, p1, pb, p4, pq, pqbar, pl, plbar, partons, nabove);
+ Tensor<2,4> Xsym = MSymW( pa, p1, pb, p4, pq, pqbar, pl, plbar, partons, nabove);
+
+ // 4 Different Helicity Choices (Differs from Pure Jet Case, where there is also the choice in qqbar helicity.
+ // (- - hel choice)
+ COM M_mmUnc = (((Xunc).contract(T1am,1)).contract(T4bm,1)).at(0);
+ COM M_mmCro = (((Xcro).contract(T1am,1)).contract(T4bm,1)).at(0);
+ COM M_mmSym = (((Xsym).contract(T1am,1)).contract(T4bm,1)).at(0);
+ // (- + hel choice)
+ COM M_mpUnc = (((Xunc).contract(T1am,1)).contract(T4bp,1)).at(0);
+ COM M_mpCro = (((Xcro).contract(T1am,1)).contract(T4bp,1)).at(0);
+ COM M_mpSym = (((Xsym).contract(T1am,1)).contract(T4bp,1)).at(0);
+ // (+ - hel choice)
+ COM M_pmUnc = (((Xunc).contract(T1ap,1)).contract(T4bm,1)).at(0);
+ COM M_pmCro = (((Xcro).contract(T1ap,1)).contract(T4bm,1)).at(0);
+ COM M_pmSym = (((Xsym).contract(T1ap,1)).contract(T4bm,1)).at(0);
+ // (+ + hel choice)
+ COM M_ppUnc = (((Xunc).contract(T1ap,1)).contract(T4bp,1)).at(0);
+ COM M_ppCro = (((Xcro).contract(T1ap,1)).contract(T4bp,1)).at(0);
+ COM M_ppSym = (((Xsym).contract(T1ap,1)).contract(T4bp,1)).at(0);
+
+ //Colour factors:
+ COM cmsms,cmumu,cmcmc,cmsmu,cmsmc,cmumc;
+ cmsms=3.;
+ cmumu=4./3.;
+ cmcmc=4./3.;
+ cmsmu =3./2.*COM(0.,1.);
+ cmsmc = -3./2.*COM(0.,1.);
+ cmumc = -1./6.;
+
+ // Work Out Interference in each case of helicity:
+ double amp_mm = real(cmsms*pow(abs(M_mmSym),2)
+ +cmumu*pow(abs(M_mmUnc),2)
+ +cmcmc*pow(abs(M_mmCro),2)
+ +2.*real(cmsmu*M_mmSym*conj(M_mmUnc))
+ +2.*real(cmsmc*M_mmSym*conj(M_mmCro))
+ +2.*real(cmumc*M_mmUnc*conj(M_mmCro)));
+
+ double amp_mp = real(cmsms*pow(abs(M_mpSym),2)
+ +cmumu*pow(abs(M_mpUnc),2)
+ +cmcmc*pow(abs(M_mpCro),2)
+ +2.*real(cmsmu*M_mpSym*conj(M_mpUnc))
+ +2.*real(cmsmc*M_mpSym*conj(M_mpCro))
+ +2.*real(cmumc*M_mpUnc*conj(M_mpCro)));
+
+ double amp_pm = real(cmsms*pow(abs(M_pmSym),2)
+ +cmumu*pow(abs(M_pmUnc),2)
+ +cmcmc*pow(abs(M_pmCro),2)
+ +2.*real(cmsmu*M_pmSym*conj(M_pmUnc))
+ +2.*real(cmsmc*M_pmSym*conj(M_pmCro))
+ +2.*real(cmumc*M_pmUnc*conj(M_pmCro)));
+
+ double amp_pp = real(cmsms*pow(abs(M_ppSym),2)
+ +cmumu*pow(abs(M_ppUnc),2)
+ +cmcmc*pow(abs(M_ppCro),2)
+ +2.*real(cmsmu*M_ppSym*conj(M_ppUnc))
+ +2.*real(cmsmc*M_ppSym*conj(M_ppCro))
+ +2.*real(cmumc*M_ppUnc*conj(M_ppCro)));
+
+ double amp=((amp_mm+amp_mp+amp_pm+amp_pp)/(9.*4.));
+
+
+
+ CLHEP::HepLorentzVector q1,q3;
+ q1=pa;
+ for(int i=0;i<nabove+1;i++){
+ q1-=partons.at(i);
+ }
+ q3 = q1 - pq - pqbar - pl - plbar;
+
+ double t1 = (q1).m2();
+ double t3 = (q3).m2();
+
+ //Divide by t-channels
+ amp/=(t1*t1*t3*t3);
+
+ //Divide by WProp
+ double WPropfact = WProp(plbar, pl);
+ amp*=WPropfact;
+
+
+ return amp;
+}
+
+// no wqq emission
+double jM2WqqtoqQQqW(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector pb,CLHEP::HepLorentzVector pl,CLHEP::HepLorentzVector plbar, std::vector<CLHEP::HepLorentzVector> partons, bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove, int nbelow, bool forwards){
+
+ static bool is_sigma_index_set(false);
+ if(!is_sigma_index_set){
+ if(init_sigma_index())
+ is_sigma_index_set = true;
+ else
+ return 0.;
+ }
+
+ if (!forwards){ //If Emission from Leg a instead, flip process.
+ HLV dummymom = pa;
+ bool dummybool= aqlinepa;
+ int dummyint = nabove;
+ pa = pb;
+ pb = dummymom;
+ std::reverse(partons.begin(),partons.end());
+ qqxmarker = !(qqxmarker);
+ aqlinepa = aqlinepb;
+ aqlinepb = dummybool;
+ nabove = nbelow;
+ nbelow = dummyint;
+ }
+
+ HLV pq, pqbar, p1,p4;
+ if (qqxmarker){
+ pqbar = partons[nabove+1];
+ pq = partons[nabove+2];}
+ else{
+ pq = partons[nabove+1];
+ pqbar = partons[nabove+2];}
+
+ p1 = partons.front();
+ p4 = partons.back();
+
+ Tensor<1,4> T1am(0.), T1ap(0.);
+ if(!(aqlinepa)){
+ T1ap = TCurrent(p1, true, pa, true);
+ T1am = TCurrent(p1, false, pa, false);}
+ else if(aqlinepa){
+ T1ap = TCurrent(pa, true, p1, true);
+ T1am = TCurrent(pa, false, p1, false);}
+
+ Tensor <1,4> T4bm = jW(pb, p4, plbar, pl, aqlinepb);
+
+ // Calculate the 3 separate contributions to the effective vertex
+ Tensor<2,4> Xunc_m = MUncross(pa, pq, pqbar,partons, false, nabove);
+ Tensor<2,4> Xcro_m = MCross( pa, pq, pqbar,partons, false, nabove);
+ Tensor<2,4> Xsym_m = MSym( pa, p1, pb, p4, pq, pqbar, partons, false, nabove);
+
+ Tensor<2,4> Xunc_p = MUncross(pa, pq, pqbar,partons, true, nabove);
+ Tensor<2,4> Xcro_p = MCross( pa, pq, pqbar,partons, true, nabove);
+ Tensor<2,4> Xsym_p = MSym( pa, p1, pb, p4, pq, pqbar, partons, true, nabove);
+
+
+ // (- - hel choice)
+ COM M_mmUnc = (((Xunc_m).contract(T1am,1)).contract(T4bm,1)).at(0);
+ COM M_mmCro = (((Xcro_m).contract(T1am,1)).contract(T4bm,1)).at(0);
+ COM M_mmSym = (((Xsym_m).contract(T1am,1)).contract(T4bm,1)).at(0);
+ // (- + hel choice)
+ COM M_mpUnc = (((Xunc_p).contract(T1am,1)).contract(T4bm,1)).at(0);
+ COM M_mpCro = (((Xcro_p).contract(T1am,1)).contract(T4bm,1)).at(0);
+ COM M_mpSym = (((Xsym_p).contract(T1am,1)).contract(T4bm,1)).at(0);
+ // (+ - hel choice)
+ COM M_pmUnc = (((Xunc_m).contract(T1ap,1)).contract(T4bm,1)).at(0);
+ COM M_pmCro = (((Xcro_m).contract(T1ap,1)).contract(T4bm,1)).at(0);
+ COM M_pmSym = (((Xsym_m).contract(T1ap,1)).contract(T4bm,1)).at(0);
+ // (+ + hel choice)
+ COM M_ppUnc = (((Xunc_p).contract(T1ap,1)).contract(T4bm,1)).at(0);
+ COM M_ppCro = (((Xcro_p).contract(T1ap,1)).contract(T4bm,1)).at(0);
+ COM M_ppSym = (((Xsym_p).contract(T1ap,1)).contract(T4bm,1)).at(0);
+
+ //Colour factors:
+ COM cmsms,cmumu,cmcmc,cmsmu,cmsmc,cmumc;
+ cmsms=3.;
+ cmumu=4./3.;
+ cmcmc=4./3.;
+ cmsmu =3./2.*COM(0.,1.);
+ cmsmc = -3./2.*COM(0.,1.);
+ cmumc = -1./6.;
+
+ // Work Out Interference in each case of helicity:
+ double amp_mm = real(cmsms*pow(abs(M_mmSym),2)
+ +cmumu*pow(abs(M_mmUnc),2)
+ +cmcmc*pow(abs(M_mmCro),2)
+ +2.*real(cmsmu*M_mmSym*conj(M_mmUnc))
+ +2.*real(cmsmc*M_mmSym*conj(M_mmCro))
+ +2.*real(cmumc*M_mmUnc*conj(M_mmCro)));
+
+ double amp_mp = real(cmsms*pow(abs(M_mpSym),2)
+ +cmumu*pow(abs(M_mpUnc),2)
+ +cmcmc*pow(abs(M_mpCro),2)
+ +2.*real(cmsmu*M_mpSym*conj(M_mpUnc))
+ +2.*real(cmsmc*M_mpSym*conj(M_mpCro))
+ +2.*real(cmumc*M_mpUnc*conj(M_mpCro)));
+
+ double amp_pm = real(cmsms*pow(abs(M_pmSym),2)
+ +cmumu*pow(abs(M_pmUnc),2)
+ +cmcmc*pow(abs(M_pmCro),2)
+ +2.*real(cmsmu*M_pmSym*conj(M_pmUnc))
+ +2.*real(cmsmc*M_pmSym*conj(M_pmCro))
+ +2.*real(cmumc*M_pmUnc*conj(M_pmCro)));
+
+ double amp_pp = real(cmsms*pow(abs(M_ppSym),2)
+ +cmumu*pow(abs(M_ppUnc),2)
+ +cmcmc*pow(abs(M_ppCro),2)
+ +2.*real(cmsmu*M_ppSym*conj(M_ppUnc))
+ +2.*real(cmsmc*M_ppSym*conj(M_ppCro))
+ +2.*real(cmumc*M_ppUnc*conj(M_ppCro)));
+
+ double amp=((amp_mm+amp_mp+amp_pm+amp_pp)/(9.*4.));
+
+ CLHEP::HepLorentzVector q1,q3;
+ q1=pa;
+ for(int i=0;i<nabove+1;i++){
+ q1-=partons.at(i);
+ }
+ q3 = q1 - pq - pqbar;
+
+ double t1 = (q1).m2();
+ double t3 = (q3).m2();
+
+ //Divide by t-channels
+ amp/=(t1*t1*t3*t3);
+
+ //Divide by WProp
+ double WPropfact = WProp(plbar, pl);
+ amp*=WPropfact;
+
+ return amp;
+}
diff --git a/src/YAMLreader.cc b/src/YAMLreader.cc
index dc2e36c..1d51bd4 100644
--- a/src/YAMLreader.cc
+++ b/src/YAMLreader.cc
@@ -1,465 +1,475 @@
/**
* \authors Jeppe Andersen, Tuomas Hapola, Marian Heil, Andreas Maier, Jennifer Smillie
* \date 2019
* \copyright GPLv2 or later
*/
#include "HEJ/YAMLreader.hh"
#include <algorithm>
#include <iostream>
#include <limits>
#include <map>
#include <string>
#include <unordered_map>
#include <vector>
#include <dlfcn.h>
#include "HEJ/ScaleFunction.hh"
#include "HEJ/event_types.hh"
#include "HEJ/output_formats.hh"
+#include "HEJ/Constants.hh"
namespace HEJ{
class Event;
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 = {
"trials", "min extparton pt", "max ext soft pt fraction",
- "FKL", "unordered", "non-HEJ",
+ "FKL", "unordered", "qqx", "non-HEJ",
"scales", "scale factors", "max scale ratio", "import scales",
- "log correction", "event output", "analysis"
+ "log correction", "event output", "analysis", "regulator parameter"
};
// add subnodes to "supported" - the assigned value is irrelevant
for(auto && opt: opts) supported[opt] = "";
for(auto && jet_opt: {"min pt", "algorithm", "R"}){
supported["resummation jets"][jet_opt] = "";
supported["fixed order jets"][jet_opt] = "";
}
for(auto && opt: {"mt", "use impact factors", "include bottom", "mb"}){
supported["Higgs coupling"][opt] = "";
}
for(auto && opt: {"name", "seed"}){
supported["random generator"][opt] = "";
}
return supported;
}();
return supported;
}
fastjet::JetAlgorithm to_JetAlgorithm(std::string const & algo){
using namespace fastjet;
static const std::map<std::string, fastjet::JetAlgorithm> known = {
{"kt", kt_algorithm},
{"cambridge", cambridge_algorithm},
{"antikt", antikt_algorithm},
{"cambridge for passive", cambridge_for_passive_algorithm},
{"plugin", plugin_algorithm}
};
const auto res = known.find(algo);
if(res == known.end()){
throw std::invalid_argument("Unknown jet algorithm " + algo);
}
return res->second;
}
EventTreatment to_EventTreatment(std::string const & name){
static const std::map<std::string, EventTreatment> known = {
{"reweight", EventTreatment::reweight},
{"keep", EventTreatment::keep},
{"discard", EventTreatment::discard}
};
const auto res = known.find(name);
if(res == known.end()){
throw std::invalid_argument("Unknown event treatment " + name);
}
return res->second;
}
} // namespace anonymous
namespace detail{
void set_from_yaml(fastjet::JetAlgorithm & setting, YAML::Node const & yaml){
setting = to_JetAlgorithm(yaml.as<std::string>());
}
void set_from_yaml(EventTreatment & setting, YAML::Node const & yaml){
setting = to_EventTreatment(yaml.as<std::string>());
}
void set_from_yaml(ParticleID & setting, YAML::Node const & yaml){
setting = to_ParticleID(yaml.as<std::string>());
}
} // namespace detail
JetParameters get_jet_parameters(
YAML::Node const & node,
std::string const & entry
){
assert(node);
JetParameters result;
fastjet::JetAlgorithm jet_algo = fastjet::antikt_algorithm;
double R;
set_from_yaml_if_defined(jet_algo, node, entry, "algorithm");
set_from_yaml(R, node, entry, "R");
result.def = fastjet::JetDefinition{jet_algo, R};
set_from_yaml(result.min_pt, node, entry, "min pt");
return result;
}
RNGConfig to_RNGConfig(
YAML::Node const & node,
std::string const & entry
){
assert(node);
RNGConfig result;
set_from_yaml(result.name, node, entry, "name");
set_from_yaml_if_defined(result.seed, node, entry, "seed");
return result;
}
HiggsCouplingSettings get_Higgs_coupling(
YAML::Node const & node,
std::string const & entry
){
assert(node);
static constexpr double mt_max = 2e4;
#ifndef HEJ_BUILD_WITH_QCDLOOP
if(node[entry]){
throw std::invalid_argument{
"Higgs coupling settings require building HEJ 2 "
"with QCDloop support"
};
}
#endif
HiggsCouplingSettings settings;
set_from_yaml_if_defined(settings.mt, node, entry, "mt");
set_from_yaml_if_defined(settings.mb, node, entry, "mb");
set_from_yaml_if_defined(settings.include_bottom, node, entry, "include bottom");
set_from_yaml_if_defined(settings.use_impact_factors, node, entry, "use impact factors");
if(settings.use_impact_factors){
if(settings.mt != std::numeric_limits<double>::infinity()){
throw std::invalid_argument{
"Conflicting settings: "
"impact factors may only be used in the infinite top mass limit"
};
}
}
else{
// huge values of the top mass are numerically unstable
settings.mt = std::min(settings.mt, mt_max);
}
return settings;
}
FileFormat to_FileFormat(std::string const & name){
static const std::map<std::string, FileFormat> known = {
{"Les Houches", FileFormat::Les_Houches},
{"HepMC", FileFormat::HepMC}
};
const auto res = known.find(name);
if(res == known.end()){
throw std::invalid_argument("Unknown file format " + name);
}
return res->second;
}
std::string extract_suffix(std::string const & filename){
size_t separator = filename.rfind('.');
if(separator == filename.npos) return {};
return filename.substr(separator + 1);
}
FileFormat format_from_suffix(std::string const & filename){
const std::string suffix = extract_suffix(filename);
if(suffix == "lhe") return FileFormat::Les_Houches;
if(suffix == "hepmc") return FileFormat::HepMC;
throw std::invalid_argument{
"Can't determine format for output file " + filename
};
}
void assert_all_options_known(
YAML::Node const & conf, YAML::Node const & supported
){
if(!conf.IsMap()) return;
if(!supported.IsMap()) throw invalid_type{"must not have sub-entries"};
for(auto const & entry: conf){
const auto name = entry.first.as<std::string>();
if(! supported[name]) throw unknown_option{name};
/* check sub-options, e.g. 'resummation jets: min pt'
* we don't check analysis sub-options
* those depend on the analysis being used and should be checked there
* similar for "import scales"
*/
if(name != "analysis" && name != "import scales"){
try{
assert_all_options_known(conf[name], supported[name]);
}
catch(unknown_option const & ex){
throw unknown_option{name + ": " + ex.what()};
}
catch(invalid_type const & ex){
throw invalid_type{name + ": " + ex.what()};
}
}
}
}
} // namespace HEJ
namespace YAML {
Node convert<HEJ::OutputFile>::encode(HEJ::OutputFile const & outfile) {
Node node;
node[to_string(outfile.format)] = outfile.name;
return node;
};
bool convert<HEJ::OutputFile>::decode(Node const & node, HEJ::OutputFile & out) {
switch(node.Type()){
case NodeType::Map: {
YAML::const_iterator it = node.begin();
out.format = HEJ::to_FileFormat(it->first.as<std::string>());
out.name = it->second.as<std::string>();
return true;
}
case NodeType::Scalar:
out.name = node.as<std::string>();
out.format = HEJ::format_from_suffix(out.name);
return true;
default:
return false;
}
}
} // namespace YAML
namespace HEJ{
namespace detail{
void set_from_yaml(OutputFile & setting, YAML::Node const & yaml){
setting = yaml.as<OutputFile>();
}
}
namespace{
void update_fixed_order_jet_parameters(
JetParameters & fixed_order_jets, YAML::Node const & yaml
){
if(!yaml["fixed order jets"]) return;
set_from_yaml_if_defined(
fixed_order_jets.min_pt, yaml, "fixed order jets", "min pt"
);
fastjet::JetAlgorithm algo = fixed_order_jets.def.jet_algorithm();
set_from_yaml_if_defined(algo, yaml, "fixed order jets", "algorithm");
double R = fixed_order_jets.def.R();
set_from_yaml_if_defined(R, yaml, "fixed order jets", "R");
fixed_order_jets.def = fastjet::JetDefinition{algo, R};
}
// like std::stod, but throw if not the whole string can be converted
double to_double(std::string const & str){
std::size_t pos;
const double result = std::stod(str, &pos);
if(pos < str.size()){
throw std::invalid_argument(str + " is not a valid double value");
}
return result;
}
using EventScale = double (*)(Event const &);
void import_scale_functions(
std::string const & file,
std::vector<std::string> const & scale_names,
std::unordered_map<std::string, EventScale> & known
) {
auto handle = dlopen(file.c_str(), RTLD_NOW);
char * error = dlerror();
if(error != nullptr) throw std::runtime_error{error};
for(auto const & scale: scale_names) {
void * sym = dlsym(handle, scale.c_str());
error = dlerror();
if(error != nullptr) throw std::runtime_error{error};
known.emplace(scale, reinterpret_cast<EventScale>(sym));
}
}
auto get_scale_map(
YAML::Node const & yaml
) {
std::unordered_map<std::string, EventScale> scale_map;
scale_map.emplace("H_T", H_T);
scale_map.emplace("max jet pperp", max_jet_pt);
scale_map.emplace("jet invariant mass", jet_invariant_mass);
scale_map.emplace("m_j1j2", m_j1j2);
if(yaml["import scales"]) {
if(! yaml["import scales"].IsMap()) {
throw invalid_type{"Entry 'import scales' is not a map"};
}
for(auto const & import: yaml["import scales"]) {
const auto file = import.first.as<std::string>();
const auto scale_names =
import.second.IsSequence()
?import.second.as<std::vector<std::string>>()
:std::vector<std::string>{import.second.as<std::string>()};
import_scale_functions(file, scale_names, scale_map);
}
}
return scale_map;
}
// simple (as in non-composite) scale functions
/**
* An example for a simple scale function would be H_T,
* H_T/2 is then composite (take H_T and then divide by 2)
*/
ScaleFunction parse_simple_ScaleFunction(
std::string const & scale_fun,
std::unordered_map<std::string, EventScale> const & known
) {
assert(
scale_fun.empty() ||
(!std::isspace(scale_fun.front()) && !std::isspace(scale_fun.back()))
);
const auto it = known.find(scale_fun);
if(it != end(known)) return {it->first, it->second};
try{
const double scale = to_double(scale_fun);
return {scale_fun, FixedScale{scale}};
} catch(std::invalid_argument const &){}
throw std::invalid_argument{"Unknown scale choice: " + scale_fun};
}
std::string trim_front(std::string const & str){
const auto new_begin = std::find_if(
begin(str), end(str), [](char c){ return ! std::isspace(c); }
);
return std::string(new_begin, end(str));
}
std::string trim_back(std::string str){
size_t pos = str.size() - 1;
// use guaranteed wrap-around behaviour to check whether we have
// traversed the whole string
for(; pos < str.size() && std::isspace(str[pos]); --pos) {}
str.resize(pos + 1); // note that pos + 1 can be 0
return str;
}
ScaleFunction parse_ScaleFunction(
std::string const & scale_fun,
std::unordered_map<std::string, EventScale> const & known
){
assert(
scale_fun.empty() ||
(!std::isspace(scale_fun.front()) && !std::isspace(scale_fun.back()))
);
// parse from right to left => a/b/c gives (a/b)/c
const size_t delim = scale_fun.find_last_of("*/");
if(delim == scale_fun.npos){
return parse_simple_ScaleFunction(scale_fun, known);
}
const std::string first = trim_back(std::string{scale_fun, 0, delim});
const std::string second = trim_front(std::string{scale_fun, delim+1});
if(scale_fun[delim] == '/'){
return parse_ScaleFunction(first, known)
/ parse_ScaleFunction(second, known);
}
else{
assert(scale_fun[delim] == '*');
return parse_ScaleFunction(first, known)
* parse_ScaleFunction(second, known);
}
}
EventTreatMap get_event_treatment(
YAML::Node const & yaml
){
using namespace event_type;
EventTreatMap treat {
{no_2_jets, EventTreatment::discard},
{bad_final_state, EventTreatment::discard},
{FKL, EventTreatment::reweight},
{unob, EventTreatment::keep},
{unof, EventTreatment::keep},
+ {qqxexb, EventTreatment::keep},
+ {qqxexf, EventTreatment::keep},
+ {qqxmid, EventTreatment::keep},
{nonHEJ, EventTreatment::keep}
};
set_from_yaml(treat.at(FKL), yaml, "FKL");
set_from_yaml(treat.at(unob), yaml, "unordered");
treat.at(unof) = treat.at(unob);
+ set_from_yaml(treat.at(qqxexb), yaml, "qqx");
+ set_from_yaml(treat.at(qqxexf), yaml, "qqx");
+ set_from_yaml(treat.at(qqxmid), yaml, "qqx");
set_from_yaml(treat.at(nonHEJ), yaml, "non-HEJ");
if(treat[nonHEJ] == EventTreatment::reweight){
throw std::invalid_argument{"Cannot reweight non-HEJ events"};
}
return treat;
}
Config to_Config(YAML::Node const & yaml){
try{
assert_all_options_known(yaml, get_supported_options());
}
catch(unknown_option const & ex){
throw unknown_option{std::string{"Unknown option '"} + ex.what() + "'"};
}
Config config;
config.resummation_jets = get_jet_parameters(yaml, "resummation jets");
config.fixed_order_jets = config.resummation_jets;
update_fixed_order_jet_parameters(config.fixed_order_jets, yaml);
set_from_yaml(config.min_extparton_pt, yaml, "min extparton pt");
+ // Sets the standard value, then changes this if defined
+ config.regulator_lambda=CLAMBDA;
+ set_from_yaml_if_defined(config.regulator_lambda, yaml, "regulator parameter");
config.max_ext_soft_pt_fraction = std::numeric_limits<double>::infinity();
set_from_yaml_if_defined(
config.max_ext_soft_pt_fraction, yaml, "max ext soft pt fraction"
);
set_from_yaml(config.trials, yaml, "trials");
set_from_yaml(config.log_correction, yaml, "log correction");
config.treat = get_event_treatment(yaml);
set_from_yaml_if_defined(config.output, yaml, "event output");
config.rng = to_RNGConfig(yaml, "random generator");
set_from_yaml_if_defined(config.analysis_parameters, yaml, "analysis");
config.scales = to_ScaleConfig(yaml);
config.Higgs_coupling = get_Higgs_coupling(yaml, "Higgs coupling");
return config;
}
} // namespace anonymous
ScaleConfig to_ScaleConfig(YAML::Node const & yaml){
ScaleConfig config;
auto scale_funs = get_scale_map(yaml);
std::vector<std::string> scales;
set_from_yaml(scales, yaml, "scales");
config.base.reserve(scales.size());
std::transform(
begin(scales), end(scales), std::back_inserter(config.base),
[scale_funs](auto const & entry){
return parse_ScaleFunction(entry, scale_funs);
}
);
set_from_yaml_if_defined(config.factors, yaml, "scale factors");
config.max_ratio = std::numeric_limits<double>::infinity();
set_from_yaml_if_defined(config.max_ratio, yaml, "max scale ratio");
return config;
}
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;
}
}
} // namespace HEJ
diff --git a/src/currents.cc b/src/currents.cc
index fe69d1c..de692eb 100644
--- a/src/currents.cc
+++ b/src/currents.cc
@@ -1,3617 +1,3210 @@
//////////////////////////////////////////////////
//////////////////////////////////////////////////
// This source code is Copyright (2012) of //
// Jeppe R. Andersen and Jennifer M. Smillie //
// and is distributed under the //
// Gnu Public License version 2 //
// http://www.gnu.org/licenses/gpl-2.0.html //
// You are allowed to distribute and alter the //
// source under the conditions of the GPLv2 //
// as long as this copyright notice //
// is unaltered and distributed with the source //
// Any use should comply with the //
// MCNET GUIDELINES //
// for Event Generator Authors and Users //
// as distributed with this source code //
//////////////////////////////////////////////////
//////////////////////////////////////////////////
#include "HEJ/currents.hh"
#include <iostream>
#include <limits>
#include <utility>
#include <vector>
#ifdef HEJ_BUILD_WITH_QCDLOOP
#include "qcdloop/qcdloop.h"
#endif
#include "HEJ/Constants.hh"
#include "HEJ/exceptions.hh"
#include "HEJ/PDG_codes.hh"
const COM looprwfactor = (COM(0.,1.)*M_PI*M_PI)/pow((2.*M_PI),4);
constexpr double infinity = std::numeric_limits<double>::infinity();
namespace {
// Loop integrals
#ifdef HEJ_BUILD_WITH_QCDLOOP
COM B0DD(CLHEP::HepLorentzVector q, double mq)
{
static std::vector<std::complex<double>> result(3);
static auto ql_B0 = [](){
ql::Bubble<std::complex<double>,double,double> ql_B0;
ql_B0.setCacheSize(100);
return ql_B0;
}();
static std::vector<double> masses(2);
static std::vector<double> momenta(1);
for(auto & m: masses) m = mq*mq;
momenta.front() = q.m2();
ql_B0.integral(result, 1, masses, momenta);
return result[0];
}
COM C0DD(CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mq)
{
static std::vector<std::complex<double>> result(3);
static auto ql_C0 = [](){
ql::Triangle<std::complex<double>,double,double> ql_C0;
ql_C0.setCacheSize(100);
return ql_C0;
}();
static std::vector<double> masses(3);
static std::vector<double> momenta(3);
for(auto & m: masses) m = mq*mq;
momenta[0] = q1.m2();
momenta[1] = q2.m2();
momenta[2] = (q1+q2).m2();
ql_C0.integral(result, 1, masses, momenta);
return result[0];
}
COM D0DD(CLHEP::HepLorentzVector q1,CLHEP::HepLorentzVector q2, CLHEP::HepLorentzVector q3, double mq)
{
static std::vector<std::complex<double>> result(3);
static auto ql_D0 = [](){
ql::Box<std::complex<double>,double,double> ql_D0;
ql_D0.setCacheSize(100);
return ql_D0;
}();
static std::vector<double> masses(4);
static std::vector<double> momenta(6);
for(auto & m: masses) m = mq*mq;
momenta[0] = q1.m2();
momenta[1] = q2.m2();
momenta[2] = q3.m2();
momenta[3] = (q1+q2+q3).m2();
momenta[4] = (q1+q2).m2();
momenta[5] = (q2+q3).m2();
ql_D0.integral(result, 1, masses, momenta);
return result[0];
}
COM A1(CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt)
// As given in Eq. (B.2) of VDD
{
double q12,q22,Q2;
CLHEP::HepLorentzVector Q;
double Delta3,mt2;
COM ans(COM(0.,0.));
q12=q1.m2();
q22=q2.m2();
Q=-q1-q2; // Define all momenta ingoing as in appendix of VDD
Q2=Q.m2();
Delta3=q12*q12+q22*q22+Q2*Q2-2*q12*q22-2*q12*Q2-2*q22*Q2;
if (mt < 0.)
std::cerr<<"Problem in A1! mt = "<<mt<<std::endl;
mt2=mt*mt;
ans=looprwfactor*COM(0,-1)*C0DD(q1,q2,mt)*( 4.*mt2/Delta3*(Q2-q12-q22)
-1.-4.*q12*q22/Delta3-12.*q12*q22*Q2/Delta3/Delta3*(q12+q22-Q2) )
- looprwfactor*COM(0,-1)*( B0DD(q2,mt)-B0DD(Q,mt) )
* ( 2.*q22/Delta3+12.*q12*q22/Delta3/Delta3*(q22-q12+Q2) )
- looprwfactor*COM(0,-1)*( B0DD(q1,mt)-B0DD(Q,mt) )
* ( 2.*q12/Delta3+12.*q12*q22/Delta3/Delta3*(q12-q22+Q2) )
- 2./Delta3/16/M_PI/M_PI*(q12+q22-Q2);
return ans;
}
COM A2(CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt)
// As given in Eq. (B.2) of VDD, but with high energy limit
// of invariants taken.
{
double q12,q22,Q2;
CLHEP::HepLorentzVector Q;
double Delta3,mt2;
COM ans(COM(0.,0.));
if (mt < 0.)
std::cerr<<"Problem in A2! mt = "<<mt<<std::endl;
mt2=mt*mt;
q12=q1.m2();
q22=q2.m2();
Q=-q1-q2; // Define all momenta ingoing as in appendix of VDD
Q2=Q.m2();
Delta3=q12*q12+q22*q22+Q2*Q2-2*q12*q22-2*q12*Q2-2*q22*Q2;
ans=looprwfactor*COM(0,-1)*C0DD(q1,q2,mt)*( 2.*mt2+1./2.*(q12+q22-Q2)
+2.*q12*q22*Q2/Delta3 )
+looprwfactor*COM(0,-1)*(B0DD(q2,mt)-B0DD(Q,mt))
*q22*(q22-q12-Q2)/Delta3
+looprwfactor*COM(0,-1)*(B0DD(q1,mt)-B0DD(Q,mt))
*q12*(q12-q22-Q2)/Delta3+1./16/M_PI/M_PI;
return ans;
}
#else // no QCDloop
COM A1(CLHEP::HepLorentzVector, CLHEP::HepLorentzVector, double) {
throw std::logic_error{"A1 called without QCDloop support"};
}
COM A2(CLHEP::HepLorentzVector, CLHEP::HepLorentzVector, double) {
throw std::logic_error{"A2 called without QCDloop support"};
}
#endif
void to_current(const CLHEP::HepLorentzVector & q, current & ret){
ret[0]=q.e();
ret[1]=q.x();
ret[2]=q.y();
ret[3]=q.z();
}
constexpr double C_A = 3.;
constexpr double C_F = 4./3.;
- using ParticleID = HEJ::pid::ParticleID;
+ // using ParticleID = HEJ::pid::ParticleID;
+
+
+} // namespace anonymous
// Colour acceleration multiplier for gluons see eq. (7) in arXiv:0910.5113
- // TODO: this is not a current and should be moved somewhere else
+ // @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)*(C_A - 1./C_A) + 1./C_A;
+ return 1./2.*(p1minus/paminus + paminus/p1minus)*(HEJ::C_A - 1./HEJ::C_A) + 1./HEJ::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());
}
-} // namespace anonymous
-
-/// @TODO move all of these functions to header? clean up in general
-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];
-}
-
-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();
-}
-
-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!?!
-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];
-}
-
-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];
-}
-
-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];
-}
-
-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];
-}
-
-double abs2(const COM & a)
-{
- return (a*conj(a)).real();
-}
-
-double vabs2(const CCurrent & cur)
-{
- return abs2(cur.c0)-abs2(cur.c1)-abs2(cur.c2)-abs2(cur.c3);
-}
-
-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));
-}
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(CLHEP::HepLorentzVector p1)
{
// Current goes (E,px,py,pz)
// std::cout<<"current = ("<<c0<<","<<c1<<","<<c2<<","<<c3<<")\n";
// Vector goes (px,py,pz,E)
// std::cout<<"vector = ("<<p1[0]<<","<<p1[1]<<","<<p1[2]<<","<<p1[3]<<")\n";
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
// Current for <outgoing state | mu | incoming state>
/// @TODO always use this instead of "j"
/// @TODO isn't this jio with flipt helicities?
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]);
}
/// @TODO remove this
void j (HLV pout, bool helout, HLV pin, bool helin,current &cur) {
joi(pout, helout, pin, helin, cur);
}
/// @TODO remove this
CCurrent j (HLV pout, bool helout, HLV pin, bool helin)
{
return joi(pout, helout, pin, helin);
}
// Current for <incoming state | mu | outgoing state>
void jio(HLV pin, bool helin, HLV pout, bool helout, current &cur) {
cur[0] = 0.0;
cur[1] = 0.0;
cur[2] = 0.0;
cur[3] = 0.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 * 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];
}
} else { // positive 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];
}
}
}
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]);
}
// Current for <outgoing state | mu | outgoing state>
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 {
/// @TODO unused function
// double jM2 (CLHEP::HepLorentzVector p1out, bool hel1out, CLHEP::HepLorentzVector p1in, bool hel1in, CLHEP::HepLorentzVector p2out, bool hel2out, CLHEP::HepLorentzVector p2in, bool hel2in)
// {
// CLHEP::HepLorentzVector q1=p1in-p1out;
// CLHEP::HepLorentzVector q2=-(p2in-p2out);
// current C1,C2;
// j (p1out,hel1out,p1in,hel1in, C1);
// j (p2out,hel2out,p2in,hel2in, C2);
// std::cout << "# From Currents, C1 : ("<<C1[0]<<","<<C1[1]<<","<<C1[2]<<","<<C1[3]<<"\n";
// std::cout << "# From Currents, C2 : ("<<C2[0]<<","<<C2[1]<<","<<C2[2]<<","<<C2[3]<<"\n";
// COM M=cdot(C1,C2);
// return (M*conj(M)).real()/(q1.m2()*q2.m2());
// }
- void jW (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe, bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin, bool helin, current cur)
- {
- // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
- // Need to swap e and nu for events with W- --> e- nubar!
- if (helin==helout && hele==helnu) {
- CLHEP::HepLorentzVector qa=pout+pe+pnu;
- CLHEP::HepLorentzVector qb=pin-pe-pnu;
- double ta(qa.m2()),tb(qb.m2());
-
- current t65,vout,vin,temp2,temp3,temp5;
- joo(pnu,helnu,pe,hele,t65);
- vout[0]=pout.e();
- vout[1]=pout.x();
- vout[2]=pout.y();
- vout[3]=pout.z();
- vin[0]=pin.e();
- vin[1]=pin.x();
- vin[2]=pin.y();
- vin[3]=pin.z();
-
- COM brac615=cdot(t65,vout);
- COM brac645=cdot(t65,vin);
-
- // prod1565 and prod6465 are zero for Ws (not Zs)!!
- // noalias(temp)=prod(trans(CurrentOutOut(pout,helout,pnu,helout)),metric);
- joo(pout,helout,pnu,helout,temp2);
- // noalias(temp2)=prod(temp,ctemp);
- COM prod1665=cdot(temp2,t65);
- // noalias(temp)=prod(trans(Current(pe,helin,pin,helin)),metric);
- // noalias(temp2)=prod(temp,ctemp);
- joi(pe,helin,pin,helin,temp3);
- COM prod5465=cdot(temp3,t65);
- // noalias(temp)=prod(trans(Current(pnu,helin,pin,helin)),metric);
- // noalias(temp2)=prod(temp,ctemp);
-
- joo(pout,helout,pe,helout,temp2);
- joi(pnu,helnu,pin,helin,temp3);
- joi(pout,helout,pin,helin,temp5);
-
- current term1,term2,term3,sum;
- cmult(2.*brac615/ta+2.*brac645/tb,temp5,term1);
- cmult(prod1665/ta,temp3,term2);
- cmult(-prod5465/tb,temp2,term3);
-
- // cur=((2.*brac615*Current(pout,helout,pin,helin)+prod1565*Current(pe,helin,pin,helin)+prod1665*Current(pnu,helin,pin,helin))/ta + (2.*brac645*Current(pout,helout,pin,helin)-prod5465*CurrentOutOut(pout,helout,pe,helout)-prod6465*CurrentOutOut(pout,helout,pnu,helout))/tb);
- // cur=((2.*brac615*temp5+prod1565*temp3+prod1665*temp4)/ta + (2.*brac645*temp5-prod5465*temp1-prod6465*temp2)/tb);
- cadd(term1,term2,term3,sum);
- // std::cout<<"sum: ("<<sum[0]<<","<<sum[1]<<","<<sum[2]<<","<<sum[3]<<")\n";
- cur[0]=sum[0];
- cur[1]=sum[1];
- cur[2]=sum[2];
- cur[3]=sum[3];
- }
- }
-
- void jWbar (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pe, bool hele, CLHEP::HepLorentzVector pnu, bool helnu, CLHEP::HepLorentzVector pin, bool helin, current cur)
- {
- // NOTA BENE: Conventions for W+ --> e+ nu, so that nu is lepton(6), e is anti-lepton(5)
- // Need to swap e and nu for events with W- --> e- nubar!
- if (helin==helout && hele==helnu) {
- CLHEP::HepLorentzVector qa=pout+pe+pnu;
- CLHEP::HepLorentzVector qb=pin-pe-pnu;
- double ta(qa.m2()),tb(qb.m2());
-
- current t65,vout,vin,temp2,temp3,temp5;
- joo(pnu,helnu,pe,hele,t65);
- vout[0]=pout.e();
- vout[1]=pout.x();
- vout[2]=pout.y();
- vout[3]=pout.z();
- vin[0]=pin.e();
- vin[1]=pin.x();
- vin[2]=pin.y();
- vin[3]=pin.z();
-
- COM brac615=cdot(t65,vout);
- COM brac645=cdot(t65,vin);
-
- // prod1565 and prod6465 are zero for Ws (not Zs)!!
- joo(pe,helout,pout,helout,temp2); // temp2 is <5|alpha|1>
- COM prod5165=cdot(temp2,t65);
- jio(pin,helin,pnu,helin,temp3); // temp3 is <4|alpha|6>
- COM prod4665=cdot(temp3,t65);
-
- joo(pnu,helout,pout,helout,temp2); // temp2 is now <6|mu|1>
- jio(pin,helin,pe,helin,temp3); // temp3 is now <4|mu|5>
- jio(pin,helin,pout,helout,temp5); // temp5 is <4|mu|1>
-
- current term1,term2,term3,sum;
- cmult(-2.*brac615/ta-2.*brac645/tb,temp5,term1);
- cmult(-prod5165/ta,temp3,term2);
- cmult(prod4665/tb,temp2,term3);
-
- // cur=((2.*brac615*Current(pout,helout,pin,helin)+prod1565*Current(pe,helin,pin,helin)+prod1665*Current(pnu,helin,pin,helin))/ta + (2.*brac645*Current(pout,helout,pin,helin)-prod5465*CurrentOutOut(pout,helout,pe,helout)-prod6465*CurrentOutOut(pout,helout,pnu,helout))/tb);
- // cur=((2.*brac615*temp5+prod1565*temp3+prod1665*temp4)/ta + (2.*brac645*temp5-prod5465*temp1-prod6465*temp2)/tb);
- cadd(term1,term2,term3,sum);
- // std::cout<<"term1: ("<<temp5[0]<<" "<<temp5[1]<<" "<<temp5[2]<<" "<<temp5[3]<<")"<<std::endl;
- // std::cout<<"sum: ("<<sum[0]<<","<<sum[1]<<","<<sum[2]<<","<<sum[3]<<")\n";
- cur[0]=sum[0];
- cur[1]=sum[1];
- cur[2]=sum[2];
- cur[3]=sum[3];
- }
- }
} // namespace anonymous
-double jMWqQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
-// Calculates the square of the current contractions for qQ->qenuQ scattering
-// p1: quark (with W emittance)
-// p2: Quark
-{
- current mj1m,mj2p,mj2m;
- CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
- CLHEP::HepLorentzVector q2=-(p2in-p2out);
-
- jW(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
- joi(p2out,true,p2in,true,mj2p);
- joi(p2out,false,p2in,false,mj2m);
-
- // std::cout<<"jMW1: ("<<mj1m[0]<<","<<mj1m[1]<<","<<mj1m[2]<<","<<mj1m[3]<<")\n";
- // std::cout<<"jMW2: ("<<mj2p[0]<<","<<mj2p[1]<<","<<mj2p[2]<<","<<mj2p[3]<<")\n";
- // std::cout<<"jMW3: ("<<mj2m[0]<<","<<mj2m[1]<<","<<mj2m[2]<<","<<mj2m[3]<<")\n";
-
- // mj1m.mj2p
-
- COM Mmp=cdot(mj1m,mj2p);
-
- // mj1m.mj2m
- COM Mmm=cdot(mj1m,mj2m);
-
- // sum of spinor strings ||^2
- double a2Mmp=abs2(Mmp);
- double a2Mmm=abs2(Mmm);
-
-// // Leave division by colour and Helicity avg until Tree files
- // Leave multi. of couplings to later
- // Multiply by Cf^2
- return (4./3.)*(4./3.)*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
-
-}
-
-double jMWqQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
-// Calculates the square of the current contractions for qQ->qenuQ scattering
-// p1: quark (with W emittance)
-// p2: Quark
-{
- current mj1m,mj2p,mj2m;
- CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
- CLHEP::HepLorentzVector q2=-(p2in-p2out);
-
- jW(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
- jio(p2in,true,p2out,true,mj2p);
- jio(p2in,false,p2out,false,mj2m);
-
- // std::cout<<"jMW1: ("<<mj1m[0]<<","<<mj1m[1]<<","<<mj1m[2]<<","<<mj1m[3]<<")\n";
- // std::cout<<"jMW2: ("<<mj2p[0]<<","<<mj2p[1]<<","<<mj2p[2]<<","<<mj2p[3]<<")\n";
- // std::cout<<"jMW3: ("<<mj2m[0]<<","<<mj2m[1]<<","<<mj2m[2]<<","<<mj2m[3]<<")\n";
-
- // mj1m.mj2p
-
- COM Mmp=cdot(mj1m,mj2p);
-
- // mj1m.mj2m
- COM Mmm=cdot(mj1m,mj2m);
-
- // sum of spinor strings ||^2
- double a2Mmp=abs2(Mmp);
- double a2Mmm=abs2(Mmm);
-
-// // Leave division by colour and Helicity avg until Tree files
- // Leave multi. of couplings to later
- // Multiply by Cf^2
- return (4./3.)*(4./3.)*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
-
-}
-
-double jMWqbarQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
-// Calculates the square of the current contractions for qQ->qenuQ scattering
-// p1: quark (with W emittance)
-// p2: Quark
-{
- current mj1m,mj2p,mj2m;
- CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
- CLHEP::HepLorentzVector q2=-(p2in-p2out);
-
- jWbar(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
- joi(p2out,true,p2in,true,mj2p);
- joi(p2out,false,p2in,false,mj2m);
-
- // std::cout<<"jMW1: ("<<mj1m[0]<<","<<mj1m[1]<<","<<mj1m[2]<<","<<mj1m[3]<<")\n";
- // std::cout<<"jMW2: ("<<mj2p[0]<<","<<mj2p[1]<<","<<mj2p[2]<<","<<mj2p[3]<<")\n";
- // std::cout<<"jMW3: ("<<mj2m[0]<<","<<mj2m[1]<<","<<mj2m[2]<<","<<mj2m[3]<<")\n";
-
- // mj1m.mj2p
-
- COM Mmp=cdot(mj1m,mj2p);
-
- // mj1m.mj2m
- COM Mmm=cdot(mj1m,mj2m);
-
- // sum of spinor strings ||^2
- double a2Mmp=abs2(Mmp);
- double a2Mmm=abs2(Mmm);
-
-// // Leave division by colour and Helicity avg until Tree files
- // Leave multi. of couplings to later
- // Multiply by Cf^2
- return (4./3.)*(4./3.)*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
-
-}
-
-double jMWqbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
-// Calculates the square of the current contractions for qQ->qenuQ scattering
-// p1: quark (with W emittance)
-// p2: Quark
-{
- current mj1m,mj2p,mj2m;
- CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
- CLHEP::HepLorentzVector q2=-(p2in-p2out);
-
- jWbar(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
- jio(p2in,true,p2out,true,mj2p);
- jio(p2in,false,p2out,false,mj2m);
-
- // std::cout<<"jMW1: ("<<mj1m[0]<<","<<mj1m[1]<<","<<mj1m[2]<<","<<mj1m[3]<<")\n";
- // std::cout<<"jMW2: ("<<mj2p[0]<<","<<mj2p[1]<<","<<mj2p[2]<<","<<mj2p[3]<<")\n";
- // std::cout<<"jMW3: ("<<mj2m[0]<<","<<mj2m[1]<<","<<mj2m[2]<<","<<mj2m[3]<<")\n";
-
- // mj1m.mj2p
-
- COM Mmp=cdot(mj1m,mj2p);
-
- // mj1m.mj2m
- COM Mmm=cdot(mj1m,mj2m);
-
- // sum of spinor strings ||^2
- double a2Mmp=abs2(Mmp);
- double a2Mmm=abs2(Mmm);
-
-// // Leave division by colour and Helicity avg until Tree files
- // Leave multi. of couplings to later
- // Multiply by Cf^2
- return (4./3.)*(4./3.)*(a2Mmp+a2Mmm)/(q1.m2()*q2.m2());
-
-}
-
-double jMWqg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
-// Calculates the square of the current contractions for qg->qenug scattering
-// p1: quark
-// p2: gluon
-{
- CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
- CLHEP::HepLorentzVector q2=-(p2in-p2out);
- current mj1m,mj2p,mj2m;
-
- jW(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
-
- joi(p2out,true,p2in,true,mj2p);
- joi(p2out,false,p2in,false,mj2m);
-
- // mj1m.mj2p
-
- COM Mmp=cdot(mj1m,mj2p);
-
- // mj1m.mj2m
- COM Mmm=cdot(mj1m,mj2m);
-
- const double K = K_g(p2out, p2in);
-
- // sum of spinor strings ||^2
- double a2Mmp=abs2(Mmp);
- double a2Mmm=abs2(Mmm);
- double sst = K/C_A*(a2Mmp+a2Mmm);
- // double sstsave=sst;
-
-// // Leave division by colour and Helicity avg until Tree files
- // Leave multi. of couplings to later
- // Multiply by Cf*Ca=4
- return 4.*sst/(q1.m2()*q2.m2());
-
-}
-
-double jMWqbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector pe, CLHEP::HepLorentzVector pnu,CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
-// Calculates the square of the current contractions for qg->qenug scattering
-// p1: quark
-// p2: gluon
-{
- CLHEP::HepLorentzVector q1=p1in-p1out-pe-pnu;
- CLHEP::HepLorentzVector q2=-(p2in-p2out);
- current mj1m,mj2p,mj2m;
-
- jWbar(p1out,false,pe,false,pnu,false,p1in,false,mj1m);
-
- joi(p2out,true,p2in,true,mj2p);
- joi(p2out,false,p2in,false,mj2m);
-
- // mj1m.mj2p
-
- COM Mmp=cdot(mj1m,mj2p);
-
- // mj1m.mj2m
- COM Mmm=cdot(mj1m,mj2m);
-
- const double K = K_g(p2out, p2in);
-
- // sum of spinor strings ||^2
- double a2Mmp=abs2(Mmp);
- double a2Mmm=abs2(Mmm);
- double sst = K/C_A*(a2Mmp+a2Mmm);
- // double sstsave=sst;
-
-// // Leave division by colour and Helicity avg until Tree files
- // Leave multi. of couplings to later
- // Multiply by Cf*Ca=4
- return 4.*sst/(q1.m2()*q2.m2());
-
-}
-
double jM2qQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
{
// std::cerr<<"Current: "<<p1out<<" "<<p1in<<" "<<p2out<<" "<<p2in<<std::endl;
CLHEP::HepLorentzVector q1=p1in-p1out;
CLHEP::HepLorentzVector q2=-(p2in-p2out);
// std::cerr<<"Current: "<<q1.m2()<<" "<<q2.m2()<<std::endl;
current mj1m,mj1p,mj2m,mj2p;
joi(p1out,true,p1in,true,mj1p);
joi(p1out,false,p1in,false,mj1m);
joi(p2out,true,p2in,true,mj2p);
joi(p2out,false,p2in,false,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());
}
double jM2qQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
{
CLHEP::HepLorentzVector q1=p1in-p1out;
CLHEP::HepLorentzVector q2=-(p2in-p2out);
current mj1m,mj1p,mj2m,mj2p;
joi(p1out,true,p1in,true,mj1p);
joi(p1out,false,p1in,false,mj1m);
jio(p2in,true,p2out,true,mj2p);
jio(p2in,false,p2out,false,mj2m);
COM Mmp=cdot(mj1m,mj2p);
COM Mmm=cdot(mj1m,mj2m);
COM Mpp=cdot(mj1p,mj2p);
COM Mpm=cdot(mj1p,mj2m);
double sumsq=abs2(Mmm)+abs2(Mmp)+abs2(Mpp)+abs2(Mpm);
// Multiply by Cf^2
- return (4./3.)*(4./3.)*(sumsq)/(q1.m2()*q2.m2());
+ return C_F*C_F*(sumsq)/(q1.m2()*q2.m2());
}
double jM2qbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
{
CLHEP::HepLorentzVector q1=p1in-p1out;
CLHEP::HepLorentzVector q2=-(p2in-p2out);
current mj1m,mj1p,mj2m,mj2p;
jio(p1in,true,p1out,true,mj1p);
jio(p1in,false,p1out,false,mj1m);
jio(p2in,true,p2out,true,mj2p);
jio(p2in,false,p2out,false,mj2m);
COM Mmp=cdot(mj1m,mj2p);
COM Mmm=cdot(mj1m,mj2m);
COM Mpp=cdot(mj1p,mj2p);
COM Mpm=cdot(mj1p,mj2m);
double sumsq=abs2(Mmm)+abs2(Mmp)+abs2(Mpp)+abs2(Mpm);
// Multiply by Cf^2
- return (4./3.)*(4./3.)*(sumsq)/(q1.m2()*q2.m2());
+ return C_F*C_F*(sumsq)/(q1.m2()*q2.m2());
}
double jM2qg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
// Calculates the square of the current contractions for qg scattering
// p1: quark
// p2: gluon
{
CLHEP::HepLorentzVector q1=p1in-p1out;
CLHEP::HepLorentzVector q2=-(p2in-p2out);
current mj1m,mj1p,mj2m,mj2p;
joi(p1out,true,p1in,true,mj1p);
joi(p1out,false,p1in,false,mj1m);
joi(p2out,true,p2in,true,mj2p);
joi(p2out,false,p2in,false,mj2m);
COM Mmp=cdot(mj1m,mj2p);
COM Mmm=cdot(mj1m,mj2m);
COM Mpp=cdot(mj1p,mj2p);
COM Mpm=cdot(mj1p,mj2m);
const double K = K_g(p2out, p2in);
// sum of spinor strings ||^2
double a2Mmp=abs2(Mmp);
double a2Mmm=abs2(Mmm);
double a2Mpp=abs2(Mpp);
double a2Mpm=abs2(Mpm);
double sst = K/C_A*(a2Mpp+a2Mpm+a2Mmp+a2Mmm);
- // double sstsave=sst;
- // std::cout <<"ratio: "<<sst/sstsave<<std::endl;
// Cf*Ca=4
- return 4.*sst/(q1.m2()*q2.m2());
+ return C_F*C_A*sst/(q1.m2()*q2.m2());
}
double jM2qbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
// Calculates the square of the current contractions for qg scattering
// p1: quark
// p2: gluon
{
CLHEP::HepLorentzVector q1=p1in-p1out;
CLHEP::HepLorentzVector q2=-(p2in-p2out);
current mj1m,mj1p,mj2m,mj2p;
jio(p1in,true,p1out,true,mj1p);
jio(p1in,false,p1out,false,mj1m);
joi(p2out,true,p2in,true,mj2p);
joi(p2out,false,p2in,false,mj2m);
COM Mmp=cdot(mj1m,mj2p);
COM Mmm=cdot(mj1m,mj2m);
COM Mpp=cdot(mj1p,mj2p);
COM Mpm=cdot(mj1p,mj2m);
const double K = K_g(p2out, p2in);
// sum of spinor strings ||^2
double a2Mmp=abs2(Mmp);
double a2Mmm=abs2(Mmm);
double a2Mpp=abs2(Mpp);
double a2Mpm=abs2(Mpm);
double sst = K/C_A*(a2Mpp+a2Mpm+a2Mmp+a2Mmm);
- // double sstsave=sst;
- // std::cout <<"ratio: "<<sst/sstsave<<std::endl;
// Cf*Ca=4
- return 4.*sst/(q1.m2()*q2.m2());
+ return C_F*C_A*sst/(q1.m2()*q2.m2());
}
double jM2gg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in)
// Calculates the square of the current contractions for gg scattering
// p1: gluon
// p2: gluon
{
CLHEP::HepLorentzVector q1=p1in-p1out;
CLHEP::HepLorentzVector q2=-(p2in-p2out);
current mj1m,mj1p,mj2m,mj2p;
joi(p1out,true,p1in,true,mj1p);
joi(p1out,false,p1in,false,mj1m);
joi(p2out,true,p2in,true,mj2p);
joi(p2out,false,p2in,false,mj2m);
COM Mmp=cdot(mj1m,mj2p);
COM Mmm=cdot(mj1m,mj2m);
COM Mpp=cdot(mj1p,mj2p);
COM Mpm=cdot(mj1p,mj2m);
const double K_g1 = K_g(p1out, p1in);
const double K_g2 = K_g(p2out, p2in);
// sum of spinor strings ||^2
double a2Mmp=abs2(Mmp);
double a2Mmm=abs2(Mmm);
double a2Mpp=abs2(Mpp);
double a2Mpm=abs2(Mpm);
double sst = K_g1/C_A*K_g2/C_A*(a2Mpp+a2Mpm+a2Mmp+a2Mmm);
- // double sstsave=sst;
- // std::cout <<"ratio: "<<sst/sstsave<<std::endl;
// Ca*Ca=9
- return 9.*sst/(q1.m2()*q2.m2());
-
+ return C_A*C_A*sst/(q1.m2()*q2.m2());
}
namespace {
- /// @TODO what was this intended to do?
- // double MH2helper(current C1, current C2, current q1, current q2)
- // {
- // COM M;
- // COM temp1,temp2;
- // // First the C1.q2 * C2.q1 - part
- // temp1=cdot(C1,q2);
- // temp2=cdot(C2,q1);
- // M=temp1*temp2;
-
- // // Then the C1.C2 * q1.q2
- // temp1=cdot(C1,C2);
- // temp2=cdot(q1,q2);
- // M-=temp1*temp2;
-
- // return (M*conj(M)).real();
- // }
-
/**
* @brief Higgs vertex contracted with current @param C1 and @param C2
*/
COM cHdot(const current & C1, const current & C2, const current & q1,
const current & q2, double mt, bool incBot, double mb)
{
if (mt == infinity) {
return (cdot(C1,C2)*cdot(q1,q2)-cdot(C1,q2)*cdot(C2,q1))/(6*M_PI*HEJ::vev);
}
else {
CLHEP::HepLorentzVector vq1,vq2;
vq1.set(q1[1].real(),q1[2].real(),q1[3].real(),q1[0].real());
vq2.set(q2[1].real(),q2[2].real(),q2[3].real(),q2[0].real());
// first minus sign obtained because of q1-difference to VDD
// std::cout<<"A1 : " << A1(-vq1,vq2)<<std::endl;
// std::cout<<"A2 : " << A2(-vq1,vq2)<<std::endl;
if(!(incBot))
// Factor is because 4 mt^2 g^2/HEJ::vev A1 -> 16 pi mt^2/HEJ::vev alphas,
// and we divide by a factor 4 at the amp sqaured level later
// which I absorb here (i.e. I divide by 2)
/// @TODO move factor 1/2 from S to |ME|^2 => consistent with general notation
return 8.*M_PI*mt*mt/HEJ::vev*(-cdot(C1,q2)*cdot(C2,q1)*A1(-vq1,vq2,mt)-cdot(C1,C2)*A2(-vq1,vq2,mt));
else
return 8.*M_PI*mt*mt/HEJ::vev*(-cdot(C1,q2)*cdot(C2,q1)*A1(-vq1,vq2,mt)-cdot(C1,C2)*A2(-vq1,vq2,mt))
+ 8.*M_PI*mb*mb/HEJ::vev*(-cdot(C1,q2)*cdot(C2,q1)*A1(-vq1,vq2,mb)-cdot(C1,C2)*A2(-vq1,vq2,mb));
}
}
} // namespace anonymous
double MH2qQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in,
CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in,
CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2,
double mt, bool incBot, double mb)
{
// CLHEP::HepLorentzVector q1=p1in-p1out;
// CLHEP::HepLorentzVector q2=-(p2in-p2out);
current j1p,j1m,j2p,j2m, q1v, q2v;
joi (p1out,true,p1in,true,j1p);
joi (p1out,false,p1in,false,j1m);
joi (p2out,true,p2in,true,j2p);
joi (p2out,false,p2in,false,j2m);
to_current(q1, q1v);
to_current(q2, q2v);
COM Mmp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
COM Mmm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
COM Mpp=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
COM Mpm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
double sst=abs2(Mmp)+abs2(Mmm)+abs2(Mpp)+abs2(Mpm);
// return (4./3.)*(4./3.)*sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
return sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
}
double MH2qQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
{
// CLHEP::HepLorentzVector q1=p1in-p1out;
// CLHEP::HepLorentzVector q2=-(p2in-p2out);
current j1p,j1m,j2p,j2m,q1v,q2v;
joi (p1out,true,p1in,true,j1p);
joi (p1out,false,p1in,false,j1m);
jio (p2in,true,p2out,true,j2p);
jio (p2in,false,p2out,false,j2m);
to_current(q1, q1v);
to_current(q2, q2v);
COM Mmp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
COM Mmm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
COM Mpp=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
COM Mpm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
double sst=abs2(Mmp)+abs2(Mmm)+abs2(Mpp)+abs2(Mpm);
// return (4./3.)*(4./3.)*sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
return sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
}
double MH2qbarQ (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
{
// CLHEP::HepLorentzVector q1=p1in-p1out;
// CLHEP::HepLorentzVector q2=-(p2in-p2out);
current j1p,j1m,j2p,j2m,q1v,q2v;
jio (p1in,true,p1out,true,j1p);
jio (p1in,false,p1out,false,j1m);
joi (p2out,true,p2in,true,j2p);
joi (p2out,false,p2in,false,j2m);
to_current(q1, q1v);
to_current(q2, q2v);
COM Mmp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
COM Mmm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
COM Mpp=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
COM Mpm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
double sst=abs2(Mmp)+abs2(Mmm)+abs2(Mpp)+abs2(Mpm);
// return (4./3.)*(4./3.)*sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
return sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
}
double MH2qbarQbar (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
{
// CLHEP::HepLorentzVector q1=p1in-p1out;
// CLHEP::HepLorentzVector q2=-(p2in-p2out);
current j1p,j1m,j2p,j2m,q1v,q2v;
jio (p1in,true,p1out,true,j1p);
jio (p1in,false,p1out,false,j1m);
jio (p2in,true,p2out,true,j2p);
jio (p2in,false,p2out,false,j2m);
to_current(q1, q1v);
to_current(q2, q2v);
COM Mmp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
COM Mmm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
COM Mpp=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
COM Mpm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
double sst=abs2(Mmp)+abs2(Mmm)+abs2(Mpp)+abs2(Mpm);
// return (4./3.)*(4./3.)*sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
return sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
}
double MH2qg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
// q~p1 g~p2 (i.e. ALWAYS p1 for quark, p2 for gluon)
// should be called with q1 meant to be contracted with p2 in first part of vertex
// (i.e. if g is backward, q1 is forward)
{
current j1p,j1m,j2p,j2m,q1v,q2v;
joi (p1out,true,p1in,true,j1p);
joi (p1out,false,p1in,false,j1m);
joi (p2out,true,p2in,true,j2p);
joi (p2out,false,p2in,false,j2m);
to_current(q1, q1v);
to_current(q2, q2v);
// First, calculate the non-flipping amplitudes:
COM Mpp=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
COM Mpm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
COM Mmp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
COM Mmm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
//cout << "Bits in MH2qg: " << Mpp << " " << Mpm << " " << Mmp << " " << Mmm << endl;
const double K = K_g(p2out, p2in);
double sst=K/C_A*(abs2(Mmp)+abs2(Mmm)+abs2(Mpp)+abs2(Mpm));
// Cf*Ca=4
// return 4.*sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
return sst/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
}
double MH2qbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
// qbar~p1 g~p2 (i.e. ALWAYS p1 for anti-quark, p2 for gluon)
// should be called with q1 meant to be contracted with p2 in first part of vertex
// (i.e. if g is backward, q1 is forward)
{
current j1p,j1m,j2p,j2m,q1v,q2v;
jio (p1in,true,p1out,true,j1p);
jio (p1in,false,p1out,false,j1m);
joi (p2out,true,p2in,true,j2p);
joi (p2out,false,p2in,false,j2m);
to_current(q1, q1v);
to_current(q2, q2v);
// First, calculate the non-flipping amplitudes:
COM amp,amm,apm,app;
app=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
apm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
amp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
amm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
double MH2sum = abs2(app)+abs2(amm)+abs2(apm)+abs2(amp);
const double K = K_g(p2out, p2in);
MH2sum*=K/C_A;
// Cf*Ca=4
// return 4.*MH2sum/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
return MH2sum/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
}
double MH2gg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mt, bool incBot, double mb)
// g~p1 g~p2
// should be called with q1 meant to be contracted with p2 in first part of vertex
// (i.e. if g is backward, q1 is forward)
{
current j1p,j1m,j2p,j2m,q1v,q2v;
joi (p1out,true,p1in,true,j1p);
joi (p1out,false,p1in,false,j1m);
joi (p2out,true,p2in,true,j2p);
joi (p2out,false,p2in,false,j2m);
to_current(q1, q1v);
to_current(q2, q2v);
// First, calculate the non-flipping amplitudes:
COM amp,amm,apm,app;
app=cHdot(j1p,j2p,q1v,q2v,mt, incBot, mb);
apm=cHdot(j1p,j2m,q1v,q2v,mt, incBot, mb);
amp=cHdot(j1m,j2p,q1v,q2v,mt, incBot, mb);
amm=cHdot(j1m,j2m,q1v,q2v,mt, incBot, mb);
double MH2sum = abs2(app)+abs2(amm)+abs2(apm)+abs2(amp);
const double K_g1 = K_g(p1out, p1in);
const double K_g2 = K_g(p2out, p2in);
MH2sum*=K_g1/C_A*K_g2/C_A;
// Ca*Ca=9
// return 9.*MH2sum/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
return MH2sum/((p1in-p1out).m2()*(p2in-p2out).m2()*q1.m2()*q2.m2());
}
// // Z's stuff
// void jZ(HLV pin, HLV pout, HLV pem, HLV pep, bool HelPartons, bool HelLeptons, current cur) {
// // Init current to zero
// cur[0] = 0.0;
// cur[1] = 0.0;
// cur[2] = 0.0;
// cur[3] = 0.0;
// // Temporary variables
// COM temp;
// current Term_1, Term_2, Term_3, Term_4, J_temp, TempCur1, TempCur2;
// // Momentum of virtual gluons aroun weak boson emission site
// HLV qa = pout + pep + pem;
// HLV qb = pin - pep - pem;
// double ta = qa.m2();
// double tb = qb.m2();
// // Out-Out currents:
// current Em_Ep, Out_Em, Out_Ep;
// // Other currents:
// current Out_In, Em_In, Ep_In;
// joi(pout, HelPartons, pin, HelPartons, Out_In);
// joi(pem, HelLeptons, pin, HelPartons, Em_In);
// joi(pep, HelLeptons, pin, HelPartons, Ep_In);
// joo(pem, HelLeptons, pep, HelLeptons, Em_Ep);
// joo(pout, HelPartons, pem, HelLeptons, Out_Em);
// joo(pout, HelPartons, pep, HelLeptons, Out_Ep);
// if (HelLeptons == HelPartons) {
// temp = 2.0 * cdot(pout, Em_Ep);
// cmult(temp / ta, Out_In, Term_1);
// temp = cdot(Out_Em, Em_Ep);
// cmult(temp / ta , Em_In, Term_2);
// temp = 2.0 * cdot(pin, Em_Ep);
// cmult(temp / tb, Out_In, Term_3);
// temp = -cdot(Ep_In, Em_Ep);
// cmult(temp / tb, Out_Ep, Term_4);
// cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
// cur[0] = J_temp[0];
// cur[1] = J_temp[1];
// cur[2] = J_temp[2];
// cur[3] = J_temp[3];
// }
// else {
// if (HelPartons == true) {
// temp = 2.0 * cdot(pout, Em_Ep);
// cmult(temp / ta, Out_In, Term_1);
// joo(pout, true, pep, true, TempCur1);
// joi(pep, true, pin, true, TempCur2);
// temp = cdot(TempCur1, Em_Ep);
// cmult(temp / ta , TempCur2, Term_2);
// temp = 2.0 * cdot(pin, Em_Ep);
// cmult(temp / tb, Out_In, Term_3);
// joo(pout, true, pem, true, TempCur1);
// joi(pem, true, pin, true, TempCur2);
// temp = -cdot(TempCur2, Em_Ep);
// cmult(temp / tb, TempCur1, Term_4);
// cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
// cur[0] = J_temp[0];
// cur[1] = J_temp[1];
// cur[2] = J_temp[2];
// cur[3] = J_temp[3];
// }
// else {
// temp = 2.0 * cdot(pout, Em_Ep);
// cmult(temp / ta, Out_In, Term_1);
// joo(pout, false, pep, false, TempCur1);
// joi(pep, false, pin, false, TempCur2);
// temp = cdot(TempCur1, Em_Ep);
// cmult(temp / ta, TempCur2, Term_2);
// temp = 2.0 * cdot(pin, Em_Ep);
// cmult(temp / tb, Out_In, Term_3);
// joo(pout, false, pem, false, TempCur1);
// joi(pem, false, pin, false, TempCur2);
// temp = -cdot(TempCur2, Em_Ep);
// cmult(temp / tb, TempCur1, Term_4);
// cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
// cur[0] = J_temp[0];
// cur[1] = J_temp[1];
// cur[2] = J_temp[2];
// cur[3] = J_temp[3];
// }
// }
// }
// void jZbar(HLV pin, HLV pout, HLV pem, HLV pep, bool HelPartons, bool HelLeptons, current cur) {
// // Init current to zero
// cur[0] = 0.0;
// cur[1] = 0.0;
// cur[2] = 0.0;
// cur[3] = 0.0;
// // Temporary variables
// COM temp;
// current Term_1, Term_2, Term_3, Term_4, J_temp, TempCur1, TempCur2;
// // Transfered 4-momenta
// HLV qa = pout + pep + pem;
// HLV qb = pin - pep - pem;
// // The square of the transfered 4-momenta
// double ta = qa.m2();
// double tb = qb.m2();
// // Out-Out currents:
// current Em_Ep, Em_Out, Ep_Out;
// // In-Out currents:
// current In_Out, In_Em, In_Ep;
// // Safe to use the currents since helicity structure is ok
// if (HelPartons == HelLeptons) {
// jio(pin, HelPartons, pout, HelPartons, In_Out);
// joo(pem, HelLeptons, pep, HelLeptons, Em_Ep);
// jio(pin, HelPartons, pem, HelLeptons, In_Em);
// jio(pin, HelPartons, pep, HelLeptons, In_Ep);
// joo(pem, HelLeptons, pout, HelPartons, Em_Out);
// joo(pep, HelLeptons, pout, HelPartons, Ep_Out);
// }
// else {
// jio(pin, HelPartons, pout, HelPartons, In_Out);
// joo(pem, HelLeptons, pep, HelLeptons, Em_Ep);
// In_Em[0] = 0.0;
// In_Em[1] = 0.0;
// In_Em[2] = 0.0;
// In_Em[3] = 0.0;
// In_Ep[0] = 0.0;
// In_Ep[1] = 0.0;
// In_Ep[2] = 0.0;
// In_Ep[3] = 0.0;
// Em_Out[0] = 0.0;
// Em_Out[1] = 0.0;
// Em_Out[2] = 0.0;
// Em_Out[3] = 0.0;
// Ep_Out[0] = 0.0;
// Ep_Out[1] = 0.0;
// Ep_Out[2] = 0.0;
// Ep_Out[3] = 0.0;
// }
// if (HelLeptons == HelPartons) {
// temp = 2.0 * cdot(pout, Em_Ep);
// cmult(temp / ta, In_Out, Term_1);
// temp = cdot(Ep_Out, Em_Ep);
// cmult(temp / ta, In_Ep, Term_2);
// temp = 2.0 * cdot(pin, Em_Ep);
// cmult(temp / tb, In_Out, Term_3);
// temp = - cdot(In_Em, Em_Ep);
// cmult(temp / tb, Em_Out, Term_4);
// cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
// cur[0] = J_temp[0];
// cur[1] = J_temp[1];
// cur[2] = J_temp[2];
// cur[3] = J_temp[3];
// }
// else {
// if (HelPartons == true) {
// temp = 2.0 * cdot(pout, Em_Ep);
// cmult(temp / ta, In_Out, Term_1);
// joo(pem, true, pout, true, TempCur1);
// jio(pin, true, pem, true, TempCur2);
// temp = cdot(TempCur1, Em_Ep);
// cmult(temp / ta , TempCur2, Term_2);
// temp = 2.0 * cdot(pin, Em_Ep);
// cmult(temp / tb, In_Out, Term_3);
// joo(pep, true, pout, true, TempCur1);
// jio(pin, true, pep, true, TempCur2);
// temp = - cdot(TempCur2, Em_Ep);
// cmult(temp / tb, TempCur1, Term_4);
// cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
// cur[0] = J_temp[0];
// cur[1] = J_temp[1];
// cur[2] = J_temp[2];
// cur[3] = J_temp[3];
// }
// else {
// temp = 2.0 * cdot(pout, Em_Ep);
// cmult(temp / ta, In_Out, Term_1);
// joo(pem, false, pout, false, TempCur1);
// jio(pin, false, pem, false, TempCur2);
// temp = cdot(TempCur1, Em_Ep);
// cmult(temp / ta , TempCur2, Term_2);
// temp = 2.0 * cdot(pin, Em_Ep);
// cmult(temp / tb, In_Out, Term_3);
// joo(pep, false, pout, false, TempCur1);
// jio(pin, false, pep, false, TempCur2);
// temp = - cdot(TempCur2, Em_Ep);
// cmult(temp / tb, TempCur1, Term_4);
// cadd(Term_1, Term_2, Term_3, Term_4, J_temp);
// cur[0] = J_temp[0];
// cur[1] = J_temp[1];
// cur[2] = J_temp[2];
// cur[3] = J_temp[3];
// }
// }
// }
// // Progagators
// COM PZ(double s) {
// double MZ, GammaZ;
// MZ = 9.118800e+01; // Mass of the mediating gauge boson
// GammaZ = 2.441404e+00; // Z peak width
// // Return Z Prop value
// return 1.0 / (s - MZ * MZ + COM(0.0, 1.0) * GammaZ * MZ);
// }
// COM PG(double s) {
// return 1.0 / s;
// }
// // Non-gluonic with pa emitting
// std::vector <double> jMZqQ (HLV pa, HLV pb, HLV p1, HLV p2, HLV pep, HLV pem, std::vector <double> VProducts, std::vector < std::vector <double> > Virtuals, int aptype, int bptype, bool UseVirtuals, bool BottomLineEmit) {
// std::vector <double> ScaledWeights;
// double Sum;
// // Propagator factors
// COM PZs = PZ((pep + pem).m2());
// COM PGs = PG((pep + pem).m2());
// // Emitting current initialisation
// current j1pptop, j1pmtop; // Emission from top line
// current j1ppbot, j1pmbot; // Emission from bottom line
// // Non-emitting current initialisation
// current j2ptop, j2mtop; // Emission from top line
// current j2pbot, j2mbot; // Emission from bottom line
// // Currents for top emission
// // Upper current calculations
// // if a is a quark
// if (aptype > 0) {
// jZ(pa, p1, pem, pep, true, true, j1pptop);
// jZ(pa, p1, pem, pep, true, false, j1pmtop);
// }
// // if a is an antiquark
// else {
// jZbar(pa, p1, pem, pep, true, true, j1pptop);
// jZbar(pa, p1, pem, pep, true, false, j1pmtop);
// }
// // Lower current calculations
// // if b is a quark
// if (bptype > 0) {
// joi(p2, true, pb, true, j2ptop);
// joi(p2, false, pb, false, j2mtop);
// }
// // if b is an antiquark
// else {
// jio(pb, true, p2, true, j2ptop);
// jio(pb, false, p2, false, j2mtop);
// }
// // Currents for bottom emission
// // Lower current calculations
// if (bptype > 0) {
// jZ(pb, p2, pem, pep, true, true, j1ppbot);
// jZ(pb, p2, pem, pep, true, false, j1pmbot);
// }
// else {
// jZbar(pb, p2, pem, pep, true, true, j1ppbot);
// jZbar(pb, p2, pem, pep, true, false, j1pmbot);
// }
// // Upper current calculations
// if (aptype > 0) {
// joi(p1, true, pa, true, j2pbot);
// joi(p1, false, pa, false, j2mbot);
// }
// else {
// jio(pa, true, p1, true, j2pbot);
// jio(pa, false, p1, false, j2mbot);
// }
// COM Coeff[2][8];
// if (!Interference) {
// double ZCharge_a_P = Zq(aptype, true);
// double ZCharge_a_M = Zq(aptype, false);
// double ZCharge_b_P = Zq(bptype, true);
// double ZCharge_b_M = Zq(bptype, false);
// if (BottomLineEmit) {
// // Emission from top-line quark (pa/p1 line)
// Coeff[0][0] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pptop, j2ptop);
// Coeff[0][1] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pptop, j2mtop);
// Coeff[0][2] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pmtop, j2ptop);
// Coeff[0][3] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pmtop, j2mtop);
// Coeff[0][4] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2ptop));
// Coeff[0][5] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2mtop));
// Coeff[0][6] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2ptop));
// Coeff[0][7] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2mtop));
// }
// else {
// // Emission from bottom-line quark (pb/p2 line)
// Coeff[1][0] = (ZCharge_b_P * Zep * PZs * RWeak + Gq(bptype) * PGs) * cdot(j1ppbot, j2pbot);
// Coeff[1][7] = (ZCharge_b_P * Zep * PZs * RWeak + Gq(bptype) * PGs) * cdot(j1ppbot, j2mbot);
// Coeff[1][2] = (ZCharge_b_P * Zem * PZs * RWeak + Gq(bptype) * PGs) * cdot(j1pmbot, j2pbot);
// Coeff[1][5] = (ZCharge_b_P * Zem * PZs * RWeak + Gq(bptype) * PGs) * cdot(j1pmbot, j2mbot);
// Coeff[1][4] = (ZCharge_b_M * Zem * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1ppbot, j2pbot));
// Coeff[1][3] = (ZCharge_b_M * Zem * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1ppbot, j2mbot));
// Coeff[1][6] = (ZCharge_b_M * Zep * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1pmbot, j2pbot));
// Coeff[1][1] = (ZCharge_b_M * Zep * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1pmbot, j2mbot));
// }
// }
// // Else calculate all the possiblities
// else {
// double ZCharge_a_P = Zq(aptype, true);
// double ZCharge_a_M = Zq(aptype, false);
// double ZCharge_b_P = Zq(bptype, true);
// double ZCharge_b_M = Zq(bptype, false);
// // Emission from top-line quark (pa/p1 line)
// Coeff[0][0] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pptop, j2ptop);
// Coeff[0][1] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pptop, j2mtop);
// Coeff[0][2] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pmtop, j2ptop);
// Coeff[0][3] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pmtop, j2mtop);
// Coeff[0][4] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2ptop));
// Coeff[0][5] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2mtop));
// Coeff[0][6] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2ptop));
// Coeff[0][7] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2mtop));
// // Emission from bottom-line quark (pb/p2 line)
// Coeff[1][0] = (ZCharge_b_P * Zep * PZs * RWeak + Gq(bptype) * PGs) * cdot(j1ppbot, j2pbot);
// Coeff[1][7] = (ZCharge_b_P * Zep * PZs * RWeak + Gq(bptype) * PGs) * cdot(j1ppbot, j2mbot);
// Coeff[1][2] = (ZCharge_b_P * Zem * PZs * RWeak + Gq(bptype) * PGs) * cdot(j1pmbot, j2pbot);
// Coeff[1][5] = (ZCharge_b_P * Zem * PZs * RWeak + Gq(bptype) * PGs) * cdot(j1pmbot, j2mbot);
// Coeff[1][4] = (ZCharge_b_M * Zem * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1ppbot, j2pbot));
// Coeff[1][3] = (ZCharge_b_M * Zem * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1ppbot, j2mbot));
// Coeff[1][6] = (ZCharge_b_M * Zep * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1pmbot, j2pbot));
// Coeff[1][1] = (ZCharge_b_M * Zep * PZs * RWeak + Gq(bptype) * PGs) * conj(cdot(j1pmbot, j2mbot));
// }
// // Find the numbers of scales
// int ScaleCount;
// #if calcscaleunc
// ScaleCount = 20;
// #else
// ScaleCount = 1;
// #endif
// // For each scale...
// for (int j = 0; j < ScaleCount; j++) {
// Sum = 0.0;
// // If we want to compare back to the W's code only emit from one quark and only couple to left handed particles
// // virtuals arent here since they are calculated and included in weight() call.
// if (!Interference) {
// if (BottomLineEmit) for (int i = 0; i < 8; i++) Sum += abs2(Coeff[1][i]) * VProducts.at(1);
// else for (int i = 0; i < 8; i++) Sum += abs2(Coeff[0][i]) * VProducts.at(0);
// }
// // Else work out the full interference
// else {
// // For the full calculation...
// if (UseVirtuals) {
// for (int i = 0; i < 8; i++) {
// Sum += abs2(Coeff[0][i]) * VProducts.at(0) * Virtuals.at(j).at(0)
// + abs2(Coeff[1][i]) * VProducts.at(1) * Virtuals.at(j).at(1)
// + 2.0 * real(Coeff[0][i] * conj(Coeff[1][i])) * VProducts.at(2) * Virtuals.at(j).at(2);
// }
// }
// // For the tree level calculation...
// else {
// for (int i = 0; i < 8; i++) {
// Sum += abs2(Coeff[0][i]) * VProducts.at(0)
// + abs2(Coeff[1][i]) * VProducts.at(1)
// + 2.0 * real(Coeff[0][i] * conj(Coeff[1][i])) * VProducts.at(2);
// }
// }
// }
// // Add this to the vector to be returned with the other factors of C_A and the helicity sum/average factors.
// ScaledWeights.push_back(Sum / 18.0);
// }
// // Return all the scale values
// return ScaledWeights;
// }
// // Semi-gluonic with pa emitting
// std::vector <double> jMZqg (HLV pa, HLV pb, HLV p1, HLV p2, HLV pep, HLV pem, std::vector <double> VProducts, std::vector < std::vector <double> > Virtuals, int aptype, int bptype, bool UseVirtuals, bool BottomLineEmit) {
// COM Coeff[8];
// double Sum;
// std::vector <double> ScaledWeights;
// COM PZs = PZ((pep + pem).m2());
// COM PGs = PG((pep + pem).m2());
// // Emitting current initialisation - Emission from top line
// current j1pptop, j1pmtop;
// // Non-emitting current initialisation - Emission from top line
// current j2ptop, j2mtop;
// // Currents for top emission
// // Upper current calculations
// if (aptype > 0) {
// jZ (pa, p1, pem, pep, true, true, j1pptop);
// jZ (pa, p1, pem, pep, true, false, j1pmtop);
// }
// else {
// jZbar(pa, p1, pem, pep, true, true, j1pptop);
// jZbar(pa, p1, pem, pep, true, false, j1pmtop);
// }
// // Lower current calculations
// joi(p2, true, pb, true, j2ptop);
// joi(p2, false, pb, false, j2mtop);
// // Calculate all the possiblities
// double ZCharge_a_P = Zq(aptype, true);
// double ZCharge_a_M = Zq(aptype, false);
// // Emission from top-line quark (pa/p1 line)
// Coeff[0] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pptop, j2ptop);
// Coeff[1] = (ZCharge_a_P * Zep * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pptop, j2mtop);
// Coeff[2] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pmtop, j2ptop);
// Coeff[3] = (ZCharge_a_P * Zem * PZs * RWeak + Gq(aptype) * PGs) * cdot(j1pmtop, j2mtop);
// Coeff[4] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2ptop));
// Coeff[5] = (ZCharge_a_M * Zem * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pptop, j2mtop));
// Coeff[6] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2ptop));
// Coeff[7] = (ZCharge_a_M * Zep * PZs * RWeak + Gq(aptype) * PGs) * conj(cdot(j1pmtop, j2mtop));
// // Calculate gluon colour accelerated factor
// double CAMFactor, z;
// // If b is a forward moving gluon define z (C.F. multiple jets papers)
// if (pb.pz() > 0) z = p2.plus() / pb.plus();
// else z = p2.minus() / pb.minus();
// CAMFactor = (1.0 - 1.0 / 9.0) / 2.0 * (z + 1.0 / z) + 1.0 / 9.0;
// // Find the numbers of scales
// int ScaleCount;
// #if calcscaleunc
// ScaleCount = 20;
// #else
// ScaleCount = 1;
// #endif
// // For each scale...
// for (int j = 0; j < ScaleCount; j++) {
// Sum = 0.0;
// // If we dont want the interference
// if (!Interference) for (int i = 0; i < 8; i++) Sum += abs2(Coeff[i]) * VProducts.at(0);
// // Else work out the full interference
// else {
// if (UseVirtuals) {
// for (int i = 0; i < 8; i++) Sum += abs2(Coeff[i]) * VProducts.at(0) * Virtuals.at(j).at(0);
// }
// else {
// for (int i = 0; i < 8; i++) Sum += abs2(Coeff[i]) * VProducts.at(0);
// }
// }
// // Add this to the vector to be returned with the other factors of C_A, the colour accelerated factor and the helicity sum/average factors.: (4/3)*3/32
// ScaledWeights.push_back(CAMFactor * Sum / 8.0);
// }
// return ScaledWeights;
// }
// // Electroweak Charge Functions
// double Zq (int PID, bool Helcitiy) {
// double temp;
// // Positive Spin
// if (Helcitiy == true) {
// if (PID == 1 || PID == 3 || PID == 5) temp = (+ 1.0 * stw2 / 3.0) / ctw;
// if (PID == 2 || PID == 4) temp = (- 2.0 * stw2 / 3.0) / ctw;
// if (PID == -1 || PID == -3 || PID == -5) temp = (- 1.0 * stw2 / 3.0) / ctw;
// if (PID == -2 || PID == -4) temp = (+ 2.0 * stw2 / 3.0) / ctw;
// // If electron or positron
// if (PID == 7 || PID == -7) temp = Zep;
// }
// // Negative Spin
// else {
// if (PID == 1 || PID == 3 || PID == 5) temp = (-0.5 + 1.0 * stw2 / 3.0) / ctw;
// if (PID == 2 || PID == 4) temp = ( 0.5 - 2.0 * stw2 / 3.0) / ctw;
// if (PID == -1 || PID == -3 || PID == -5) temp = ( 0.5 - 1.0 * stw2 / 3.0) / ctw;
// if (PID == -2 || PID == -4) temp = (-0.5 + 2.0 * stw2 / 3.0) / ctw;
// // If electron or positron
// if (PID == 7 || PID == -7) temp = Zem;
// }
// return temp;
// }
// double Gq (int PID) {
// if (!VirtualPhoton) return 0.0;
// if (PID == -1) return 1.0 * ee / 3.0;
// if (PID == -2) return -2.0 * ee / 3.0;
// if (PID == -3) return 1.0 * ee / 3.0;
// if (PID == -4) return -2.0 * ee / 3.0;
// if (PID == -5) return 1.0 * ee / 3.0;
// if (PID == 1) return -1.0 * ee / 3.0;
// if (PID == 2) return 2.0 * ee / 3.0;
// if (PID == 3) return -1.0 * ee / 3.0;
// if (PID == 4) return 2.0 * ee / 3.0;
// if (PID == 5) return -1.0 * ee / 3.0;
// std::cout << "ERROR! No Electroweak Charge Found at line " << __LINE__ << "..." << std::endl;
// return 0.0;
// }
namespace {
//@{
/// @brief Higgs vertex contracted with one current
CCurrent jH (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin,
bool helin, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2,
double mt, bool incBot, double mb)
{
CCurrent j2 = joi(pout,helout,pin,helin);
CCurrent jq2(q2.e(),q2.px(),q2.py(),q2.pz());
if(mt == infinity)
return ((q1.dot(q2))*j2 - j2.dot(q1)*jq2)/(3*M_PI*HEJ::vev);
else
{
if(incBot)
return (-16.*M_PI*mb*mb/HEJ::vev*j2.dot(q1)*jq2*A1(-q1,q2,mb)-16.*M_PI*mb*mb/HEJ::vev*j2*A2(-q1,q2,mb))
+ (-16.*M_PI*mt*mt/HEJ::vev*j2.dot(q1)*jq2*A1(-q1,q2,mt)-16.*M_PI*mt*mt/HEJ::vev*j2*A2(-q1,q2,mt));
else
return (-16.*M_PI*mt*mt/HEJ::vev*j2.dot(q1)*jq2*A1(-q1,q2,mt)-16.*M_PI*mt*mt/HEJ::vev*j2*A2(-q1,q2,mt));
}
}
CCurrent jioH (CLHEP::HepLorentzVector pin, bool helin, CLHEP::HepLorentzVector pout,
bool helout, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2,
double mt, bool incBot, double mb)
{
CCurrent j2 = jio(pin,helin,pout,helout);
CCurrent jq2(q2.e(),q2.px(),q2.py(),q2.pz());
if(mt == infinity)
return ((q1.dot(q2))*j2 - j2.dot(q1)*jq2)/(3*M_PI*HEJ::vev);
else
{
if(incBot)
return (-16.*M_PI*mb*mb/HEJ::vev*j2.dot(q1)*jq2*A1(-q1,q2,mb)-16.*M_PI*mb*mb/HEJ::vev*j2*A2(-q1,q2,mb))
+ (-16.*M_PI*mt*mt/HEJ::vev*j2.dot(q1)*jq2*A1(-q1,q2,mt)-16.*M_PI*mt*mt/HEJ::vev*j2*A2(-q1,q2,mt));
else
return (-16.*M_PI*mt*mt/HEJ::vev*j2.dot(q1)*jq2*A1(-q1,q2,mt)-16.*M_PI*mt*mt/HEJ::vev*j2*A2(-q1,q2,mt));
}
}
CCurrent jHtop (CLHEP::HepLorentzVector pout, bool helout, CLHEP::HepLorentzVector pin,
bool helin, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2,
double mt, bool incBot, double mb)
{
CCurrent j1 = joi(pout,helout,pin,helin);
CCurrent jq1(q1.e(),q1.px(),q1.py(),q1.pz());
if(mt == infinity)
return ((q1.dot(q2))*j1 - j1.dot(q2)*jq1)/(3*M_PI*HEJ::vev);
else
{
if(incBot)
return (-16.*M_PI*mb*mb/HEJ::vev*j1.dot(q2)*jq1*A1(-q1,q2,mb)-16.*M_PI*mb*mb/HEJ::vev*j1*A2(-q1,q2,mb))
+ (-16.*M_PI*mt*mt/HEJ::vev*j1.dot(q2)*jq1*A1(-q1,q2,mt)-16.*M_PI*mt*mt/HEJ::vev*j1*A2(-q1,q2,mt));
else
return (-16.*M_PI*mt*mt/HEJ::vev*j1.dot(q2)*jq1*A1(-q1,q2,mt)-16.*M_PI*mt*mt/HEJ::vev*j1*A2(-q1,q2,mt));
}
}
CCurrent jioHtop (CLHEP::HepLorentzVector pin, bool helin, CLHEP::HepLorentzVector pout,
bool helout, CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2,
double mt, bool incBot, double mb)
{
CCurrent j1 = jio(pin,helin,pout,helout);
CCurrent jq1(q1.e(),q1.px(),q1.py(),q1.pz());
if(mt == infinity)
return ((q1.dot(q2))*j1 - j1.dot(q2)*jq1)/(3*M_PI*HEJ::vev);
else
{
if(incBot)
return (-16.*M_PI*mb*mb/HEJ::vev*j1.dot(q2)*jq1*A1(-q1,q2,mb)-16.*M_PI*mb*mb/HEJ::vev*j1*A2(-q1,q2,mb))
+ (-16.*M_PI*mt*mt/HEJ::vev*j1.dot(q2)*jq1*A1(-q1,q2,mt)-16.*M_PI*mt*mt/HEJ::vev*j1*A2(-q1,q2,mt));
else
return (-16.*M_PI*mt*mt/HEJ::vev*j1.dot(q2)*jq1*A1(-q1,q2,mt)-16.*M_PI*mt*mt/HEJ::vev*j1*A2(-q1,q2,mt));
}
}
//@}
} // namespace anonymous
double jM2unogqHQ (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
// This construction is taking rapidity order: pg > p1out >> p2out
// std::cerr<<"This Uno Current: "<<p1out<<" "<<p1in<<" "<<p2out<<" "<<p2in<<" "<<pg<<std::endl;
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out); // Bottom End
CLHEP::HepLorentzVector qg=p1in-p1out-pg; // Extra bit post-gluon
// std::cerr<<"Current: "<<q1.m2()<<" "<<q2.m2()<<std::endl;
CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
mj1p=joi(p1out,true,p1in,true);
mj1m=joi(p1out,false,p1in,false);
mjH2p=jH(p2out,true,p2in,true,qH1,qH2, mt, incBot, mb);
mjH2m=jH(p2out,false,p2in,false,qH1,qH2, mt, incBot, mb);
// Dot products of these which occur again and again
COM MHmp=mj1m.dot(mjH2p); // And now for the Higgs ones
COM MHmm=mj1m.dot(mjH2m);
COM MHpp=mj1p.dot(mjH2p);
COM MHpm=mj1p.dot(mjH2m);
// std::cout<< p1out.rapidity() << " " << p2out.rapidity()<< " " << qH1 << " " << qH2 << "\n" <<MHmm << " " << MHmp << " " << MHpm << " " << MHpp << std::endl;
// Currents with pg
CCurrent jgam,jgap,j2gm,j2gp;
j2gp=joo(p1out,true,pg,true);
j2gm=joo(p1out,false,pg,false);
jgap=joi(pg,true,p1in,true);
jgam=joi(pg,false,p1in,false);
CCurrent qsum(q1+qg);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
CCurrent p1o(p1out);
CCurrent p1i(p1in);
Lmm=(qsum*(MHmm) + (-2.*mjH2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmm/2.))/q1.m2();
Lmp=(qsum*(MHmp) + (-2.*mjH2p.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmp/2.))/q1.m2();
Lpm=(qsum*(MHpm) + (-2.*mjH2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpm/2.))/q1.m2();
Lpp=(qsum*(MHpp) + (-2.*mjH2p.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpp/2.))/q1.m2();
U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
double ampsq=-(amm+amp+apm+app)/(q2.m2()*qH2.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
double th=qH1.m2()*qg.m2();
ampsq/=th;
ampsq/=16.;
ampsq*=HEJ::C_F*HEJ::C_F/HEJ::C_A/HEJ::C_A; // Factor of (Cf/Ca) for each quark to match MH2qQ.
//Higgs coupling is included in Hjets.C
return ampsq;
}
double jM2unogqbarHQ (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
// This construction is taking rapidity order: pg > p1out >> p2out
// std::cerr<<"This Uno Current: "<<p1out<<" "<<p1in<<" "<<p2out<<" "<<p2in<<" "<<pg<<std::endl;
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out); // Bottom End
CLHEP::HepLorentzVector qg=p1in-p1out-pg; // Extra bit post-gluon
// std::cerr<<"Current: "<<q1.m2()<<" "<<q2.m2()<<std::endl;
CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
mj1p=jio(p1in,true,p1out,true);
mj1m=jio(p1in,false,p1out,false);
mjH2p=jH(p2out,true,p2in,true,qH1,qH2, mt, incBot, mb);
mjH2m=jH(p2out,false,p2in,false,qH1,qH2, mt, incBot, mb);
// Dot products of these which occur again and again
COM MHmp=mj1m.dot(mjH2p); // And now for the Higgs ones
COM MHmm=mj1m.dot(mjH2m);
COM MHpp=mj1p.dot(mjH2p);
COM MHpm=mj1p.dot(mjH2m);
// Currents with pg
CCurrent jgam,jgap,j2gm,j2gp;
j2gp=joo(pg,true,p1out,true);
j2gm=joo(pg,false,p1out,false);
jgap=jio(p1in,true,pg,true);
jgam=jio(p1in,false,pg,false);
CCurrent qsum(q1+qg);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
CCurrent p1o(p1out);
CCurrent p1i(p1in);
Lmm=(qsum*(MHmm) + (-2.*mjH2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmm/2.))/q1.m2();
Lmp=(qsum*(MHmp) + (-2.*mjH2p.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmp/2.))/q1.m2();
Lpm=(qsum*(MHpm) + (-2.*mjH2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpm/2.))/q1.m2();
Lpp=(qsum*(MHpp) + (-2.*mjH2p.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpp/2.))/q1.m2();
U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
double ampsq=-(amm+amp+apm+app)/(q2.m2()*qH2.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
double th=qH1.m2()*qg.m2();
ampsq/=th;
ampsq/=16.;
ampsq*=4.*4./(9.*9.); // Factor of (Cf/Ca) for each quark to match MH2qQ.
//Higgs coupling is included in Hjets.C
return ampsq;
}
double jM2unogqHQbar (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
// This construction is taking rapidity order: pg > p1out >> p2out
// std::cerr<<"This Uno Current: "<<p1out<<" "<<p1in<<" "<<p2out<<" "<<p2in<<" "<<pg<<std::endl;
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out); // Bottom End
CLHEP::HepLorentzVector qg=p1in-p1out-pg; // Extra bit post-gluon
// std::cerr<<"Current: "<<q1.m2()<<" "<<q2.m2()<<std::endl;
CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
mj1p=joi(p1out,true,p1in,true);
mj1m=joi(p1out,false,p1in,false);
mjH2p=jioH(p2in,true,p2out,true,qH1,qH2, mt, incBot, mb);
mjH2m=jioH(p2in,false,p2out,false,qH1,qH2, mt, incBot, mb);
// Dot products of these which occur again and again
COM MHmp=mj1m.dot(mjH2p); // And now for the Higgs ones
COM MHmm=mj1m.dot(mjH2m);
COM MHpp=mj1p.dot(mjH2p);
COM MHpm=mj1p.dot(mjH2m);
// Currents with pg
CCurrent jgam,jgap,j2gm,j2gp;
j2gp=joo(p1out,true,pg,true);
j2gm=joo(p1out,false,pg,false);
jgap=joi(pg,true,p1in,true);
jgam=joi(pg,false,p1in,false);
CCurrent qsum(q1+qg);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
CCurrent p1o(p1out);
CCurrent p1i(p1in);
Lmm=(qsum*(MHmm) + (-2.*mjH2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmm/2.))/q1.m2();
Lmp=(qsum*(MHmp) + (-2.*mjH2p.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmp/2.))/q1.m2();
Lpm=(qsum*(MHpm) + (-2.*mjH2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpm/2.))/q1.m2();
Lpp=(qsum*(MHpp) + (-2.*mjH2p.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpp/2.))/q1.m2();
U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
double ampsq=-(amm+amp+apm+app)/(q2.m2()*qH2.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
double th=qH1.m2()*qg.m2();
ampsq/=th;
ampsq/=16.;
ampsq*=4.*4./(9.*9.); // Factor of (Cf/Ca) for each quark to match MH2qQ.
//Higgs coupling is included in Hjets.C
return ampsq;
}
double jM2unogqbarHQbar (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
// This construction is taking rapidity order: pg > p1out >> p2out
// std::cerr<<"This Uno Current: "<<p1out<<" "<<p1in<<" "<<p2out<<" "<<p2in<<" "<<pg<<std::endl;
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out); // Bottom End
CLHEP::HepLorentzVector qg=p1in-p1out-pg; // Extra bit post-gluon
// std::cerr<<"Current: "<<q1.m2()<<" "<<q2.m2()<<std::endl;
CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
mj1p=jio(p1in,true,p1out,true);
mj1m=jio(p1in,false,p1out,false);
mjH2p=jioH(p2in,true,p2out,true,qH1,qH2, mt, incBot, mb);
mjH2m=jioH(p2in,false,p2out,false,qH1,qH2, mt, incBot, mb);
// Dot products of these which occur again and again
COM MHmp=mj1m.dot(mjH2p); // And now for the Higgs ones
COM MHmm=mj1m.dot(mjH2m);
COM MHpp=mj1p.dot(mjH2p);
COM MHpm=mj1p.dot(mjH2m);
// Currents with pg
CCurrent jgam,jgap,j2gm,j2gp;
j2gp=joo(pg,true,p1out,true);
j2gm=joo(pg,false,p1out,false);
jgap=jio(p1in,true,pg,true);
jgam=jio(p1in,false,pg,false);
CCurrent qsum(q1+qg);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
CCurrent p1o(p1out);
CCurrent p1i(p1in);
Lmm=(qsum*(MHmm) + (-2.*mjH2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmm/2.))/q1.m2();
Lmp=(qsum*(MHmp) + (-2.*mjH2p.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmp/2.))/q1.m2();
Lpm=(qsum*(MHpm) + (-2.*mjH2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpm/2.))/q1.m2();
Lpp=(qsum*(MHpp) + (-2.*mjH2p.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpp/2.))/q1.m2();
U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
double ampsq=-(amm+amp+apm+app)/(q2.m2()*qH2.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
double th=qH1.m2()*qg.m2();
ampsq/=th;
ampsq/=16.;
//Higgs coupling is included in Hjets.C
ampsq*=4.*4./(9.*9.); // Factor of (Cf/Ca) for each quark to match MH2qQ.
return ampsq;
}
double jM2unogqHg (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
// This construction is taking rapidity order: pg > p1out >> p2out
// std::cerr<<"This Uno Current: "<<p1out<<" "<<p1in<<" "<<p2out<<" "<<p2in<<" "<<pg<<std::endl;
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out); // Bottom End
CLHEP::HepLorentzVector qg=p1in-p1out-pg; // Extra bit post-gluon
CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
mj1p=joi(p1out,true,p1in,true);
mj1m=joi(p1out,false,p1in,false);
mjH2p=jH(p2out,true,p2in,true,qH1,qH2, mt, incBot, mb);
mjH2m=jH(p2out,false,p2in,false,qH1,qH2, mt, incBot, mb);
// Dot products of these which occur again and again
COM MHmp=mj1m.dot(mjH2p); // And now for the Higgs ones
COM MHmm=mj1m.dot(mjH2m);
COM MHpp=mj1p.dot(mjH2p);
COM MHpm=mj1p.dot(mjH2m);
// Currents with pg
CCurrent jgam,jgap,j2gm,j2gp;
j2gp=joo(p1out,true,pg,true);
j2gm=joo(p1out,false,pg,false);
jgap=joi(pg,true,p1in,true);
jgam=joi(pg,false,p1in,false);
CCurrent qsum(q1+qg);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
CCurrent p1o(p1out);
CCurrent p1i(p1in);
Lmm=(qsum*(MHmm) + (-2.*mjH2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmm/2.))/q1.m2();
Lmp=(qsum*(MHmp) + (-2.*mjH2p.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmp/2.))/q1.m2();
Lpm=(qsum*(MHpm) + (-2.*mjH2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpm/2.))/q1.m2();
Lpp=(qsum*(MHpp) + (-2.*mjH2p.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpp/2.))/q1.m2();
U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
double ampsq=-(amm+amp+apm+app)/(q2.m2()*qH2.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
double th=qH1.m2()*qg.m2();
ampsq/=th;
ampsq/=16.;
ampsq*=4./9.*4./9.; // Factor of (Cf/Ca) for each quark to match MH2qQ.
// here we need 2 to match with the normalization
// gq is 9./4. times the qQ
//Higgs coupling is included in Hjets.C
const double K = K_g(p2out, p2in);
return ampsq*K/C_A*9./4.; //ca/cf = 9/4
}
double jM2unogqbarHg (CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
// This construction is taking rapidity order: pg > p1out >> p2out
// std::cerr<<"This Uno Current: "<<p1out<<" "<<p1in<<" "<<p2out<<" "<<p2in<<" "<<pg<<std::endl;
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out); // Bottom End
CLHEP::HepLorentzVector qg=p1in-p1out-pg; // Extra bit post-gluon
CCurrent mj1m,mj1p,mj2m,mj2p,mjH2m,mjH2p;
mj1p=jio(p1in,true,p1out,true);
mj1m=jio(p1in,false,p1out,false);
mjH2p=jH(p2out,true,p2in,true,qH1,qH2, mt, incBot, mb);
mjH2m=jH(p2out,false,p2in,false,qH1,qH2, mt, incBot, mb);
// Dot products of these which occur again and again
COM MHmp=mj1m.dot(mjH2p); // And now for the Higgs ones
COM MHmm=mj1m.dot(mjH2m);
COM MHpp=mj1p.dot(mjH2p);
COM MHpm=mj1p.dot(mjH2m);
// Currents with pg
CCurrent jgam,jgap,j2gm,j2gp;
j2gp=joo(pg,true,p1out,true);
j2gm=joo(pg,false,p1out,false);
jgap=jio(p1in,true,pg,true);
jgam=jio(p1in,false,pg,false);
CCurrent qsum(q1+qg);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p2o(p2out),p2i(p2in);
CCurrent p1o(p1out);
CCurrent p1i(p1in);
Lmm=(qsum*(MHmm) + (-2.*mjH2m.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmm/2.))/q1.m2();
Lmp=(qsum*(MHmp) + (-2.*mjH2p.dot(pg))*mj1m+2.*mj1m.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHmp/2.))/q1.m2();
Lpm=(qsum*(MHpm) + (-2.*mjH2m.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2m+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpm/2.))/q1.m2();
Lpp=(qsum*(MHpp) + (-2.*mjH2p.dot(pg))*mj1p+2.*mj1p.dot(pg)*mjH2p+(p2o/pg.dot(p2out) + p2i/pg.dot(p2in))*(qg.m2()*MHpp/2.))/q1.m2();
U1mm=(jgam.dot(mjH2m)*j2gm+2.*p1o*MHmm)/(p1out+pg).m2();
U1mp=(jgam.dot(mjH2p)*j2gm+2.*p1o*MHmp)/(p1out+pg).m2();
U1pm=(jgap.dot(mjH2m)*j2gp+2.*p1o*MHpm)/(p1out+pg).m2();
U1pp=(jgap.dot(mjH2p)*j2gp+2.*p1o*MHpp)/(p1out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH2m)*jgam+2.*p1i*MHmm)/(p1in-pg).m2();
U2mp=((-1.)*j2gm.dot(mjH2p)*jgam+2.*p1i*MHmp)/(p1in-pg).m2();
U2pm=((-1.)*j2gp.dot(mjH2m)*jgap+2.*p1i*MHpm)/(p1in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH2p)*jgap+2.*p1i*MHpp)/(p1in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
double ampsq=-(amm+amp+apm+app)/(q2.m2()*qH2.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
double th=qH1.m2()*qg.m2();
ampsq/=th;
ampsq/=16.;
ampsq*=4./9.*4./9.; // Factor of (Cf/Ca) for each quark to match MH2qQ.
// here we need 2 to match with the normalization
// gq is 9./4. times the qQ
//Higgs coupling is included in Hjets.C
const double K = K_g(p2out, p2in);
return ampsq*K/C_F;
}
double jM2unobqHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
// std::cout << "####################\n";
// std::cout << "# p1in : "<<p1in<< " "<<p1in.plus()<<" "<<p1in.minus()<<std::endl;
// std::cout << "# p2in : "<<p2in<< " "<<p2in.plus()<<" "<<p2in.minus()<<std::endl;
// std::cout << "# p1out : "<<p1out<< " "<<p1out.rapidity()<<std::endl;
// std::cout << "# (qH1-qH2) : "<<(qH1-qH2)<< " "<<(qH1-qH2).rapidity()<<std::endl;
// std::cout << "# pg : "<<pg<< " "<<pg.rapidity()<<std::endl;
// std::cout << "# p2out : "<<p2out<< " "<<p2out.rapidity()<<std::endl;
// std::cout << "####################\n";
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out-pg); // Extra bit pre-gluon
CLHEP::HepLorentzVector q3=-(p2in-p2out); // Bottom End
// std::cerr<<"Current: "<<q1.m2()<<" "<<q2.m2()<<std::endl;
CCurrent mjH1m,mjH1p,mj2m,mj2p;
mjH1p=jHtop(p1out,true,p1in,true,qH1,qH2, mt, incBot, mb);
mjH1m=jHtop(p1out,false,p1in,false,qH1,qH2, mt, incBot, mb);
mj2p=joi(p2out,true,p2in,true);
mj2m=joi(p2out,false,p2in,false);
// Dot products of these which occur again and again
COM MHmp=mjH1m.dot(mj2p); // And now for the Higgs ones
COM MHmm=mjH1m.dot(mj2m);
COM MHpp=mjH1p.dot(mj2p);
COM MHpm=mjH1p.dot(mj2m);
// Currents with pg
CCurrent jgbm,jgbp,j2gm,j2gp;
j2gp=joo(p2out,true,pg,true);
j2gm=joo(p2out,false,pg,false);
jgbp=joi(pg,true,p2in,true);
jgbm=joi(pg,false,p2in,false);
CCurrent qsum(q2+q3);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
CCurrent p2o(p2out);
CCurrent p2i(p2in);
CCurrent pplus((p1in+p1out)/2.);
CCurrent pminus((p2in+p2out)/2.);
// COM test=pminus.dot(p1in);
Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m
+ (p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m
+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p
+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p
+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
// 1/3. = 1/C_A ?
double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
const double th=qH2.m2()*q2.m2();
ampsq/=th;
ampsq/=16.;
ampsq*=HEJ::C_F*HEJ::C_F/(HEJ::C_A*HEJ::C_A); // Factor of (Cf/Ca) for each quark to match MH2qQ.
return ampsq;
}
double jM2unobqbarHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out-pg); // Extra bit pre-gluon
CLHEP::HepLorentzVector q3=-(p2in-p2out); // Bottom End
// std::cerr<<"Current: "<<q1.m2()<<" "<<q2.m2()<<std::endl;
CCurrent mjH1m,mjH1p,mj2m,mj2p;
mjH1p=jioHtop(p1in,true,p1out,true,qH1,qH2, mt, incBot, mb);
mjH1m=jioHtop(p1in,false,p1out,false,qH1,qH2, mt, incBot, mb);
mj2p=joi(p2out,true,p2in,true);
mj2m=joi(p2out,false,p2in,false);
// Dot products of these which occur again and again
COM MHmp=mjH1m.dot(mj2p); // And now for the Higgs ones
COM MHmm=mjH1m.dot(mj2m);
COM MHpp=mjH1p.dot(mj2p);
COM MHpm=mjH1p.dot(mj2m);
// Currents with pg
CCurrent jgbm,jgbp,j2gm,j2gp;
j2gp=joo(p2out,true,pg,true);
j2gm=joo(p2out,false,pg,false);
jgbp=joi(pg,true,p2in,true);
jgbm=joi(pg,false,p2in,false);
CCurrent qsum(q2+q3);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
CCurrent p2o(p2out);
CCurrent p2i(p2in);
CCurrent pplus((p1in+p1out)/2.);
CCurrent pminus((p2in+p2out)/2.);
// COM test=pminus.dot(p1in);
Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
double th=qH2.m2()*q2.m2();
ampsq/=th;
ampsq/=16.;
ampsq*=4.*4./(9.*9.); // Factor of (Cf/Ca) for each quark to match MH2qQ.
//Higgs coupling is included in Hjets.C
return ampsq;
}
double jM2unobqHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out-pg); // Extra bit pre-gluon
CLHEP::HepLorentzVector q3=-(p2in-p2out); // Bottom End
// std::cerr<<"Current: "<<q1.m2()<<" "<<q2.m2()<<std::endl;
CCurrent mjH1m,mjH1p,mj2m,mj2p;
mjH1p=jHtop(p1out,true,p1in,true,qH1,qH2,mt, incBot, mb);
mjH1m=jHtop(p1out,false,p1in,false,qH1,qH2,mt, incBot, mb);
mj2p=jio(p2in,true,p2out,true);
mj2m=jio(p2in,false,p2out,false);
// Dot products of these which occur again and again
COM MHmp=mjH1m.dot(mj2p); // And now for the Higgs ones
COM MHmm=mjH1m.dot(mj2m);
COM MHpp=mjH1p.dot(mj2p);
COM MHpm=mjH1p.dot(mj2m);
// Currents with pg
CCurrent jgbm,jgbp,j2gm,j2gp;
j2gp=joo(pg,true,p2out,true);
j2gm=joo(pg,false,p2out,false);
jgbp=jio(p2in,true,pg,true);
jgbm=jio(p2in,false,pg,false);
CCurrent qsum(q2+q3);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
CCurrent p2o(p2out);
CCurrent p2i(p2in);
CCurrent pplus((p1in+p1out)/2.);
CCurrent pminus((p2in+p2out)/2.);
// COM test=pminus.dot(p1in);
Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
double th=qH2.m2()*q2.m2();
ampsq/=th;
ampsq/=16.;
ampsq*=4.*4./(9.*9.); // Factor of (Cf/Ca) for each quark to match MH2qQ.
//Higgs coupling is included in Hjets.C
return ampsq;
}
double jM2unobqbarHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out-pg); // Extra bit pre-gluon
CLHEP::HepLorentzVector q3=-(p2in-p2out); // Bottom End
// std::cerr<<"Current: "<<q1.m2()<<" "<<q2.m2()<<std::endl;
CCurrent mjH1m,mjH1p,mj2m,mj2p;
mjH1p=jioHtop(p1in,true,p1out,true,qH1,qH2,mt, incBot, mb);
mjH1m=jioHtop(p1in,false,p1out,false,qH1,qH2,mt, incBot, mb);
mj2p=jio(p2in,true,p2out,true);
mj2m=jio(p2in,false,p2out,false);
// Dot products of these which occur again and again
COM MHmp=mjH1m.dot(mj2p); // And now for the Higgs ones
COM MHmm=mjH1m.dot(mj2m);
COM MHpp=mjH1p.dot(mj2p);
COM MHpm=mjH1p.dot(mj2m);
// Currents with pg
CCurrent jgbm,jgbp,j2gm,j2gp;
j2gp=joo(pg,true,p2out,true);
j2gm=joo(pg,false,p2out,false);
jgbp=jio(p2in,true,pg,true);
jgbm=jio(p2in,false,pg,false);
CCurrent qsum(q2+q3);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
CCurrent p2o(p2out);
CCurrent p2i(p2in);
CCurrent pplus((p1in+p1out)/2.);
CCurrent pminus((p2in+p2out)/2.);
// COM test=pminus.dot(p1in);
Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
double th=qH2.m2()*q2.m2();
ampsq/=th;
ampsq/=16.;
ampsq*=4.*4./(9.*9.); // Factor of (Cf/Ca) for each quark to match MH2qQ.
//Higgs coupling is included in Hjets.C
return ampsq;
}
double jM2unobgHQg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
// std::cout << "####################\n";
// std::cout << "# p1in : "<<p1in<< " "<<p1in.plus()<<" "<<p1in.minus()<<std::endl;
// std::cout << "# p2in : "<<p2in<< " "<<p2in.plus()<<" "<<p2in.minus()<<std::endl;
// std::cout << "# p1out : "<<p1out<< " "<<p1out.rapidity()<<std::endl;
// std::cout << "# (qH1-qH2) : "<<(qH1-qH2)<< " "<<(qH1-qH2).rapidity()<<std::endl;
// std::cout << "# pg : "<<pg<< " "<<pg.rapidity()<<std::endl;
// std::cout << "# p2out : "<<p2out<< " "<<p2out.rapidity()<<std::endl;
// std::cout << "####################\n";
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out-pg); // Extra bit pre-gluon
CLHEP::HepLorentzVector q3=-(p2in-p2out); // Bottom End
// std::cerr<<"Current: "<<q1.m2()<<" "<<q2.m2()<<std::endl;
CCurrent mjH1m,mjH1p,mj2m,mj2p;
mjH1p=jHtop(p1out,true,p1in,true,qH1,qH2,mt, incBot, mb);
mjH1m=jHtop(p1out,false,p1in,false,qH1,qH2,mt, incBot, mb);
mj2p=joi(p2out,true,p2in,true);
mj2m=joi(p2out,false,p2in,false);
// Dot products of these which occur again and again
COM MHmp=mjH1m.dot(mj2p); // And now for the Higgs ones
COM MHmm=mjH1m.dot(mj2m);
COM MHpp=mjH1p.dot(mj2p);
COM MHpm=mjH1p.dot(mj2m);
// Currents with pg
CCurrent jgbm,jgbp,j2gm,j2gp;
j2gp=joo(p2out,true,pg,true);
j2gm=joo(p2out,false,pg,false);
jgbp=joi(pg,true,p2in,true);
jgbm=joi(pg,false,p2in,false);
CCurrent qsum(q2+q3);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
CCurrent p2o(p2out);
CCurrent p2i(p2in);
CCurrent pplus((p1in+p1out)/2.);
CCurrent pminus((p2in+p2out)/2.);
// COM test=pminus.dot(p1in);
Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
double th=qH2.m2()*q2.m2();
ampsq/=th;
ampsq/=16.;
ampsq*=4./9.*4./9.; // Factor of (Cf/Ca) for each quark to match MH2qQ.
// need twice to match the normalization
//Higgs coupling is included in Hjets.C
const double K = K_g(p1out, p1in);
return ampsq*K/C_F;
}
double jM2unobgHQbarg (CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector pg, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector qH1, CLHEP::HepLorentzVector qH2, double mt, bool incBot, double mb)
{
CLHEP::HepLorentzVector q1=p1in-p1out; // Top End
CLHEP::HepLorentzVector q2=-(p2in-p2out-pg); // Extra bit pre-gluon
CLHEP::HepLorentzVector q3=-(p2in-p2out); // Bottom End
// std::cerr<<"Current: "<<q1.m2()<<" "<<q2.m2()<<std::endl;
CCurrent mjH1m,mjH1p,mj2m,mj2p;
mjH1p=jHtop(p1out,true,p1in,true,qH1,qH2,mt, incBot, mb);
mjH1m=jHtop(p1out,false,p1in,false,qH1,qH2,mt, incBot, mb);
mj2p=jio(p2in,true,p2out,true);
mj2m=jio(p2in,false,p2out,false);
// Dot products of these which occur again and again
COM MHmp=mjH1m.dot(mj2p); // And now for the Higgs ones
COM MHmm=mjH1m.dot(mj2m);
COM MHpp=mjH1p.dot(mj2p);
COM MHpm=mjH1p.dot(mj2m);
// Currents with pg
CCurrent jgbm,jgbp,j2gm,j2gp;
j2gp=joo(pg,true,p2out,true);
j2gm=joo(pg,false,p2out,false);
jgbp=jio(p2in,true,pg,true);
jgbm=jio(p2in,false,pg,false);
CCurrent qsum(q2+q3);
CCurrent Lmp,Lmm,Lpp,Lpm,U1mp,U1mm,U1pp,U1pm,U2mp,U2mm,U2pp,U2pm,p1o(p1out),p1i(p1in);
CCurrent p2o(p2out);
CCurrent p2i(p2in);
CCurrent pplus((p1in+p1out)/2.);
CCurrent pminus((p2in+p2out)/2.);
// COM test=pminus.dot(p1in);
Lmm=((-1.)*qsum*(MHmm) + (-2.*mjH1m.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmm/2.))/q3.m2();
Lmp=((-1.)*qsum*(MHmp) + (-2.*mjH1m.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1m+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHmp/2.))/q3.m2();
Lpm=((-1.)*qsum*(MHpm) + (-2.*mjH1p.dot(pg))*mj2m+2.*mj2m.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpm/2.))/q3.m2();
Lpp=((-1.)*qsum*(MHpp) + (-2.*mjH1p.dot(pg))*mj2p+2.*mj2p.dot(pg)*mjH1p+(p1o/pg.dot(p1out) + p1i/pg.dot(p1in))*(q2.m2()*MHpp/2.))/q3.m2();
U1mm=(jgbm.dot(mjH1m)*j2gm+2.*p2o*MHmm)/(p2out+pg).m2();
U1mp=(jgbp.dot(mjH1m)*j2gp+2.*p2o*MHmp)/(p2out+pg).m2();
U1pm=(jgbm.dot(mjH1p)*j2gm+2.*p2o*MHpm)/(p2out+pg).m2();
U1pp=(jgbp.dot(mjH1p)*j2gp+2.*p2o*MHpp)/(p2out+pg).m2();
U2mm=((-1.)*j2gm.dot(mjH1m)*jgbm+2.*p2i*MHmm)/(p2in-pg).m2();
U2mp=((-1.)*j2gp.dot(mjH1m)*jgbp+2.*p2i*MHmp)/(p2in-pg).m2();
U2pm=((-1.)*j2gm.dot(mjH1p)*jgbm+2.*p2i*MHpm)/(p2in-pg).m2();
U2pp=((-1.)*j2gp.dot(mjH1p)*jgbp+2.*p2i*MHpp)/(p2in-pg).m2();
const double cf=HEJ::C_F;
double amm,amp,apm,app;
amm=cf*(2.*vre(Lmm-U1mm,Lmm+U2mm))+2.*cf*cf/3.*vabs2(U1mm+U2mm);
amp=cf*(2.*vre(Lmp-U1mp,Lmp+U2mp))+2.*cf*cf/3.*vabs2(U1mp+U2mp);
apm=cf*(2.*vre(Lpm-U1pm,Lpm+U2pm))+2.*cf*cf/3.*vabs2(U1pm+U2pm);
app=cf*(2.*vre(Lpp-U1pp,Lpp+U2pp))+2.*cf*cf/3.*vabs2(U1pp+U2pp);
double ampsq=-(amm+amp+apm+app)/(q1.m2()*qH1.m2());
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) > 1.0000001)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// if ((vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm))/(2*vre(Lmm-U1mm,Lmm+U2mm)) < 0.9999999)
// std::cout << " Big Problem!! " << vabs2(Lmm-U1mm+U2mm)+vabs2(Lmm)-vabs2(U1mm)-vabs2(U2mm) << " " << 2*vre(Lmm-U1mm,Lmm+U2mm) << std::endl;
// Now add the t-channels for the Higgs
double th=qH2.m2()*q2.m2();
ampsq/=th;
ampsq/=16.;
ampsq*=4./9.*4./9.; // Factor of (Cf/Ca) for each quark to match MH2qQ.
//Higgs coupling is included in Hjets.C
const double K = K_g(p1out, p1in);
return ampsq*K/C_F; //ca/cf = 9/4
}
// Begin finite mass stuff
#ifdef HEJ_BUILD_WITH_QCDLOOP
namespace {
// All the stuff needed for the box functions in qg->qgH now...
//COM E1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM E1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//CLHEP::HepLorentzVector q2=k3+k4;
CLHEP::HepLorentzVector q2=-(k1+k2+kh);
double Delta, Sigma, S1, S2, s12, s34;
S1 = 2.*k1.dot(q2);
S2 = 2.*k2.dot(q2);
s12 = 2.*k1.dot(k2);
//s34 = 2.*k3.dot(k4);
s34 = q2.m2();
Delta = s12*s34 - S1*S2;
Sigma = 4.*s12*s34 - pow(S1+S2,2);
return looprwfactor*(-s12*D0DD(k2, k1, q2, mq)*(1 - 8.*mq*mq/s12 + S2/(2.*s12) +
S2*(s12 - 8.*mq*mq)*(s34 + S1)/(2.*s12*Delta) +
2.*(s34 + S1)*(s34 + S1)/Delta +
S2*pow((s34 + S1),3)/Delta/Delta) - ((s12 + S2)*C0DD(k2,
k1 + q2, mq) -
s12*C0DD(k1, k2, mq) + (S1 - S2)*C0DD(k1 + k2, q2, mq) -
S1*C0DD(k1, q2,
mq))*(S2*(s12 - 4.*mq*mq)/(2.*s12*Delta) +
2.*(s34 + S1)/Delta +
S2*pow((s34 + S1),2)/Delta/Delta) + (C0DD(k1, q2, mq) -
C0DD(k1 + k2, q2, mq))*(1. - 4.*mq*mq/s12) -
C0DD(k1 + k2, q2, mq)*2.*s34/
S1 - (B0DD(k1 + q2, mq) -
B0DD(k1 + k2 + q2, mq))*2.*s34*(s34 +
S1)/(S1*Delta) + (B0DD(q2, mq) -
B0DD(k1 + k2 + q2, mq) +
s12*C0DD(k1 + k2, q2,
mq))*(2.*s34*(s34 +
S1)*(S1 - S2)/(Delta*Sigma) +
2.*s34*(s34 + S1)/(S1*Delta)) + (B0DD(k1 + k2, mq) -
B0DD(k1 + k2 + q2,
mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))*2.*(s34 +
S1)*(2.*s12*s34 -
S2*(S1 + S2))/(Delta*Sigma));
}
//COM F1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM F1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//CLHEP::HepLorentzVector q2=k3+k4;
CLHEP::HepLorentzVector q2 = -(k1+k2+kh);
double Delta, Sigma, S1, S2, s12, s34;
S1 = 2.*k1.dot(q2);
S2 = 2.*k2.dot(q2);
s12 = 2.*k1.dot(k2);
//s34 = 2.*k3.dot(k4);
s34 = q2.m2();
Delta = s12*s34 - S1*S2;
Sigma = 4.*s12*s34 - pow(S1+S2,2);
return looprwfactor*(-S2*D0DD(k1, k2, q2,
mq)*(0.5 - (s12 - 8.*mq*mq)*(s34 + S2)/(2.*Delta) -
s12*pow((s34 + S2),3)/Delta/Delta) + ((s12 + S1)*C0DD(k1,
k2 + q2, mq) -
s12*C0DD(k1, k2, mq) - (S1 - S2)*C0DD(k1 + k2, q2, mq) -
S2*C0DD(k2, q2,
mq))*(S2*(s12 - 4.*mq*mq)/(2.*s12*Delta) +
S2*pow((s34 + S2),2)/Delta/Delta) - (C0DD(k1 + k2, q2, mq) - C0DD(k1, k2 + q2, mq))*(1. - 4.*mq*mq/s12) -
C0DD(k1, k2 + q2, mq) + (B0DD(k2 + q2, mq) -
B0DD(k1 + k2 + q2,
mq))*2.*pow((s34 + S2),2)/((s12 + S1)*Delta) - (B0DD(
q2, mq) - B0DD(k1 + k2 + q2, mq) +
s12*C0DD(k1 + k2, q2, mq))*2.*s34*(s34 +
S2)*(S2 - S1)/(Delta*Sigma) + (B0DD(
k1 + k2, mq) -
B0DD(k1 + k2 + q2,
mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))*2.*(s34 +
S2)*(2.*s12*s34 -
S2*(S1 + S2))/(Delta*Sigma));
}
//COM G1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM G1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//CLHEP::HepLorentzVector q2=k3+k4;
CLHEP::HepLorentzVector q2 = -(k1+k2+kh);
double Delta, S1, S2, s12, s34;
S1 = 2.*k1.dot(q2);
S2 = 2.*k2.dot(q2);
s12 = 2.*k1.dot(k2);
//s34 = 2.*k3.dot(k4);
s34 = q2.m2();
Delta = s12*s34 - S1*S2;
return looprwfactor*(S2*D0DD(k1, q2, k2,
mq)*(Delta/s12/s12 - 4.*mq*mq/s12) -
S2*((s12 + S1)*C0DD(k1, k2 + q2, mq) -
S1*C0DD(k1, q2, mq))*(1./
s12/s12 - (s12 - 4.*mq*mq)/(2.*s12*Delta)) -
S2*((s12 + S2)*C0DD(k1 + q2, k2, mq) -
S2*C0DD(k2, q2, mq))*(1./
s12/s12 + (s12 - 4.*mq*mq)/(2.*s12*Delta)) -
C0DD(k1, q2, mq) - (C0DD(k1, k2 + q2, mq) -
C0DD(k1, q2, mq))*4.*mq*mq/
s12 + (B0DD(k1 + q2, mq) - B0DD(k1 + k2 + q2, mq))*2./
s12 + (B0DD(k1 + q2, mq) -
B0DD(q2, mq))*2.*s34/(s12*S1) + (B0DD(k2 + q2, mq) -
B0DD(k1 + k2 + q2, mq))*2.*(s34 + S2)/(s12*(s12 + S1)));
}
//COM E4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM E4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//CLHEP::HepLorentzVector q2=k3+k4;
CLHEP::HepLorentzVector q2 = -(k1+k2+kh);
double Delta, Sigma, S1, S2, s12, s34;
S1 = 2.*k1.dot(q2);
S2 = 2.*k2.dot(q2);
s12 = 2.*k1.dot(k2);
//s34 = 2.*k3.dot(k4);
s34 = q2.m2();
Delta = s12*s34 - S1*S2;
Sigma = 4.*s12*s34 - pow(S1+S2,2);
return looprwfactor* (-s12*D0DD(k2, k1, q2,
mq)*(0.5 - (S1 - 8.*mq*mq)*(s34 + S1)/(2.*Delta) -
s12*pow((s34 + S1),3)/Delta/Delta) + ((s12 + S2)*C0DD(k2,
k1 + q2, mq) -
s12*C0DD(k1, k2, mq) + (S1 - S2)*C0DD(k1 + k2, q2, mq) -
S1*C0DD(k1, q2, mq))*((S1 - 4.*mq*mq)/(2.*Delta) +
s12*pow((s34 + S1),2)/Delta/Delta) -
C0DD(k1 + k2, q2, mq) + (B0DD(k1 + q2, mq) -
B0DD(k1 + k2 + q2, mq))*(2.*s34/Delta +
2.*s12*(s34 + S1)/((s12 + S2)*Delta)) - (B0DD(
q2, mq) - B0DD(k1 + k2 + q2, mq) +
s12*C0DD(k1 + k2, q2,
mq))*((2.*s34*(2.*s12*s34 - S2*(S1 + S2) +
s12*(S1 -
S2)))/(Delta*Sigma)) + (B0DD(k1 + k2, mq) -
B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))*((2.*s12*(2.*s12*s34 - S1*(S1 + S2) +
s34*(S2 - S1)))/(Delta*Sigma)));
}
//COM F4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM F4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//CLHEP::HepLorentzVector q2=k3+k4;
CLHEP::HepLorentzVector q2 = -(k1+k2+kh);
double Delta, Sigma, S1, S2, s12, s34;
S1 = 2.*k1.dot(q2);
S2 = 2.*k2.dot(q2);
s12 = 2.*k1.dot(k2);
//s34 = 2.*k3.dot(k4);
s34 = q2.m2();
Delta = s12*s34 - S1*S2;
Sigma = 4.*s12*s34 - pow(S1+S2,2);
return looprwfactor* (-s12*D0DD(k1, k2, q2,
mq)*(0.5 + (S1 - 8.*mq*mq)*(s34 + S2)/(2.*Delta) +
s12*pow((s34 + S2),3)/Delta/Delta) - ((s12 + S1)*C0DD(k1,
k2 + q2, mq) -
s12*C0DD(k1, k2, mq) - (S1 - S2)*C0DD(k1 + k2, q2, mq) -
S2*C0DD(k2, q2, mq))*((S1 - 4.*mq*mq)/(2.*Delta) +
s12*pow((s34 + S2),2)/Delta/Delta) -
C0DD(k1 + k2, q2, mq) - (B0DD(k2 + q2, mq) -
B0DD(k1 + k2 + q2, mq))*2.*(s34 +
S2)/Delta + (B0DD(q2, mq) -
B0DD(k1 + k2 + q2, mq) +
s12*C0DD(k1 + k2, q2, mq))*2.*s34*(2.*s12*s34 -
S1*(S1 + S2) +
s12*(S2 - S1))/(Delta*Sigma) - (B0DD(k1 + k2, mq) -
B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))*(2.*s12*(2.*s12*s34 - S2*(S1 + S2) +
s34*(S1 - S2))/(Delta*Sigma)));
}
//COM G4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM G4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//CLHEP::HepLorentzVector q2=k3+k4;
CLHEP::HepLorentzVector q2 = -(k1+k2+kh);
double Delta, S1, S2, s12, s34;
S1 = 2.*k1.dot(q2);
S2 = 2.*k2.dot(q2);
s12 = 2.*k1.dot(k2);
//s34 = 2.*k3.dot(k4);
s34 = q2.m2();
Delta = s12*s34 - S1*S2;
return looprwfactor* (-D0DD(k1, q2, k2,
mq)*(Delta/s12 + (s12 + S1)/2. -
4.*mq*mq) + ((s12 + S1)*C0DD(k1, k2 + q2, mq) -
S1*C0DD(k1, q2, mq))*(1./
s12 - (S1 - 4.*mq*mq)/(2.*Delta)) + ((s12 + S2)*C0DD(
k1 + q2, k2, mq) -
S2*C0DD(k2, q2, mq))*(1./
s12 + (S1 - 4.*mq*mq)/(2.*Delta)) + (B0DD(
k1 + k2 + q2, mq) -
B0DD(k1 + q2, mq))*2./(s12 + S2));
}
//COM E10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM E10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//CLHEP::HepLorentzVector q2=k3+k4;
CLHEP::HepLorentzVector q2 = -(k1+k2+kh);
double Delta, Sigma, S1, S2, s12, s34;
S1 = 2.*k1.dot(q2);
S2 = 2.*k2.dot(q2);
s12 = 2.*k1.dot(k2);
//s34 = 2.*k3.dot(k4);
s34 = q2.m2();
Delta = s12*s34 - S1*S2;
Sigma = 4.*s12*s34 - pow(S1+S2,2);
return looprwfactor*(-s12*D0DD(k2, k1, q2, mq)*((s34 + S1)/Delta +
12.*mq*mq*S1*(s34 + S1)/Delta/Delta -
4.*s12*S1*pow((s34 + S1),3)/Delta/Delta/Delta) - ((s12 + S2)*C0DD(k2, k1 + q2, mq) -
s12*C0DD(k1, k2, mq) + (S1 - S2)*C0DD(k1 + k2, q2, mq) -
S1*C0DD(k1, q2, mq))*(1./Delta +
4.*mq*mq*S1/Delta/Delta -
4.*s12*S1*pow((s34 + S1),2)/Delta/Delta/Delta) +
C0DD(k1 + k2, q2, mq)*(4.*s12*s34*(S1 - S2)/(Delta*Sigma) -
4.*(s12 -
2.*mq*mq)*(2.*s12*s34 -
S1*(S1 + S2))/(Delta*Sigma)) + (B0DD(k1 + q2, mq) -
B0DD(k1 + k2 + q2, mq))*(4.*(s34 + S1)/((s12 + S2)*Delta) +
8.*S1*(s34 + S1)/Delta/Delta) + (B0DD(q2, mq) -
B0DD(k1 + k2 + q2, mq) +
s12*C0DD(k1 + k2, q2, mq))*(12.*s34*(2.*s12 + S1 +
S2)*(2.*s12*s34 -
S1*(S1 + S2))/(Delta*Sigma*Sigma) -
4.*s34*(4.*s12 + 3.*S1 +
S2)/(Delta*Sigma) +
8.*s12*s34*(s34*(s12 + S2) -
S1*(s34 +
S1))/(Delta*Delta*Sigma)) + (B0DD(k1 + k2, mq) -
B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2,
mq))*(12.*s12*(2.*s34 + S1 +
S2)*(2.*s12*s34 -
S1*(S1 + S2))/(Delta*Sigma*Sigma) +
8.*s12*S1*(s34*(s12 + S2) -
S1*(s34 +
S1))/(Delta*Delta*Sigma))) + (COM(0.,1.)/(4.*M_PI*M_PI))*((2.*s12*s34 -
S1*(S1 + S2))/(Delta*Sigma));
}
//COM F10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM F10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//CLHEP::HepLorentzVector q2=k3+k4;
CLHEP::HepLorentzVector q2 = -(k1+k2+kh);
double Delta, Sigma, S1, S2, s12, s34;
S1 = 2.*k1.dot(q2);
S2 = 2.*k2.dot(q2);
s12 = 2.*k1.dot(k2);
//s34 = 2.*k3.dot(k4);
s34 = q2.m2();
Delta = s12*s34 - S1*S2;
Sigma = 4.*s12*s34 - pow(S1+S2,2);
return looprwfactor* (s12*D0DD(k1, k2, q2,
mq)*((s34 + S2)/Delta - 4.*mq*mq/Delta +
12.*mq*mq*s34*(s12 + S1)/Delta/Delta -
4.*s12*pow((s34 + S2),2)/Delta/Delta -
4.*s12*S1*pow((s34 + S2),3)/Delta/Delta/Delta) + ((s12 + S1)*C0DD(k1, k2 + q2, mq) -
s12*C0DD(k1, k2, mq) - (S1 - S2)*C0DD(k1 + k2, q2, mq) -
S2*C0DD(k2, q2, mq))*(1./Delta +
4.*mq*mq*S1/Delta/Delta -
4.*s12*(s34 + S2)/Delta/Delta -
4.*s12*S1*pow((s34 + S2),2)/Delta/Delta/Delta) -
C0DD(k1 + k2, q2, mq)*(4.*s12*s34/(S2*Delta) +
4.*s12*s34*(S2 - S1)/(Delta*Sigma) +
4.*(s12 -
2.*mq*mq)*(2.*s12*s34 -
S1*(S1 + S2))/(Delta*Sigma)) - (B0DD(
k2 + q2, mq) -
B0DD(k1 + k2 + q2, mq))*(4.*s34/(S2*Delta) +
8.*s34*(s12 + S1)/Delta/Delta) - (B0DD(q2, mq) -
B0DD(k1 + k2 + q2, mq) +
s12*C0DD(k1 + k2, q2,
mq))*(-12*s34*(2*s12 + S1 +
S2)*(2.*s12*s34 -
S1*(S1 + S2))/(Delta*Sigma*Sigma) -
4.*s12*s34*s34/(S2*Delta*Delta) +
4.*s34*S1/(Delta*Sigma) -
4.*s34*(s12*s34*(2.*s12 + S2) -
S1*S1*(2.*s12 +
S1))/(Delta*Delta*Sigma)) - (B0DD(k1 + k2, mq) -
B0DD(k1 + k2 + q2, mq) - (s34 + S1 + S2)*C0DD(k1 + k2, q2, mq))*(-12.*s12*(2.*s34 + S1 +
S2)*(2.*s12*s34 -
S1*(S1 + S2))/(Delta*Sigma*Sigma) +
8.*s12*(2.*s34 + S1)/(Delta*Sigma) -
8.*s12*s34*(2.*s12*s34 - S1*(S1 + S2) +
s12*(S2 -
S1))/(Delta*Delta*Sigma))) + (COM(0.,1.)/(4.*M_PI*M_PI))*((2.*s12*s34 -
S1*(S1 + S2))/(Delta*Sigma));
}
//COM G10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM G10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//CLHEP::HepLorentzVector q2=k3+k4;
CLHEP::HepLorentzVector q2 = -(k1+k2+kh);
double Delta, S1, S2, s12, s34;
S1 = 2.*k1.dot(q2);
S2 = 2.*k2.dot(q2);
s12 = 2.*k1.dot(k2);
//s34 = 2.*k3.dot(k4);
s34 = q2.m2();
Delta = s12*s34 - S1*S2;
return looprwfactor* (-D0DD(k1, q2, k2, mq)*(1. +
4.*S1*mq*mq/Delta) + ((s12 + S1)*C0DD(k1,
k2 + q2, mq) -
S1*C0DD(k1, q2, mq))*(1./Delta +
4.*S1*mq*mq/Delta/Delta) - ((s12 + S2)*C0DD(k1 + q2,
k2, mq) - S2*C0DD(k2, q2, mq))*(1./Delta +
4.*S1*mq*mq/Delta/Delta) + (B0DD(k1 + k2 + q2, mq) -
B0DD(k1 + q2, mq))*4.*(s34 +
S1)/(Delta*(s12 + S2)) + (B0DD(q2, mq) -
B0DD(k2 + q2, mq))*4.*s34/(Delta*S2));
}
//COM H1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM H1(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//return E1(k1,k2,k3,k4,mq)+F1(k1,k2,k3,k4,mq)+G1(k1,k2,k3,k4,mq);
return E1(k1,k2,kh,mq)+F1(k1,k2,kh,mq)+G1(k1,k2,kh,mq);
}
//COM H4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM H4(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//return E4(k1,k2,k3,k4,mq)+F4(k1,k2,k3,k4,mq)+G4(k1,k2,k3,k4,mq);
return E4(k1,k2,kh,mq)+F4(k1,k2,kh,mq)+G4(k1,k2,kh,mq);
}
//COM H10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM H10(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//return E10(k1,k2,k3,k4,mq)+F10(k1,k2,k3,k4,mq)+G10(k1,k2,k3,k4,mq);
return E10(k1,k2,kh,mq)+F10(k1,k2,kh,mq)+G10(k1,k2,kh,mq);
}
//COM H2(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM H2(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//return -1.*H1(k2,k1,k3,k4,mq);
return -1.*H1(k2,k1,kh,mq);
}
//COM H5(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM H5(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//return -1.*H4(k2,k1,k3,k4,mq);
return -1.*H4(k2,k1,kh,mq);
}
//COM H12(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector k3, CLHEP::HepLorentzVector k4, double mq)
COM H12(CLHEP::HepLorentzVector k1, CLHEP::HepLorentzVector k2, CLHEP::HepLorentzVector kh, double mq)
{
//return -1.*H10(k2,k1,k3,k4,mq);
return -1.*H10(k2,k1,kh,mq);
}
// FL and FT functions
COM FL(CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mq)
{
CLHEP::HepLorentzVector Q = q1 + q2;
double detQ2 = q1.m2()*q2.m2() - q1.dot(q2)*q1.dot(q2);
return -1./(2.*detQ2)*((2.-
3.*q1.m2()*q2.dot(Q)/detQ2)*(B0DD(q1, mq) -
B0DD(Q, mq)) + (2. -
3.*q2.m2()*q1.dot(Q)/detQ2)*(B0DD(q2, mq) -
B0DD(Q, mq)) - (4.*mq*mq + q1.m2() + q2.m2() +
Q.m2() - 3.*q1.m2()*q2.m2()*Q.m2()/detQ2)*C0DD(
q1, q2, mq) - 2.);
}
COM FT(CLHEP::HepLorentzVector q1, CLHEP::HepLorentzVector q2, double mq)
{
CLHEP::HepLorentzVector Q = q1 + q2;
double detQ2 = q1.m2()*q2.m2() - q1.dot(q2)*q1.dot(q2);
return -1./(2.*detQ2)*(Q.m2()*(B0DD(q1, mq) + B0DD(q2, mq) - 2.*B0DD(Q, mq) -
2.*q1.dot(q2)*C0DD(q1, q2, mq)) + (q1.m2() -
q2.m2()) *(B0DD(q1, mq) - B0DD(q2, mq))) -
q1.dot(q2)*FL(q1, q2, mq);
}
CLHEP::HepLorentzVector ParityFlip(CLHEP::HepLorentzVector p)
{
CLHEP::HepLorentzVector flippedVector;
flippedVector.setE(p.e());
flippedVector.setX(-p.x());
flippedVector.setY(-p.y());
flippedVector.setZ(-p.z());
return flippedVector;
}
/// @brief HC amp for qg->qgH with finite top (i.e. j^{++}_H)
void g_gH_HC(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector p1,
CLHEP::HepLorentzVector pH, double mq, current &retAns)
{
current cura1,pacur,p1cur,pHcur,conjeps1,conjepsH1,epsa,epsHa,epsHapart1,
epsHapart2,conjepsH1part1,conjepsH1part2;
COM ang1a,sqa1;
const double F = 4.*mq*mq/HEJ::vev;
// Easier to have the whole thing as current object so I can use cdot functionality.
// Means I need to write pa,p1 as current objects
to_current(pa, pacur);
to_current(p1,p1cur);
to_current(pH,pHcur);
bool gluonforward = true;
if(pa.z() < 0)
gluonforward = false;
//HEJ gauge
jio(pa,false,p1,false,cura1);
if(gluonforward){
// sqrt(2pa_-/p1_-)*p1_perp/abs(p1_perp)
ang1a = sqrt(pa.plus()*p1.minus())*(p1.x()+COM(0.,1.)*p1.y())/p1.perp();
// sqrt(2pa_-/p1_-)*p1_perp*/abs(p1_perp)
sqa1 = sqrt(pa.plus()*p1.minus())*(p1.x()-COM(0.,1.)*p1.y())/p1.perp();
} else {
ang1a = sqrt(pa.minus()*p1.plus());
sqa1 = sqrt(pa.minus()*p1.plus());
}
const double prop = (pa-p1-pH).m2();
cmult(-1./sqrt(2)/ang1a,cura1,conjeps1);
cmult(1./sqrt(2)/sqa1,cura1,epsa);
const COM Fta = FT(-pa,pa-pH,mq)/(pa-pH).m2();
const COM Ft1 = FT(-p1-pH,p1,mq)/(p1+pH).m2();
const COM h4 = H4(p1,-pa,pH,mq);
const COM h5 = H5(p1,-pa,pH,mq);
const COM h10 = H10(p1,-pa,pH,mq);
const COM h12 = H12(p1,-pa,pH,mq);
cmult(Fta*pa.dot(pH), epsa, epsHapart1);
cmult(-1.*Fta*cdot(pHcur,epsa), pacur, epsHapart2);
cmult(Ft1*cdot(pHcur,conjeps1), p1cur, conjepsH1part1);
cmult(-Ft1*p1.dot(pH), conjeps1, conjepsH1part2);
cadd(epsHapart1, epsHapart2, epsHa);
cadd(conjepsH1part1, conjepsH1part2, conjepsH1);
const COM aH1 = cdot(pHcur, cura1);
current T1,T2,T3,T4,T5,T6,T7,T8,T9,T10;
if(gluonforward){
cmult(sqrt(2.)*sqrt(p1.plus()/pa.plus())*prop/sqa1, conjepsH1, T1);
cmult(-sqrt(2.)*sqrt(pa.plus()/p1.plus())*prop/ang1a, epsHa, T2);
}
else{
cmult(-sqrt(2.)*sqrt(p1.minus()/pa.minus())
*((p1.x()-COM(0.,1.)*p1.y())/p1.perp())*prop/sqa1, conjepsH1, T1);
cmult(sqrt(2.)*sqrt(pa.minus()/p1.minus())
*((p1.x()-COM(0.,1.)*p1.y())/p1.perp())*prop/ang1a, epsHa, T2);
}
cmult(sqrt(2.)/ang1a*aH1, epsHa, T3);
cmult(sqrt(2.)/sqa1*aH1, conjepsH1, T4);
cmult(-sqrt(2.)*Fta*pa.dot(p1)*aH1/sqa1, conjeps1, T5);
cmult(-sqrt(2.)*Ft1*pa.dot(p1)*aH1/ang1a, epsa, T6);
cmult(-aH1/sqrt(2.)/sqa1*h4*8.*COM(0.,1.)*M_PI*M_PI, conjeps1, T7);
cmult(aH1/sqrt(2.)/ang1a*h5*8.*COM(0.,1.)*M_PI*M_PI, epsa, T8);
cmult(aH1*aH1/2./ang1a/sqa1*h10*8.*COM(0.,1.)*M_PI*M_PI, pacur, T9);
cmult(-aH1*aH1/2./ang1a/sqa1*h12*8.*COM(0.,1.)*M_PI*M_PI, p1cur, T10);
current ans;
for(int i=0;i<4;i++)
{
ans[i] = T1[i]+T2[i]+T3[i]+T4[i]+T5[i]+T6[i]+T7[i]+T8[i]+T9[i]+T10[i];
}
retAns[0] = F/prop*ans[0];
retAns[1] = F/prop*ans[1];
retAns[2] = F/prop*ans[2];
retAns[3] = F/prop*ans[3];
}
/// @brief HNC amp for qg->qgH with finite top (i.e. j^{+-}_H)
void g_gH_HNC(CLHEP::HepLorentzVector pa, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector pH, double mq, current &retAns)
{
const double F = 4.*mq*mq/HEJ::vev;
COM ang1a,sqa1;
current conjepsH1,epsHa,p1cur,pacur,pHcur,conjeps1,epsa,paplusp1cur,
p1minuspacur,cur1a,cura1,epsHapart1,epsHapart2,conjepsH1part1,
conjepsH1part2;
// Find here if pa, meaning the gluon, is forward or backward
bool gluonforward = true;
if(pa.z() < 0)
gluonforward = false;
jio(pa,true,p1,true,cura1);
joi(p1,true,pa,true,cur1a);
to_current(pa,pacur);
to_current(p1,p1cur);
to_current(pH,pHcur);
to_current(pa+p1,paplusp1cur);
to_current(p1-pa,p1minuspacur);
const COM aH1 = cdot(pHcur,cura1);
const COM oneHa = std::conj(aH1); // = cdot(pHcur,cur1a)
if(gluonforward){
// sqrt(2pa_-/p1_-)*p1_perp/abs(p1_perp)
ang1a = sqrt(pa.plus()*p1.minus())*(p1.x()+COM(0.,1.)*p1.y())/p1.perp();
// sqrt(2pa_-/p1_-)*p1_perp*/abs(p1_perp)
sqa1 = sqrt(pa.plus()*p1.minus())*(p1.x()-COM(0.,1.)*p1.y())/p1.perp();
}
else {
ang1a = sqrt(pa.minus()*p1.plus());
sqa1 = sqrt(pa.minus()*p1.plus());
}
const double prop = (pa-p1-pH).m2();
cmult(1./sqrt(2)/sqa1, cur1a, epsa);
cmult(-1./sqrt(2)/sqa1, cura1, conjeps1);
const COM phase = cdot(conjeps1, epsa);
const COM Fta = FT(-pa,pa-pH,mq)/(pa-pH).m2();
const COM Ft1 = FT(-p1-pH,p1,mq)/(p1+pH).m2();
const COM Falpha = FT(p1-pa,pa-p1-pH,mq);
const COM Fbeta = FL(p1-pa,pa-p1-pH,mq);
const COM h1 = H1(p1,-pa, pH, mq);
const COM h2 = H2(p1,-pa, pH, mq);
const COM h4 = H4(p1,-pa, pH, mq);
const COM h5 = H5(p1,-pa, pH, mq);
const COM h10 = H10(p1,-pa, pH, mq);
const COM h12 = H12(p1,-pa, pH, mq);
cmult(Fta*pa.dot(pH), epsa, epsHapart1);
cmult(-1.*Fta*cdot(pHcur,epsa), pacur, epsHapart2);
cmult(Ft1*cdot(pHcur,conjeps1), p1cur, conjepsH1part1);
cmult(-Ft1*p1.dot(pH), conjeps1, conjepsH1part2);
cadd(epsHapart1, epsHapart2, epsHa);
cadd(conjepsH1part1, conjepsH1part2, conjepsH1);
current T1,T2,T3,T4,T5a,T5b,T6,T7,T8a,T8b,T9,T10,T11a,
T11b,T12a,T12b,T13;
if(gluonforward){
cmult(sqrt(2.)*sqrt(p1.plus()/pa.plus())*prop/sqa1, conjepsH1, T1);
cmult(-sqrt(2.)*sqrt(pa.plus()/p1.plus())*prop/sqa1, epsHa, T2);
}
else{
cmult(-sqrt(2.)*sqrt(p1.minus()/pa.minus())*((p1.x()-COM(0.,1.)*p1.y())/p1.perp())
*prop/sqa1, conjepsH1, T1);
cmult(sqrt(2.)*sqrt(pa.minus()/p1.minus())*((p1.x()+COM(0.,1.)*p1.y())/p1.perp())
*prop/sqa1, epsHa, T2);
}
const COM boxdiagFact = 8.*COM(0.,1.)*M_PI*M_PI;
cmult(aH1*sqrt(2.)/sqa1, epsHa, T3);
cmult(oneHa*sqrt(2.)/sqa1, conjepsH1, T4);
cmult(-2.*phase*Fta*pa.dot(pH), p1cur, T5a);
cmult(2.*phase*Ft1*p1.dot(pH), pacur, T5b);
cmult(-sqrt(2.)*Fta*p1.dot(pa)*oneHa/sqa1, conjeps1, T6);
cmult(-sqrt(2.)*Ft1*pa.dot(p1)*aH1/sqa1, epsa, T7);
cmult(-boxdiagFact*phase*h2, pacur, T8a);
cmult(boxdiagFact*phase*h1, p1cur, T8b);
cmult(boxdiagFact*aH1/sqrt(2.)/sqa1*h5, epsa, T9);
cmult(-boxdiagFact*oneHa/sqrt(2.)/sqa1*h4, conjeps1, T10);
cmult(boxdiagFact*aH1*oneHa/2./sqa1/sqa1*h10, pacur, T11a);
cmult(-boxdiagFact*aH1*oneHa/2./sqa1/sqa1*h12, p1cur, T11b);
cmult(-phase/(pa-p1).m2()*Falpha*(p1-pa).dot(pa-p1-pH), paplusp1cur, T12a);
cmult(phase/(pa-p1).m2()*Falpha*(pa+p1).dot(pa-p1-pH), p1minuspacur, T12b);
cmult(-phase*Fbeta*(pa-p1-pH).m2(), paplusp1cur, T13);
current ans;
for(int i=0;i<4;i++)
{
ans[i] = T1[i]+T2[i]+T3[i]+T4[i]+T5a[i]+T5b[i]+T6[i]+T7[i]+T8a[i]+T8b[i]+T9[i]+T10[i]+T11a[i]+T11b[i]+T12a[i]+T12b[i]+T13[i];
}
retAns[0] = F/prop*ans[0];
retAns[1] = F/prop*ans[1];
retAns[2] = F/prop*ans[2];
retAns[3] = F/prop*ans[3];
}
} // namespace anonymous
// JDC - new amplitude with Higgs emitted close to gluon with full mt effects. Keep usual HEJ-style function call
double MH2gq_outsideH(CLHEP::HepLorentzVector p1out, CLHEP::HepLorentzVector p1in, CLHEP::HepLorentzVector p2out, CLHEP::HepLorentzVector p2in, CLHEP::HepLorentzVector pH, double mq, bool includeBottom, double mq2)
{
current cur2bplus,cur2bminus, cur2bplusFlip, cur2bminusFlip;
current retAns,retAnsb;
joi(p2out,true,p2in,true,cur2bplus);
joi(p2out,false,p2in,false,cur2bminus);
joi(ParityFlip(p2out),true,ParityFlip(p2in),true,cur2bplusFlip);
joi(ParityFlip(p2out),false,ParityFlip(p2in),false,cur2bminusFlip);
COM app1,app2,apm1,apm2;
COM app3, app4, apm3, apm4;
if(!includeBottom)
{
g_gH_HC(p1in,p1out,pH,mq,retAns);
app1=cdot(retAns,cur2bplus);
app2=cdot(retAns,cur2bminus);
g_gH_HC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq,retAns);
app3=cdot(retAns,cur2bplusFlip);
app4=cdot(retAns,cur2bminusFlip);
// And non-conserving bits
g_gH_HNC(p1in,p1out,pH,mq,retAns);
apm1=cdot(retAns,cur2bplus);
apm2=cdot(retAns,cur2bminus);
g_gH_HNC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq,retAns);
apm3=cdot(retAns,cur2bplusFlip);
apm4=cdot(retAns,cur2bminusFlip);
} else {
g_gH_HC(p1in,p1out,pH,mq,retAns);
g_gH_HC(p1in,p1out,pH,mq2,retAnsb);
app1=cdot(retAns,cur2bplus) + cdot(retAnsb,cur2bplus);
app2=cdot(retAns,cur2bminus) + cdot(retAnsb,cur2bminus);
g_gH_HC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq,retAns);
g_gH_HC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq2,retAnsb);
app3=cdot(retAns,cur2bplusFlip) + cdot(retAnsb,cur2bplusFlip);
app4=cdot(retAns,cur2bminusFlip) + cdot(retAnsb,cur2bminusFlip);
// And non-conserving bits
g_gH_HNC(p1in,p1out,pH,mq,retAns);
g_gH_HNC(p1in,p1out,pH,mq2,retAnsb);
apm1=cdot(retAns,cur2bplus) + cdot(retAnsb,cur2bplus);
apm2=cdot(retAns,cur2bminus) + cdot(retAnsb,cur2bminus);
g_gH_HNC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq,retAns);
g_gH_HNC(ParityFlip(p1in),ParityFlip(p1out),ParityFlip(pH),mq2,retAnsb);
apm3=cdot(retAns,cur2bplusFlip) + cdot(retAnsb,cur2bplusFlip);
apm4=cdot(retAns,cur2bminusFlip) + cdot(retAnsb,cur2bminusFlip);
}
return abs2(app1) + abs2(app2) + abs2(app3) + abs2(app4) + abs2(apm1)
+ abs2(apm2) + abs2(apm3) + abs2(apm4);
}
#endif // HEJ_BUILD_WITH_QCDLOOP
double C2gHgm(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector pH)
{
static double A=1./(3.*M_PI*HEJ::vev);
// Implements Eq. (4.22) in hep-ph/0301013 with modifications to incoming plus momenta
double s12,p1p,p2p;
COM p1perp,p3perp,phperp;
// Determine first whether this is the case p1p\sim php>>p3p og the opposite
s12=p1.invariantMass2(-p2);
if (p2.pz()>0.) { // case considered in hep-ph/0301013
p1p=p1.plus();
p2p=p2.plus();
} else { // opposite case
p1p=p1.minus();
p2p=p2.minus();
}
p1perp=p1.px()+COM(0,1)*p1.py();
phperp=pH.px()+COM(0,1)*pH.py();
p3perp=-(p1perp+phperp);
COM temp=COM(0,1)*A/(2.*s12)*(p2p/p1p*conj(p1perp)*p3perp+p1p/p2p*p1perp*conj(p3perp));
temp=temp*conj(temp);
return temp.real();
}
double C2gHgp(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector pH)
{
static double A=1./(3.*M_PI*HEJ::vev);
// Implements Eq. (4.23) in hep-ph/0301013
double s12,php,p1p,phm;
COM p1perp,p3perp,phperp;
// Determine first whether this is the case p1p\sim php>>p3p or the opposite
s12=p1.invariantMass2(-p2);
if (p2.pz()>0.) { // case considered in hep-ph/0301013
php=pH.plus();
phm=pH.minus();
p1p=p1.plus();
} else { // opposite case
php=pH.minus();
phm=pH.plus();
p1p=p1.minus();
}
p1perp=p1.px()+COM(0,1)*p1.py();
phperp=pH.px()+COM(0,1)*pH.py();
p3perp=-(p1perp+phperp);
COM temp=-COM(0,1)*A/(2.*s12)*( conj(p1perp*p3perp)*pow(php/p1p,2)/(1.+php/p1p)
+s12*(pow(conj(phperp),2)/(pow(abs(phperp),2)+p1p*phm)
-pow(conj(p3perp)
+(1.+php/p1p)*conj(p1perp),2)/((1.+php/p1p)*(pH.m2()+2.*p1.dot(pH)))) );
temp=temp*conj(temp);
return temp.real();
}
double C2qHqm(CLHEP::HepLorentzVector p2, CLHEP::HepLorentzVector p1, CLHEP::HepLorentzVector pH)
{
static double A=1./(3.*M_PI*HEJ::vev);
// Implements Eq. (4.22) in hep-ph/0301013
double s12,p2p,p1p;
COM p1perp,p3perp,phperp;
// Determine first whether this is the case p1p\sim php>>p3p or the opposite
s12=p1.invariantMass2(-p2);
if (p2.pz()>0.) { // case considered in hep-ph/0301013
p2p=p2.plus();
p1p=p1.plus();
} else { // opposite case
p2p=p2.minus();
p1p=p1.minus();
}
p1perp=p1.px()+COM(0,1)*p1.py();
phperp=pH.px()+COM(0,1)*pH.py();
p3perp=-(p1perp+phperp);
COM temp=A/(2.*s12)*( sqrt(p2p/p1p)*p3perp*conj(p1perp)
+sqrt(p1p/p2p)*p1perp*conj(p3perp) );
temp=temp*conj(temp);
return temp.real();
}
diff --git a/t/ME_data/ME_h_mt.dat b/t/ME_data/ME_h_mt_tree.dat
similarity index 100%
rename from t/ME_data/ME_h_mt.dat
rename to t/ME_data/ME_h_mt_tree.dat
diff --git a/t/ME_data/ME_h_mtinf.dat b/t/ME_data/ME_h_mtinf_tree.dat
similarity index 100%
rename from t/ME_data/ME_h_mtinf.dat
rename to t/ME_data/ME_h_mtinf_tree.dat
diff --git a/t/ME_data/ME_h_mtmb.dat b/t/ME_data/ME_h_mtmb_tree.dat
similarity index 100%
rename from t/ME_data/ME_h_mtmb.dat
rename to t/ME_data/ME_h_mtmb_tree.dat
diff --git a/t/ME_data/ME_jets.dat b/t/ME_data/ME_jets_tree.dat
similarity index 100%
rename from t/ME_data/ME_jets.dat
rename to t/ME_data/ME_jets_tree.dat
diff --git a/t/ME_data/ME_w_FKL_tree.dat b/t/ME_data/ME_w_FKL_tree.dat
new file mode 100644
index 0000000..3c21bd1
--- /dev/null
+++ b/t/ME_data/ME_w_FKL_tree.dat
@@ -0,0 +1,556 @@
+1.66735e-10
+4.4041e-08
+5.92405e-10
+0.0366658
+3.02387e-05
+6.33019e-05
+1.3673e-05
+0.0181281
+0.0140049
+2.7364e-07
+1.42529e-06
+0.376058
+1.4039e-07
+0.000204353
+3.25009e-06
+0.0202204
+4.52458e-06
+0.577611
+0.00126865
+1.42403e-05
+5.69446e-05
+3.24538e-06
+6.95782e-06
+502.564
+0.5466
+5.6995e-08
+0.0172244
+4.88591e-06
+1.38707e-07
+3.05536e-07
+0.00398169
+1.53828e-09
+7.82136e-12
+0.000227506
+4.39617e-08
+0.00013258
+0.000308858
+1.19829e-09
+2.09184e-06
+4.61199e-10
+0.00033569
+444.624
+2.96405
+6.36854e-09
+4.08676e-07
+0.14296
+2.36192e-08
+0.000639599
+2.76895e-06
+0.00415682
+1.31852e-09
+0.0549343
+7.37083e-05
+1.55399
+1.27455e-07
+3.36237e-07
+3.20486e-10
+3.5427e-05
+3.09312e-08
+0.0143784
+4.62088e-07
+9.02783
+0.00219736
+1.57684e-09
+1.32025e-05
+1.21352e-09
+2.81855e-07
+0.000574464
+1.50161e-07
+0.00157949
+0.000365113
+1.00946e-05
+0.0132691
+1.66234e-07
+2.28424e-07
+0.000192614
+18453.2
+0.000166803
+2.09525e-06
+3.20392e-07
+2.31454e-05
+0.000354074
+0.037135
+0.000172935
+4543.48
+4.26989e-05
+462.744
+2.12671e-09
+0.000418861
+5.95467e-05
+109.695
+235.696
+5.95639e-10
+1.72486e-05
+2.91207e-08
+1.81559e-05
+0.000350347
+7.02993e-08
+0.0704984
+2.96942e-07
+7.6676e-11
+5.13603e-05
+2.97235e-06
+0.223145
+1.64837e-07
+2.89016e-13
+9.51596e-12
+0.00375317
+1.85032e-07
+2.34686e-05
+1.20398e-05
+7.04312e-06
+2.02827e-06
+0.00464863
+2.03636e-05
+1.04609
+0.00591302
+4.77803e-07
+2.01462e-06
+0.000182964
+0.0489411
+2.61445e-09
+0.000100035
+5148.58
+0.000216259
+0.000332495
+6.04945e-08
+8.57456e-05
+2.76748e-05
+1.25562e-12
+0.000422337
+0.00133835
+0.00744617
+1.14326
+1.43195e-08
+6.38635e-07
+0.00862448
+4.37711e-06
+0.212646
+4.61289e+06
+4.01648e-05
+1.0193e-10
+2.31501e-05
+1.15591e-08
+1.13292e-07
+6.22732e-06
+2.5339e-05
+5.253e-08
+0.0957011
+0.00346245
+0.00202415
+0.000809109
+9.25638e-08
+0.00377243
+0.0273365
+4.03002e-07
+3.29569e-08
+7.93097e-06
+3.40496e-08
+0.000230937
+1.81192e-11
+6.81293e-10
+3.40697e-05
+0.240183
+0.00378173
+109851
+6.14314e-07
+1.35922e-06
+3.41102e-11
+3.51399e-07
+0.000198309
+0.000188839
+6.76021e-08
+0.000284694
+1.43864e-08
+5.16049e-09
+5.62878e-05
+0.770015
+0.247726
+9.93266e-09
+3.18242e-07
+1.00451e-05
+3.30423e-05
+1.06448
+6.225e-07
+6.60516e-08
+1.17284e-05
+0.00509921
+1.99188e-06
+1.50062e-10
+2.80521e-07
+2.828e-06
+0.445898
+2.33741e-08
+0.0750609
+1.61982e-08
+2.38598e-06
+3.91605e-10
+0.00044492
+9.87935e-05
+6.33457e-06
+0.00212007
+1.7068e-05
+12800.8
+7.84114e-05
+3.56353e-06
+1.53868e-07
+0.000147522
+1.59291e-06
+0.0760704
+6.16233e-07
+0.0110517
+0.132904
+0.0208312
+2.65967e-08
+5.05612e-05
+0.00799967
+6.28914e-07
+3.67441e-07
+0.711692
+1.4769e-07
+0.00133689
+9.65703e-05
+0.000140625
+0.000165611
+1.4526e-10
+84.6939
+7.30804e-05
+4.34679e-05
+1.13212e-05
+9.76841e-07
+0.138946
+0.857284
+4.80432e-07
+159.45
+0.0037607
+0.000330063
+8.6496e-05
+0.969737
+0.0461401
+548.271
+3.43983e-07
+3.45997e-06
+1.404e-12
+1.60387e-05
+4.70059e-07
+4630.86
+8.43376e-05
+7.53079e-06
+1.23222e-12
+0.0482061
+7.35608
+3.0975e-05
+1.80607e-05
+6.0602e-06
+1.25394e-08
+1.04957e-06
+3.32049e-06
+5.35062e-07
+0.00359605
+7.3544e-08
+9.09049e-06
+1.36527e-10
+2.98454e-06
+2.66174e-05
+7395.92
+3.77381e-07
+1.82459e-07
+0.0035087
+3.15536e-07
+0.00029903
+4.47086e-08
+0.000322599
+3.19833e-05
+1.44715e-05
+2.91342e-07
+3.66301e-07
+4.57968e-05
+5.56722e-10
+6.5099e-07
+1.54889e-07
+0.000163301
+2.26083e-11
+0.00015639
+3.58445e-05
+4.53362e-07
+2.07853e-05
+0.000543815
+0.000193472
+5.55595e-05
+0.0003522
+2.36567e-05
+4.95004e-06
+5.22835
+1.45351e-05
+0.00108416
+0.00155746
+0.740537
+2.04926e-06
+6.74606e-07
+0.525897
+2.86106e-09
+0.00140433
+9.73885e-07
+7.87825e-07
+9.11382e-07
+1.03271e-05
+0.00819761
+9.34316e-07
+102.715
+3.12936e-06
+8.17265e-05
+0.793069
+0.0394783
+0.249998
+3.2951e-10
+3.14814e-05
+6.84633e-07
+4.12731e-08
+3.30826
+3.83301e-05
+5.17716e-11
+0.00863598
+4.86168e-13
+2.07733
+1.52121e-05
+0.00762508
+3.9995e-07
+1.20631e-07
+8.72061e-14
+0.167408
+0.0349983
+2.80134e-08
+0.000149104
+42.7578
+0.0174395
+0.000805168
+4.51894e-05
+1.13497e-08
+0.00223994
+0.327996
+2.51105e-06
+6.52328e-06
+0.00307739
+0.00010686
+0.0826528
+3.40586e-09
+4.443e-08
+3.13325e-09
+0.393115
+2.24245e-05
+0.514506
+0.012296
+2.91465e-08
+6.13021e-11
+0.0106812
+2.1283e-05
+0.219704
+0.000904437
+0.00613495
+4.52535e-07
+0.00248037
+0.00206347
+9.02615e-05
+1.5555e-07
+5.08439e-06
+8.87029e-05
+0.00398221
+6.00901e-08
+3.42807e-06
+6.36962e-06
+1.09107e-05
+5.67e-06
+1.39205
+4.60967e-06
+0.101108
+0.0930008
+4.45779e-09
+0.000216392
+8.08965e-13
+0.00669366
+0.31851
+1.95031e-09
+1.27845e-08
+1.75725
+6.02183e-06
+9.47245e-06
+2.73499e-09
+1.31829e-06
+2.70901e-06
+6541.91
+0.0432065
+3.53221e-07
+6.71928e-05
+0.787997
+0.000468341
+0.0260916
+8.38173e-07
+9.59311
+1.42948e-06
+3.57455e-07
+9.90402e-07
+3.97145
+0.0663521
+1.9818e-06
+0.000625738
+1.44948e-06
+1.71863e-06
+3.2594e-06
+0.413732
+5.49708e-09
+81359.3
+9.32927e-06
+9.07516e-08
+8.47019e-06
+529.796
+8.03296
+2.46034e-05
+4.02271e-05
+6.76255e-05
+1.28593
+0.000184522
+5.46581e-11
+0.0292004
+0.00286131
+2.53505e-05
+2.14022e-10
+0.0119781
+3.36826e-11
+2.26669e-07
+3.71746e-07
+1.63972e-09
+1.79883e-05
+1.12241e-06
+0.000786734
+3.75728e-11
+1.04631e-05
+1.83096e-06
+0.000908951
+1.19379e-08
+5.85447e-06
+1.6532e-08
+3.08531e-05
+5.15335e-09
+6.67385e-08
+0.000987984
+0.0218896
+0.000673661
+1.4376e-07
+0.00919708
+1.93858e-06
+3.72294e-05
+0.00374186
+81844.1
+2.98802e-06
+0.113867
+3.84423e-06
+7.78978e-06
+40.3067
+1.64835e-06
+3773.67
+4.4311e-12
+0.031312
+0.000274236
+5.74005e-10
+4.09009e-06
+0.00976802
+6.13682e-07
+1.89011e-06
+3.18096e-07
+6.37238e-06
+7.34926e-06
+1.05138e-11
+0.00014211
+0.435855
+1.14883e-06
+8.41324e-08
+1.65963e-07
+0.000258003
+0.000278053
+3.97598e-06
+0.00385072
+6.17263e-06
+4.28477e+09
+3.35054e-05
+5.38143e-05
+26.8569
+0.000212268
+4.56831e-07
+2.43236e-06
+0.00044186
+1.61801
+1.29384e-05
+7.09936e-05
+0.0632148
+2.28731e-06
+8.46878e-06
+3.02247e-06
+4.90988e-08
+1.56847e-11
+63.7539
+3.22618e-07
+7.88706e-05
+4.0831e-07
+2.56971e-05
+0.00368127
+3.40935e-05
+7.56007e-08
+5.57694e-09
+2.19208e-07
+0.241623
+1.2466e-07
+1.21792e-06
+2.99997e-06
+7.90484e-05
+44.0162
+7.27495e-11
+0.255535
+20.4483
+1.10093e-09
+0.799591
+2.4149e-05
+0.0275875
+0.523435
+1.05659e-06
+0.0372607
+2.63343e-08
+9.11403e-07
+0.000531948
+3.19487e-07
+1.22984e-11
+468.197
+1.06812e-09
+0.00768798
+1.39065e-05
+0.000886794
+1.76499e-10
+1.0843e-05
+0.00534105
+2.39915e-11
+4.19033e-05
+0.00318565
+8.05371
+5.87035e-10
+1.77471e-07
+78509.9
+15.3982
+6.79612e-07
+1.14968e-06
+0.0236821
+8.65278e-05
+0.317341
+0.0186315
+1.09832e-10
+5.45839e-10
+5.49319e-09
diff --git a/t/ME_data/ME_w_FKL_virt.dat b/t/ME_data/ME_w_FKL_virt.dat
new file mode 100644
index 0000000..e39c31f
--- /dev/null
+++ b/t/ME_data/ME_w_FKL_virt.dat
@@ -0,0 +1,556 @@
+0.0497099
+0.00328534
+0.0147012
+0.020193
+0.000309577
+0.00560437
+0.00505377
+0.000343753
+0.0399841
+0.642162
+0.169265
+0.00330061
+0.00159609
+0.0809455
+0.0655149
+0.000195609
+0.0272479
+6.61767e-06
+0.0811269
+0.0012771
+0.398515
+8.82763e-05
+0.945396
+0.000671791
+0.00264372
+0.0139293
+0.0751354
+0.0155671
+0.248777
+0.00341141
+0.0066515
+0.000488746
+0.0413859
+0.016005
+0.0186275
+0.0179902
+0.457869
+0.128595
+0.0012122
+0.00101076
+0.00206961
+8.9809e-06
+0.00168069
+0.00281786
+0.134534
+3.35655e-05
+0.0011696
+0.00198948
+0.122625
+0.000103552
+0.418435
+0.000172599
+0.0033688
+1.87279e-05
+0.0391809
+0.572826
+9.97036e-06
+0.00383872
+0.0606418
+0.0523566
+4.40603e-05
+0.000364929
+4.46366e-05
+0.122265
+0.321635
+0.00192007
+0.125465
+0.453387
+0.118487
+0.000408672
+0.00535771
+0.126006
+0.0465388
+0.166726
+0.0178628
+0.0618902
+4.56415e-05
+0.0394273
+0.002585
+8.79209e-05
+0.00455023
+0.328086
+0.0574179
+0.427367
+1.17608e-05
+0.316322
+0.00138375
+0.00563467
+0.122478
+0.94281
+0.00275501
+0.000245034
+0.0113642
+0.00159055
+0.0630292
+9.12609e-05
+0.00284041
+0.94737
+0.00119309
+0.0476172
+0.218217
+0.010076
+0.00122674
+0.00552329
+0.391251
+0.0025612
+0.000453071
+0.0130086
+5.28188e-05
+0.0087111
+0.000940431
+0.450528
+2.83656e-05
+0.00974776
+0.0977905
+0.000772798
+6.37054e-05
+0.00946609
+0.634904
+0.00541805
+0.000252007
+0.00180654
+0.00287226
+0.0151483
+0.0186047
+0.000399212
+0.279313
+0.000767438
+0.00268605
+0.000789699
+0.00178272
+0.0751404
+0.00569408
+0.00822184
+0.00257023
+0.259267
+0.00544876
+0.00301817
+5.43607e-06
+0.000929501
+0.0198565
+0.203743
+0.0986335
+0.399346
+0.174506
+0.0128236
+0.000295165
+0.000271028
+0.000221462
+0.092837
+0.00549042
+0.000588
+0.004004
+0.00038862
+0.0397239
+0.000969016
+0.447361
+0.034203
+0.00409697
+0.179071
+1.19907e-05
+0.00741877
+0.000119697
+0.000426041
+0.0520057
+7.23046e-05
+0.419917
+0.437248
+0.000805709
+0.00680678
+0.208606
+0.00035519
+0.350762
+0.0228401
+0.0236822
+1.52997e-05
+0.000880712
+0.00206161
+1.61694e-05
+0.257217
+0.0229676
+0.414855
+0.00535397
+0.0015876
+0.852536
+0.193917
+0.0176488
+0.00103398
+0.644271
+0.0325095
+0.0127118
+0.347172
+0.000584263
+0.301568
+0.000265323
+0.00162253
+0.000963908
+0.059089
+0.00549926
+0.221323
+0.000102401
+0.0323381
+0.412372
+0.000410601
+0.00382715
+0.470508
+0.000158385
+0.0639688
+0.00522347
+0.00383838
+0.158371
+0.00209653
+0.000578405
+5.46861e-05
+0.438386
+0.116989
+0.000329175
+0.0391663
+0.568486
+0.000728723
+0.000105152
+0.0357729
+0.0197163
+0.040167
+0.0225419
+1.20972e-05
+0.000175654
+0.628918
+1.13026e-05
+0.154973
+0.0039188
+0.000409658
+0.00753526
+0.0117746
+0.00479097
+0.000709101
+0.0601758
+0.509616
+0.0115003
+0.000367883
+0.000239623
+1.33523e-05
+0.0518589
+0.0129499
+0.00205639
+0.608829
+0.000307885
+0.00616058
+0.0507761
+0.0174353
+0.042298
+0.000625384
+0.0268547
+0.000366927
+0.167232
+0.393889
+0.177583
+0.00111827
+0.234087
+0.110054
+0.57153
+0.00728181
+0.000146395
+0.00102076
+0.403359
+4.37874e-05
+0.00101398
+0.0808867
+0.000487696
+0.000677843
+0.00605401
+0.224471
+0.10263
+0.161427
+0.0088327
+0.262653
+0.972856
+0.0846882
+0.000702771
+0.0131973
+0.893805
+0.00128189
+0.0794788
+0.00241231
+0.041713
+0.0639807
+4.26811e-06
+0.70333
+0.0180322
+0.00279468
+0.000519782
+0.00672012
+0.0243523
+0.0143111
+0.275634
+0.166137
+0.0104151
+0.0708953
+6.79513e-05
+0.0424011
+0.000108608
+0.0179019
+0.0178296
+0.0423429
+0.00791899
+0.668533
+0.987576
+0.00625421
+0.331144
+0.000138486
+0.00033895
+0.000256202
+0.000351972
+0.0295068
+0.000729216
+5.73111e-06
+0.00071512
+0.200453
+0.36089
+0.0109833
+0.00092795
+0.0928141
+0.0938798
+0.042888
+0.00192403
+0.00188736
+0.270049
+0.000226073
+0.753174
+0.0144809
+0.0022794
+0.000194553
+0.0411431
+0.0018625
+4.29789e-05
+7.79974e-06
+0.000828788
+0.234458
+0.0174216
+0.00352481
+0.0787032
+0.750794
+0.0825594
+0.0660201
+0.211884
+0.0001425
+0.0979417
+0.0190508
+0.14727
+0.000189859
+0.519813
+9.10048e-05
+0.000165997
+0.031302
+0.063854
+0.0513921
+0.530132
+0.0891198
+0.000356927
+0.0444384
+0.0469301
+0.1688
+0.00219657
+0.026455
+0.636943
+0.721106
+0.210272
+0.00219831
+0.0402371
+0.0800513
+0.000340376
+0.00255903
+0.11277
+0.000792799
+0.771612
+0.00689809
+0.0921421
+0.00159501
+0.00264901
+0.00461346
+0.00501571
+0.0740425
+0.00643918
+0.000622319
+0.0673963
+0.000322712
+0.66385
+0.0698823
+0.044905
+0.000902134
+0.00622504
+0.0145289
+0.10609
+0.0249262
+0.000214141
+0.00126957
+0.361332
+0.0612673
+0.00213986
+0.000205457
+0.014436
+0.0415126
+0.00453427
+0.110129
+0.000563909
+0.000171548
+0.037811
+0.195567
+0.334809
+0.000212302
+0.0612249
+6.28441e-05
+3.54296e-05
+0.0390224
+0.0589327
+3.17812e-05
+2.33628e-05
+0.00270777
+0.0901005
+3.84658e-05
+4.39333e-06
+0.00456314
+0.00166269
+0.000128473
+0.0215438
+0.860329
+0.000270542
+2.44465e-06
+5.34295e-05
+0.000525535
+0.0908858
+0.00967689
+0.0373088
+0.0585668
+0.000408192
+7.82725e-05
+0.65669
+0.00532279
+0.0121984
+0.855695
+0.646552
+0.0124097
+0.227927
+0.0939566
+0.720134
+0.0160724
+4.58945e-05
+0.150884
+0.060642
+0.191017
+0.000414464
+0.0024551
+0.0138826
+2.2266e-06
+0.00591809
+0.0078036
+0.129411
+0.204875
+0.000529919
+0.25251
+0.000135085
+0.0102931
+0.000116482
+0.000230741
+0.000252837
+0.862278
+0.000960436
+0.0154629
+0.000162838
+0.0287251
+0.794307
+0.00414683
+0.0692738
+0.003297
+0.000106313
+0.0335229
+8.57734e-06
+0.532292
+0.000580644
+0.00390132
+0.0448218
+0.024409
+0.00506512
+9.71647e-06
+0.00510581
+8.25e-05
+8.13446e-05
+4.42837e-05
+0.212912
+0.00934719
+6.16408e-05
+1.08719e-05
+0.499308
+0.00179902
+4.43106e-06
+0.0121883
+0.000234417
+0.00680043
+0.00812466
+0.000124486
+1.79161e-06
+0.000160851
+0.0557466
+0.0703156
+0.395348
+0.0462632
+0.00749533
+0.484603
+0.338947
+0.0103385
+0.000179026
+0.230775
+0.0791346
+0.0415642
+0.0308446
+0.000592224
+0.182154
+0.00271044
+0.000109131
+0.615301
+0.000182805
+0.00178521
+4.17891e-06
+0.00511286
+0.19323
+0.0465622
+0.142455
+0.00504891
+0.00494418
+0.0876792
+0.0347178
+0.00110251
+0.0022339
+0.0146147
+0.0196155
+0.00217005
+0.117797
+0.05899
+0.00141735
+0.000185495
+0.00890192
+0.000249425
+0.000601579
+9.03852e-05
+0.00192577
+0.000251987
+1.81331e-05
+0.0825302
+0.000233496
+0.00368371
+0.101285
+0.00016656
+0.0074816
+0.615504
+0.0115954
+0.000374781
diff --git a/t/ME_data/ME_w_tree.dat b/t/ME_data/ME_w_tree.dat
new file mode 100644
index 0000000..2f71330
--- /dev/null
+++ b/t/ME_data/ME_w_tree.dat
@@ -0,0 +1,3523 @@
+5.845866667e-05
+5.845866667e-05
+0.0005597095939
+0.164877405
+1.238277008e-05
+0.001099368374
+0.2174278896
+3.104776438e-10
+5.213398474e-05
+4.87353531e-09
+0.01249264006
+6.234685231e-07
+1.081473456e-06
+0.0008338875842
+8.857168747e-05
+0.003593268171
+8.508318861e-06
+1.274524903
+0.001632806123
+12.8651116
+0.0004967058822
+6.044210558e-06
+0.000676372557
+0.0008814709527
+7.456359607e-07
+0.001397055135
+8.52127656e-06
+0.001887481386
+3.604717921e-07
+0.0003377915782
+4.272685538e-05
+9.020992352e-05
+1.880300941e-05
+1.896382771e-07
+1.02773478e-06
+1.362661111e-06
+7.334216029e-05
+1.606964214e-06
+1.259559267e-05
+0.0002753267863
+1.085203133e-05
+0.00183775394
+0.03879034647
+0.01180018165
+4.140890176e-06
+0.0001267343683
+0.0001971412599
+6.013059081e-05
+0.005015968731
+0.0247059457
+0.004772978843
+0.0003478043589
+9.259887163e-06
+3.780332554e-05
+0.03715338142
+3.597201027e-05
+0.003009809659
+2.72420715e-07
+0.0001672456658
+3.830198838e-05
+0.0002344735041
+0.04145865145
+0.04561154975
+1.703280615e-05
+0.003800472708
+4.295918746e-05
+2.910915134e-05
+5.615798329e-07
+3.540332527e-06
+0.01040962955
+4.163794112e-06
+8.77755675e-07
+2.960284954e-06
+4.805937595e-06
+8.581414801e-08
+3.838091053e-05
+0.0001094850646
+2.918892677e-06
+5.939462321e-07
+2.297697138e-05
+1.063615033e-05
+1.431149858e-05
+6.161211871e-08
+1.63523192e-06
+1.068237563e-07
+0.00931404829
+1.281206788e-05
+3.219662386e-05
+0.001363354764
+1.563835637e-05
+5.281201375e-06
+0.244479713
+2.006935448e-05
+4.462060767e-06
+3.132902219e-06
+0.06965116331
+0.0003403971027
+0.0004061313269
+0.000286882512
+7.934274488e-06
+0.1009206201
+5.581155912e-07
+7.953784559e-06
+1.227616708e-06
+5.353172135e-06
+7.997062103e-06
+3.834292465e-06
+0.0564784376
+0.000861058728
+8.582389064e-07
+5.143176592e-05
+2.640005444e-07
+0.004532211177
+0.02024218468
+0.0006202736465
+2.263418055e-05
+3.067543452e-07
+0.02250232853
+4.159681825e-05
+1.07504599e-06
+1.591891897e-06
+0.9125597854
+1.013591958e-05
+1.826117506e-05
+3.800824593e-05
+0.003555293734
+0.0001981514519
+4.504429881e-05
+1.508651117e-08
+1.639529349e-05
+9.474658049e-07
+1.947713058e-07
+4.02135672e-07
+0.001725090853
+8.019780552e-08
+0.0003340110247
+0.004733965344
+1.55383349e-06
+0.0002396797742
+2.378194257e-06
+0.0002105313386
+0.000611885514
+0.0003530841489
+6.144453469e-05
+0.0004924702101
+0.003354066228
+3.952424326e-05
+1.726625219e-06
+0.0242303487
+1.302660805e-07
+0.002663139889
+1.09900607e-06
+6.758779892e-07
+0.0006405810556
+1.385333353e-06
+1.220744643e-06
+4.870107671e-07
+0.006236705279
+0.02151858383
+3.685322317e-06
+0.0008095104486
+3.458337371e-07
+1.77682106e-08
+2.778225915e-05
+2.518147733e-06
+3.054811801e-07
+9.633949058e-05
+3.06357109e-06
+1.002092148e-06
+1.271139876e-05
+1.360976123e-05
+1.086172628e-05
+1.525276977e-06
+6.490647857e-06
+0.0002283714482
+2.824863725e-05
+8.216755852e-06
+1.433428156e-05
+0.0008642439685
+7.341349894e-07
+1.490016449e-06
+6.506587002e-06
+8.105224022e-07
+0.01137692845
+0.01171223861
+8.410402103e-06
+7.619604013e-05
+0.0005321834645
+1.061759713e-07
+0.006402793101
+3.739394931e-06
+0.0001445229467
+2.917551793e-05
+1.764790853e-07
+8.223644257e-05
+2.611501245e-05
+0.002792494123
+6.918182525e-06
+0.0002499475673
+4.10421708e-05
+1.578639006e-06
+0.0001611429284
+6.17002333e-09
+0.0001286075239
+0.001213394329
+2.532644787e-06
+0.1142713043
+4.526923541e-07
+3.055264981e-06
+0.05156595727
+0.001030500948
+1.058740147e-07
+2.604449972e-05
+11.87417008
+0.0006387327215
+1.366235162e-07
+0.001188004573
+3.347702941e-06
+2.361201543e-05
+0.0001733654682
+0.0001392942455
+4.040019727e-05
+3.703082762e-05
+4.705242675e-07
+7.430518531e-06
+7.701673381e-06
+4.060990623e-07
+6.375797077e-06
+0.0001288608957
+0.01437974533
+1.133588729e-05
+4.04222159e-10
+0.0001493634726
+8.402163035e-06
+0.0002462393196
+0.0003896123871
+0.0358262502
+1.082478444e-05
+3.083818638e-07
+0.0004207161145
+1.003074917e-05
+5.947339279e-06
+0.01496297084
+3.524764297e-05
+0.0004140223966
+5.37071745e-08
+7.434802213e-05
+0.0003854988873
+1.656243873e-06
+0.01077424132
+2.82288489e-07
+3.042202689e-06
+0.01602895732
+0.0004438415281
+5.903621622e-07
+0.08174661235
+1.935697095e-05
+0.000151140291
+1.78922084e-05
+5.207672106e-07
+0.0002178121694
+3.728191251e-06
+4.925187409e-06
+8.238987907e-05
+3.703217294e-05
+0.0002135040284
+0.0008860089534
+0.02507374943
+0.001400241935
+1.913243681e-05
+5.54173035e-05
+1.176427166e-06
+0.03233599044
+1.695924774e-05
+0.0001082735738
+2.3628291e-06
+3.290390716e-05
+0.0002726212184
+1.510351352e-07
+1.673568792e-05
+0.0001007268602
+4.107823013e-07
+5.516794282e-06
+1.938753577e-05
+0.0003028926336
+2.302499391e-05
+8.783589766e-05
+6.899470202e-08
+9.781912402e-06
+2.676701917e-06
+0.000130215145
+0.000265502357
+5.478604377e-08
+4.70610071e-05
+3.072411757e-05
+7.365342097e-05
+0.0006848328635
+0.0003834719419
+1.302988468e-05
+0.01615655542
+0.1746245979
+4.915971606e-08
+7.41352614e-05
+2.825200344e-06
+6.168123385e-05
+1.357745105e-06
+1.636306875e-05
+3.215608056e-07
+0.002858009513
+0.001930898505
+0.0005449670351
+4.258850092e-06
+1.015172939e-05
+6.180204617e-05
+2.762385555e-06
+5.029916189e-06
+0.006987505052
+7.798750493e-05
+0.006306407233
+6.522670586e-06
+4.062241508e-07
+3.139942573e-05
+0.001245934879
+2.46292422e-05
+5.964194995e-06
+0.0004856836599
+0.0001707164632
+8.635515251e-07
+0.0001260860766
+0.0002326604394
+2.20517852e-07
+2.265184229e-06
+5.950037201e-06
+0.02878480043
+7.560643045e-06
+8.509463069e-07
+1.466825244e-07
+1.364321431e-05
+0.005469791231
+0.05490727566
+3.466115342e-07
+0.04751183436
+0.00024977012
+0.001562238859
+3.441367175e-07
+0.004658203807
+0.0002499330644
+1.761752442e-06
+1.96648007e-08
+1.903512469e-06
+3.200646313e-06
+1.128951995e-05
+2.895504678e-05
+0.0003226457
+0.002799345805
+0.0007448785184
+8.028225473e-06
+0.002301131749
+4.797970902e-06
+0.0001740056417
+9.375395441e-06
+1.736613357e-06
+3.936239031e-05
+8.921563537e-05
+7.839164024e-05
+1.832253936e-05
+0.001679967814
+0.05210485949
+0.0005982834069
+1.248432932e-05
+1.904411948e-05
+1.26166073e-07
+2.998788749e-05
+0.0001913898204
+0.0007334318493
+2.869553634e-09
+1.114755501e-05
+2.324258198e-05
+0.0001352480475
+0.0006504696478
+0.001258510648
+0.005388902567
+0.1146329779
+1.740977163e-06
+0.001055941394
+0.0006479731274
+1.569580485e-05
+0.02518352958
+2.34382277e-05
+4.49391368e-05
+0.002127052626
+1.232569588e-08
+1.552108897e-06
+0.0001438252678
+1.984755364e-05
+4.425660607e-06
+0.06036163849
+1.706813069e-05
+6.82971402e-05
+0.0001356940312
+2.939503129e-07
+0.002473587727
+0.0001873592438
+1.86190068e-07
+1.963823387e-06
+4.52770324e-06
+0.02604548503
+0.7954083918
+3.741185642e-08
+0.0001894596879
+1.285093752e-06
+3.847839116e-05
+7.038505399e-07
+2.921132422e-05
+0.00226021646
+1.070167395e-05
+5.45055332e-10
+2.354054662e-05
+1.047796615e-06
+0.00387253967
+2.421888817e-05
+0.00333063566
+0.0004092125723
+0.0001211823431
+0.4853407027
+1.275086111e-06
+0.0001955012816
+7.960320746e-05
+0.0081104
+0.9004667908
+2.737438748e-08
+0.007211297939
+0.002507564043
+2.26636944e-07
+0.0009351442706
+155.0413151
+8.303854284e-07
+0.7558195307
+2.15115601
+0.0002474448548
+0.000184616816
+0.06389049799
+1.38755391e-05
+8.806321315e-06
+7.285917011e-08
+1.288512325e-09
+9.808129999e-06
+6.27387243e-07
+2.137974303e-05
+2.829715652e-06
+2.888533169e-05
+4.986055004e-06
+3.687875904e-06
+3.534685605e-05
+1.622996645e-06
+8.146732951e-06
+3.419775073e-07
+0.3926232762
+6.8888458e-07
+0.003015481667
+6.355950236e-06
+1.588671112e-06
+0.003555489651
+0.02845804287
+0.0001514145942
+0.001403717424
+0.01756840182
+0.0009441846791
+3.437323294e-05
+0.005683174668
+0.008942921936
+2.950184551e-06
+1.251407837e-05
+5.795795086e-06
+0.001262544311
+1.925701113e-07
+7.568475469e-09
+0.0001337439055
+1.617949332e-05
+6.636291682e-07
+4.469073018e-06
+0.008012974338
+8.936038448e-05
+5.110662793e-05
+2.666094424e-07
+0.0001431486202
+8.09548794e-06
+0.0008117623999
+2.197125404e-05
+5.341173122e-06
+2.827700815e-05
+5.15242883e-05
+1.285384922e-07
+0.001340701001
+1.996397129e-06
+0.04951498525
+8.605390207e-07
+1.006999201e-05
+3.4996961e-06
+0.0001279295918
+0.0001494486858
+1.392951885e-06
+0.0003333890925
+0.003282171103
+1.20600893e-09
+2.694687337e-07
+3.658291865e-05
+7.86494727e-05
+6.741661493e-07
+0.000125081009
+1.026783208e-05
+5.842239085e-06
+0.04352446663
+8.013314682e-07
+6.050098684e-07
+0.06264350563
+0.02688640542
+1.951349999e-05
+5.012802944e-06
+0.008327160728
+2.714316917e-05
+0.002992000708
+1.45130435e-06
+4.209613291e-06
+0.0006091383334
+2.573817525e-06
+1.56963461e-05
+1.961026818e-06
+1.688532857e-07
+0.04410765852
+7.823518775e-07
+0.0006953685847
+1.821398444e-05
+6.485049511e-06
+0.0007833355882
+1.649985194e-06
+7.189958716e-05
+1.435252202e-05
+2.0065669e-05
+0.1219440875
+3.684900156e-06
+4.662493958e-05
+1.888959532e-05
+2.748338721e-05
+0.03051503465
+1.773735853e-07
+5.819345927e-07
+1.375819858e-06
+2.546020239e-06
+0.01492757464
+1.830512164e-06
+0.0008222660675
+2.68503019e-05
+1.877082525e-06
+2.193179416e-05
+8.446637435e-07
+5.493465625e-06
+2.823976608e-05
+1.199497925e-06
+0.03679720621
+0.0004846263043
+7.555971138e-07
+1.892598405e-07
+1.43005773e-05
+0.1298322927
+1.642236981e-05
+6.382559688e-07
+7.527720274e-06
+0.002343494753
+2.728593418e-05
+4.055300563e-05
+9.28575229e-08
+1.350089293e-07
+0.003724171286
+0.0008681879589
+0.0001306343492
+2.526585783e-06
+1.64172915e-05
+5.572912046e-07
+0.0001072229289
+0.01275589013
+0.3853037615
+0.0005971594455
+2.909539573e-06
+0.000375995401
+1.309991037e-05
+2.949193676e-08
+9.805615567e-07
+5.710558171e-05
+0.0003297872852
+4.095933859e-08
+4.576673808e-06
+1.144591246e-06
+0.003789400419
+4.804712141e-08
+0.002201844621
+0.008060097815
+0.1158087002
+0.000495542311
+5.321416859e-06
+7.133532155e-07
+0.01914996214
+0.0004349260176
+4.896915084e-08
+0.0007634056989
+1.160778998e-05
+0.0001396706074
+8.427506827e-06
+1.887324038e-05
+1.432910804e-10
+0.1554683643
+3.282828629e-07
+0.005628636813
+8.043388548e-06
+0.003930588633
+0.0001279191022
+1.443538095e-07
+6.98043349e-05
+3.49574152e-05
+0.0006385207779
+4.642399133e-08
+7.884483492e-05
+6.29745737e-05
+0.0003529517611
+1.482570942e-05
+0.01000507811
+2.286119559e-05
+0.1523893924
+1.603196535e-07
+8.723420194e-06
+3.28439035e-06
+9.859092285e-05
+0.005898623773
+5.937054694e-06
+0.00177509443
+4.951715444e-06
+6.908918308e-08
+9.811912102e-06
+5.362385831e-07
+0.0001644521822
+4.037683749e-09
+0.0252754326
+8.283611074e-06
+0.000303042793
+0.001591921296
+1.983655902e-05
+0.002302940297
+2.908640572e-06
+1.629505636e-07
+0.007460574416
+0.0001090316624
+1.195697504e-05
+5.649361039e-06
+0.0002041953721
+9.529175802e-06
+7.058379318e-06
+0.00273886735
+6.599070362e-06
+0.0009192974427
+2.849396168e-06
+4.006247935e-06
+7.748445771e-05
+0.001535487761
+2.824906311e-08
+2.000122943e-08
+0.002327813189
+4.421189054e-05
+9.268463222e-06
+5.863285806e-07
+2.096433219e-05
+8.390568507e-06
+1.89739139e-06
+0.0001591234528
+3.401570422e-06
+0.001492945444
+0.01089906857
+0.004044265839
+0.0003021922076
+0.03439557447
+0.0001165015448
+6.791333352e-06
+0.0001434349119
+3.401825103e-05
+8.806501707e-06
+0.05547353762
+9.225131237e-06
+0.0002390805293
+7.198093146e-05
+2.458149161e-06
+0.05924981137
+0.001691612673
+3.403389153e-06
+2.780668585e-07
+0.001216512851
+0.00345602963
+0.003659218892
+0.002972242457
+4.410189865e-07
+9.472323855e-05
+0.0001192718853
+8.589861261e-05
+2.566123056e-05
+2.226694724e-07
+2.009606741e-05
+5.727408987e-06
+1.745939618e-06
+1.888084834e-07
+9.328503251e-05
+0.0005658922145
+0.01615175798
+0.001279094664
+0.0001371569691
+3.146783993e-05
+5.477453775e-05
+9.15128413e-06
+0.002089084512
+7.282943833e-06
+3.289027452e-07
+2.961185114e-05
+0.0005405365666
+4.948147776e-06
+3.963784572e-05
+2.677898294e-06
+3.089145619e-07
+7.536711559e-06
+3.844788307e-06
+4.23263168e-05
+6.588158675e-07
+0.1115554004
+7.448837332e-05
+2.118489802e-05
+2.025326762e-05
+4.147514351e-05
+2.535883326e-05
+1.717207623e-05
+5.011010955e-05
+1.260371653e-05
+5.599839229e-08
+1.354284932e-06
+3.991802594e-05
+0.0001924961938
+1.745638921e-05
+0.007860747357
+1.918897457e-06
+8.346390268e-05
+0.001245385467
+4.18313987e-12
+0.000401643271
+1.152545503e-08
+9.167489034e-05
+3.018606254e-07
+2.914735265e-07
+6.820950859e-07
+5.499553593e-06
+0.0001408726378
+0.002264617851
+3.276928831e-06
+9.315309103e-05
+0.001575737327
+3.659423859e-06
+1.257190987e-05
+4.855687442e-05
+0.009750180008
+6.318326179e-06
+4.93297812e-06
+0.002009397541
+0.001013065054
+7.932418402e-08
+0.05023339101
+0.0001188849355
+2.29644797e-05
+0.0001202931979
+0.002029115737
+8.808272697e-06
+1.136035862e-05
+2.852464437e-06
+1.062952945e-05
+0.005828709169
+9.331914748e-05
+0.0009325023676
+0.002833280891
+0.000735770138
+7.596824104e-06
+6.203557036e-10
+0.0002398879967
+2.824534754e-06
+0.001463786462
+6.83480766e-06
+0.0006022971379
+0.0004052585256
+5.223968522e-06
+1.838743566e-08
+0.0001316901261
+0.0007354678202
+3.712764234e-05
+0.0001049914017
+1.428003628e-06
+6.688208009e-06
+0.00139415912
+4.131647988e-06
+0.006434338874
+3.841821188e-07
+0.002656963601
+8.446869821e-05
+0.002087235898
+3.316158731e-06
+9.96477117e-07
+1.778363638e-05
+0.002913950719
+1.327953017e-05
+8.193276267e-05
+0.0002004183852
+1.714201801e-05
+1.980424399e-06
+3.09278907e-05
+0.0001025400202
+6.954841186e-06
+0.004459568349
+0.04722955009
+2.41336752e-06
+6.112226535e-06
+0.001171983128
+3.962522736e-05
+0.05706691747
+5.45929166e-06
+0.0003107148837
+6.82057008e-06
+0.000161778673
+5.964094026e-06
+1.13804191e-07
+6.386657315e-07
+2.759494776e-07
+1.456244436e-08
+1.060087949e-06
+2.809554607e-07
+1.878267345e-06
+0.007130660423
+0.0007287299113
+3.258458174e-05
+8.07683517e-07
+6.600990831e-06
+3.358428223e-06
+3.248032257e-05
+0.0002264557367
+0.0002975450859
+2.245001341e-05
+6.873427104e-05
+3.609993195e-06
+7.382139051e-06
+8.946472104e-06
+0.0004600684992
+3.996261121e-07
+6.079582506e-08
+4.579722109e-06
+7.617120591e-05
+1.111775663e-05
+0.0001386058772
+0.05745945226
+9.469744916e-05
+4.696514941e-05
+2.020407872e-05
+6.983467494e-05
+0.005301752622
+0.0001347882743
+6.492615622e-05
+2.401488665e-06
+6.708066023e-05
+7.034342829e-09
+4.498163861e-06
+8.415831988e-06
+2.184123631e-05
+0.005343857118
+0.06659613416
+0.0002266964674
+0.01904453264
+0.0007464321788
+3.568231088e-06
+2.575387744e-06
+1.335581316e-05
+1.058655107e-05
+0.0004054675624
+0.0001335213243
+6.972218225e-09
+4.897465523e-06
+7.406672376e-06
+0.0002276068751
+4.81090812e-05
+0.003553619618
+9.646914869e-05
+2.097234297e-05
+5.799670904e-10
+4.144198272e-06
+4.906539612e-06
+0.003652693588
+0.0003855081416
+2.843697456e-07
+8.62543507e-08
+9.939370221e-06
+8.583758166e-06
+3.354566271e-05
+2.40718302e-05
+2.952001822e-05
+0.0004758556561
+0.0007973751955
+3.071239447e-05
+0.001038349104
+0.001654900924
+8.106183423e-06
+1.417517517e-05
+9.546878778e-05
+0.0766647737
+5.456984819e-06
+3.09853044e-06
+2.483157249e-09
+0.002881056388
+0.2823658633
+1.683603191e-08
+1.08578588e-05
+1.49976881e-07
+0.0004118572547
+4.296681364e-06
+0.0001582848801
+4.140036568e-06
+0.0002190682542
+0.002992037285
+0.2882349297
+0.0002647117958
+15.70027754
+0.002903313787
+7.33019231e-05
+6.590202124e-08
+9.003700016e-05
+5.226878855e-06
+0.008233181025
+2.400494098e-07
+2.61127073e-07
+0.0002895212101
+3.604785239e-07
+1.096798838e-05
+1.865834314e-05
+3.950696048e-06
+8.856598146e-06
+0.0001681684742
+2.611298096e-06
+0.0007296104383
+0.0002709094388
+0.01562074429
+8.176526975e-06
+0.0004634588257
+4.953614413e-06
+6.702538552e-05
+4.212304718e-06
+1.514128897e-05
+0.07175070213
+6.378032767e-05
+3.228755877e-06
+0.003299673199
+1.42400409e-06
+0.0005127485564
+3.134259033e-05
+0.06776189737
+0.02753077423
+1.632748427e-05
+3.384391557e-08
+2.690572706e-07
+9.670445296e-05
+5.101960225e-07
+0.0003038627079
+2.09400365e-05
+2.571793384e-05
+3.441687027e-05
+0.00590562962
+0.002916076403
+1.394457259e-07
+0.0004939065746
+0.0005155436368
+3.332511186e-05
+2.949884497e-06
+4.212832661e-07
+0.001449165194
+1.66988575e-05
+1.702094606e-05
+0.08358109034
+2.896129202e-06
+1.017101815e-06
+0.0001449882497
+0.00667464967
+5.736532316e-06
+9.429753816e-07
+0.00446361932
+1.303649777e-06
+1.306074839e-05
+1.191021496e-05
+0.0006604731732
+2.509744599e-07
+6.792796017e-09
+0.0008592758202
+7.998278425e-06
+1.569339563e-06
+0.0001670030159
+4.675591277e-05
+4.78921617e-06
+3.175145611e-06
+6.454825082e-08
+0.0005985929183
+0.01641552845
+6.637529385e-06
+1.119165781e-06
+9.522358724e-07
+0.0002699987751
+0.0003015665237
+0.0007760873861
+0.0004021591159
+2.289389397e-06
+0.002135955797
+0.008254598639
+2.811300012e-06
+1.668612491e-05
+4.134765106e-05
+0.00283836989
+8.163132121e-06
+2.095523307e-05
+4.166285309e-06
+1.196861204e-09
+0.0004386611208
+5.761642517e-06
+1.226200261e-09
+1.287826944e-06
+1.388342407e-06
+0.0138992295
+0.001200985648
+8.737646522e-07
+1.292433042e-05
+0.0005247537468
+1.849244285e-05
+0.0006103541242
+2.658544755e-05
+0.0005570971738
+1.003959651e-10
+0.009537527557
+2.211186806e-06
+0.002015677659
+0.004088340454
+0.01158525104
+5.570986633e-05
+0.01173396838
+0.03151862741
+4.903425749e-07
+9.104474077e-06
+9.041032749e-06
+1.236311915e-05
+2.200710124
+2.961910412e-05
+6.397930798e-05
+0.000539211502
+0.0007350857781
+9.548057014e-07
+0.000384105841
+0.0004834988934
+0.3302211352
+0.0001342757864
+6.91776482e-06
+0.003135297414
+5.522267806e-07
+0.8642843079
+5.78836398e-07
+0.0002188844955
+6.579396898e-08
+9.765199966e-06
+0.0001775288039
+0.0004758128759
+0.01227167952
+6.974216282e-05
+1.325077749e-05
+6.318479137e-06
+0.02524105209
+1.075053683e-06
+0.002253207211
+1.24094897e-08
+1.923855322e-05
+1.016536343e-05
+0.0005164178122
+4.580470227e-05
+0.0002032670006
+2.788558477e-06
+0.01981434798
+1.138543379e-07
+6.571997892e-06
+0.01969277399
+1.131339504e-06
+5.32690359e-06
+6.205196648e-06
+1.052876518e-05
+0.0005698161662
+0.6971726525
+3.21350037e-07
+0.003283509147
+3.297881282e-07
+0.003219186543
+0.08553928071
+0.0001746392035
+1.166023268e-05
+0.0008764319391
+2.771942099e-08
+4.959223127e-06
+0.0001086801919
+8.989536201e-05
+3.858329191e-05
+0.001052278197
+0.002034271464
+0.001325081027
+1.849841166e-05
+6.861632777e-07
+2.94092577e-05
+0.000844982807
+0.0134702774
+3.223562252e-06
+0.003214816301
+8.216834418e-08
+3.005688973e-05
+7.524580984e-05
+2.576264344e-05
+0.0009088875825
+4.649559262e-13
+1.039997533e-07
+5.371405446e-10
+2.877802295e-09
+8.199307201e-09
+1.857698214e-10
+8.472551509e-05
+7.614032202e-08
+9.686742201e-10
+9.38546373e-05
+8.812157048e-12
+2.08576495e-09
+1.195921584e-05
+2.583251045e-05
+1.363721009e-06
+5.905060226e-07
+1.741841468e-07
+4.519645889e-07
+1.771769626e-07
+9.326017384e-08
+1.467827102e-06
+1.055655314e-05
+0.001860504258
+6.722036395e-07
+1.488987511e-07
+4.131625064e-08
+1.475015069e-08
+4.277917049e-07
+2.348160384e-09
+1.589860143e-07
+2.023610372e-06
+2.738233466e-06
+8.601735938e-09
+6.628022017e-08
+1.841938445e-07
+1.36974276e-06
+1.209720186e-07
+2.125794107e-11
+8.528361071e-07
+4.867100808e-07
+1.246401442e-07
+5.085591699e-09
+2.56058156e-07
+3.855598105e-07
+4.352300838e-06
+1.19799979e-06
+2.013004952e-08
+6.039970364e-09
+8.703773429e-05
+1.314165429e-09
+0.0002732777593
+5.242161929e-06
+6.566529357e-08
+1.015640547e-07
+4.28960212e-06
+1.883679033e-07
+5.088942984e-05
+8.851238783e-10
+7.916860766e-07
+4.27312084e-09
+1.334626912e-05
+4.394286459e-14
+5.871868802e-06
+8.802196772e-06
+3.318185139e-08
+8.030929535e-08
+5.049080313e-07
+0.0003575303749
+5.534346274e-06
+4.847197986e-05
+1.281559946e-05
+1.044094783e-09
+1.876760784e-08
+1.008524726e-07
+0.0001832202526
+6.237315033e-06
+1.72658137e-06
+0.1233667887
+0.0001204860775
+7.662293206e-08
+5.039694371e-07
+0.0001434309982
+4.767379032e-09
+4.484615086e-06
+7.619287657e-07
+5.998388289e-06
+9.454159823e-07
+0.008718282202
+7.06623224e-06
+3.5342366e-09
+2.998723114e-06
+5.803336987e-06
+2.174568259e-07
+5.762153536e-07
+2.047743794e-08
+6.955633865e-08
+3.582930842e-07
+9.783798212e-05
+2.090110238e-06
+1.510191442e-08
+1.498455174e-08
+9.291378093e-10
+3.366471683e-05
+2.306806191e-08
+2.115835604e-10
+3.336400768e-07
+5.974828414e-06
+3.180256622e-06
+8.813379238e-08
+1.763575768e-05
+2.188811687e-08
+0.2801761805
+5.365276869e-08
+2.754807602e-08
+4.784982865e-07
+8.70354998e-09
+1.006607116e-09
+1.912746446e-08
+8.610301172e-11
+5.05306352e-08
+4.955888957e-10
+2.082077311e-05
+2.832597941e-06
+3.829600198e-07
+0.0001398045573
+1.363527508e-07
+4.006426395e-11
+3.218114401e-10
+1.271603028e-09
+3.76404128e-08
+2.995886936e-07
+0.002748463667
+7.712911209e-06
+8.77525707e-08
+6.292508188e-09
+3.966965926e-07
+1.003368849e-08
+2.014737422e-07
+4.651493415e-09
+6.964433461e-07
+0.0001013753616
+7.35099186e-08
+9.562949752e-05
+3.811496048e-11
+1.584605138e-07
+3.670929965e-06
+1.816502237e-07
+1.479198193e-08
+2.715454224e-08
+2.617700181e-08
+7.594116302e-10
+1.573844198e-06
+5.736058553e-06
+6.6770728e-08
+1.985465242e-05
+1.376700419e-06
+8.462602621e-10
+0.0004057354918
+7.01338475e-06
+1.449983528e-07
+6.471703687e-08
+1.269956683e-07
+4.782215004e-06
+3.315823863e-07
+1.822484909e-07
+4.279214857e-11
+6.024582658e-06
+6.479204345e-09
+1.925607297e-05
+0.009631606305
+8.417805008e-08
+7.806365332e-08
+7.773646468e-06
+4.891401136e-05
+8.53548137e-07
+5.753698438e-09
+9.235740967e-07
+1.949476385e-08
+4.839116051e-08
+1.707217727e-08
+1.713911101e-08
+4.63426902e-07
+2.984480177e-09
+2.436972228e-10
+0.00012044612
+8.47548406e-07
+4.972500256e-07
+2.673568883e-07
+1.750544811e-07
+3.364851333e-07
+1.622661012e-09
+5.430839661e-08
+2.85533949e-07
+1.652112352e-09
+1.352816505e-06
+2.782857671e-07
+2.098236019e-05
+1.790999374e-06
+3.157992464e-08
+9.58134087e-08
+1.014707126e-07
+4.555674216e-05
+4.134261911e-09
+6.261901583e-06
+1.715038177e-07
+5.840554508e-08
+1.451359382e-07
+1.056393653e-08
+2.427187856e-07
+2.248690027e-06
+8.323758841e-06
+5.160066276e-06
+2.279494593e-08
+1.919831279e-08
+2.21685168e-06
+7.169142697e-06
+1.500011654e-06
+0.0003424289922
+9.813868913e-08
+7.662113906e-10
+1.190827393e-09
+9.067381606e-08
+0.004636391907
+0.0003075258163
+0.002407987744
+1.532014873e-06
+1.732785937e-05
+8.620678469e-08
+2.84365239e-05
+3.106649894e-08
+1.438844233e-08
+1.11454856e-06
+1.009996118e-06
+6.395082653e-08
+8.23508755e-09
+1.425218179e-07
+9.588910784e-06
+0.0001792991737
+0.007552852331
+7.850440239e-07
+0.0003728606318
+2.222213251e-06
+3.236749431e-06
+0.0001700306007
+6.61382806e-08
+3.445535887e-06
+1.676397342e-08
+1.627804565e-06
+3.710915815e-08
+0.000300480916
+6.140748324e-08
+3.103675071e-08
+4.172183081e-10
+4.776998326e-10
+4.768894773e-09
+4.891788146e-09
+4.998128728e-07
+1.551481784e-08
+1.744596412e-08
+3.828174198e-10
+8.156756581e-07
+1.704248032e-08
+2.279278055e-06
+2.489783166e-06
+8.649782795e-08
+1.543101421e-07
+3.800918744e-05
+3.01983658e-10
+1.989609202e-06
+1.833482677e-08
+5.018008211e-08
+1.095921818e-06
+1.364347834e-06
+6.087867042e-06
+5.380019706e-10
+4.719806377e-07
+1.090933279e-06
+3.504951062e-08
+1.347757567e-07
+4.178963403e-09
+9.155496185e-09
+2.418361079e-06
+6.552132839e-11
+1.013888567e-08
+7.075052436e-08
+5.715837212e-07
+5.783397513e-06
+3.64250045e-07
+4.489268588e-08
+3.02718298e-07
+1.180034816e-07
+4.39237268e-07
+3.41454226e-09
+5.571115347e-08
+1.39823498e-09
+2.209958615e-09
+1.081841378e-05
+6.884744506e-09
+2.570693863e-05
+1.115771389e-09
+3.256030938e-06
+1.367649582e-08
+4.750130037e-08
+6.537568433e-06
+4.277112018e-08
+2.430481981e-08
+3.36997671e-06
+2.398028924e-07
+5.021625874e-09
+5.450601646e-08
+2.435383296e-05
+0.0001385161534
+2.90291383e-09
+8.634862311e-10
+6.063102411e-08
+1.355691813e-08
+4.963996453e-09
+9.615443171e-09
+1.920659942e-08
+1.590821047e-08
+2.60196392e-06
+1.68529985e-06
+6.408437e-05
+5.022795422e-07
+0.0004724648037
+1.664763196e-07
+1.471004347e-08
+7.203304007e-07
+2.188808726e-05
+1.458335642e-07
+0.0002609802076
+8.435987578e-05
+3.249663625e-08
+0.01629845516
+0.0001848610729
+2.97729011e-07
+3.790738682e-08
+1.864480018e-08
+1.490775138e-08
+1.438791067e-05
+1.198538009e-06
+5.139712682e-08
+4.733839632e-07
+0.0002376036735
+8.826273483e-08
+2.022140654e-07
+4.170524946e-07
+2.666036408e-08
+0.001852493675
+3.377855561e-07
+1.31683152e-07
+1.702959121e-07
+2.121928172e-07
+1.212726475e-10
+7.650574168e-06
+4.886729976e-07
+1.34216659e-08
+3.884542094e-08
+4.308950592e-06
+0.00151455936
+7.369051053e-10
+1.06022548e-07
+4.817792393e-09
+1.627234267e-08
+2.563922961e-10
+5.845234808e-05
+1.01157045e-07
+9.567830754e-07
+6.183915662e-08
+6.564187158e-08
+3.425939862e-09
+3.529487333e-10
+4.157168696e-07
+4.565414555e-06
+0.0001696635846
+0.0006927961288
+7.953770246e-08
+1.548058403e-05
+1.170937322e-07
+5.352555177e-08
+2.452210022e-08
+7.365641336e-07
+5.540043933e-08
+7.618764239e-10
+2.646353008e-09
+0.0006798850159
+3.846835079e-08
+4.895823658e-07
+3.953201394e-06
+4.020746479e-09
+0.0001497641336
+2.37163524e-06
+5.172201259e-06
+2.344434141e-05
+1.736772497e-08
+1.143553881e-05
+5.168328037e-07
+0.0001315155753
+9.302942066e-07
+2.461041217e-07
+4.471465429e-05
+4.381307116e-08
+4.264010872e-08
+3.768292822e-05
+1.116013392e-07
+1.006751203e-07
+1.033526693e-09
+7.384953267e-07
+0.0005210100515
+9.149212577e-06
+5.843889201e-08
+5.876270593e-07
+2.997503477e-09
+5.956252507e-06
+4.402983891e-07
+3.110487717e-10
+9.700945906e-09
+1.810911004e-07
+4.374010256e-06
+7.717809162e-08
+1.513737908e-05
+7.77854177e-06
+3.948607985e-12
+1.069153627e-07
+1.316861987e-07
+9.36663271e-13
+1.608275791e-06
+1.10942413e-05
+6.997937031e-09
+3.851773884e-07
+4.746937619e-06
+1.518667741e-09
+6.337598797e-07
+7.594766328e-09
+0.0003516380193
+1.931226132e-06
+1.396402922e-10
+1.619874689e-11
+1.25792297e-06
+9.048003201e-08
+9.363242303e-09
+5.448700352e-10
+1.849997528e-08
+2.241399068e-07
+1.422450432e-07
+3.108790667e-07
+2.873438243e-06
+1.345257692e-05
+8.875817938e-07
+0.001116119138
+2.915932187e-07
+1.127592511e-10
+1.540968007e-07
+1.952273469e-10
+4.921839139e-07
+1.673187927e-05
+3.715062492e-07
+2.458552253e-06
+4.298368202e-05
+2.363761428e-08
+4.4460392e-08
+3.856844622e-07
+0.0003135362089
+4.832901509e-08
+6.879506367e-11
+9.82358656e-08
+9.133749031e-07
+1.678898558e-09
+1.281644829e-08
+3.565833444e-07
+2.326280181e-10
+6.219967462e-05
+8.248735756e-06
+8.04872586e-07
+5.364049912e-08
+4.497927837e-06
+7.454470383e-06
+3.725481801e-09
+7.533621119e-08
+1.917903663e-06
+3.80489855e-08
+6.437347005e-08
+5.965187272e-07
+1.074932818e-05
+1.300799687e-08
+7.145484613e-06
+3.385226445e-07
+3.58821642e-08
+4.773754285e-08
+2.354807761e-06
+1.537967226e-08
+1.223819781e-05
+6.214468255e-07
+1.828305344e-09
+0.0002297455882
+3.113207365e-09
+9.309429551e-05
+0.0006353054278
+9.27437772e-09
+0.001055673527
+1.825901129e-07
+5.215237775e-06
+1.194110648e-06
+6.245473889e-05
+7.765867005e-06
+4.518377506e-07
+6.114803817e-08
+8.385941421e-08
+7.254627621e-06
+2.164020253e-08
+9.72096777e-08
+5.980686084e-08
+2.082783048e-05
+2.38858814e-12
+2.560661528e-08
+1.009605656e-07
+1.021447118e-08
+6.095271771e-10
+1.411126663e-10
+3.718013415e-07
+1.188746406e-06
+8.593381058e-08
+4.090871684e-10
+4.688272316e-09
+7.248886911e-09
+1.137002654e-05
+0.0002917117584
+3.942997641e-10
+7.29593335e-06
+4.468861e-09
+1.619484084e-08
+3.788543831e-08
+9.667678893e-08
+0.001461748035
+1.022750089e-07
+2.277838156e-07
+2.434304042e-05
+2.557457797e-09
+6.108036911e-07
+1.140974589e-07
+2.649856385e-05
+5.415259839e-07
+2.630277777e-08
+1.650692332e-07
+7.401528144e-12
+1.46313959e-09
+6.400920663e-09
+1.39858952e-08
+2.470234219e-10
+2.090839278e-09
+1.673066068e-08
+3.656949372e-08
+4.204231462e-12
+6.230489232e-08
+7.29453662e-07
+3.382745347e-06
+1.13625287e-06
+6.425961361e-06
+4.56976115e-06
+3.710503765e-06
+7.357618502e-07
+3.801254619e-09
+3.339680017e-05
+1.915985169e-07
+0.0004347381864
+3.251250484e-10
+9.190455509e-08
+4.440436305e-06
+1.473549028e-09
+1.686325722e-05
+1.065032403e-09
+5.53052625e-05
+3.878078132e-07
+7.27060483e-05
+3.098042242e-08
+2.328742199e-07
+9.633958976e-09
+0.001440234796
+1.191930456e-07
+3.821396721e-07
+9.41444313e-07
+7.302062946e-08
+2.295175856e-05
+4.596989319e-09
+3.720241938e-05
+3.486627914e-08
+2.146264966e-05
+2.186956068e-05
+9.625827743e-08
+8.383559439e-06
+6.79699435e-07
+5.499940905e-06
+6.514798178e-11
+6.650614601e-07
+7.620527865e-08
+3.842260844e-09
+5.117516491e-06
+2.694945311e-09
+4.317513782e-08
+1.127576018e-08
+0.001539726227
+6.531931307e-05
+1.150702406e-06
+8.468250785e-08
+4.775564958e-07
+4.511437998e-08
+4.426844887e-06
+7.893427692e-07
+8.472652543e-09
+3.894404483e-05
+5.873606707e-06
+1.035933871e-05
+3.660713602e-07
+3.001567313e-08
+1.048838207e-06
+9.692636248e-07
+0.0001558290841
+6.335999815e-07
+5.649805025e-07
+1.055668374e-10
+6.641196294e-08
+2.040376723e-07
+1.469424987e-08
+1.80584434e-06
+4.713956528e-09
+2.03772537e-07
+3.143789881e-07
+1.458697384e-07
+6.281251258e-05
+2.504954467e-09
+2.714936194e-05
+7.983782373e-05
+8.688492282e-05
+9.814469044e-08
+2.906889086e-08
+0.0001449806996
+1.215173057e-07
+1.726335976e-07
+0.005972472197
+1.701602785e-06
+1.081132242e-05
+8.781158357e-08
+6.206466753e-11
+2.498255783e-08
+2.999837747e-10
+4.150515919e-06
+6.195921647e-08
+4.39933318e-09
+1.367730313e-08
+9.597693546e-06
+7.933847532e-09
+1.343706977e-07
+2.875446333e-08
+9.75154466e-08
+3.983486241e-06
+5.76272113e-09
+1.462897063e-06
+3.320449486e-08
+4.14502491e-07
+1.05517296e-07
+7.933724259e-07
+3.960407068e-07
+4.999445539e-07
+5.566036422e-08
+2.961293949e-07
+1.112313635e-06
+2.109854601e-07
+4.945264481e-09
+9.753162366e-06
+8.050908462e-09
+2.557418016e-08
+7.382960453e-09
+1.791102084e-08
+5.728305235e-07
+2.440751828e-07
+6.201979557e-08
+2.307110343e-08
+3.67970425e-08
+1.747247265e-05
+0.002406513557
+8.005708649e-08
+3.170556332e-09
+8.426361767e-07
+5.556954709e-09
+2.378889825e-05
+4.364368928e-05
+1.237967957e-05
+9.64574924e-07
+2.507529982e-07
+3.275055181e-12
+3.068132883e-07
+2.273842879e-05
+1.63357253e-07
+5.95365439e-09
+1.001648252e-08
+1.635005535e-10
+0.004187633373
+4.679190771e-08
+1.522516118e-05
+1.36231811e-06
+6.638545116e-09
+2.298078957e-07
+2.652453889e-08
+2.369248597e-10
+0.0006963667692
+7.359049757e-07
+4.097761124e-08
+8.717312201e-08
+0.001340673215
+9.210740972e-10
+2.889031975e-06
+2.174839886e-08
+5.985585813e-08
+9.187588212e-07
+9.374845883e-09
+4.711527305e-07
+1.64178679e-05
+1.54465281e-07
+1.611740644e-11
+5.129359967e-07
+3.080737696e-07
+8.533424913e-09
+9.30728741e-07
+7.902285234e-05
+1.949916168e-07
+3.74820849e-09
+0.0001972028128
+8.380910284e-06
+7.305260618e-06
+2.91617874e-08
+3.141314716e-09
+7.051100729e-08
+2.638683669e-08
+3.487137064e-08
+2.295618942e-11
+3.381465792e-07
+2.223630402e-08
+1.269506904e-05
+0.0001125007982
+1.471628445e-07
+1.470628179e-06
+1.83320451e-09
+0.001669497652
+9.630665847e-08
+0.0003438142533
+5.89314493e-05
+2.14874452e-10
+1.705755305e-05
+4.744323108e-09
+4.132213835e-09
+1.354679585e-08
+4.434255107e-07
+5.184528622e-08
+9.119320824e-10
+1.156553886e-07
+2.008605532e-09
+1.62460885e-08
+5.105314811e-05
+4.450072199e-09
+4.727947016e-08
+1.852122228e-06
+1.221660092e-05
+3.855443278e-06
+0.0001432006196
+3.100080203e-10
+2.926983031e-07
+9.976899911e-11
+4.549848912e-09
+0.0004098867583
+4.931909648e-08
+0.0001216582159
+3.925224815e-08
+3.492693241e-08
+1.002456493e-07
+8.907342584e-09
+1.257578434e-06
+1.965448737e-12
+1.068793393e-07
+2.433751798e-07
+7.933471705e-11
+2.281049506e-07
+1.325304013e-09
+2.739407128e-07
+1.01425267e-06
+3.215693149e-07
+1.931584066e-08
+0.0001240221531
+3.892024641e-08
+4.402113379e-09
+7.872189106e-07
+9.740564323e-07
+0.0001917130167
+2.740357369e-06
+3.381599241e-06
+1.162935756e-05
+0.0001703998848
+8.771866895e-06
+1.209292995e-07
+1.231450465e-08
+2.099557034e-06
+3.599685947e-05
+4.511581013e-06
+1.261144506e-07
+8.529130839e-08
+0.0002071916737
+2.310553125e-07
+3.031601174e-06
+1.695963674e-06
+0.0002781573063
+0.0003140026752
+1.866613071e-06
+3.567523005e-07
+1.028397877e-08
+4.269713146e-06
+5.53601493e-05
+1.408085701e-06
+1.325887495e-05
+2.916030898e-05
+2.279414507e-06
+1.199283435e-07
+2.663434231e-05
+3.642159999e-06
+5.666261515e-06
+7.61892445e-07
+2.321362021e-06
+5.317826421e-07
+4.711446263e-05
+1.43457323e-09
+4.047492908e-07
+3.577118361e-08
+6.051607554e-08
+7.136414344e-08
+4.089414715e-07
+3.264949267e-07
+1.011125544e-06
+1.208313433e-07
+3.249169193e-08
+4.701557522e-09
+5.468040822e-08
+5.845896292e-07
+6.947818692e-08
+4.509945091e-08
+1.207236944e-08
+3.772967914e-07
+9.083561859e-08
+9.573050911e-10
+8.146104727e-05
+2.222899917e-05
+2.932839819e-08
+8.540812104e-11
+2.859331928e-09
+5.748265527e-08
+1.697718883e-08
+1.061810166e-08
+9.742239646e-09
+2.232577986e-08
+2.520086439e-06
+4.954981202e-10
+2.461731111e-08
+5.567264286e-06
+3.871066356e-08
+1.891014226e-07
+1.407010689e-06
+1.085986524e-09
+0.0001440358514
+1.424529965e-09
+9.919043657e-08
+0.0006049852534
+0.0005832561023
+8.430537256e-09
+5.450623081e-08
+1.399226453e-08
+1.127913225e-08
+7.042162392e-06
+0.0001574036974
+3.081821043e-08
+3.442793406e-08
+3.032242594e-06
+4.107189036e-09
+7.799077905e-07
+1.120709904e-10
+5.714956562e-08
+7.962089553e-07
+1.118876377e-11
+5.087010448e-05
+6.245375352e-09
+2.968607189e-05
+3.357398075e-07
+1.590697449e-09
+2.152560201e-06
+2.03114324e-07
+5.532326805e-08
+1.488330525e-08
+5.068794932e-08
+4.557291604e-08
+8.608684593e-09
+1.831193289e-06
+8.139149253e-05
+2.011673157e-10
+2.149174043e-09
+5.796611927e-09
+4.537920831e-07
+8.310476798e-08
+2.304558211e-06
+9.901685103e-07
+1.886763012e-06
+1.317514213e-05
+7.14480352e-07
+2.031980727e-08
+1.646922057e-08
+1.730405691e-06
+2.248434137e-08
+2.072045614e-08
+2.251652694e-08
+8.090004791e-13
+2.337137031e-08
+2.928931374e-07
+3.904919295e-07
+1.948281527e-05
+1.354569648e-07
+3.033747141e-08
+1.968708599e-09
+1.218187027e-07
+4.322104322e-06
+5.403487449e-06
+1.749083523e-08
+1.321457333e-08
+2.283122323e-08
+3.97985726e-08
+5.445505037e-05
+2.489768687e-06
+1.55875376e-05
+2.531792024e-08
+9.94033744e-05
+8.571919557e-07
+5.782450808e-09
+5.917678229e-08
+4.916838158e-06
+0.000574717804
+0.0001330291075
+4.532389138e-06
+6.308135248e-05
+1.516855576e-05
+1.145552438e-05
+3.819567328e-10
+1.173040141e-07
+0.0002542422783
+8.338714799e-09
+1.64991298e-08
+2.733471389e-06
+0.0001259670916
+2.539703872e-06
+4.883605183e-05
+7.188554165e-10
+1.615915583e-09
+6.482771745e-08
+1.622683548e-07
+9.025149253e-08
+4.801889261e-08
+1.554817852e-06
+2.511580057e-09
+8.368836321e-08
+5.05079492e-10
+3.450186595e-07
+4.390537121e-08
+4.036277766e-06
+8.268274517e-07
+2.472560986e-07
+4.655448218e-06
+2.847191166e-08
+1.663348022e-08
+4.528372608e-08
+5.077196915e-05
+1.267944939e-08
+9.971930529e-06
+9.036356093e-08
+3.615083614e-05
+6.232087437e-08
+1.351822707e-07
+7.912859911e-06
+2.224204268e-06
+0.0004810553745
+7.130214772e-07
+1.657719147e-09
+0.0004592838556
+3.293390335e-12
+1.307888719e-07
+1.400826841e-05
+4.656008331e-08
+4.034365734e-08
+1.291493284e-08
+3.664370061e-08
+1.7278017e-08
+3.286533402e-06
+6.412802378e-11
+6.569448887e-07
+1.912543709e-10
+7.949845689e-08
+0.0001674068002
+3.094729832e-05
+2.921218026e-08
+4.975890121e-11
+6.120194753e-11
+1.266878707e-10
+1.271257938e-10
+3.450193133e-12
+8.772756115e-12
+2.107559013e-09
+6.732747937e-11
+1.151822934e-09
+1.109441287e-14
+4.015919294e-14
+4.613625509e-11
+2.27625669e-08
+2.176625819e-12
+1.035048234e-13
+6.438680292e-06
+1.404877669e-10
+4.890973987e-12
+5.696438339e-14
+1.937217536e-11
+1.112625112e-14
+4.237847621e-10
+5.269893452e-13
+4.199563818e-13
+1.197032755e-14
+8.464242851e-10
+1.050674415e-10
+1.412211537e-09
+1.34969033e-10
+8.09662531e-08
+8.720115299e-09
+2.073314497e-08
+1.080355083e-10
+6.225546843e-11
+5.359529673e-06
+9.614761513e-12
+1.578570272e-09
+2.976407937e-09
+3.600843946e-15
+1.708087173e-11
+2.817749415e-07
+5.631776757e-09
+3.555113198e-11
+5.756623533e-11
+2.644097926e-09
+2.820562159e-08
+2.649037792e-09
+8.047781258e-08
+6.511674381e-13
+6.245451325e-07
+1.420507173e-08
+6.170657677e-06
+2.080024994e-10
+1.052382925e-09
+9.011490763e-09
+4.726376992e-11
+9.457436378e-10
+2.413340896e-11
+5.90848221e-06
+3.102046718e-08
+6.336019143e-11
+2.676370541e-09
+2.283539225e-08
+1.024498031e-11
+6.973784765e-10
+2.659828251e-12
+1.998592736e-09
+7.097769156e-09
+1.747389099e-11
+6.816117865e-14
+3.226166844e-11
+2.862361089e-11
+2.368019811e-11
+7.15135344e-10
+8.873771607e-09
+1.152428563e-08
+4.210055139e-09
+1.607578191e-06
+3.40859553e-11
+5.224131055e-13
+6.975520632e-11
+5.610492251e-09
+1.31115104e-12
+7.171932058e-10
+1.940974893e-12
+4.254206535e-09
+3.051020616e-09
+6.42880678e-08
+4.967701425e-11
+2.602648952e-06
+9.606103428e-08
+1.310470487e-06
+2.141102793e-09
+4.681400341e-11
+1.016253043e-12
+1.379839749e-09
+1.393194538e-09
+7.477919593e-10
+1.268890584e-13
+2.531284851e-13
+1.867616473e-09
+1.580350595e-13
+1.701599026e-09
+1.364490494e-11
+3.486024346e-09
+4.122212419e-10
+2.409871694e-11
+4.511280283e-08
+3.925711173e-11
+3.109773524e-07
+2.662559351e-09
+1.19431339e-13
+9.750611765e-06
+1.742504114e-10
+1.525693054e-11
+1.375291045e-11
+2.730277581e-07
+8.925399198e-10
+9.902224276e-11
+1.195658402e-07
+1.327228103e-10
+1.683688658e-09
+1.844902188e-09
+1.336954161e-06
+3.01614933e-10
+2.821108708e-12
+7.00240355e-11
+8.244656564e-15
+4.250388475e-08
+2.224291195e-09
+1.88932305e-07
+4.063964877e-11
+1.233101104e-11
+1.002588916e-11
+7.538971851e-09
+1.179185703e-10
+1.52619143e-16
+8.464306086e-09
+1.029936705e-11
+3.567946679e-12
+7.504624357e-12
+4.779118811e-12
+1.159218896e-08
+1.249661171e-08
+1.046105811e-07
+2.886845009e-06
+4.512361956e-11
+1.001408394e-07
+5.317921371e-10
+6.356490903e-11
+9.999808745e-09
+1.464164514e-08
+5.660634803e-09
+3.906424735e-13
+2.279297367e-11
+1.55862998e-08
+2.698792882e-09
+1.21595548e-11
+1.320933044e-11
+2.419324683e-12
+9.13637499e-07
+3.706565907e-08
+4.831608212e-13
+3.522989268e-09
+3.783775747e-07
+2.32680469e-08
+7.709953968e-07
+5.833334861e-08
+1.88227939e-09
+1.387811548e-09
+7.344800686e-11
+1.426565729e-09
+1.338246367e-12
+1.760151515e-10
+1.731843184e-13
+1.348435577e-12
+8.260613658e-18
+5.551085332e-10
+3.154244322e-09
+3.713752841e-12
+1.194719549e-10
+6.648262174e-07
+3.762699574e-13
+3.015241428e-13
+4.188160881e-08
+4.113324295e-09
+1.015485117e-11
+3.906449693e-09
+8.439846762e-12
+6.339596419e-06
+1.77775774e-07
+6.421111307e-07
+1.20744587e-11
+4.464097413e-06
+3.943880495e-11
+2.776965328e-10
+7.811992916e-07
+1.695506907e-11
+3.53996155e-09
+3.149794613e-11
+2.401460114e-14
+1.046817336e-09
+5.732596809e-12
+4.883564002e-12
+7.795659464e-09
+2.445967571e-12
+6.336283885e-08
+2.567609138e-09
+5.08170982e-09
+4.909995459e-09
+1.532617696e-12
+3.6374213e-10
+1.732823719e-07
+1.439795877e-06
+2.338214351e-13
+4.882386709e-12
+1.119383494e-05
+2.698049879e-13
+6.792839517e-09
+3.059583771e-09
+7.81514527e-09
+1.076354997e-10
+3.131633807e-07
+3.294370107e-08
+5.48850062e-06
+2.198216375e-10
+6.863876362e-13
+6.832658312e-09
+2.321134457e-09
+1.570973998e-07
+1.153511922e-09
+3.449442316e-10
+4.25083772e-08
+1.23882163e-10
+5.057067081e-11
+2.850619111e-07
+1.86985387e-11
+5.412584791e-08
+4.131798068e-08
+1.484347112e-08
+5.345029135e-13
+5.451457674e-14
+5.764825624e-08
+4.11652334e-11
+4.195862266e-08
+6.468274125e-10
+3.335079209e-06
+4.526187999e-09
+1.528839144e-09
+9.084402491e-11
+5.765505e-10
+3.880379384e-10
+2.190268276e-13
+1.81953957e-10
+6.132202626e-09
+1.936882135e-08
+2.542375344e-10
+5.565827501e-07
+9.143072093e-08
+1.537209734e-09
+1.484268127e-13
+2.227546768e-11
+3.721352238e-11
+2.328595382e-12
+1.458487283e-10
+2.927772602e-12
+4.211530351e-10
+1.664478165e-08
+8.323953903e-07
+8.469484454e-14
+4.068718429e-09
+1.124371227e-08
+1.046739933e-10
+5.099634816e-10
+1.669113732e-06
+7.815348266e-12
+2.25773956e-09
+1.862656372e-09
+1.492009562e-09
+3.816910919e-16
+7.604852808e-09
+8.382039809e-08
+8.917045389e-09
+5.837037752e-06
+9.311148012e-06
+2.82567282e-12
+5.493012193e-07
+3.784906811e-13
+2.702979605e-05
+4.231891965e-08
+4.437605088e-09
+1.024261779e-08
+8.974957561e-11
+2.442016607e-12
+7.313245078e-09
+6.197456885e-10
+2.103973643e-12
+3.176328121e-12
+7.789070076e-09
+8.424084241e-10
+2.756892789e-08
+8.93896188e-11
+5.449535492e-10
+2.935961404e-07
+2.441708271e-12
+3.266830887e-09
+1.054102559e-08
+1.813550709e-08
+3.148727875e-11
+7.750994103e-12
+5.603564313e-15
+1.015850955e-10
+1.345625157e-10
+1.354250715e-09
+2.418112851e-13
+4.861020524e-11
+2.192322827e-06
+2.831673386e-11
+8.675577743e-10
+4.680858262e-13
+2.495190059e-08
+1.065135523e-09
+1.530755162e-06
+5.339100861e-14
+1.145441749e-10
+1.070438234e-09
+3.073416531e-10
+2.702331835e-10
+1.470912374e-12
+1.621977484e-11
+2.49326618e-09
+1.24719364e-13
+1.573189854e-09
+1.468569169e-06
+5.042463911e-12
+6.286364054e-14
+1.058313755e-10
+1.584265456e-06
+1.319429307e-09
+3.531376418e-09
+8.110818563e-07
+3.454267553e-10
+6.182478182e-11
+1.593055547e-10
+1.726352007e-10
+1.411146157e-09
+7.017565323e-09
+7.826047112e-14
+3.073771758e-12
+2.297054602e-09
+4.600124718e-12
+4.106857773e-12
+4.490705211e-13
+4.810270173e-08
+1.727444944e-11
+1.07673142e-10
+1.653984852e-08
+1.367770743e-10
+7.701860593e-10
+8.606650001e-11
+1.031451427e-09
+8.750742548e-08
+7.336607608e-09
+3.208314431e-09
+4.136216805e-08
+2.724678117e-06
+1.512104782e-08
+5.809911274e-15
+5.383670406e-07
+8.049070298e-09
+2.558180949e-09
+8.356542183e-16
+4.609766372e-12
+6.52544031e-09
+1.518904616e-11
+1.275076589e-08
+6.606481797e-15
+1.452404095e-09
+3.066260576e-11
+2.051768454e-10
+2.563978053e-09
+3.11605495e-09
+5.95562309e-09
+2.923781184e-09
+1.67011367e-12
+2.676425071e-10
+1.498453354e-09
+4.126134628e-09
+2.872502741e-05
+1.041985884e-09
+2.582703912e-10
+6.132852639e-10
+2.873124277e-07
+1.253298949e-08
+8.782462373e-11
+1.132354778e-08
+1.195535721e-11
+5.923249485e-12
+9.576828754e-12
+4.819347995e-10
+3.183761357e-09
+2.777854821e-12
+1.073846086e-06
+2.483484683e-12
+3.120461593e-11
+7.070427848e-10
+5.85875636e-16
+5.486841842e-08
+6.093646206e-13
+5.559560806e-07
+1.139016957e-07
+6.56789865e-09
+1.453705126e-11
+1.329715968e-09
+2.446418928e-09
+1.708445298e-12
+2.459939326e-11
+2.535373172e-09
+4.819556804e-07
+2.873481984e-07
+1.782679691e-13
+1.13567984e-10
+3.678990757e-09
+6.680476818e-09
+1.027264184e-10
+3.387689308e-09
+1.806677868e-11
+9.951542851e-09
+8.771298035e-12
+3.172228136e-12
+1.819215505e-07
+2.071111666e-14
+1.412603135e-07
+4.825262585e-10
+6.328046882e-08
+1.808593481e-08
+4.18423657e-11
+9.112020867e-11
+2.426140485e-11
+2.701657419e-08
+2.075986233e-16
+2.229363124e-12
+2.50294476e-11
+1.600785661e-07
+9.161923558e-10
+5.264107933e-08
+1.982015097e-12
+1.010199684e-09
+4.418064563e-10
+1.374291508e-09
+3.708922105e-10
+6.06632521e-08
+8.634590561e-13
+1.390275259e-06
+2.009574488e-13
+6.996607621e-08
+3.500402072e-05
+4.106243773e-07
+2.504313324e-06
+1.412171841e-10
+1.979450576e-13
+6.533510455e-12
+7.417374502e-11
+1.219628084e-09
+7.083397976e-09
+6.872524792e-09
+4.165547133e-10
+8.830069457e-11
+1.116072479e-11
+2.169980023e-11
+1.042765496e-10
+3.789015727e-08
+3.103479866e-12
+5.541089243e-11
+1.18744043e-09
+1.039767043e-07
+1.714503758e-06
+4.186214194e-07
+2.017250367e-05
+3.857829162e-15
+4.140386765e-09
+1.477459677e-10
+7.170738954e-10
+9.926732218e-09
+1.127215038e-08
+1.286719947e-10
+9.591238765e-09
+2.847313382e-10
+1.361234323e-10
+4.629298173e-08
+1.119187285e-05
+1.390518873e-07
+7.276308984e-08
+1.017711765e-07
+1.326478494e-11
+1.013173472e-08
+9.746616115e-11
+7.757700032e-09
+6.592101953e-14
+7.813881955e-09
+2.936493433e-07
+4.413183076e-10
+2.042631458e-09
+4.596448286e-09
+2.533123461e-09
+6.245369873e-09
+6.572149192e-18
+9.116226891e-07
+2.868988498e-10
+6.074294101e-07
+1.204205371e-08
+2.178701145e-10
+9.165020705e-08
+2.258733347e-10
+1.334152079e-11
+9.451966518e-16
+5.882958346e-10
+7.892593513e-10
+6.543860409e-11
+3.14717306e-09
+4.330108909e-10
+3.574416001e-08
+1.542735421e-09
+9.199759441e-07
+6.523875018e-11
+1.513355869e-09
+9.665487517e-07
+6.764147506e-12
+1.235404108e-10
+4.716843984e-07
+2.271862865e-15
+3.440934537e-07
+2.641851984e-08
+2.240789892e-10
+2.138467049e-09
+3.339867214e-10
+1.05512903e-08
+2.327323828e-09
+1.939201101e-09
+1.401285424e-09
+3.062640943e-09
+1.682168611e-11
+3.351590753e-10
+8.157438747e-11
+2.268010337e-13
+1.966446618e-08
+1.405693367e-12
+1.013686326e-09
+4.377407226e-08
+1.109588109e-08
+3.381609357e-11
+1.237526344e-06
+2.795774072e-09
+1.216987204e-09
+1.605088588e-09
+2.919147016e-09
+5.448826541e-11
+2.453594039e-07
+1.405537939e-09
+3.174287111e-10
+5.07076832e-14
+7.975313136e-12
+2.850438386e-09
+2.482740985e-05
+8.584533294e-08
+5.176822074e-09
+9.515980345e-13
+3.288696299e-08
+2.616899678e-11
+2.510933542e-12
+2.027817639e-10
+2.535308705e-08
+1.673383135e-07
+1.601439962e-12
+1.169685464e-08
+6.554167892e-11
+5.70354138e-12
+1.225890778e-09
+7.623611056e-08
+6.255889916e-07
+5.90876427e-08
+6.597392738e-10
+6.757965814e-12
+5.298097065e-09
+7.478207217e-11
+1.015925235e-09
+4.175190595e-06
+4.225692513e-10
+7.53621761e-08
+8.762742383e-12
+1.436213394e-13
+2.3516016e-12
+3.096242356e-09
+2.942126408e-09
+2.989952921e-11
+9.057647342e-10
+1.240065478e-14
+2.437614878e-09
+8.624872213e-07
+5.576253959e-10
+1.486177929e-09
+5.870850028e-08
+1.181548701e-14
+1.568237181e-12
+2.282182045e-10
+4.816591179e-11
+1.977834379e-06
+9.328854194e-12
+3.619811954e-09
+2.711648208e-12
+5.511621247e-09
+1.410221815e-10
+4.884114591e-14
+3.275728071e-06
+2.256058708e-11
+4.394234743e-11
+1.451874136e-12
+5.501430335e-11
+3.4862794e-05
+2.876382802e-05
+8.492630442e-07
+4.16829136e-12
+7.776193852e-06
+7.421373569e-12
+1.092168608e-09
+8.92100198e-10
+9.997712242e-09
+2.636253625e-08
+4.974718468e-09
+1.739274741e-17
+3.504951362e-10
+8.350201237e-07
+4.106463589e-10
+4.37698741e-10
+2.109273423e-10
+9.493873336e-11
+1.750908817e-09
+4.424421895e-11
+6.940327364e-11
+1.268101052e-11
+3.726927223e-08
+1.917324919e-11
+5.7218274e-10
+2.567044954e-10
+9.295326854e-08
+1.183067802e-10
+8.058438029e-12
+1.803787286e-09
+9.891948703e-09
+3.657578349e-13
+2.291652772e-11
+3.136213654e-09
+1.581235439e-08
+3.121272078e-08
+4.442994702e-08
+4.802826964e-07
+5.601913866e-12
+5.065632373e-08
+3.095942582e-07
+4.12375447e-12
+7.998880421e-10
+2.098275913e-15
+3.252049374e-11
+6.446595194e-10
+1.626001822e-10
+7.347668108e-08
+1.29274374e-10
+3.405770569e-09
+1.422811423e-14
+1.40164153e-10
+7.013783076e-08
+1.329150393e-11
+4.091819182e-12
+1.079713034e-08
+1.937495711e-07
+1.003608622e-13
+3.54305089e-06
+1.190485502e-08
+5.78951268e-07
+1.054642054e-11
+8.755906998e-12
+1.063782787e-09
+1.667816953e-10
+9.16978904e-09
+2.488920064e-10
+4.302801477e-09
+1.068395685e-13
+2.396278221e-08
+4.49695579e-08
+1.975359774e-06
+2.015633025e-08
+2.211601123e-09
+1.976375638e-08
+1.062454908e-09
+4.429640524e-12
+2.537255045e-08
+1.250287165e-10
+6.193724214e-09
+9.769795291e-09
+1.024370654e-07
+1.811215133e-08
+6.471122622e-11
+8.409200179e-10
+8.881876885e-13
+2.246335139e-12
+2.053780388e-14
+2.13389474e-09
+1.675949964e-09
+1.17421273e-07
+2.504251151e-10
+4.362850799e-12
+1.799302572e-09
+6.899730071e-11
+1.730787365e-07
+7.042010099e-08
+3.399807184e-14
+4.706558644e-09
+3.511502652e-09
+1.739570868e-11
+4.283391663e-09
+1.721497772e-10
+4.719481755e-10
+6.527961485e-09
+4.967133322e-12
+1.257582424e-12
+1.979539029e-12
+2.575860625e-08
+8.760030609e-06
+8.147404687e-09
+6.03450361e-11
+6.541424589e-10
+3.205770474e-09
+1.414609599e-07
+1.134406833e-12
+1.387648425e-11
+6.399355921e-10
+1.709333044e-09
+1.925276268e-11
+3.438997758e-11
+4.997741336e-10
+1.898137632e-09
+2.731573423e-11
+7.746237478e-16
+1.39719261e-16
+4.423683206e-10
+2.357061815e-06
+7.629135587e-10
+1.083259751e-07
+1.996656466e-05
+2.69112051e-08
+7.690429556e-09
+1.423638528e-07
+4.669863917e-08
+2.344929374e-11
+7.02769171e-06
+4.0527596e-11
+1.401813118e-07
+5.095671032e-12
+1.967573816e-13
+3.166203774e-12
+3.013358507e-08
+1.430528284e-08
+4.059215111e-09
+2.988224804e-08
+8.18399656e-09
+9.73449e-13
+2.257533895e-12
+5.9392103e-09
+8.616288348e-09
+2.09184704e-06
+9.902920204e-09
+5.580915345e-10
+4.38184338e-10
+2.344875576e-09
+3.518254989e-05
+1.805485391e-10
+8.87245113e-07
+1.851304394e-07
+9.184284519e-05
+2.029368993e-08
+5.503663789e-08
+1.349061368e-09
+7.600116017e-12
+0.0004483583669
+7.064192633e-10
+1.249135076e-08
+1.155055978e-09
+1.616554994e-11
+1.721154764e-10
+1.253349049e-11
+3.342956886e-11
+2.773611997e-07
+1.247745149e-08
+3.412457066e-07
+5.517897925e-11
+2.106941166e-12
+9.714808722e-09
+5.28466453e-07
+7.516978728e-07
+1.23662932e-09
+1.41886155e-07
+5.02029946e-06
+2.096861573e-05
+2.997843209e-10
+1.341913622e-12
+1.615961611e-09
+4.068647529e-09
+9.422755202e-11
+1.633305062e-09
+6.885888694e-08
+4.254027387e-10
+2.927624977e-08
+1.075202198e-07
+7.29027861e-09
+5.128204322e-08
+3.162207769e-10
+3.062785879e-09
+7.913506677e-09
+4.947691105e-08
+5.094581719e-07
+9.555513788e-11
+1.278351042e-07
+2.440128992e-14
+7.133797233e-13
+5.299350367e-12
+2.224780073e-09
+2.657917115e-12
+2.240562226e-09
+1.054168498e-09
+1.583030867e-09
+4.055021283e-13
+3.062192229e-14
+1.354861451e-09
+9.853145393e-10
+2.952223895e-07
+3.135730135e-11
+6.25171188e-08
+4.616657019e-06
+7.76953832e-10
+5.441118536e-06
+1.281594457e-08
+2.195831776e-10
+6.162086319e-14
+1.900535206e-10
+1.698770358e-11
+2.492331878e-14
+1.349443396e-06
+5.969634004e-09
+7.861738848e-12
+2.642312019e-11
+9.568830432e-07
+2.552897838e-13
+1.520865628e-10
+5.645172904e-10
+1.09040928e-10
+8.669614232e-10
+4.253913545e-14
+1.343548333e-07
+1.155396203e-11
+3.307343249e-10
+3.972215309e-11
+2.304896928e-07
+1.447562305e-08
+3.276529923e-12
+1.946917201e-08
+7.289938947e-10
+1.323849011e-06
+2.416737409e-09
+6.103001678e-09
+5.014043755e-09
+5.622255865e-08
+3.357693457e-09
+2.953063412e-05
+6.989663755e-12
+4.346587815e-09
+7.281963532e-14
+7.178501947e-08
+9.779027192e-06
+2.351383335e-13
+3.263581497e-12
+6.686918095e-09
+1.405202725e-06
+6.235525227e-11
+6.389047963e-05
+3.173250167e-09
+1.110734766e-09
+1.32807738e-07
+4.294340206e-09
+7.220035319e-08
+3.638787734e-06
+2.72721493e-09
+5.512818313e-11
+1.816011983e-10
+6.745599346e-10
+3.757048745e-12
+9.547212795e-08
+1.002682381e-11
+6.25901337e-10
+9.601914464e-09
+5.011720125e-11
+7.113985917e-07
+1.886311946e-08
+8.307593515e-09
+5.182785591e-13
+1.003063151e-11
+1.580116609e-06
+4.10108632e-10
+1.8095714e-09
+1.407282931e-10
+3.594780991e-11
+2.021847478e-07
+1.279143815e-09
+9.070690842e-08
+4.613300696e-16
+5.405485525e-11
+2.592638201e-10
+1.157392802e-12
+3.910216113e-09
+1.517007682e-09
+3.690121333e-08
+2.556231965e-08
+4.68956634e-12
+1.263256373e-08
+1.7933556e-08
+2.297922121e-13
+1.219156494e-08
+1.717046836e-09
+2.876367219e-12
+5.222559923e-11
+2.290884719e-11
+3.398302863e-13
+1.898694407e-10
+5.370900444e-10
+4.530993473e-11
+2.054569798e-06
+1.63475221e-12
+1.192073516e-10
+6.51242474e-11
+2.068420244e-13
+1.995390047e-09
+1.035182141e-08
+3.170997606e-09
+6.500262342e-13
+1.509731301e-08
+2.979717368e-12
+1.396905663e-12
+4.169345827e-09
+3.867971266e-10
+9.588679591e-10
+1.535542874e-13
+1.663968757e-06
+4.243300846e-11
+3.029573042e-06
+3.67147691e-08
+1.902360564e-07
+2.076998172e-06
+6.373775512e-11
+4.31899134e-12
+4.339742767e-08
+2.068474666e-12
+4.251464176e-07
+4.284386281e-09
+3.680844531e-13
+7.537086875e-09
+5.628913226e-11
+7.351560184e-10
+4.395862237e-09
+2.293110906e-07
+0.0001855023117
+1.278225948e-10
+6.7390449e-08
+1.400788819e-09
+3.440775312e-12
+1.006267893e-10
+1.211296e-09
+2.488630138e-06
+6.482919505e-09
+2.682403585e-09
+2.608665573e-09
+2.702719841e-09
+1.211437185e-13
+1.121043125e-06
+7.046401178e-12
+6.881948317e-14
+1.640095106e-08
+1.441510779e-09
+3.434419375e-14
+7.38340511e-09
+5.159515637e-11
+7.659718782e-08
+1.911541751e-09
+1.093384238e-10
+3.719754604e-06
+1.834341754e-10
+8.741855967e-11
+1.650432336e-10
+3.505577956e-11
+3.370128892e-11
+4.130673708e-10
+1.043903677e-12
+7.622605332e-18
+9.765026125e-13
+4.591235334e-11
+8.569599939e-15
+6.402926451e-11
+9.30672852e-13
+2.292079631e-16
+3.860487057e-10
+2.554953424e-12
+9.176056855e-14
+2.990576004e-13
+9.051926604e-14
+6.73062063e-12
+7.411283805e-13
+1.909754241e-09
+2.18461332e-13
+1.6566755e-12
+6.855423525e-13
+1.543127066e-08
+1.744417279e-11
+5.428602239e-13
+1.666014805e-12
+9.162273205e-16
+1.264815364e-10
+3.313226125e-12
+2.82681541e-12
+3.770435532e-11
+1.851927323e-09
+2.826558032e-09
+2.260267754e-10
+4.01564372e-08
+1.246048966e-07
+2.530816923e-14
+2.413545687e-10
+2.641202498e-16
+2.653947182e-10
+4.62493955e-13
+1.053473549e-13
+4.984488305e-07
+8.010019593e-11
+8.151547101e-12
+2.104227886e-11
+1.48739437e-14
+6.73022504e-11
+2.746364552e-11
+5.825923282e-10
+8.342013679e-10
+3.292650074e-13
+4.35906567e-15
+1.156117637e-08
+7.571945971e-10
+3.003747372e-12
+3.103098395e-11
+4.814600807e-12
+3.347696192e-15
+1.896819277e-12
+4.39567775e-20
+1.879896196e-12
+3.733280481e-16
+2.385225797e-13
+3.792396634e-10
+5.284148658e-10
+1.236899164e-13
+4.302156203e-09
+1.141458062e-12
+1.849420465e-12
+2.934830143e-17
+1.814128317e-12
+5.546953648e-13
+1.832695916e-11
+3.392066758e-11
+5.595093321e-09
+2.159400907e-12
+1.825362385e-14
+5.641169799e-09
+5.609360808e-12
+1.503956753e-12
+9.005858387e-18
+4.422242634e-15
+2.570100051e-13
+2.344892283e-12
+3.806300027e-11
+4.704338964e-13
+3.821672467e-12
+4.690108305e-12
+2.241165812e-11
+2.535051478e-11
+8.946474175e-15
+1.09013024e-14
+1.674513622e-13
+4.658507005e-13
+5.943042983e-19
+5.374611285e-12
+4.886843432e-13
+8.855636237e-15
+9.824676103e-14
+2.71697571e-11
+6.568068901e-10
+3.253171474e-12
+4.891927976e-17
+1.591049389e-17
+3.685849055e-13
+2.121424411e-13
+5.540015327e-12
+1.478395235e-12
+6.574780233e-13
+1.925986594e-17
+1.251674353e-10
+2.783870474e-13
+2.588346545e-15
+1.501054663e-16
+5.347031954e-12
+1.387448638e-11
+5.907798651e-19
+3.369165736e-11
+6.833829995e-15
+3.682458401e-14
+1.027956137e-13
+2.631056908e-13
+1.249942267e-12
+1.96008864e-12
+1.582305465e-17
+2.295094718e-15
+4.69250928e-17
+2.296318512e-15
+2.942228132e-13
+2.349705064e-12
+2.736249247e-15
+6.12670926e-16
+3.170059232e-12
+8.146163442e-17
+1.325487875e-12
+1.387736559e-11
+1.869873643e-14
+3.235685367e-12
+3.013413769e-13
+7.794226871e-13
+1.163707775e-12
+1.266103347e-11
+1.036429832e-13
+1.232033528e-20
+4.768193488e-21
+3.918840929e-16
+2.400227406e-16
+2.007856505e-15
+9.783188578e-19
+9.711515502e-17
+1.792115741e-15
+2.174277297e-14
+5.746845889e-12
+1.049963527e-15
+3.476900646e-17
+2.336766601e-13
+3.60397896e-17
+1.288121049e-18
+6.062502063e-12
+3.545133371e-15
+2.672731788e-11
+1.244123815e-15
+4.216634557e-11
+4.018433565e-19
+1.446038565e-19
+8.547709349e-13
+1.19853637e-08
+1.90337094e-12
+4.653830696e-14
+3.332939874e-14
+2.778725064e-13
+4.564313544e-11
+1.070103411e-18
+3.849910418e-15
+1.265576336e-12
+3.408959956e-11
+9.323991383e-11
+2.475894719e-11
+1.416023684e-14
+6.446985953e-12
+1.888343756e-14
+2.042598775e-17
+9.875335381e-13
+3.712810297e-12
+9.001861234e-17
+2.131436477e-15
+2.5635871e-16
+1.057343689e-21
+3.016690851e-14
+2.726647179e-15
+4.051876089e-15
+3.172284933e-14
+1.257261585e-17
+8.752106001e-12
+1.100620168e-12
+1.429190087e-13
+1.888222977e-12
+6.685129859e-14
+7.798268205e-17
+2.157180347e-17
+2.79628005e-14
+1.163483998e-13
+1.008964679e-16
+2.58849168e-16
+1.079779272e-19
+2.540983282e-15
+5.113984314e-21
+1.667850525e-13
+6.614109805e-16
+8.399078637e-19
+1.49208222e-15
+7.351199677e-13
+3.770945349e-19
+1.231069438e-18
+8.799947163e-15
+1.443204864e-15
+8.803977322e-20
+4.677958501e-16
+4.672536782e-13
+2.423975674e-15
+4.865501412e-13
+6.149482947e-16
+1.047530446e-16
+1.601471093e-18
+5.905130756e-17
+2.868612209e-15
+3.247537319e-15
+2.529286562e-18
+1.214234273e-18
+1.865270623e-16
+8.71635287e-18
+3.73337862e-20
+1.162089791e-17
+7.395420515e-17
+3.144785846e-17
+4.619050132e-14
+6.921186907e-17
+2.817393743e-20
+3.475312202e-17
+3.968027961e-19
+7.090124804e-20
+1.994642291e-17
+1.908024583e-16
+8.106034742e-20
+2.582283754e-17
+6.808634865e-20
+1.910837203e-10
+5.925663216e-22
+4.083345451e-24
+1.455174989e-17
+2.194070686e-13
+2.654554787e-13
+6.668337066e-16
+7.277292424e-18
+1.189161108e-17
+5.800734089e-15
+4.973958057e-15
+7.587912031e-16
+3.87764681e-14
+6.371946185e-19
+4.694251834e-16
+1.432647194e-13
+3.882128893e-13
+1.386919571e-16
+8.032263251e-15
+7.095608076e-16
+1.56502289e-18
+1.865965635e-14
+1.651312432e-16
+2.044852549e-16
+3.280309035e-16
+3.302465085e-18
+8.042276818e-18
+1.623942316e-18
+3.350198131e-19
+6.50302582e-15
+2.119837202e-13
+1.2160661e-13
+9.55843764e-18
+1.380410958e-15
+3.370720808e-18
+1.249700194e-16
+1.041221322e-12
+3.929319469e-16
+4.780672882e-14
+4.184388599e-22
+1.745456682e-16
+1.217499103e-15
+1.546763484e-16
+1.214585682e-16
+1.727931382e-18
+1.411499906e-19
+5.478069436e-16
+7.977485421e-17
+6.715731925e-19
+1.131285342e-15
+1.833302228e-17
+9.933675407e-21
+1.026202786e-19
+7.763122466e-19
+3.535135961e-15
+8.155166807e-18
+6.876925223e-19
+2.743262179e-16
+1.739120154e-17
+3.454301269e-17
+5.761631964e-18
+1.823055895e-19
+6.706828804e-28
+3.013577248e-18
+3.179406422e-21
+1.848524288e-18
+1.949753141e-26
+3.18448996e-20
+1.342022663e-13
+2.03949524e-21
+9.006476748e-18
+2.279313769e-16
+6.593737692e-18
+2.140450441e-21
+2.317895393e-21
+1.226539577e-22
+3.873136785e-22
+1.17324448e-19
+2.234770167e-16
+7.850221222e-25
+2.476747462e-16
+6.47122045e-23
+5.903905819e-20
+2.753373903e-21
+1.001620642e-14
+9.269308998e-17
+3.758182681e-20
+3.11376773e-20
+2.020826657e-18
+1.240808424e-20
+4.658793703e-21
+9.603528186e-22
+4.408181088e-19
+3.465015788e-24
+5.332863657e-16
+5.431518704e-27
+6.986635201e-21
+1.790901807e-23
+4.714028734e-20
+1.921508991e-16
+1.939778345e-16
+7.243322404e-20
+8.724465053e-19
+5.398622251e-19
+2.035277194e-19
+4.481036525e-24
+4.61608242e-22
+1.54728119e-18
+4.037681338e-22
+5.199137422e-20
+2.300546824e-25
+2.822383063e-18
+1.425742973e-21
+3.839718157e-16
+1.778294514e-18
+1.505801639e-26
+3.929064828e-16
+9.306231318e-19
+1.791557063e-20
+2.956452564e-19
+1.209440117e-22
+6.260854212e-20
+2.984418603e-17
+6.619984411e-21
+6.750352903e-15
+8.079484949e-19
+2.023663363e-15
+1.240912348e-18
+5.14780248e-20
+1.175170564e-23
+4.900597438e-19
+2.698214063e-22
+6.884103983e-20
+5.352290159e-19
+2.457127797e-15
+9.164098699e-18
+2.534079173e-18
+2.459294088e-19
+4.42175536e-16
+4.819502203e-17
+1.248158711e-21
+2.716160093e-22
+1.048818326e-20
+3.452341558e-24
+1.458270064e-21
+5.179101961e-20
+8.049803083e-18
+1.151886694e-19
+5.589025578e-21
+2.12572731e-19
+5.466939716e-18
+3.105262352e-25
+1.213845e-18
+2.149221667e-16
+3.679417895e-23
+4.019108797e-20
diff --git a/t/ME_data/PSP_w.lhe.gz b/t/ME_data/PSP_w.lhe.gz
new file mode 100644
index 0000000..183600b
Binary files /dev/null and b/t/ME_data/PSP_w.lhe.gz differ
diff --git a/t/ME_data/PSP_w_FKL.lhe.gz b/t/ME_data/PSP_w_FKL.lhe.gz
new file mode 100644
index 0000000..52958d2
Binary files /dev/null and b/t/ME_data/PSP_w_FKL.lhe.gz differ
diff --git a/t/ME_data/config_mt.yml b/t/ME_data/config_mt.yml
index 5a73374..eae06e5 100644
--- a/t/ME_data/config_mt.yml
+++ b/t/ME_data/config_mt.yml
@@ -1,28 +1,29 @@
trials: 1
min extparton pt: 30
resummation jets:
min pt: 30
algorithm: antikt
R: 0.4
fixed order jets:
min pt: 30
FKL: reweight
unordered: reweight
+qqx: discard
non-HEJ: discard
scales: 125
log correction: false
random generator:
name: mixmax
seed: 1
Higgs coupling:
use impact factors: false
mt: 174
include bottom: false
diff --git a/t/ME_data/config_mtinf.yml b/t/ME_data/config_mtinf.yml
index a7c71b6..dbac6c1 100644
--- a/t/ME_data/config_mtinf.yml
+++ b/t/ME_data/config_mtinf.yml
@@ -1,23 +1,24 @@
trials: 1
min extparton pt: 30
resummation jets:
min pt: 30
algorithm: antikt
R: 0.4
fixed order jets:
min pt: 30
FKL: reweight
unordered: reweight
+qqx: discard
non-HEJ: discard
scales: 125
log correction: false
random generator:
name: mixmax
seed: 1
diff --git a/t/ME_data/config_mtmb.yml b/t/ME_data/config_mtmb.yml
index c23cb8c..5f965cd 100644
--- a/t/ME_data/config_mtmb.yml
+++ b/t/ME_data/config_mtmb.yml
@@ -1,29 +1,30 @@
trials: 1
min extparton pt: 30
resummation jets:
min pt: 30
algorithm: antikt
R: 0.4
fixed order jets:
min pt: 30
FKL: reweight
unordered: reweight
+qqx: discard
non-HEJ: discard
scales: 125
log correction: false
random generator:
name: mixmax
seed: 1
Higgs coupling:
use impact factors: false
mt: 174
include bottom: true
mb: 4.7
diff --git a/t/ME_data/config_mtinf.yml b/t/ME_data/config_w_ME.yml
similarity index 94%
copy from t/ME_data/config_mtinf.yml
copy to t/ME_data/config_w_ME.yml
index a7c71b6..228fb7b 100644
--- a/t/ME_data/config_mtinf.yml
+++ b/t/ME_data/config_w_ME.yml
@@ -1,23 +1,24 @@
trials: 1
min extparton pt: 30
resummation jets:
min pt: 30
algorithm: antikt
R: 0.4
fixed order jets:
min pt: 30
FKL: reweight
unordered: reweight
+qqx: reweight
non-HEJ: discard
scales: 125
log correction: false
random generator:
name: mixmax
seed: 1
diff --git a/t/check_res.cc b/t/check_res.cc
index c832f55..88fdd47 100644
--- a/t/check_res.cc
+++ b/t/check_res.cc
@@ -1,131 +1,134 @@
#include <iostream>
#include "LHEF/LHEF.h"
#include "HEJ/Event.hh"
#include "HEJ/EventReweighter.hh"
#include "HEJ/Mixmax.hh"
#include "HEJ/stream.hh"
#define ASSERT(x) if(!(x)) { \
std::cerr << "Assertion '" #x "' failed.\n"; \
return EXIT_FAILURE; \
}
namespace{
const fastjet::JetDefinition jet_def{fastjet::kt_algorithm, 0.4};
const fastjet::JetDefinition Born_jet_def{jet_def};
constexpr double Born_jetptmin = 30;
constexpr double extpartonptmin = 30;
constexpr double max_ext_soft_pt_fraction =
std::numeric_limits<double>::infinity();
constexpr double jetptmin = 35;
constexpr bool log_corr = false;
using EventTreatment = HEJ::EventTreatment;
using namespace HEJ::event_type;
HEJ::EventTreatMap treat{
{no_2_jets, EventTreatment::discard},
{bad_final_state, EventTreatment::discard},
{nonHEJ, EventTreatment::discard},
{unof, EventTreatment::discard},
{unob, EventTreatment::discard},
+ {qqxexb, EventTreatment::discard},
+ {qqxexf, EventTreatment::discard},
+ {qqxmid, EventTreatment::discard},
{FKL, EventTreatment::reweight}
};
/// true if colour is allowed for particle
bool correct_colour(HEJ::Particle const & part){
if(HEJ::is_AWZH_boson(part) && !part.colour) return true;
if(!part.colour) return false;
int const colour = part.colour->first;
int const anti_colour = part.colour->second;
if(part.type == HEJ::ParticleID::gluon)
return colour != anti_colour && colour > 0 && anti_colour > 0;
if(HEJ::is_quark(part))
return anti_colour == 0 && colour > 0;
return colour == 0 && anti_colour > 0;
}
bool correct_colour(HEJ::Event const & ev){
if(!HEJ::event_type::is_HEJ(ev.type()))
return true;
for(auto const & part: ev.incoming()){
if(!correct_colour(part))
return false;
}
for(auto const & part: ev.outgoing()){
if(!correct_colour(part))
return false;
}
return true;
}
};
int main(int argn, char** argv) {
if(argn == 5 && std::string(argv[4]) == "uno"){
--argn;
treat[unof] = EventTreatment::reweight;
treat[unob] = EventTreatment::reweight;
treat[FKL] = EventTreatment::discard;
}
if(argn != 4){
std::cerr << "Usage: check_res eventfile xsection tolerance [uno]";
return EXIT_FAILURE;
}
const double xsec_ref = std::stod(argv[2]);
const double tolerance = std::stod(argv[3]);
HEJ::istream in{argv[1]};
LHEF::Reader reader{in};
HEJ::PhaseSpacePointConfig psp_conf;
psp_conf.jet_param = HEJ::JetParameters{jet_def, jetptmin};
psp_conf.min_extparton_pt = extpartonptmin;
psp_conf.max_ext_soft_pt_fraction = max_ext_soft_pt_fraction;
HEJ::MatrixElementConfig ME_conf;
ME_conf.log_correction = log_corr;
ME_conf.Higgs_coupling = HEJ::HiggsCouplingSettings{};
HEJ::EventReweighterConfig conf;
conf.psp_config = std::move(psp_conf);
conf.ME_config = std::move(ME_conf);
conf.jet_param = psp_conf.jet_param;
conf.treat = treat;
reader.readEvent();
const bool has_Higgs = std::find(
begin(reader.hepeup.IDUP),
end(reader.hepeup.IDUP),
25
) != end(reader.hepeup.IDUP);
const double mu = has_Higgs?125.:91.188;
HEJ::ScaleGenerator scale_gen{
{{std::to_string(mu), HEJ::FixedScale{mu}}}, {}, 1.
};
HEJ::Mixmax ran{};
HEJ::EventReweighter hej{reader.heprup, std::move(scale_gen), conf, ran};
double xsec = 0.;
double xsec_err = 0.;
do{
HEJ::Event ev{
HEJ::Event::EventData{reader.hepeup}.cluster(
Born_jet_def, Born_jetptmin
)
};
auto resummed_events = hej.reweight(ev, 20);
for(auto const & ev: resummed_events) {
ASSERT(correct_colour(ev));
xsec += ev.central().weight;
xsec_err += ev.central().weight*ev.central().weight;
}
} while(reader.readEvent());
xsec_err = std::sqrt(xsec_err);
const double significance =
std::abs(xsec - xsec_ref) / std::sqrt( xsec_err*xsec_err + tolerance*tolerance );
std::cout << xsec_ref << " +/- " << tolerance << " ~ "
<< xsec << " +- " << xsec_err << " => " << significance << " sigma\n";
if(significance > 3.){
std::cerr << "Cross section is off by over 3 sigma!\n";
return EXIT_FAILURE;
}
}
diff --git a/t/jet_config.yml b/t/jet_config.yml
index 1c56c5c..510c3f0 100644
--- a/t/jet_config.yml
+++ b/t/jet_config.yml
@@ -1,25 +1,26 @@
trials: 10
min extparton pt: 30
resummation jets:
min pt: 35
algorithm: antikt
R: 0.4
fixed order jets:
min pt: 30
FKL: reweight
unordered: discard
+qqx: discard
non-HEJ: discard
log correction: false
scales: 91.188
random generator:
name: ranlux64
event output:
- tst.lhe
diff --git a/t/jet_config_with_import.yml b/t/jet_config_with_import.yml
index 4ad014a..aeb3566 100644
--- a/t/jet_config_with_import.yml
+++ b/t/jet_config_with_import.yml
@@ -1,28 +1,29 @@
trials: 10
min extparton pt: 30
resummation jets:
min pt: 35
algorithm: antikt
R: 0.4
fixed order jets:
min pt: 30
FKL: reweight
unordered: discard
+qqx: discard
non-HEJ: discard
log correction: false
scales: softest_jet_pt
event output:
- tst.lhe
random generator:
name: ranlux64
import scales:
./libscales.so: softest_jet_pt
diff --git a/t/test_ME_generic.cc b/t/test_ME_generic.cc
index 02c4556..7ad3f45 100644
--- a/t/test_ME_generic.cc
+++ b/t/test_ME_generic.cc
@@ -1,120 +1,132 @@
// Generic tester for the ME for a given set of PSP
// reference weights and PSP (as LHE file) have to be given as _individual_ files
#include <fstream>
#include <random>
#include <algorithm>
#include "LHEF/LHEF.h"
#include "HEJ/MatrixElement.hh"
#include "HEJ/Event.hh"
#include "HEJ/YAMLreader.hh"
#include "HEJ/stream.hh"
constexpr double alpha_s = 0.118;
-constexpr double ep = 1e-6;
+constexpr double ep = 1e-5;
void shuffle_particles(HEJ::Event::EventData & ev) {
static std::mt19937_64 ran{0};
std::shuffle(begin(ev.incoming), end(ev.incoming), ran);
std::shuffle(begin(ev.outgoing), end(ev.outgoing), ran);
}
void dump(HEJ::Event const & ev){
{
LHEF::Writer writer{std::cout};
std::cout << std::setprecision(6);
writer.hepeup = to_HEPEUP(std::move(ev), nullptr);
writer.writeEvent();
}
std::cout << "Rapidity ordering:\n";
for(const auto & part: ev.outgoing()){
std::cout << std::setw(2) << part.type << ": "<< std::setw(7) << part.rapidity() << std::endl;
}
}
+enum MEComponent {tree, virt};
+
+MEComponent guess_component(std::string const & data_file) {
+ if(data_file.find("virt") != data_file.npos) return MEComponent::virt;
+ return MEComponent::tree;
+}
+
int main(int argn, char** argv){
if(argn != 4 && argn != 5){
std::cerr << "\n# Usage:\n."<< argv[0] <<" config.yml ME_weights input_file.lhe\n\n";
return EXIT_FAILURE;
}
bool OUTPUT_MODE = false;
if(argn == 5 && std::string("OUTPUT")==std::string(argv[4]))
OUTPUT_MODE = true;
const HEJ::Config config = HEJ::load_config(argv[1]);
std::fstream wgt_file;
if ( OUTPUT_MODE ) {
std::cout << "_______________________USING OUTPUT MODE!_______________________" << std::endl;
wgt_file.open(argv[2], std::fstream::out);
wgt_file.precision(10);
} else {
wgt_file.open(argv[2], std::fstream::in);
}
HEJ::istream in{argv[3]};
LHEF::Reader reader{in};
+ const auto component = guess_component(argv[2]);
+
HEJ::MatrixElement ME{
[](double){ return alpha_s; },
HEJ::to_MatrixElementConfig(config)
};
double max_ratio = 0.;
size_t idx_max_ratio = 0;
HEJ::Event ev_max_ratio(HEJ::Event::EventData{}.cluster(
config.resummation_jets.def,0
)
);
double av_ratio = 0;
size_t i = 0;
while(reader.readEvent()){
++i;
HEJ::Event::EventData data{reader.hepeup};
shuffle_particles(data);
HEJ::Event event{
data.cluster(
config.resummation_jets.def,
config.resummation_jets.min_pt
)
};
- const double our_ME = ME.tree(event).central;
+ const double our_ME = (component == MEComponent::tree)?
+ ME.tree(event).central:
+ ME.virtual_corrections(event).central
+ ;
if ( OUTPUT_MODE ) {
wgt_file << our_ME << std::endl;
} else {
std::string line;
if(!std::getline(wgt_file,line)) break;
const double ref_ME = std::stod(line);
const double diff = std::abs(our_ME/ref_ME-1.);
av_ratio+=diff;
if( diff > max_ratio ) {
max_ratio = diff;
idx_max_ratio = i;
ev_max_ratio = event;
}
if( diff > ep ){
size_t precision(std::cout.precision());
std::cout.precision(16);
std::cout<< "Large difference in PSP " << i << "\nis: "<<our_ME << " should: " << ref_ME << " => difference: " << diff << std::endl;
std::cout.precision(precision);
dump(event);
return EXIT_FAILURE;
}
}
}
wgt_file.close();
if ( !OUTPUT_MODE ) {
size_t precision(std::cout.precision());
std::cout.precision(16);
std::cout << "Avg ratio after " << i << " PSP: " << av_ratio/i << std::endl;
std::cout << "maximal ratio at " << idx_max_ratio << ": " << max_ratio << std::endl;
std::cout.precision(precision);
}
return EXIT_SUCCESS;
}

File Metadata

Mime Type
text/x-diff
Expires
Mon, Jan 20, 9:49 PM (1 d, 7 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4242523
Default Alt Text
(746 KB)

Event Timeline