From 70e77528cf9c984869622950eb468e14d33592ed Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 14 Apr 2026 14:35:36 +0200 Subject: [PATCH 01/16] Add a first go at a basic smoking backend. Currently just called a test scenario on the example slha with a hard coded path --- .../gambit/Backends/backend_types/smoking.hpp | 109 ++++++++++++++++++ .../Backends/frontends/smoking_1_0_0.hpp | 58 ++++++++++ .../ColliderBit/ColliderBit_MC_rollcall.hpp | 12 ++ ColliderBit/src/ColliderBit_smoking.cpp | 55 +++++++++ cmake/backends.cmake | 33 ++++++ config/backend_locations.yaml.default | 3 + config/bibtex_entries.bib | 17 +++ config/capabilities.dat | 4 + 8 files changed, 291 insertions(+) create mode 100644 Backends/include/gambit/Backends/backend_types/smoking.hpp create mode 100644 Backends/include/gambit/Backends/frontends/smoking_1_0_0.hpp create mode 100644 ColliderBit/src/ColliderBit_smoking.cpp diff --git a/Backends/include/gambit/Backends/backend_types/smoking.hpp b/Backends/include/gambit/Backends/backend_types/smoking.hpp new file mode 100644 index 0000000000..12aa5996ac --- /dev/null +++ b/Backends/include/gambit/Backends/backend_types/smoking.hpp @@ -0,0 +1,109 @@ +// GAMBIT: Global and Modular BSM Inference Tool +// ********************************************* +/// \file +/// +/// GAMBIT-side type definitions for the smoking backend. +/// +/// These structs mirror the definitions in smoking's +/// include/smoking/settings.h and include/smoking/input_parser.h. +/// Both sides must remain in sync so that the binary layout matches +/// when a smoking_variables reference is passed across the dlopen +/// boundary into init_SMOKING / Calculate_cross_section. +/// +/// ********************************************* +/// +/// Authors (add name and date if you modify): +/// +/// \author Christopher Chang +/// (christopher.chang@uqconnect.edu.au) +/// \date 2026 Apr +/// +/// ********************************************* + +#ifndef __smoking_types_hpp__ +#define __smoking_types_hpp__ + +#include +#include + +// --------------------------------------------------------------------------- +// Types from smoking's include/smoking/settings.h +// --------------------------------------------------------------------------- + +struct IntegratorConfig +{ + std::string backend = "GSL"; + std::string strategy = "VEGAS"; + bool use_GPU_integrator = false; + int chunksize = 8192; + double err_tol_rel = 5e-2; + size_t max_iters = 10; + size_t n_call = 0; +}; + +struct VegasParams { double alpha = 1.5; }; +struct SuaveParams {}; +struct DivonneParams {}; +struct CuhreParams {}; + +// --------------------------------------------------------------------------- +// Types from smoking's include/smoking/input_parser.h +// --------------------------------------------------------------------------- + +struct smoking_variables +{ + double sqrt_s = 13600.0; + int ipid1 = 2212; + int ipid2 = 2212; + std::vector pid1; + std::vector pid2; + + int order = 1; + bool dm = false; + bool dt = false; + std::vector diff_name; + std::vector diff_val; + int default_scheme = 0; + + int scale_scheme = 0; + std::vector central_scale; + double central_scale_F, central_scale_R; + std::vector scale_ratio; + double scale_ratio_F, scale_ratio_R; + bool scale_error = false; + int scale_strategy = 3; + + bool alphas_error = false; + bool pdf_error = false; + std::string pdf_set = "PDF4LHC15_nnlo_100"; + bool model_alphas; // intentionally uninitialised, matching smoking + std::string slha_file = "example/sps1a.slha"; + SLHAea::Coll slhaea; + bool output = false; + std::string output_file; + + bool diffname_flag = false; + bool diffval_flag = false; + bool scale_flag = false; + bool central_scale_flag = false; + bool scale_ratio_flag = false; + bool output_file_name = false; + + double xmin = 0; + bool PDFxmin = false; + bool invMellin_force_physical = false; + + double NLP = 1; + double NLL = 1; + double NNLL = 0; + double H_1loop = 0; + double H_2loop = 0; + + IntegratorConfig int_config; + VegasParams vegas_params; + SuaveParams suave_params; + DivonneParams divonne_params; + CuhreParams cuhre_params; +}; + +#endif /* defined __smoking_types_hpp__ */ diff --git a/Backends/include/gambit/Backends/frontends/smoking_1_0_0.hpp b/Backends/include/gambit/Backends/frontends/smoking_1_0_0.hpp new file mode 100644 index 0000000000..7522e4328f --- /dev/null +++ b/Backends/include/gambit/Backends/frontends/smoking_1_0_0.hpp @@ -0,0 +1,58 @@ +// GAMBIT: Global and Modular BSM Inference Tool +// ********************************************* +/// \file +/// +/// Frontend header for the smoking backend v1.0.0. +/// +/// smoking computes NLO+NLL hadronic cross-sections for +/// slepton and electroweakino pair production. +/// +/// The backend exposes three extern "C" functions from +/// libsmoking_gambit.so: +/// +/// init_SMOKING -- initialise integrators, PDFs, processes +/// Calculate_cross_section -- run the calculation for one SLHA point +/// finalise_SMOKING -- clean up all resources +/// +/// ********************************************* +/// +/// Authors (add name and date if you modify): +/// +/// \author Christopher Chang +/// (c.j.chang@fys.uio.no) +/// \date 2026 Apr +/// +/// ********************************************* + +#define BACKENDNAME smoking +#define BACKENDLANG CXX +#define VERSION 1.0.0 +#define SAFE_VERSION 1_0_0 +#define REFERENCE TODO + +// Load the shared library +LOAD_LIBRARY + +// Pull in the GAMBIT-side mirror of smoking's types +#include "gambit/Backends/backend_types/smoking.hpp" + +/* Syntax: + * BE_FUNCTION(gambit_name, return_type, (arg_types), "symbol_name", "capability_name") + * + * The symbol names are unmangled because the functions are declared extern "C" + * in smoking's gambit_interface.cpp. + */ + +BE_FUNCTION(smoking_init, int, (smoking_variables&), "init_SMOKING", "smoking_init") +BE_FUNCTION(smoking_calc, void, (smoking_variables&), "Calculate_cross_section", "smoking_calc") +BE_FUNCTION(smoking_finalise, int, (), "finalise_SMOKING", "smoking_finalise") + +// Initialisation function +BE_INI_FUNCTION +{ +} +END_BE_INI_FUNCTION + + +// Undefine macros to avoid conflict with other backends +#include "gambit/Backends/backend_undefs.hpp" diff --git a/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp b/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp index 1b4419041f..511464260d 100644 --- a/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp +++ b/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp @@ -44,6 +44,7 @@ #pragma once #include "gambit/Utils/util_types.hpp" +#include "gambit/Backends/backend_types/smoking.hpp" #define MODULE ColliderBit @@ -508,6 +509,17 @@ #undef FUNCTION #undef CAPABILITY + /// Run the smoking NLO+NLL cross-section calculation with default settings. + #define CAPABILITY RunSmoking + START_CAPABILITY + #define FUNCTION runSmoking + START_FUNCTION(double) + BACKEND_REQ(smoking_init, (), int, (smoking_variables&)) + BACKEND_REQ(smoking_calc, (), void, (smoking_variables&)) + BACKEND_REQ(smoking_finalise, (), int, ()) + #undef FUNCTION + #undef CAPABILITY + /// Detector sim capabilities. /// @{ #define CAPABILITY ATLASDetectorSim diff --git a/ColliderBit/src/ColliderBit_smoking.cpp b/ColliderBit/src/ColliderBit_smoking.cpp new file mode 100644 index 0000000000..e7d4b5c03c --- /dev/null +++ b/ColliderBit/src/ColliderBit_smoking.cpp @@ -0,0 +1,55 @@ +// GAMBIT: Global and Modular BSM Inference Tool +// ********************************************* +/// \file +/// +/// ColliderBit module functions for the smoking backend. +/// +/// ********************************************* +/// +/// Authors (add name and date if you modify): +/// +/// \author Christopher Chang +/// (c.j.chang@fys.uio.no) +/// \date 2026 Apr +/// +/// ********************************************* + +#include "gambit/Elements/gambit_module_headers.hpp" +#include "gambit/ColliderBit/ColliderBit_rollcall.hpp" +#include "gambit/Backends/backend_types/smoking.hpp" + +#include "gambit/Utils/slhaea_helpers.hpp" + +namespace Gambit +{ + namespace ColliderBit + { + + /// Run the smoking NLO+NLL cross-section calculation with default settings. + void runSmoking(double &result) + { + using namespace Pipes::runSmoking; + + smoking_variables vars; + // TODO: This should be done in the frontend, not here... + // const str backendDir = Backends::backendInfo().path_dir(STRINGIFY(smoking), STRINGIFY(VERSION)); + // TODO: If done properly in frontend header, can use bandendDir to automatically get this. + // I am just gonna try it hacked for now. + vars.slha_file = "/home/chris-chang/WORK/GAMBIT/CB_development/SMOKING_backend/gambit/Backends/installed/smoking/1.0.0/example/sps1a.slha"; + + // std::ifstream slhafilein(vars.slha_file); + // const SLHAea::Coll* slhaea = new SLHAea::Coll(slhafilein); + SLHAstruct slhaea = read_SLHA(vars.slha_file); + vars.slhaea = slhaea; + + std::cout << "HEY CHRIS. I got here after reading in the SLHA..." << std::endl; + + BEreq::smoking_init(vars); + BEreq::smoking_calc(vars); + BEreq::smoking_finalise(); + + result = 0.0; + } + + } +} diff --git a/cmake/backends.cmake b/cmake/backends.cmake index cd447dae61..8875c03b22 100644 --- a/cmake/backends.cmake +++ b/cmake/backends.cmake @@ -664,6 +664,39 @@ if(NOT ditched_${name}_${ver}) set_as_default_version("backend" ${name} ${ver}) endif() +# smoking +# Builds libsmoking_gambit.so via the smoking cmake build system. +# The shared library exposes three extern "C" functions: +# init_SMOKING, Calculate_cross_section, finalise_SMOKING +set(name "smoking") +set(ver "1.0.0") +set(lib "libsmoking_gambit") +set(dl "https://github.com/ahye/smoking/archive/refs/heads/gambit_interface.zip") +set(md5 "cd5665f7c7e289425185a1e02ea66599") +set(dir "${PROJECT_SOURCE_DIR}/Backends/installed/${name}/${ver}") + +set(smoking_CXX_FLAGS "${BACKEND_CXX_FLAGS}") + +check_ditch_status(${name} ${ver} ${dir}) +if(NOT ditched_${name}_${ver}) + ExternalProject_Add(${name}_${ver} + DOWNLOAD_COMMAND ${DL_BACKEND} ${dl} ${md5} ${dir} ${name} ${ver} + SOURCE_DIR ${dir} + PATCH_COMMAND "" + CMAKE_ARGS + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} + -DCMAKE_CXX_FLAGS=${smoking_CXX_FLAGS} + -DCMAKE_C_FLAGS=${BACKEND_C_FLAGS} + -DCMAKE_Fortran_COMPILER=${CMAKE_Fortran_COMPILER} + -DCMAKE_BUILD_TYPE=Debug # TODO: Change to Release + -DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} + -DWITH_GAMBIT_INTERFACE=ON + BUILD_COMMAND ${MAKE_PARALLEL} smoking_gambit + INSTALL_COMMAND "" + ) + add_extra_targets("backend" ${name} ${ver} ${dir} ${dl} clean) + set_as_default_version("backend" ${name} ${ver}) +endif() # DDCalc set(name "ddcalc") diff --git a/config/backend_locations.yaml.default b/config/backend_locations.yaml.default index dc564a98c0..c337abb141 100644 --- a/config/backend_locations.yaml.default +++ b/config/backend_locations.yaml.default @@ -133,6 +133,9 @@ obscura: pbarlike: 1.0: ./Backends/installed/pbarlike/1.0/pbarlike-gambit-interface.py +smoking: + 1.0.0: ./Backends/installed/smoking/1.0.0/lib/libsmoking_gambit.so + Rivet: 3.1.5: ./Backends/installed/rivet/3.1.5/local/lib/libRivet.so diff --git a/config/bibtex_entries.bib b/config/bibtex_entries.bib index 92df7f6058..32aec7abd2 100644 --- a/config/bibtex_entries.bib +++ b/config/bibtex_entries.bib @@ -1,3 +1,20 @@ +@article{TODO, + author = "TODO", + collaboration = "TODO", + title = "TODO", + eprint = "TODO", + archivePrefix = "TODO", + primaryClass = "TODO", + reportNumber = "TODO", + doi = "TODO", + journal = "TODO", + volume = "TODO", + number = "TODO", + pages = "TODO", + year = "TODO", + note = "TODO" +} + # GAMBIT @article{GAMBIT:2017yxo, author = "Athron, Peter and others", diff --git a/config/capabilities.dat b/config/capabilities.dat index 9660967581..3f16f54e11 100644 --- a/config/capabilities.dat +++ b/config/capabilities.dat @@ -397,6 +397,10 @@ SPheno_internal: | # ColliderBit capabilities #------------------------------------- +RunSmoking: | + Run the smoking NLO+NLL hadronic cross-section calculation (init, calculate, + finalise) with default settings. + DummyColliderObservable: | Dummy observable that creates a dependency on TestModel1D, which is used to satisfy the normal GAMBIT model requrements in a minimal way. Used From b275c6c04ca1234d264e1401b524c5633b2c6de1 Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 14 Apr 2026 14:38:18 +0200 Subject: [PATCH 02/16] update md5sum --- cmake/backends.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/backends.cmake b/cmake/backends.cmake index 8875c03b22..495f2f0823 100644 --- a/cmake/backends.cmake +++ b/cmake/backends.cmake @@ -672,7 +672,7 @@ set(name "smoking") set(ver "1.0.0") set(lib "libsmoking_gambit") set(dl "https://github.com/ahye/smoking/archive/refs/heads/gambit_interface.zip") -set(md5 "cd5665f7c7e289425185a1e02ea66599") +set(md5 "f06c96a007c2fafba54189e83e444672") set(dir "${PROJECT_SOURCE_DIR}/Backends/installed/${name}/${ver}") set(smoking_CXX_FLAGS "${BACKEND_CXX_FLAGS}") From e1ad68af65043f8d6e0bfb297b3c18781a69dbed Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 14 Apr 2026 14:53:14 +0200 Subject: [PATCH 03/16] update md5sum --- cmake/backends.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/backends.cmake b/cmake/backends.cmake index 495f2f0823..f84ede0171 100644 --- a/cmake/backends.cmake +++ b/cmake/backends.cmake @@ -672,7 +672,7 @@ set(name "smoking") set(ver "1.0.0") set(lib "libsmoking_gambit") set(dl "https://github.com/ahye/smoking/archive/refs/heads/gambit_interface.zip") -set(md5 "f06c96a007c2fafba54189e83e444672") +set(md5 "6b7f70d509ee651ade1b765ab4b370cf") set(dir "${PROJECT_SOURCE_DIR}/Backends/installed/${name}/${ver}") set(smoking_CXX_FLAGS "${BACKEND_CXX_FLAGS}") From d8dda2ccda7acf9a664c05b1d5ecebf7c773ffe1 Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 14 Apr 2026 16:37:02 +0200 Subject: [PATCH 04/16] Add get xsec perform Initial xsec smoking --- .../gambit/ColliderBit/models/SUSY.hpp | 9 ++++++++ ColliderBit/src/getxsec.cpp | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/ColliderBit/include/gambit/ColliderBit/models/SUSY.hpp b/ColliderBit/include/gambit/ColliderBit/models/SUSY.hpp index b00c97d140..c82b8cc859 100644 --- a/ColliderBit/include/gambit/ColliderBit/models/SUSY.hpp +++ b/ColliderBit/include/gambit/ColliderBit/models/SUSY.hpp @@ -41,6 +41,7 @@ #pragma once #include "gambit/ColliderBit/models/SUSY_extras.hpp" +#include "gambit/Backends/backend_types/smoking.hpp" #define MODULE ColliderBit @@ -52,6 +53,14 @@ DEPENDENCY(SpectrumAndDecaysForPythia, SLHAstruct) #undef FUNCTION + #define FUNCTION PerformInitialCrossSection_smoking + START_FUNCTION(initialxsec_container) + DEPENDENCY(SpectrumAndDecaysForPythia, SLHAstruct) + BACKEND_REQ(smoking_init, (), int, (smoking_variables&)) + BACKEND_REQ(smoking_calc, (), void, (smoking_variables&)) + BACKEND_REQ(smoking_finalise, (), int, ()) + #undef FUNCTION + #undef CAPABILITY // Construct an SLHAea object with spectrum and decays for Pythia diff --git a/ColliderBit/src/getxsec.cpp b/ColliderBit/src/getxsec.cpp index 816687c95c..aff46ccedb 100644 --- a/ColliderBit/src/getxsec.cpp +++ b/ColliderBit/src/getxsec.cpp @@ -20,6 +20,7 @@ #include "gambit/ColliderBit/ColliderBit_eventloop.hpp" #include "gambit/ColliderBit/complete_process_PID_pair_multimaps.hpp" +#include "gambit/Backends/backend_types/smoking.hpp" // #define COLLIDERBIT_DEBUG #define DEBUG_PREFIX "DEBUG: OMP thread " << omp_get_thread_num() << ": " << __FILE__ << ":" << __LINE__ << ": " @@ -1912,5 +1913,26 @@ namespace Gambit } // end InitialTotalCrossSection_YAMLSLHA + /// Run the smoking NLO+NLL cross-section calculation using the SLHAea object + /// already constructed by ColliderBit (normally passed to Pythia). + void PerformInitialCrossSection_smoking(initialxsec_container& result) + { + using namespace Pipes::PerformInitialCrossSection_smoking; + + SLHAstruct slhaea = *Dep::SpectrumAndDecaysForPythia; + + smoking_variables vars; + vars.slhaea = slhaea; + + BEreq::smoking_init(vars); + BEreq::smoking_calc(vars); + BEreq::smoking_finalise(); + + // smoking_calc currently prints results to stdout; no structured + // return value is available from the backend yet. + result = initialxsec_container(); + } + + } } From 45765f7a087c8e97c1050ee33ee15d6bdbdbf9a6 Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Mon, 20 Apr 2026 16:56:32 +0200 Subject: [PATCH 05/16] Add passing of smoking result through to Initial and Total CrossSection in gambit (now used in likelihood evaluation) - Still need to pass process xsecs. Should follow simply enough, but we have not actually used it in gambit yet I think --- .../gambit/Backends/backend_types/smoking.hpp | 131 ++++++++++++++++++ .../Backends/frontends/smoking_1_0_0.hpp | 2 +- .../ColliderBit/ColliderBit_MC_rollcall.hpp | 12 +- .../gambit/ColliderBit/models/SUSY.hpp | 2 +- ColliderBit/src/getxsec.cpp | 58 +++++++- cmake/backends.cmake | 2 +- cmake/contrib.cmake | 2 +- 7 files changed, 201 insertions(+), 8 deletions(-) diff --git a/Backends/include/gambit/Backends/backend_types/smoking.hpp b/Backends/include/gambit/Backends/backend_types/smoking.hpp index 12aa5996ac..440afdbca7 100644 --- a/Backends/include/gambit/Backends/backend_types/smoking.hpp +++ b/Backends/include/gambit/Backends/backend_types/smoking.hpp @@ -25,6 +25,8 @@ #include #include +#include +#include // --------------------------------------------------------------------------- // Types from smoking's include/smoking/settings.h @@ -106,4 +108,133 @@ struct smoking_variables CuhreParams cuhre_params; }; +// +// Structures for keeping track of results +// + + +// Struct for single cross section calculations with numerical errors +// Errors propagate under addition, subtraction and multiplication by constant +// The struct has a simple printing << operator +struct xsec{ + double central; + double upper; + double lower; + + // Status flag, not used to store fatal errors + int status; + + // Constructor + xsec(double central=0, double upper=0, double lower=0, int status=0): central(central), upper(upper), lower(lower), status(status) {} + + // Addition of cross sections, does not modify object therefore const + xsec operator+(const xsec& a) const { + // If an error occurred, return the first error + int combined_status = 0; + if (status < 0) {combined_status = status;} + else if (a.status < 0) {combined_status = a.status;} + else {combined_status = std::max(status, a.status);} + + return xsec(central+a.central, sqrt(upper*upper+a.upper*a.upper), sqrt(lower*lower+a.lower*a.lower), combined_status); + } + + // Subtraction of cross sections, does not modify object therefore const + xsec operator-(const xsec& a) const { + // If an error occurred, return the first error + int combined_status = 0; + if (status < 0) {combined_status = status;} + else if (a.status < 0) {combined_status = a.status;} + else {combined_status = std::max(status, a.status);} + + return xsec(central-a.central, sqrt(upper*upper+a.upper*a.upper), sqrt(lower*lower+a.lower*a.lower), combined_status); + } + + // Scalar multiplication, does modify object + xsec operator*(const double a) { + return xsec(a*central, a*upper, a*lower, status); + } + +}; + +xsec operator*(const double k, const xsec& a); +std::ostream& operator<<(std::ostream& os, const xsec& a); + + +// Struct for bookkeeping results of a complete calculation +struct Result{ + xsec cross_section {0,0,0}; + xsec upper_sca_err {0,0,0}; + xsec lower_sca_err {0,0,0}; + std::vector sca_err; // Contains cross-section for other scales: For strategy 3 (mu_F,mu_R)/mu_0 = [(0.5,0.5), (2,2)] + // For strategy 7 (mu_F,mu_R)/mu_0 = [(0.5,0.5), (0.5,1), (1,0.5), (1,2), (2,1), (2,2)] + std::vector pdf_err; + double upper_pdf_err; + double lower_pdf_err; + double upper_alphas_err; + double lower_alphas_err; + + // Used to indicate success/failure. Anything other than zero is a failure. + int status; + + // Constructor + Result() = default; + Result(xsec cross_section, std::vector sca_err, std::vector pdf_err): cross_section(cross_section), sca_err(sca_err), pdf_err(pdf_err) {} + + // Addition of results, does not modify object therefore const + Result operator+(const Result& a) const { + std::vector total_pdferr; + for(size_t i=0; i < pdf_err.size(); i++){ + total_pdferr.push_back(pdf_err[i]+a.pdf_err[i]); + } + std::vector total_scaerr; + for(size_t i=0; i < sca_err.size(); i++){ + total_scaerr.push_back(sca_err[i]+a.sca_err[i]); + } + Result res = Result(cross_section+a.cross_section, total_scaerr, total_pdferr); + res.status = std::min(status, a.status); + + return res; + } + + // Subtraction of results, does not modify object therefore const + Result operator-(const Result& a) const { + std::vector total_pdferr; + for(size_t i=0; i < pdf_err.size(); i++){ + total_pdferr.push_back(pdf_err[i]-a.pdf_err[i]); + } + std::vector total_scaerr; + for(size_t i=0; i < sca_err.size(); i++){ + total_scaerr.push_back(sca_err[i]-a.sca_err[i]); + } + Result res = Result(cross_section-a.cross_section, total_scaerr, total_pdferr); + res.status = std::min(status, a.status); + return res; + } + + // Scalar multiplication, does modify object + Result operator*(const double a) { + std::vector total_pdferr; + for(size_t i=0; i < pdf_err.size(); i++){ + total_pdferr.push_back(a*pdf_err[i]); + } + std::vector total_scaerr; + for(size_t i=0; i < pdf_err.size(); i++){ + total_scaerr.push_back(a*sca_err[i]); + } + Result res = Result(a*cross_section, total_scaerr, total_pdferr); + return res; + } + + // Set values equal to a xsec struct (cross section result) + Result& operator=(const xsec& a) { + cross_section = a; + return *this; + } + + +}; + +Result operator*(const double k, const Result& a); + + #endif /* defined __smoking_types_hpp__ */ diff --git a/Backends/include/gambit/Backends/frontends/smoking_1_0_0.hpp b/Backends/include/gambit/Backends/frontends/smoking_1_0_0.hpp index 7522e4328f..7b4fdaf865 100644 --- a/Backends/include/gambit/Backends/frontends/smoking_1_0_0.hpp +++ b/Backends/include/gambit/Backends/frontends/smoking_1_0_0.hpp @@ -44,7 +44,7 @@ LOAD_LIBRARY */ BE_FUNCTION(smoking_init, int, (smoking_variables&), "init_SMOKING", "smoking_init") -BE_FUNCTION(smoking_calc, void, (smoking_variables&), "Calculate_cross_section", "smoking_calc") +BE_FUNCTION(smoking_calc, std::vector, (smoking_variables&), "Calculate_cross_section", "smoking_calc") BE_FUNCTION(smoking_finalise, int, (), "finalise_SMOKING", "smoking_finalise") // Initialisation function diff --git a/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp b/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp index 511464260d..21ef1fa376 100644 --- a/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp +++ b/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp @@ -155,6 +155,13 @@ NEEDS_MANAGER(RunMC, MCLoopInfo) ALLOW_MODELS(ColliderBit_SLHA_scan_model) #undef FUNCTION + + /// Get the Total CrossSection by copying the Initial Cross Section (useful when evaluating with an xsec calculator other than Pythia) + #define FUNCTION useInitialCrossSectionasFinalTotalCrossSection + START_FUNCTION(xsec_container) + NEEDS_MANAGER(RunMC, MCLoopInfo) + DEPENDENCY(PerformInitialCrossSection, initialxsec_container) + #undef FUNCTION #undef CAPABILITY /// Output info on TotalCrossSection as @@ -228,6 +235,9 @@ NEEDS_MANAGER(RunMC, MCLoopInfo) DEPENDENCY(ActivePIDPairs, vec_PID_pair) #undef FUNCTION + + /// TODO: Chris Chang: Copy process cross-sections from initial cross-section estimate + #undef CAPABILITY /// Output PID pair cross-sections as a @@ -515,7 +525,7 @@ #define FUNCTION runSmoking START_FUNCTION(double) BACKEND_REQ(smoking_init, (), int, (smoking_variables&)) - BACKEND_REQ(smoking_calc, (), void, (smoking_variables&)) + BACKEND_REQ(smoking_calc, (), std::vector, (smoking_variables&)) BACKEND_REQ(smoking_finalise, (), int, ()) #undef FUNCTION #undef CAPABILITY diff --git a/ColliderBit/include/gambit/ColliderBit/models/SUSY.hpp b/ColliderBit/include/gambit/ColliderBit/models/SUSY.hpp index c82b8cc859..26ab160966 100644 --- a/ColliderBit/include/gambit/ColliderBit/models/SUSY.hpp +++ b/ColliderBit/include/gambit/ColliderBit/models/SUSY.hpp @@ -57,7 +57,7 @@ START_FUNCTION(initialxsec_container) DEPENDENCY(SpectrumAndDecaysForPythia, SLHAstruct) BACKEND_REQ(smoking_init, (), int, (smoking_variables&)) - BACKEND_REQ(smoking_calc, (), void, (smoking_variables&)) + BACKEND_REQ(smoking_calc, (), std::vector, (smoking_variables&)) BACKEND_REQ(smoking_finalise, (), int, ()) #undef FUNCTION diff --git a/ColliderBit/src/getxsec.cpp b/ColliderBit/src/getxsec.cpp index aff46ccedb..6200f84521 100644 --- a/ColliderBit/src/getxsec.cpp +++ b/ColliderBit/src/getxsec.cpp @@ -1921,18 +1921,70 @@ namespace Gambit SLHAstruct slhaea = *Dep::SpectrumAndDecaysForPythia; + // Add MODSEL block if it is missing + if(slhaea.find("MODSEL") == slhaea.end()) \ + { \ + SLHAea::Block block("MODSEL"); \ + block.push_back("BLOCK MODSEL # Model selection"); \ + SLHAea::Line line; \ + line << 1 << 0 << "# Tell smoking that this is a SUSY model."; \ + block.push_back(line); \ + slhaea.push_front(block); \ + } + smoking_variables vars; vars.slhaea = slhaea; BEreq::smoking_init(vars); - BEreq::smoking_calc(vars); + std::vector res = BEreq::smoking_calc(vars); // TODO: This needs to be renamed in smoking, as Result is far too generic a term BEreq::smoking_finalise(); - // smoking_calc currently prints results to stdout; no structured - // return value is available from the backend yet. + std::cout << "LO xsec from smoking: " << res[0].cross_section.central << std::endl; + + // Forming the output... + // Calculating the total cross-section as the sum of the process cross sections + std::string collider = runOptions->getValueOrDef("LHC_13TeV", "Collider"); // TODO: Support multiple Colliders (just loop through a list) + map_str_xsec_container TotalXsecContainer; + map_int_process_xsec int_proc_xsec_map; + map_str_map_int_process_xsec ProcessXsecContainer; + xsec total_xsec; + for (size_t i = 0; i < vars.pid1.size(); i++) + { + // TODO: What to put as the codes here, Would eneed to be careful to make sure they match Pythia? + int code = vars.pid1[i];// input_variables.pid2[i]; // TODO: Just for testing, I am setting the code to the first pid1, this is incorrect!! + xsec cross_section = res[i].cross_section; + total_xsec = total_xsec + cross_section; + double process_xsec = cross_section.central; //combined_process_xsec[code]; + double process_xsecErr = cross_section.upper - cross_section.central; //combined_process_xsecErr[code]; + process_xsec_container newprocess; + newprocess.set_xsec(process_xsec, process_xsecErr); + newprocess.set_process_code(code); + int_proc_xsec_map[code] = newprocess; + } + ProcessXsecContainer[collider] = int_proc_xsec_map; + xsec_container xsContainer; + xsContainer.set_xsec(total_xsec.central, total_xsec.upper - total_xsec.central); // NOTE: Assuming symmetric uncertainty, but smoking can in theory return assymetric uncertainty + TotalXsecContainer[collider] = xsContainer; + + result = initialxsec_container(); + result.first = TotalXsecContainer; + result.second = ProcessXsecContainer; } + /// Copy the Initial CrossSection estimate into the Final as the Total CrossSection + /// This is useful when evalutating both using e.g. NLO xsec calculators + void useInitialCrossSectionasFinalTotalCrossSection(xsec_container& result) + { + using namespace Pipes::useInitialCrossSectionasFinalTotalCrossSection; + std::string collider = Dep::RunMC->current_collider(); + + initialxsec_container initial_xsec = *Dep::PerformInitialCrossSection; + result = initial_xsec.first[collider]; + } + + // TODO: Same but for process xsecs + } } diff --git a/cmake/backends.cmake b/cmake/backends.cmake index f84ede0171..2006ffd45d 100644 --- a/cmake/backends.cmake +++ b/cmake/backends.cmake @@ -672,7 +672,7 @@ set(name "smoking") set(ver "1.0.0") set(lib "libsmoking_gambit") set(dl "https://github.com/ahye/smoking/archive/refs/heads/gambit_interface.zip") -set(md5 "6b7f70d509ee651ade1b765ab4b370cf") +set(md5 "a7f0eafbeae04b9935dacf0f0dbf5c7f") set(dir "${PROJECT_SOURCE_DIR}/Backends/installed/${name}/${ver}") set(smoking_CXX_FLAGS "${BACKEND_CXX_FLAGS}") diff --git a/cmake/contrib.cmake b/cmake/contrib.cmake index 1585d1d7e8..867a99de36 100644 --- a/cmake/contrib.cmake +++ b/cmake/contrib.cmake @@ -103,7 +103,7 @@ add_dependencies(contrib mkpath) #contrib/yaml-cpp-0.6.2 set(yaml_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/contrib/yaml-cpp-0.6.2/include) -include_directories("${yaml_INCLUDE_DIR}") +include_directories(SYSTEM "${yaml_INCLUDE_DIR}") add_definitions(-DYAML_CPP_DLL) add_subdirectory(${PROJECT_SOURCE_DIR}/contrib/yaml-cpp-0.6.2 EXCLUDE_FROM_ALL) From 29cf3e84cb7f5cf5ba19165eb5d014b0eb08cb7d Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 21 Apr 2026 16:57:26 +0200 Subject: [PATCH 06/16] Add new MODSEL line to be clearer about presence of flavour violation (required for smoking) --- ColliderBit/include/gambit/ColliderBit/getPy8Collider.hpp | 3 +++ ColliderBit/src/getxsec.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/ColliderBit/include/gambit/ColliderBit/getPy8Collider.hpp b/ColliderBit/include/gambit/ColliderBit/getPy8Collider.hpp index 840320f049..e564bd3bc7 100644 --- a/ColliderBit/include/gambit/ColliderBit/getPy8Collider.hpp +++ b/ColliderBit/include/gambit/ColliderBit/getPy8Collider.hpp @@ -294,6 +294,9 @@ namespace Gambit SLHAea::Line line; \ line << 1 << 0 << "# Tell Pythia that this is a SUSY model."; \ block.push_back(line); \ + SLHAea::Line line2; \ + line2 << 6 << 3 << "# There is Flavour violations in squark and slepton sectors"; \ + block.push_back(line2); \ result.push_front(block); \ } \ \ diff --git a/ColliderBit/src/getxsec.cpp b/ColliderBit/src/getxsec.cpp index 6200f84521..b234cb98d9 100644 --- a/ColliderBit/src/getxsec.cpp +++ b/ColliderBit/src/getxsec.cpp @@ -1929,6 +1929,9 @@ namespace Gambit SLHAea::Line line; \ line << 1 << 0 << "# Tell smoking that this is a SUSY model."; \ block.push_back(line); \ + SLHAea::Line line2; \ + line2 << 6 << 3 << "# There is Flavour violations in squark and slepton sectors"; \ + block.push_back(line2); \ slhaea.push_front(block); \ } From 2c3368fc78335b03a83050268fb2510e421572e5 Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Mon, 4 May 2026 16:07:04 +0200 Subject: [PATCH 07/16] Smoking Interface Partial Changes --- .../gambit/ColliderBit/getPy8Collider.hpp | 4 +- yaml_files/ColliderBit_CMSSM.yaml | 231 +----------------- 2 files changed, 9 insertions(+), 226 deletions(-) diff --git a/ColliderBit/include/gambit/ColliderBit/getPy8Collider.hpp b/ColliderBit/include/gambit/ColliderBit/getPy8Collider.hpp index e564bd3bc7..fc2f6b4a3e 100644 --- a/ColliderBit/include/gambit/ColliderBit/getPy8Collider.hpp +++ b/ColliderBit/include/gambit/ColliderBit/getPy8Collider.hpp @@ -294,8 +294,8 @@ namespace Gambit SLHAea::Line line; \ line << 1 << 0 << "# Tell Pythia that this is a SUSY model."; \ block.push_back(line); \ - SLHAea::Line line2; \ - line2 << 6 << 3 << "# There is Flavour violations in squark and slepton sectors"; \ + SLHAea::Line line2; \ + line2 << 6 << 3 << "# Flavour Violation in the Quark and Lepton sector."; \ block.push_back(line2); \ result.push_front(block); \ } \ diff --git a/yaml_files/ColliderBit_CMSSM.yaml b/yaml_files/ColliderBit_CMSSM.yaml index 52ae8cf7fa..ade3efc3ee 100644 --- a/yaml_files/ColliderBit_CMSSM.yaml +++ b/yaml_files/ColliderBit_CMSSM.yaml @@ -16,22 +16,6 @@ Parameters: # SM nuisance parameters fixed for now. StandardModel_SLHA2: !import include/StandardModel_SLHA2_defaults.yaml - # # CMSSM parameter ranges and priors - # CMSSM: - # M0: - # range: [100, 5000] - # prior_type: log - # M12: - # range: [100, 5000] - # prior_type: log - # A0: - # range: [-7000, 7000] - # prior_type: flat - # TanBeta: - # range: [3.0, 70] - # prior_type: flat - # SignMu: 1 - # CMSSM parameters for a single test point CMSSM: M0: 300 @@ -53,29 +37,12 @@ Printer: printer: cout - # printer: hdf5 - # options: - # output_file: "ColliderBit_CMSSM.hdf5" - # group: "/ColliderBit_CMSSM" - # delete_file_on_restart: true - - # printer: ascii - # options: - # output_file: "gambit_output.txt" - - Scanner: use_scanner: random scanners: - multinest: - plugin: multinest - like: LogLike - nlive: 4000 - tol: 0.5 - random: plugin: random point_number: 1 @@ -84,76 +51,11 @@ Scanner: files: output_file: "weights ..." - de: - plugin: diver - like: LogLike - NP: 19200 - convthresh: 1e-5 - verbosity: 1 - - ObsLikes: # Calculate the LHC likelihood - purpose: LogLike capability: LHC_Combined_LogLike - # sub_capabilities: - # skip_analyses: - - - purpose: LogLike - capability: LHC_Higgs_LogLike - - - purpose: LogLike - capability: LHC_measurements_LogLike - - # Calculate the LEP likelihoods - - purpose: LogLike - capability: LEP_Higgs_LogLike - - - purpose: LogLike - capability: ALEPH_Selectron_LLike - - - purpose: LogLike - capability: ALEPH_Smuon_LLike - - - purpose: LogLike - capability: ALEPH_Stau_LLike - - - purpose: LogLike - capability: L3_Selectron_LLike - - - purpose: LogLike - capability: L3_Smuon_LLike - - - purpose: LogLike - capability: L3_Stau_LLike - - - purpose: LogLike - capability: L3_Neutralino_All_Channels_LLike - - - purpose: LogLike - capability: L3_Neutralino_Leptonic_LLike - - - purpose: LogLike - capability: L3_Chargino_All_Channels_LLike - - - purpose: LogLike - capability: L3_Chargino_Leptonic_LLike - - - purpose: LogLike - capability: OPAL_Chargino_Hadronic_LLike - - - purpose: LogLike - capability: OPAL_Chargino_SemiLeptonic_LLike - - - purpose: LogLike - capability: OPAL_Chargino_Leptonic_LLike - - - purpose: LogLike - capability: OPAL_Chargino_All_Channels_LLike - - - purpose: LogLike - capability: OPAL_Neutralino_Hadronic_LLike # Other observables - purpose: Observable @@ -165,9 +67,6 @@ ObsLikes: - purpose: Observable capability: LHCEventLoopInfo - - purpose: Observable - capability: LHC_measurements_LogLike_perPool - - purpose: Observable capability: SLHA1_violation @@ -189,6 +88,7 @@ Rules: - Beams:eCM = 13000 - Next:numberShowProcess = 1 - Print:quiet = off # on + - Print:verbosity = 3 - Random:setSeed = on - PartonLevel:MPI = off - PartonLevel:ISR = on @@ -199,6 +99,9 @@ Rules: - TimeShower:pTmin = 2 - 23:mMin = 0.1 - 24:mMin = 0.1 + + #- capability: PerformInitialCrossSection + # function: PerformInitialCrossSection_smoking # Choose to get decays from DecayBit proper, not from an SLHA file. - capability: decay_rates @@ -228,12 +131,6 @@ Rules: function: make_MSSM_precision_spectrum_none # Choose to use functions that get Higgs decays from SUSY-HIT, and t decays from DecayBit native implementation (instead of FeynHiggs) - - capability: Reference_SM_Higgs_decay_rates - function: Ref_SM_Higgs_decays_table - - capability: Reference_SM_other_Higgs_decay_rates - function: Ref_SM_other_Higgs_decays_table - - capability: Reference_SM_A0_decay_rates - function: Ref_SM_A0_decays_table - capability: Higgs_decay_rates function: MSSM_h0_1_decays - capability: h0_2_decay_rates @@ -245,17 +142,13 @@ Rules: - capability: t_decay_rates function: t_decays - # Choose where to get the Higgs couplings from - - capability: Higgs_Couplings - function: MSSM_higgs_couplings_pwid - # Pass an SLHA2 spectrum to Pythia - capability: SpectrumAndDecaysForPythia function: getSpectrumAndDecaysForPythia options: slha_version: 2 - write_summary_to_log: false + write_summary_to_log: true #false # Choose to where to get cross-sections from - capability: TotalCrossSection @@ -269,41 +162,18 @@ Rules: - capability: HardScatteringEvent type: Pythia_default::Pythia8::Event function: generateEventPythia - # options: - # drop_HepMC3_file: true - # # drop_HepMC2_file: true - + - capability: HardScatteringEvent type: HEPUtils::Event function: generateEventPythia_HEPUtils - - capability: HardScatteringEvent - type: HepMC3::GenEvent - function: generateEventPythia_HepMC - # Choose colliders to simulate and their convergence settings, and pick analyses to run with each collider. - capability: RunMC function: operateLHCLoop options: silenceLoop: false use_colliders: - - LHC_8TeV - LHC_13TeV - LHC_8TeV: - poisson_estimator: "MLE" # "MLE" (default), "UMVUE" - min_nEvents: 1000 - max_nEvents: 1000 - #mean_relative_nEvents: 0.01 - #mean_nEvents: 1000 - events_between_convergence_checks: 5000 - target_fractional_uncert: 0.3 - halt_when_systematic_dominated: true - all_analyses_must_converge: false - all_SR_must_converge: false - maxFailedEvents: 10 - analyses: - - ATLAS_8TeV_2LEPEW_20invfb - - ATLAS_8TeV_3LEPEW_20invfb LHC_13TeV: poisson_estimator: "MLE" # "MLE" (default), "UMVUE" min_nEvents: 1000 @@ -318,52 +188,12 @@ Rules: maxFailedEvents: 10 analyses: - CMS_13TeV_0LEP_36invfb - - CMS_13TeV_1LEPbb_36invfb - - CMS_13TeV_2OSLEP_36invfb - - CMS_13TeV_2LEPsoft_36invfb - - CMS_13TeV_1LEPStop_36invfb - - CMS_13TeV_2LEPStop_36invfb - - CMS_13TeV_MultiLEP_36invfb - - CMS_13TeV_MONOJET_36invfb - - ATLAS_13TeV_0LEP_36invfb - - ATLAS_13TeV_MultiLEP_36invfb - - ATLAS_13TeV_0LEPStop_36invfb - - ATLAS_13TeV_2LEPStop_36invfb - - ATLAS_13TeV_2bMET_36invfb - - ATLAS_13TeV_1Lep2b_139invfb - # - ATLAS_13TeV_RJ3L_lowmass_36invfb - # - ATLAS_13TeV_1LEPStop_36invfb - # The last two analyses depend on ROOT. # Choose Monte Carlo event simulator and options. - capability: HardScatteringSim type: Py8Collider_defaultversion function: getPythia options: - LHC_8TeV: - xsec_veto: 0.00 - partonOnly: false - jet_collections: - antikt_R04: - algorithm: antikt - R: 0.4 - recombination_scheme: E_scheme - strategy: Best - jet_collection_taus: antikt_R04 - pythia_settings: - - Beams:eCM = 8000 - - Next:numberShowProcess = 1 - - Print:quiet = off - - Random:setSeed = on - - PartonLevel:MPI = off - - PartonLevel:ISR = on - - PartonLevel:FSR = on - - HadronLevel:all = on - - SUSY:all = on - - TauDecays:mode = 0 - - TimeShower:pTmin = 2 - - 23:mMin = 0.1 - - 24:mMin = 0.1 LHC_13TeV: # 0.028 fb corresponds to ~1 expected event at L = 36 fb^-1. xsec_veto: 0.028 @@ -374,16 +204,12 @@ Rules: R: 0.4 recombination_scheme: E_scheme # E_scheme, pt_scheme, pt2_scheme strategy: Best # Best, NlnN - # antikt_R08: - # algorithm: antikt - # R: 0.8 - # recombination_scheme: E_scheme - # strategy: Best jet_collection_taus: antikt_R04 pythia_settings: - Beams:eCM = 13000 - Next:numberShowProcess = 1 - Print:quiet = off + - Print:verbosity = 3 - Random:setSeed = on - PartonLevel:MPI = off - PartonLevel:ISR = on @@ -425,49 +251,6 @@ Rules: cap_loglike: false cap_loglike_individual_analyses: false - # Set analyses for Rivet measurements - - capability: Rivet_measurements - options: - drop_YODA_file: true - LHC_8TeV: - analyses: - # - 8TeV - - ATLAS_2014_I1279489 - - ATLAS_2014_I1306615 - - ATLAS_2014_I1310835 - - ATLAS_2015_I1394679 - - ATLAS_2015_I1394865 - - ATLAS_2015_I1397637 - - ATLAS_2015_I1404878 - - ATLAS_2015_I1408516:LMODE=EL - - ATLAS_2015_I1408516:LMODE=MU - LHC_13TeV: - analyses: - # - 13TeV - - ATLAS_2016_I1458270 - - ATLAS_2017_I1514251:LMODE=EL - - ATLAS_2017_I1514251:LMODE=MU - exclude_analyses: - - ATLAS_2016_I1469071 # This analysis causes crashes if run on BSM outside of rivet. - - - - - capability: LHC_measurements - function: Contur_LHC_measurements_from_stream - # function: Contur_LHC_measurements_from_file - #options: - # Adding a contur option is equivalent to running contur with the equivalent flag. - # contur_options: - # - use-searches - # - theory - # YODA_filename: "./GAMBIT_collider_measurements_LHC_13TeV.yoda" - - - capability: LHC_measurements_LogLike - function: Contur_LHC_measurements_LogLike - - - capability: LHC_measurements_LogLike_perPool - function: Contur_LHC_measurements_LogLike_perPool - Logger: redirection: From 795f80125520121c10af024174a191b38aa6bc86 Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 5 May 2026 13:49:42 +0200 Subject: [PATCH 08/16] Add PID lookup for process xsecs --- ColliderBit/src/getxsec.cpp | 39 +++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/ColliderBit/src/getxsec.cpp b/ColliderBit/src/getxsec.cpp index b234cb98d9..ecd2b4d447 100644 --- a/ColliderBit/src/getxsec.cpp +++ b/ColliderBit/src/getxsec.cpp @@ -1953,16 +1953,39 @@ namespace Gambit xsec total_xsec; for (size_t i = 0; i < vars.pid1.size(); i++) { - // TODO: What to put as the codes here, Would eneed to be careful to make sure they match Pythia? - int code = vars.pid1[i];// input_variables.pid2[i]; // TODO: Just for testing, I am setting the code to the first pid1, this is incorrect!! xsec cross_section = res[i].cross_section; total_xsec = total_xsec + cross_section; - double process_xsec = cross_section.central; //combined_process_xsec[code]; - double process_xsecErr = cross_section.upper - cross_section.central; //combined_process_xsecErr[code]; - process_xsec_container newprocess; - newprocess.set_xsec(process_xsec, process_xsecErr); - newprocess.set_process_code(code); - int_proc_xsec_map[code] = newprocess; + double process_xsec = cross_section.central; + double process_xsecErr = cross_section.upper - cross_section.central; + + // Look up all Pythia process codes for this (pid1, pid2) pair. + // PID_pair sorts its arguments so ordering in smoking's output doesn't matter. + PID_pair pp(vars.pid1[i], vars.pid2[i]); + auto range = all_PID_pairs_to_process_codes().equal_range(pp); + + if (range.first == range.second) + { + ColliderBit_warning().raise(LOCAL_INFO, + "smoking returned a cross-section for PID pair (" + + std::to_string(vars.pid1[i]) + ", " + std::to_string(vars.pid2[i]) + + ") that has no entry in all_PID_pairs_to_process_codes. Skipping."); + continue; + } + + std::vector codes_for_pair; + for (auto it = range.first; it != range.second; ++it) + codes_for_pair.push_back(it->second); + + // Register all Pythia codes for this PID pair, noting codes that share the xsec. + for (int code : codes_for_pair) + { + process_xsec_container newprocess; + newprocess.set_xsec(process_xsec, process_xsecErr); + newprocess.set_process_code(code); + for (int other : codes_for_pair) + if (other != code) newprocess.register_process_sharing_xsec(other); + int_proc_xsec_map[code] = newprocess; + } } ProcessXsecContainer[collider] = int_proc_xsec_map; xsec_container xsContainer; From 2a8d5907b9f1f5c666ccf5f12a7e39767a8c079d Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 12 May 2026 10:21:07 +0200 Subject: [PATCH 09/16] Add warning about smoking backend being WIP until smoking is publicly released --- cmake/backends.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake/backends.cmake b/cmake/backends.cmake index 2006ffd45d..3877c4df84 100644 --- a/cmake/backends.cmake +++ b/cmake/backends.cmake @@ -680,7 +680,8 @@ set(smoking_CXX_FLAGS "${BACKEND_CXX_FLAGS}") check_ditch_status(${name} ${ver} ${dir}) if(NOT ditched_${name}_${ver}) ExternalProject_Add(${name}_${ver} - DOWNLOAD_COMMAND ${DL_BACKEND} ${dl} ${md5} ${dir} ${name} ${ver} + DOWNLOAD_COMMAND echo "WARNING: This is a WIP backend until Smoking is publicly released. Please provide a tarball to use this backend. Look forward to updates from the Oslo group :)" && ${DL_BACKEND} ${dl} ${md5} ${dir} ${name} ${ver} # TODO: Delete this line when smoking is publicly released + #DOWNLOAD_COMMAND ${DL_BACKEND} ${dl} ${md5} ${dir} ${name} ${ver} SOURCE_DIR ${dir} PATCH_COMMAND "" CMAKE_ARGS From 85d0cf69ac5845a0bb2cbf8d6e9f9823574e76df Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 12 May 2026 10:23:11 +0200 Subject: [PATCH 10/16] Remove out-dated email address --- Backends/include/gambit/Backends/backend_types/smoking.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Backends/include/gambit/Backends/backend_types/smoking.hpp b/Backends/include/gambit/Backends/backend_types/smoking.hpp index 440afdbca7..7fd7544b61 100644 --- a/Backends/include/gambit/Backends/backend_types/smoking.hpp +++ b/Backends/include/gambit/Backends/backend_types/smoking.hpp @@ -15,7 +15,6 @@ /// Authors (add name and date if you modify): /// /// \author Christopher Chang -/// (christopher.chang@uqconnect.edu.au) /// \date 2026 Apr /// /// ********************************************* From 31a43747ace9732122707097bf0fbb5eb84b68ba Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 12 May 2026 11:04:27 +0200 Subject: [PATCH 11/16] Remove old runSmoking function, and move smoking functionality into its separate cpp file --- .../ColliderBit/ColliderBit_MC_rollcall.hpp | 12 --- ColliderBit/src/ColliderBit_smoking.cpp | 93 +++++++++++++++---- ColliderBit/src/getxsec.cpp | 87 ----------------- 3 files changed, 76 insertions(+), 116 deletions(-) diff --git a/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp b/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp index 21ef1fa376..ddbcfb14c2 100644 --- a/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp +++ b/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp @@ -44,7 +44,6 @@ #pragma once #include "gambit/Utils/util_types.hpp" -#include "gambit/Backends/backend_types/smoking.hpp" #define MODULE ColliderBit @@ -519,17 +518,6 @@ #undef FUNCTION #undef CAPABILITY - /// Run the smoking NLO+NLL cross-section calculation with default settings. - #define CAPABILITY RunSmoking - START_CAPABILITY - #define FUNCTION runSmoking - START_FUNCTION(double) - BACKEND_REQ(smoking_init, (), int, (smoking_variables&)) - BACKEND_REQ(smoking_calc, (), std::vector, (smoking_variables&)) - BACKEND_REQ(smoking_finalise, (), int, ()) - #undef FUNCTION - #undef CAPABILITY - /// Detector sim capabilities. /// @{ #define CAPABILITY ATLASDetectorSim diff --git a/ColliderBit/src/ColliderBit_smoking.cpp b/ColliderBit/src/ColliderBit_smoking.cpp index e7d4b5c03c..5dd17ad962 100644 --- a/ColliderBit/src/ColliderBit_smoking.cpp +++ b/ColliderBit/src/ColliderBit_smoking.cpp @@ -9,7 +9,6 @@ /// Authors (add name and date if you modify): /// /// \author Christopher Chang -/// (c.j.chang@fys.uio.no) /// \date 2026 Apr /// /// ********************************************* @@ -17,6 +16,7 @@ #include "gambit/Elements/gambit_module_headers.hpp" #include "gambit/ColliderBit/ColliderBit_rollcall.hpp" #include "gambit/Backends/backend_types/smoking.hpp" +#include "gambit/ColliderBit/complete_process_PID_pair_multimaps.hpp" #include "gambit/Utils/slhaea_helpers.hpp" @@ -25,30 +25,89 @@ namespace Gambit namespace ColliderBit { - /// Run the smoking NLO+NLL cross-section calculation with default settings. - void runSmoking(double &result) + /// Run the smoking NLO+NLL cross-section calculation using the SLHAea object + /// already constructed by ColliderBit (normally passed to Pythia). + void PerformInitialCrossSection_smoking(initialxsec_container& result) { - using namespace Pipes::runSmoking; + using namespace Pipes::PerformInitialCrossSection_smoking; + + SLHAstruct slhaea = *Dep::SpectrumAndDecaysForPythia; + + // Add MODSEL block if it is missing + if(slhaea.find("MODSEL") == slhaea.end()) \ + { \ + SLHAea::Block block("MODSEL"); \ + block.push_back("BLOCK MODSEL # Model selection"); \ + SLHAea::Line line; \ + line << 1 << 0 << "# Tell smoking that this is a SUSY model."; \ + block.push_back(line); \ + SLHAea::Line line2; \ + line2 << 6 << 3 << "# There is Flavour violations in squark and slepton sectors"; \ + block.push_back(line2); \ + slhaea.push_front(block); \ + } smoking_variables vars; - // TODO: This should be done in the frontend, not here... - // const str backendDir = Backends::backendInfo().path_dir(STRINGIFY(smoking), STRINGIFY(VERSION)); - // TODO: If done properly in frontend header, can use bandendDir to automatically get this. - // I am just gonna try it hacked for now. - vars.slha_file = "/home/chris-chang/WORK/GAMBIT/CB_development/SMOKING_backend/gambit/Backends/installed/smoking/1.0.0/example/sps1a.slha"; - - // std::ifstream slhafilein(vars.slha_file); - // const SLHAea::Coll* slhaea = new SLHAea::Coll(slhafilein); - SLHAstruct slhaea = read_SLHA(vars.slha_file); vars.slhaea = slhaea; - std::cout << "HEY CHRIS. I got here after reading in the SLHA..." << std::endl; - BEreq::smoking_init(vars); - BEreq::smoking_calc(vars); + std::vector res = BEreq::smoking_calc(vars); // TODO: This needs to be renamed in smoking, as Result is far too generic a term BEreq::smoking_finalise(); - result = 0.0; + std::cout << "LO xsec from smoking: " << res[0].cross_section.central << std::endl; + + // Forming the output... + // Calculating the total cross-section as the sum of the process cross sections + std::string collider = runOptions->getValueOrDef("LHC_13TeV", "Collider"); // TODO: Support multiple Colliders (just loop through a list) + map_str_xsec_container TotalXsecContainer; + map_int_process_xsec int_proc_xsec_map; + map_str_map_int_process_xsec ProcessXsecContainer; + xsec total_xsec; + for (size_t i = 0; i < vars.pid1.size(); i++) + { + xsec cross_section = res[i].cross_section; + total_xsec = total_xsec + cross_section; + double process_xsec = cross_section.central; + double process_xsecErr = cross_section.upper - cross_section.central; + + // Look up all Pythia process codes for this (pid1, pid2) pair. + // PID_pair sorts its arguments so ordering in smoking's output doesn't matter. + PID_pair pp(vars.pid1[i], vars.pid2[i]); + auto range = all_PID_pairs_to_process_codes().equal_range(pp); + + if (range.first == range.second) + { + ColliderBit_warning().raise(LOCAL_INFO, + "smoking returned a cross-section for PID pair (" + + std::to_string(vars.pid1[i]) + ", " + std::to_string(vars.pid2[i]) + + ") that has no entry in all_PID_pairs_to_process_codes. Skipping."); + continue; + } + + std::vector codes_for_pair; + for (auto it = range.first; it != range.second; ++it) + codes_for_pair.push_back(it->second); + + // Register all Pythia codes for this PID pair, noting codes that share the xsec. + for (int code : codes_for_pair) + { + process_xsec_container newprocess; + newprocess.set_xsec(process_xsec, process_xsecErr); + newprocess.set_process_code(code); + for (int other : codes_for_pair) + if (other != code) newprocess.register_process_sharing_xsec(other); + int_proc_xsec_map[code] = newprocess; + } + } + ProcessXsecContainer[collider] = int_proc_xsec_map; + xsec_container xsContainer; + xsContainer.set_xsec(total_xsec.central, total_xsec.upper - total_xsec.central); // NOTE: Assuming symmetric uncertainty, but smoking can in theory return assymetric uncertainty + TotalXsecContainer[collider] = xsContainer; + + + result = initialxsec_container(); + result.first = TotalXsecContainer; + result.second = ProcessXsecContainer; } } diff --git a/ColliderBit/src/getxsec.cpp b/ColliderBit/src/getxsec.cpp index ecd2b4d447..4733b1ae51 100644 --- a/ColliderBit/src/getxsec.cpp +++ b/ColliderBit/src/getxsec.cpp @@ -20,7 +20,6 @@ #include "gambit/ColliderBit/ColliderBit_eventloop.hpp" #include "gambit/ColliderBit/complete_process_PID_pair_multimaps.hpp" -#include "gambit/Backends/backend_types/smoking.hpp" // #define COLLIDERBIT_DEBUG #define DEBUG_PREFIX "DEBUG: OMP thread " << omp_get_thread_num() << ": " << __FILE__ << ":" << __LINE__ << ": " @@ -1913,92 +1912,6 @@ namespace Gambit } // end InitialTotalCrossSection_YAMLSLHA - /// Run the smoking NLO+NLL cross-section calculation using the SLHAea object - /// already constructed by ColliderBit (normally passed to Pythia). - void PerformInitialCrossSection_smoking(initialxsec_container& result) - { - using namespace Pipes::PerformInitialCrossSection_smoking; - - SLHAstruct slhaea = *Dep::SpectrumAndDecaysForPythia; - - // Add MODSEL block if it is missing - if(slhaea.find("MODSEL") == slhaea.end()) \ - { \ - SLHAea::Block block("MODSEL"); \ - block.push_back("BLOCK MODSEL # Model selection"); \ - SLHAea::Line line; \ - line << 1 << 0 << "# Tell smoking that this is a SUSY model."; \ - block.push_back(line); \ - SLHAea::Line line2; \ - line2 << 6 << 3 << "# There is Flavour violations in squark and slepton sectors"; \ - block.push_back(line2); \ - slhaea.push_front(block); \ - } - - smoking_variables vars; - vars.slhaea = slhaea; - - BEreq::smoking_init(vars); - std::vector res = BEreq::smoking_calc(vars); // TODO: This needs to be renamed in smoking, as Result is far too generic a term - BEreq::smoking_finalise(); - - std::cout << "LO xsec from smoking: " << res[0].cross_section.central << std::endl; - - // Forming the output... - // Calculating the total cross-section as the sum of the process cross sections - std::string collider = runOptions->getValueOrDef("LHC_13TeV", "Collider"); // TODO: Support multiple Colliders (just loop through a list) - map_str_xsec_container TotalXsecContainer; - map_int_process_xsec int_proc_xsec_map; - map_str_map_int_process_xsec ProcessXsecContainer; - xsec total_xsec; - for (size_t i = 0; i < vars.pid1.size(); i++) - { - xsec cross_section = res[i].cross_section; - total_xsec = total_xsec + cross_section; - double process_xsec = cross_section.central; - double process_xsecErr = cross_section.upper - cross_section.central; - - // Look up all Pythia process codes for this (pid1, pid2) pair. - // PID_pair sorts its arguments so ordering in smoking's output doesn't matter. - PID_pair pp(vars.pid1[i], vars.pid2[i]); - auto range = all_PID_pairs_to_process_codes().equal_range(pp); - - if (range.first == range.second) - { - ColliderBit_warning().raise(LOCAL_INFO, - "smoking returned a cross-section for PID pair (" + - std::to_string(vars.pid1[i]) + ", " + std::to_string(vars.pid2[i]) + - ") that has no entry in all_PID_pairs_to_process_codes. Skipping."); - continue; - } - - std::vector codes_for_pair; - for (auto it = range.first; it != range.second; ++it) - codes_for_pair.push_back(it->second); - - // Register all Pythia codes for this PID pair, noting codes that share the xsec. - for (int code : codes_for_pair) - { - process_xsec_container newprocess; - newprocess.set_xsec(process_xsec, process_xsecErr); - newprocess.set_process_code(code); - for (int other : codes_for_pair) - if (other != code) newprocess.register_process_sharing_xsec(other); - int_proc_xsec_map[code] = newprocess; - } - } - ProcessXsecContainer[collider] = int_proc_xsec_map; - xsec_container xsContainer; - xsContainer.set_xsec(total_xsec.central, total_xsec.upper - total_xsec.central); // NOTE: Assuming symmetric uncertainty, but smoking can in theory return assymetric uncertainty - TotalXsecContainer[collider] = xsContainer; - - - result = initialxsec_container(); - result.first = TotalXsecContainer; - result.second = ProcessXsecContainer; - } - - /// Copy the Initial CrossSection estimate into the Final as the Total CrossSection /// This is useful when evalutating both using e.g. NLO xsec calculators void useInitialCrossSectionasFinalTotalCrossSection(xsec_container& result) From 76503f0b0e224241ee442633a565f9cc6770a65b Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 12 May 2026 11:06:49 +0200 Subject: [PATCH 12/16] Revert ColliderBit_CMSSM.yaml to maste version. To test the interface, I have a ColliderBit_TEST.yaml file --- yaml_files/ColliderBit_CMSSM.yaml | 231 +++++++++++++++++++++++++++++- 1 file changed, 224 insertions(+), 7 deletions(-) diff --git a/yaml_files/ColliderBit_CMSSM.yaml b/yaml_files/ColliderBit_CMSSM.yaml index ade3efc3ee..52ae8cf7fa 100644 --- a/yaml_files/ColliderBit_CMSSM.yaml +++ b/yaml_files/ColliderBit_CMSSM.yaml @@ -16,6 +16,22 @@ Parameters: # SM nuisance parameters fixed for now. StandardModel_SLHA2: !import include/StandardModel_SLHA2_defaults.yaml + # # CMSSM parameter ranges and priors + # CMSSM: + # M0: + # range: [100, 5000] + # prior_type: log + # M12: + # range: [100, 5000] + # prior_type: log + # A0: + # range: [-7000, 7000] + # prior_type: flat + # TanBeta: + # range: [3.0, 70] + # prior_type: flat + # SignMu: 1 + # CMSSM parameters for a single test point CMSSM: M0: 300 @@ -37,12 +53,29 @@ Printer: printer: cout + # printer: hdf5 + # options: + # output_file: "ColliderBit_CMSSM.hdf5" + # group: "/ColliderBit_CMSSM" + # delete_file_on_restart: true + + # printer: ascii + # options: + # output_file: "gambit_output.txt" + + Scanner: use_scanner: random scanners: + multinest: + plugin: multinest + like: LogLike + nlive: 4000 + tol: 0.5 + random: plugin: random point_number: 1 @@ -51,11 +84,76 @@ Scanner: files: output_file: "weights ..." + de: + plugin: diver + like: LogLike + NP: 19200 + convthresh: 1e-5 + verbosity: 1 + + ObsLikes: # Calculate the LHC likelihood - purpose: LogLike capability: LHC_Combined_LogLike + # sub_capabilities: + # skip_analyses: + + - purpose: LogLike + capability: LHC_Higgs_LogLike + + - purpose: LogLike + capability: LHC_measurements_LogLike + + # Calculate the LEP likelihoods + - purpose: LogLike + capability: LEP_Higgs_LogLike + + - purpose: LogLike + capability: ALEPH_Selectron_LLike + + - purpose: LogLike + capability: ALEPH_Smuon_LLike + + - purpose: LogLike + capability: ALEPH_Stau_LLike + + - purpose: LogLike + capability: L3_Selectron_LLike + + - purpose: LogLike + capability: L3_Smuon_LLike + + - purpose: LogLike + capability: L3_Stau_LLike + + - purpose: LogLike + capability: L3_Neutralino_All_Channels_LLike + + - purpose: LogLike + capability: L3_Neutralino_Leptonic_LLike + + - purpose: LogLike + capability: L3_Chargino_All_Channels_LLike + + - purpose: LogLike + capability: L3_Chargino_Leptonic_LLike + + - purpose: LogLike + capability: OPAL_Chargino_Hadronic_LLike + + - purpose: LogLike + capability: OPAL_Chargino_SemiLeptonic_LLike + + - purpose: LogLike + capability: OPAL_Chargino_Leptonic_LLike + + - purpose: LogLike + capability: OPAL_Chargino_All_Channels_LLike + + - purpose: LogLike + capability: OPAL_Neutralino_Hadronic_LLike # Other observables - purpose: Observable @@ -67,6 +165,9 @@ ObsLikes: - purpose: Observable capability: LHCEventLoopInfo + - purpose: Observable + capability: LHC_measurements_LogLike_perPool + - purpose: Observable capability: SLHA1_violation @@ -88,7 +189,6 @@ Rules: - Beams:eCM = 13000 - Next:numberShowProcess = 1 - Print:quiet = off # on - - Print:verbosity = 3 - Random:setSeed = on - PartonLevel:MPI = off - PartonLevel:ISR = on @@ -99,9 +199,6 @@ Rules: - TimeShower:pTmin = 2 - 23:mMin = 0.1 - 24:mMin = 0.1 - - #- capability: PerformInitialCrossSection - # function: PerformInitialCrossSection_smoking # Choose to get decays from DecayBit proper, not from an SLHA file. - capability: decay_rates @@ -131,6 +228,12 @@ Rules: function: make_MSSM_precision_spectrum_none # Choose to use functions that get Higgs decays from SUSY-HIT, and t decays from DecayBit native implementation (instead of FeynHiggs) + - capability: Reference_SM_Higgs_decay_rates + function: Ref_SM_Higgs_decays_table + - capability: Reference_SM_other_Higgs_decay_rates + function: Ref_SM_other_Higgs_decays_table + - capability: Reference_SM_A0_decay_rates + function: Ref_SM_A0_decays_table - capability: Higgs_decay_rates function: MSSM_h0_1_decays - capability: h0_2_decay_rates @@ -142,13 +245,17 @@ Rules: - capability: t_decay_rates function: t_decays + # Choose where to get the Higgs couplings from + - capability: Higgs_Couplings + function: MSSM_higgs_couplings_pwid + # Pass an SLHA2 spectrum to Pythia - capability: SpectrumAndDecaysForPythia function: getSpectrumAndDecaysForPythia options: slha_version: 2 - write_summary_to_log: true #false + write_summary_to_log: false # Choose to where to get cross-sections from - capability: TotalCrossSection @@ -162,18 +269,41 @@ Rules: - capability: HardScatteringEvent type: Pythia_default::Pythia8::Event function: generateEventPythia - + # options: + # drop_HepMC3_file: true + # # drop_HepMC2_file: true + - capability: HardScatteringEvent type: HEPUtils::Event function: generateEventPythia_HEPUtils + - capability: HardScatteringEvent + type: HepMC3::GenEvent + function: generateEventPythia_HepMC + # Choose colliders to simulate and their convergence settings, and pick analyses to run with each collider. - capability: RunMC function: operateLHCLoop options: silenceLoop: false use_colliders: + - LHC_8TeV - LHC_13TeV + LHC_8TeV: + poisson_estimator: "MLE" # "MLE" (default), "UMVUE" + min_nEvents: 1000 + max_nEvents: 1000 + #mean_relative_nEvents: 0.01 + #mean_nEvents: 1000 + events_between_convergence_checks: 5000 + target_fractional_uncert: 0.3 + halt_when_systematic_dominated: true + all_analyses_must_converge: false + all_SR_must_converge: false + maxFailedEvents: 10 + analyses: + - ATLAS_8TeV_2LEPEW_20invfb + - ATLAS_8TeV_3LEPEW_20invfb LHC_13TeV: poisson_estimator: "MLE" # "MLE" (default), "UMVUE" min_nEvents: 1000 @@ -188,12 +318,52 @@ Rules: maxFailedEvents: 10 analyses: - CMS_13TeV_0LEP_36invfb + - CMS_13TeV_1LEPbb_36invfb + - CMS_13TeV_2OSLEP_36invfb + - CMS_13TeV_2LEPsoft_36invfb + - CMS_13TeV_1LEPStop_36invfb + - CMS_13TeV_2LEPStop_36invfb + - CMS_13TeV_MultiLEP_36invfb + - CMS_13TeV_MONOJET_36invfb + - ATLAS_13TeV_0LEP_36invfb + - ATLAS_13TeV_MultiLEP_36invfb + - ATLAS_13TeV_0LEPStop_36invfb + - ATLAS_13TeV_2LEPStop_36invfb + - ATLAS_13TeV_2bMET_36invfb + - ATLAS_13TeV_1Lep2b_139invfb + # - ATLAS_13TeV_RJ3L_lowmass_36invfb + # - ATLAS_13TeV_1LEPStop_36invfb + # The last two analyses depend on ROOT. # Choose Monte Carlo event simulator and options. - capability: HardScatteringSim type: Py8Collider_defaultversion function: getPythia options: + LHC_8TeV: + xsec_veto: 0.00 + partonOnly: false + jet_collections: + antikt_R04: + algorithm: antikt + R: 0.4 + recombination_scheme: E_scheme + strategy: Best + jet_collection_taus: antikt_R04 + pythia_settings: + - Beams:eCM = 8000 + - Next:numberShowProcess = 1 + - Print:quiet = off + - Random:setSeed = on + - PartonLevel:MPI = off + - PartonLevel:ISR = on + - PartonLevel:FSR = on + - HadronLevel:all = on + - SUSY:all = on + - TauDecays:mode = 0 + - TimeShower:pTmin = 2 + - 23:mMin = 0.1 + - 24:mMin = 0.1 LHC_13TeV: # 0.028 fb corresponds to ~1 expected event at L = 36 fb^-1. xsec_veto: 0.028 @@ -204,12 +374,16 @@ Rules: R: 0.4 recombination_scheme: E_scheme # E_scheme, pt_scheme, pt2_scheme strategy: Best # Best, NlnN + # antikt_R08: + # algorithm: antikt + # R: 0.8 + # recombination_scheme: E_scheme + # strategy: Best jet_collection_taus: antikt_R04 pythia_settings: - Beams:eCM = 13000 - Next:numberShowProcess = 1 - Print:quiet = off - - Print:verbosity = 3 - Random:setSeed = on - PartonLevel:MPI = off - PartonLevel:ISR = on @@ -251,6 +425,49 @@ Rules: cap_loglike: false cap_loglike_individual_analyses: false + # Set analyses for Rivet measurements + - capability: Rivet_measurements + options: + drop_YODA_file: true + LHC_8TeV: + analyses: + # - 8TeV + - ATLAS_2014_I1279489 + - ATLAS_2014_I1306615 + - ATLAS_2014_I1310835 + - ATLAS_2015_I1394679 + - ATLAS_2015_I1394865 + - ATLAS_2015_I1397637 + - ATLAS_2015_I1404878 + - ATLAS_2015_I1408516:LMODE=EL + - ATLAS_2015_I1408516:LMODE=MU + LHC_13TeV: + analyses: + # - 13TeV + - ATLAS_2016_I1458270 + - ATLAS_2017_I1514251:LMODE=EL + - ATLAS_2017_I1514251:LMODE=MU + exclude_analyses: + - ATLAS_2016_I1469071 # This analysis causes crashes if run on BSM outside of rivet. + + + + - capability: LHC_measurements + function: Contur_LHC_measurements_from_stream + # function: Contur_LHC_measurements_from_file + #options: + # Adding a contur option is equivalent to running contur with the equivalent flag. + # contur_options: + # - use-searches + # - theory + # YODA_filename: "./GAMBIT_collider_measurements_LHC_13TeV.yoda" + + - capability: LHC_measurements_LogLike + function: Contur_LHC_measurements_LogLike + + - capability: LHC_measurements_LogLike_perPool + function: Contur_LHC_measurements_LogLike_perPool + Logger: redirection: From ab4e763ab1e8c795ad7d97771430a87054548085 Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 12 May 2026 11:08:55 +0200 Subject: [PATCH 13/16] Remove out-dated capability description --- config/capabilities.dat | 4 ---- 1 file changed, 4 deletions(-) diff --git a/config/capabilities.dat b/config/capabilities.dat index 3f16f54e11..9660967581 100644 --- a/config/capabilities.dat +++ b/config/capabilities.dat @@ -397,10 +397,6 @@ SPheno_internal: | # ColliderBit capabilities #------------------------------------- -RunSmoking: | - Run the smoking NLO+NLL hadronic cross-section calculation (init, calculate, - finalise) with default settings. - DummyColliderObservable: | Dummy observable that creates a dependency on TestModel1D, which is used to satisfy the normal GAMBIT model requrements in a minimal way. Used From 4496088f1575cb3cc8ab1d914511bc78c732a0ab Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 12 May 2026 11:52:59 +0200 Subject: [PATCH 14/16] Add copy of initial and final process xsecs. Should now have everything it needs to weight Pythia events from smoking --- .../gambit/ColliderBit/ColliderBit_MC_rollcall.hpp | 11 ++++++++--- ColliderBit/src/ColliderBit_smoking.cpp | 1 + ColliderBit/src/getxsec.cpp | 10 +++++++++- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp b/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp index ddbcfb14c2..cf82cd5b10 100644 --- a/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp +++ b/ColliderBit/include/gambit/ColliderBit/ColliderBit_MC_rollcall.hpp @@ -214,7 +214,7 @@ /// Process-level cross-sections /// @{ - /// A map between Pythia process codes and cross-sections + /// A map between process codes and cross-sections #define CAPABILITY ProcessCrossSectionsMap START_CAPABILITY #define FUNCTION getProcessCrossSectionsMap @@ -224,6 +224,13 @@ DEPENDENCY(ActiveProcessCodeToPIDPairsMap, multimap_int_PID_pair) DEPENDENCY(PIDPairCrossSectionsMap, map_PID_pair_PID_pair_xsec) #undef FUNCTION + + // Copy the initial ProcessCrossSectionMap. Useful when calculating xsecs with an external calculator + #define FUNCTION useInitialProcessCrossSectionsMapasFinal + START_FUNCTION(map_int_process_xsec) + NEEDS_MANAGER(RunMC, MCLoopInfo) + DEPENDENCY(InitialProcessCrossSections, map_str_map_int_process_xsec) + #undef FUNCTION #undef CAPABILITY /// A map between PID pairs and cross-sections @@ -235,8 +242,6 @@ DEPENDENCY(ActivePIDPairs, vec_PID_pair) #undef FUNCTION - /// TODO: Chris Chang: Copy process cross-sections from initial cross-section estimate - #undef CAPABILITY /// Output PID pair cross-sections as a diff --git a/ColliderBit/src/ColliderBit_smoking.cpp b/ColliderBit/src/ColliderBit_smoking.cpp index 5dd17ad962..4100ba655d 100644 --- a/ColliderBit/src/ColliderBit_smoking.cpp +++ b/ColliderBit/src/ColliderBit_smoking.cpp @@ -110,5 +110,6 @@ namespace Gambit result.second = ProcessXsecContainer; } + } } diff --git a/ColliderBit/src/getxsec.cpp b/ColliderBit/src/getxsec.cpp index 4733b1ae51..d185725ecb 100644 --- a/ColliderBit/src/getxsec.cpp +++ b/ColliderBit/src/getxsec.cpp @@ -1923,7 +1923,15 @@ namespace Gambit result = initial_xsec.first[collider]; } - // TODO: Same but for process xsecs + // Same but for process xsecs + void useInitialProcessCrossSectionsMapasFinal(map_int_process_xsec& result) + { + using namespace Pipes::useInitialProcessCrossSectionsMapasFinal; + std::string collider = Dep::RunMC->current_collider(); + + map_str_map_int_process_xsec initial_process_xsecs = *Dep::InitialProcessCrossSections; + result = initial_process_xsecs[collider]; + } } } From e4bb814417e961614d79ec935da69d1212e251f6 Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 19 May 2026 12:14:11 +0200 Subject: [PATCH 15/16] Add in UPMNS block calculation inside SLHA calculations. Add warning in event weighting so Pythia generating processes without correpsonding xsecs fails gracefully. --- ColliderBit/src/collider_event_weights.cpp | 15 +++++++- Elements/include/gambit/Elements/sminputs.hpp | 6 ++++ Elements/src/sminputs.cpp | 36 +++++++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/ColliderBit/src/collider_event_weights.cpp b/ColliderBit/src/collider_event_weights.cpp index 43bb6e63a9..891e1f99ff 100644 --- a/ColliderBit/src/collider_event_weights.cpp +++ b/ColliderBit/src/collider_event_weights.cpp @@ -62,7 +62,20 @@ namespace Gambit #endif // Get the process_xsec_container instance that holds the externally provided cross-section for this process - process_xsec_container xs = ProcessCrossSectionsMap.at(process_code); + auto it = ProcessCrossSectionsMap.find(process_code); + if (it == ProcessCrossSectionsMap.end()) + { + std::stringstream errmsg_ss; + errmsg_ss << "setEventWeight_fromCrossSection: Pythia generated an event with process code " + << process_code << ", but no external cross-section is available for this process. " + << "Your collider settings are generating processes that your cross-section provider " + << "does not cover. Either restrict the Pythia process settings to only the processes " + << "your cross-section provider computes (e.g. replace 'SUSY:all = on' with explicit " + << "process switches), or use setEventWeight_unity instead."; + piped_errors.request(LOCAL_INFO, errmsg_ss.str()); + return; + } + process_xsec_container xs = it->second; // Get the generator cross-section for this process double process_xsec_generator = HardScatteringSim_ptr->xsec_fb(process_code); diff --git a/Elements/include/gambit/Elements/sminputs.hpp b/Elements/include/gambit/Elements/sminputs.hpp index 582fdefa95..916f092f34 100644 --- a/Elements/include/gambit/Elements/sminputs.hpp +++ b/Elements/include/gambit/Elements/sminputs.hpp @@ -21,6 +21,8 @@ #include "gambit/Utils/slhaea_helpers.hpp" #include "gambit/Utils/numerical_constants.hpp" +#include +#include namespace Gambit { @@ -87,6 +89,10 @@ namespace Gambit double delta13; // the Dirac CP-violating phase double alpha1; // the first Majorana CP-violating phase double alpha2; // the second CP-violating Majorana phase + + // Returns the full 3x3 complex UPMNS matrix using the standard PDG parameterisation. + // Indices are zero-based: U[i][j]. + std::array,3>,3> get_matrix() const; }; PMNSdef PMNS; diff --git a/Elements/src/sminputs.cpp b/Elements/src/sminputs.cpp index a93683fbdc..11c6c10a0d 100644 --- a/Elements/src/sminputs.cpp +++ b/Elements/src/sminputs.cpp @@ -18,10 +18,35 @@ #include "gambit/Utils/standalone_error_handlers.hpp" #include "gambit/Elements/sminputs.hpp" #include "gambit/Elements/mssm_slhahelp.hpp" +#include +#include namespace Gambit { + std::array,3>,3> SMInputs::PMNSdef::get_matrix() const + { + using std::sin; using std::cos; using std::polar; + const double s12 = sin(theta12), c12 = cos(theta12); + const double s13 = sin(theta13), c13 = cos(theta13); + const double s23 = sin(theta23), c23 = cos(theta23); + const std::complex eid = polar(1.0, delta13); + const std::complex eia1 = polar(1.0, 0.5 * alpha1); + const std::complex eia2 = polar(1.0, 0.5 * alpha2); + + std::array,3>,3> U; + U[0][0] = c12 * c13 * eia1; + U[0][1] = s12 * c13; + U[0][2] = s13 / eid; + U[1][0] = (-s12 * c23 - c12 * s23 * s13 * eid) * eia1; + U[1][1] = ( c12 * c23 - s12 * s23 * s13 * eid) * eia2; + U[1][2] = s23 * c13; + U[2][0] = ( s12 * s23 - c12 * c23 * s13 * eid) * eia1; + U[2][1] = (-c12 * s23 - s12 * c23 * s13 * eid); + U[2][2] = c23 * c13; + return U; + } + // Create an SMInputs struct from an SLHAea object SMInputs::SMInputs(SLHAea::Coll& data) { @@ -128,6 +153,17 @@ namespace Gambit SLHAea_add(data,"UPMNSIN",5, PMNS.alpha1 , "alpha1 (first Majorana CP-violating phase)" ); SLHAea_add(data,"UPMNSIN",6, PMNS.alpha2 , "alpha2 (second CP-violating Majorana phase)"); + // UPMNS and IMUPMNS blocks (real and imaginary parts of the full mixing matrix) + SLHAea_add_block(data,"UPMNS"); + SLHAea_add_block(data,"IMUPMNS"); + auto U = PMNS.get_matrix(); + for (int i = 1; i <= 3; i++) + for (int j = 1; j <= 3; j++) + { + SLHAea_add(data,"UPMNS", i, j, U[i-1][j-1].real(), "Re(UPMNS_"+std::to_string(i)+std::to_string(j)+")"); + SLHAea_add(data,"IMUPMNS",i, j, U[i-1][j-1].imag(), "Im(UPMNS_"+std::to_string(i)+std::to_string(j)+")"); + } + // MASS block SLHAea_add(data,"MASS", 24, mW, "mW(pole)"); From 1775956263a85d2f9f30bde3376b457d658d3cf1 Mon Sep 17 00:00:00 2001 From: ChrisJChang Date: Tue, 19 May 2026 14:22:45 +0200 Subject: [PATCH 16/16] Fix bug in PMNS matrix calculation --- Elements/src/sminputs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Elements/src/sminputs.cpp b/Elements/src/sminputs.cpp index 11c6c10a0d..4e15002a9b 100644 --- a/Elements/src/sminputs.cpp +++ b/Elements/src/sminputs.cpp @@ -36,13 +36,13 @@ namespace Gambit std::array,3>,3> U; U[0][0] = c12 * c13 * eia1; - U[0][1] = s12 * c13; + U[0][1] = s12 * c13 * eia2; U[0][2] = s13 / eid; U[1][0] = (-s12 * c23 - c12 * s23 * s13 * eid) * eia1; U[1][1] = ( c12 * c23 - s12 * s23 * s13 * eid) * eia2; U[1][2] = s23 * c13; U[2][0] = ( s12 * s23 - c12 * c23 * s13 * eid) * eia1; - U[2][1] = (-c12 * s23 - s12 * c23 * s13 * eid); + U[2][1] = (-c12 * s23 - s12 * c23 * s13 * eid) * eia2; U[2][2] = c23 * c13; return U; }