GAMBIT: The Global and Modular Beyond-the-Standard-Model Inference Tool

# GAMBIT: The Global and Modular Beyond-the-Standard-Model Inference Tool

###### Abstract

We describe the open-source global fitting package GAMBIT: the Global And Modular Beyond-the-Standard-Model Inference Tool. GAMBIT combines extensive calculations of observables and likelihoods in particle and astroparticle physics with a hierarchical model database, advanced tools for automatically building analyses of essentially any model, a flexible and powerful system for interfacing to external codes, a suite of different statistical methods and parameter scanning algorithms, and a host of other utilities designed to make scans faster, safer and more easily-extendible than in the past. Here we give a detailed description of the framework, its design and motivation, and the current models and other specific components presently implemented in GAMBIT. Accompanying papers deal with individual modules and present first GAMBIT results. GAMBIT can be downloaded from gambit.hepforge.org.

journal: Eur. Phys. J. C

\lst@KeylabelnameListing language=C++, basicstyle=, basewidth=0.53em,0.44em, numbers=none, tabsize=2, breaklines=true, escapeinside=@@, showstringspaces=false, numberstyle=, keywordstyle=, stringstyle=, identifierstyle=, commentstyle=, directivestyle=, emphstyle=, frame=single, rulecolor=, rulesepcolor=, literate=  \sim 1, moredelim=*[directive]  #, moredelim=*[directive]    # language=C++, basicstyle=, basewidth=0.53em,0.44em, numbers=none, tabsize=2, breaklines=true, escapeinside=*@@*, showstringspaces=false, numberstyle=, keywordstyle=, stringstyle=, identifierstyle=, commentstyle=, directivestyle=, emphstyle=, frame=single, rulecolor=, rulesepcolor=, literate=  \sim 1, moredelim=**[is][#define]BeginLongMacroEndLongMacro language=C++, basicstyle=, basewidth=0.53em,0.44em, numbers=none, tabsize=2, breaklines=true, escapeinside=@@, numberstyle=, showstringspaces=false, numberstyle=, keywordstyle=, stringstyle=, identifierstyle=, commentstyle=, directivestyle=, emphstyle=, frame=single, rulecolor=, rulesepcolor=, literate=  \sim 1, moredelim=*[directive]  #, moredelim=*[directive]    # language=Python, basicstyle=, basewidth=0.53em,0.44em, numbers=none, tabsize=2, breaklines=true, escapeinside=@@, showstringspaces=false, numberstyle=, keywordstyle=, stringstyle=, identifierstyle=, commentstyle=, emphstyle=, frame=single, rulecolor=, rulesepcolor=, literate =   \sim 1  as  as 3 language=Fortran, basicstyle=, basewidth=0.53em,0.44em, numbers=none, tabsize=2, breaklines=true, escapeinside=@@, showstringspaces=false, numberstyle=, keywordstyle=, stringstyle=, identifierstyle=, commentstyle=, emphstyle=, morekeywords=and, or, true, false, frame=single, rulecolor=, rulesepcolor=, literate=  \sim 1 language=bash, basicstyle=, numbers=none, tabsize=2, breaklines=true, escapeinside=@@, frame=single, showstringspaces=false, numberstyle=, keywordstyle=, stringstyle=, identifierstyle=, commentstyle=, emphstyle=, frame=single, rulecolor=, rulesepcolor=, morekeywords=gambit, cmake, make, mkdir, deletekeywords=test, literate =  gambit gambit7 /gambit/gambit6 gambit/gambit/6 /include/include8 cmake/cmake/6 .cmake.cmake6   \sim 1 language=bash, basicstyle=, numbers=none, tabsize=2, breaklines=true, escapeinside=*@@*, frame=single, showstringspaces=false, numberstyle=, keywordstyle=, stringstyle=, identifierstyle=, commentstyle=, emphstyle=, frame=single, rulecolor=, rulesepcolor=, morekeywords=gambit, cmake, make, mkdir, deletekeywords=test, literate =  gambit gambit7 /gambit/gambit6 gambit/gambit/6 /include/include8 cmake/cmake/6 .cmake.cmake6   \sim 1 language=, basicstyle=, identifierstyle=, numbers=none, tabsize=2, breaklines=true, escapeinside=*@@*, showstringspaces=false, frame=single, rulecolor=, rulesepcolor=, literate=  \sim 1 language=bash, escapeinside=@@, keywords=true,false,null, otherkeywords=, keywordstyle=, basicstyle=, identifierstyle=, sensitive=false, commentstyle=, morecomment=[l]#, morecomment=[s]/**/, stringstyle=, moredelim=**[s][],:, moredelim=**[l][]:, morestring=[b]’, morestring=[b]", literate = ------3 >>1 ||1  -  - 3 } }1 { {1 [ [1 ] ]1   \sim 1, breakindent=0pt, breakatwhitespace, columns=fullflexible language=Mathematica, basicstyle=, basewidth=0.53em,0.44em, numbers=none, tabsize=2, breaklines=true, escapeinside=@@, numberstyle=, showstringspaces=false, numberstyle=, keywordstyle=, stringstyle=, identifierstyle=, commentstyle=, directivestyle=, emphstyle=, frame=single, rulecolor=, rulesepcolor=, literate=  \sim 1, moredelim=*[directive]  #, moredelim=*[directive]    #, mathescape=true

\thankstext

e1benjamin.farmer@fysik.su.se \thankstexte2anders.kvellestad@nordita.org \thankstexte3p.scott@imperial.ac.uk \thankstexte4c.weniger@uva.nl \thankstext[*]e5Also Institut Universitaire de France, 103 boulevard Saint-Michel, 75005 Paris, France.

## 1 Introduction

The search for physics Beyond the Standard Model (BSM) is a necessarily multidisciplinary effort, as evidence for new physics could appear in any observable in particle, astroparticle or nuclear physics. Strategies include producing new particles at high-energy colliders ATLAS_diphoton (); ATLAS15 (); CMS_SMS (), hunting for their influences on rare processes and precision measurements gm2exp (); BelleII (); CMSLHCb_Bs0mumu (), directly detecting dark matter (DM) in the laboratory XENON2013 (); PICO60 (); LUX2016 (), carefully examining cosmological observations for the influence of new physics Planck15cosmo (); Slatyer15a (); keVsterile_whitepaper (), and detecting high-energy particles from DM annihilation or decay BringmannWeniger (); LATdwarfP8 (); IC79_SUSY (). In this context, exclusions have so far been just as valuable as apparent detections; many purported signals of new physics have appeared Bernabei08 (); Goodenough09 (); Pamelapositron (); CoGeNTAnnMod11 (); Bringmann12 (); Bulbul14 (); Boyarsky14 (); Vincent14 (); ATLAS_diboson (), often only to be disproven by a lack of correlated signals in other experiments CDMSLowE12 (); Bartels15 (); Lee:2015fea (); Jeltema15 (); CRESST_momdep (); LATdwarfP8 ().

Properly and completely weighing the sum of data relevant to a theory, from many disparate experimental sources, and making rigorous statistical statements about which models are allowed and which are not, has become a challenging task for both theory and experiment. This is the problem addressed by global fits: simultaneous predictions of a raft of different observables from theory, coupled with a detailed combined statistical analysis of the various experimental searches sensitive to them. Several attempts to address this problem have been made in particle physics, from the characterisation of electroweak physics with ZFitter ZFitter () and later GFitter GFitter11 () to CKM fits CKMFitter (), neutrino global fits Bari13 (); Tortola14 (); NuFit15 () and global analyses of supersymmetry (SUSY) Baltz04 (); Allanach06 (); SFitter (), in particular with packages like SuperBayeS Ruiz06 (); 2007NewAR..51..316T (); 2007JHEP…07..075R (); Roszkowski09a (); Trotta08 (); Martinez09 (); Roszkowski09b (); Roszkowski10 (); Scott09c (); BertoneLHCDD (); SBCoverage (); SuperbayesHiggs (); Nightmare (); BertoneLHCID (); IC22Methods (); Strege13 (); SuperbayesXENON100 (); SuperBayesGC (), Fittino Fittino06 (); Fittino (); Fittino12 (), MasterCode Buchmueller08 (); Buchmueller09 (); MasterCodemSUGRA (); MasterCode11 (); MastercodeXENON100 (); Mastercode12 (); MastercodeHiggs (); Mastercode12b (); MastercodeCMSSM (); Buchmueller:2014yva (); Bagnaschi:2016afc (); Bagnaschi:2016xfg () and others Allanach:2007qk (); Abdussalam09a (); Abdussalam09b (); Allanach11b (); Allanach11a (); arXiv:1111.6098 (); Roszkowski12 (); Farmer13 (); arXiv:1212.4821 (); Fowlie13 (); Henrot14 (); Kim:2013uxa (); arXiv:1402.5419 (); arXiv:1405.4289 (); arXiv:1503.08219 (); arXiv:1604.02102 (); Han:2016gvr ().

BSM global fits today remain overwhelmingly focused on SUSY, specifically lower-dimensional subspaces of the minimal supersymmetric standard model (MSSM) Strege15 (); Fittinocoverage (); Catalan:2015cna (); MasterCodeMSSM10 (); Mastercode15 (), or, more rarely, the next-to-minimal variant (NMSSM) Balazs08 (); LopezFogliani:2009np (); Kowalska:2012gs (); Fowlie14 (). There are only a handful of notable exceptions for non-SUSY models BertoneUED (); Cheung:2012xb (); Arhrib:2013ela (); Sming14 (); Chowdhury15 (); Liem16 (); LikeDM (); Banerjee:2016hsk (); Matsumoto:2016hbs (); Cuoco:2016jqt () and none for SUSY beyond the NMSSM. These studies, and their underlying software frameworks, were each predicated on one specific theoretical framework, relying on the phenomenologist-as-developer to hardcode the relevant observables and theory definitions. This inflexibility and the correspondingly long development cycle required to recode things to work with a new theory, are two of the primary reasons that global fits have been applied to so few other models. The unfortunate result has been that proper statistical analyses have not been carried out for most of the theories of greatest current interest. This is in spite of the fact that the LHC and other experiments have yet to discover any direct evidence for SUSY, heavily constraining the minimal variant Strege15 (); Fittinocoverage (); Catalan:2015cna (); MasterCodeMSSM10 (); Mastercode15 (). It is therefore essential that as many new ideas as possible are rigorously tested with global fits.

Even working within the limited theoretical context for which they were designed, existing global fits do not offer a public framework that can be easily extended to integrate new observables, datasets and likelihood functions into the fit as they become available. Neither do they provide any standardised or streamlined way to deal with the complex interfaces to external codes for calculating specific observables or experimental likelihoods. Of the major SUSY global fit codes, only one (the now-discontinued SuperBayeS SBWeb ()) has seen a public code release, in stark contrast to many of the public phenomenological tools that they employ. Public code releases improve the reproducibility, accessibility, development and, ultimately, critique, acceptance and adoptance of methods in the community.

Another difficulty is that carrying out detailed joint statistical analyses in many-dimensional BSM parameter spaces is technically hard. It requires full understanding of many different theory calculations and experiments, considerable coding experience, large amounts of computing time, and careful attention to statistical and numerical methods Akrami09 (); SBSpike (); Akrami11coverage (); Strege12 (); Fittinocoverage (). Outside of global fits, the response has been to focus instead on individual parameter combinations or a limited, not-necessarily-representative part of the parameter space, e.g. ATLAS15 (); CMS_SMS (); Berger09 (). Making concrete statements across ranges of parameters requires adopting either the Bayesian or frequentist statistical framework. These each impose specific mathematical conditions on how one discretely samples the parameter space and then combines the samples to make statements about continuous parameter ranges. The choice of statistical framework therefore has a strong bearing upon the appropriateness and efficiency of the scanning algorithm one employs Akrami09 (); SBSpike (); random sampling is rarely adequate. Most global fits have so far assumed either Bayesian or frequentist statistics, discarding the additional information available from the other. They have also employed only a single parameter sampling algorithm each, despite the availability and complementarity of a wide range of relevant numerical methods.

Here we introduce GAMBIT, the Global And Modular BSM Inference Tool. GAMBIT is a global fitting software framework designed to address the needs listed above: theory flexibility, straightforward extension to new observables and external interfaces, code availability, statistical secularism and computational speed. In this paper we describe the GAMBIT framework itself in detail. First results for SUSY and the scalar singlet DM model can be found in accompanying papers CMSSM (); MSSM (); SSDM (), as can detailed descriptions of the constituent physics and statistics modules ColliderBit (); FlavBit (); DarkBit (); SDPBit (); ScannerBit (). The GAMBIT codebase is released under the standard 3-clause BSD license111http://opensource.org/licenses/BSD-3-Clause. Note that fjcore Cacciari:2011ma () and some outputs of FlexibleSUSY Athron:2014yba () (incorporating routines from SOFTSUSY Allanach:2001kg ()) are also shipped with GAMBIT 1.0. These code snippets are distributed under the GNU General Public License (GPL; http://opensource.org/licenses/GPL-3.0), with the special exception, granted to GAMBIT by the authors, that they do not require the rest of GAMBIT to inherit the GPL., and can be obtained from gambit.hepforge.org.

This paper serves three purposes. It is:

1. An announcement of the public release of GAMBIT,

2. A generally-accessible presentation of the novel and innovative aspects of GAMBIT, along with the possibilities it provides for future particle phenomenology,

3. A reference manual for the framework and associated code.

Goals 2 and 3 imply slightly different things for the structure and content of this paper. Here we begin by specifically addressing Goal 2, in Sec. 2. This section provides an extended synopsis of the flexible and modular design concept of GAMBIT, describing its main features and advances compared to previous global fits. Sec. 2 provides something of a teaser for the more extended ‘manual’, which can be found in Secs. 313. These sections describe how the features of GAMBIT are actually implemented, used and extended. A quick start guide can be found in Appendix A, library dependencies and supported compiler lists in Appendix B, specific SM parameter definitions in Appendix C, and a glossary of GAMBIT-specific terms in Appendix D. When terms make their first or other crucial appearances in the text, we cross-link them to their entries in the glossary. To the end of this arXiv submission, we also append the published Addendum to this paper, which describes the changes implemented in GAMBIT 1.1 compared to GAMBIT 1.0, including support for calling external Mathematica codes from GAMBIT.

Within the ‘manual’ part of the paper, Sec. 3 describes in detail how a physics module in GAMBIT works, Sec. 4 details the system GAMBIT uses for interfacing with external codes, and Sec. 5 covers the internal model database and its influence on analyses and the rest of the code. Sec. 6 explains the user interface to GAMBIT and documents the available settings in the master initialisation file. Sec. 7 details the GAMBIT system for instigating scans by automatically activating different calculations, depending on the models scanned and the observables requested by the user. Sec. 8 explains how GAMBIT deals with statistical and parameter scanning issues; further details of the specific methods and optimisation options in the scanning module can be found in Ref. ScannerBit (). Sec. 9 describes the system for outputting results from GAMBIT. Sec. 10 covers other assorted utility subsystems. Section 11 discusses the build and automatic component registration system, including a crash course in adding new models, observables, likelihoods, scanners and other components to GAMBIT. Sec. 12 describes some minimal examples included in the base distribution, and provides information about releases and support.

A code like GAMBIT and a paper such as this have multiple levels of user and reader. The relevant sections of this paper for each are summarised in Table 1. Those more interested in understanding what GAMBIT offers than actually running or extending it need only this introduction, Sec. 2 and the glossary (Appendix D). Users interested in running scans without modifying any code should find more than enough to get started in Appendix A, Secs. 11.211.4 and 12. To get the most out of the code, such users should then move progressively on to Secs. 5.4, 6, 8, 9.1, 9.2, 10.2, 10.4, 10.7 and 10.8. Those interested in adding new observables, likelihoods or interfaces to external codes should also read Secs. 3, 4.1, 4.4, and the rest of Secs. 10 and 11. Users wanting to extend GAMBIT to deal with new models and theories should add the remainder of Sec. 5 to this tally. Power users and developers wanting to have a complete understanding of the software framework should also familiarise themselves with Secs. 4.5, 4.6, 7 and 9.3. Readers and users with specific interests in particular physical observables, experiments or likelihoods should also add the relevant physics module paper(s) ColliderBit (); FlavBit (); DarkBit (); SDPBit () to this list, and those interested in details of parameter scanning or statistics should likewise add Ref. ScannerBit ().

## 2 Design overview

GAMBIT consists of a number of modules or ‘Bits’, along with various Core components and utilities. Fig. 1 is a simplified representation of how these fit together. GAMBIT modules are each either physics modules (DarkBit, ColliderBit, etc.) or the scanning module, ScannerBit. ScannerBit is responsible for parameter sampling, prior transformations, interfaces to external scanning and optimisation packages and related issues; it is discussed in more detail in Sec. 8 and Ref. ScannerBit ().

### 2.1 Modularity

#### 2.1.1 Physics modules, observables and likelihoods

The first version of GAMBIT ships with six physics modules:

ColliderBit

calculates particle collider observables and likelihoods. It includes detailed implementations of LEP, ATLAS and CMS searches for new particle production, and measurements of the Higgs boson. The LEP likelihoods are based on direct cross-section limits on sparticle pair production from ALEPH, OPAL and L3. Fast Monte Carlo simulation of signals at ATLAS and CMS can be performed with a specially parallelised version of Pythia 8 Sjostrand:2014zea (). ColliderBit offers the option to carry out detector simulation with BuckFast, a fast smearing tool, or the external package Delphes Ovyn:2009tx (); deFavereau:2013fsa (). We have validated all likelihoods and limits via extensive comparison to experimental limits and cutflows. Higgs likelihoods in the first version of ColliderBit are provided exclusively by communication with HiggsBounds Bechtle:2008jh (); Bechtle:2011sb (); Bechtle:2013wla () and HiggsSignals HiggsSignals (). Supersymmetic models are presently supported natively by the LEP and LHC likelihoods. The Higgs likelihoods are model-independent in as much as they require only Higgs couplings as inputs. Other models can be supported in LHC calculations by reading matrix elements into Pythia 8, e.g. from MadGraph Alwall:2011uj (); Alwall:2014hca (). For a detailed description, see ColliderBit ().

FlavBit

calculates observables and likelihoods from flavour physics, in particular B, D and K meson decays as observed by LHCb, including angular observables and correlations. Possibilities for inter-code communication exist with SuperIso Mahmoudi:2007vz (); Mahmoudi:2008tp (); Mahmoudi:2009zz () and FeynHiggs Bahl:2017aev (); Bahl:2016brp (); Hahn:2013ria (); Frank:2006yh (); Degrassi:2002fi (); Heinemeyer:1998np (); Heinemeyer:1998yj (). Supersymmetry is supported directly. A broad range of other models is supported, via the use of effective field theory. Likelihoods and observables have been validated by comparison to existing flavour fits Mahmoudi:2014mja (); Altmannshofer:2013foa (); Descotes-Genon:2015uva (). See FlavBit ().

DarkBit

calculates DM observables and likelihoods, from the relic abundance to direct and indirect searches. It includes an on-the-fly cascade decay spectral yield calculator, and a flexible, model-independent relic density calculator capable of mixing and matching aspects from existing backends, including DarkSUSY darksusy () and micrOMEGAs Belanger:2001fz (); Belanger:2004yn (); Belanger:2006is (); Belanger:2010gh (); Belanger:2013oya (); Belanger:2014vza (). Direct detection likelihoods in DarkBit are based on calls to the DDCalc package DarkBit (). Indirect detection can be carried out with the help of nulike IC79_SUSY () (neutrinos) and gamLike DarkBit () (gamma rays). Validation of relic density calculations is based on extensive comparison with results from standalone versions of DarkSUSY and micrOMEGAs. Direct and indirect limits are validated by comparison with exclusion curves from the relevant experiments. All calculations support MSSM neutralinos and all other WIMPs (in particular, this includes Higgs portal models such as scalar singlet dark matter). See DarkBit () for details.

SpecBit

interfaces to one of a number of possible external spectrum generators in order to determine pole masses and running parameters, and provides them to the rest of GAMBIT in a standardised spectrum container format. Spectrum generators currently supported include FlexibleSUSY Athron:2014yba () and SPheno Porod:2003um (); Porod:2011nf (). Models include MSSM models defined at arbitrary scales and the scalar singlet model. Support for additional spectrum generators and models is straightforward for users to add. Results of the existing code have been validated by comparison to standalone versions of FlexibleSUSY, SPheno and SOFTSUSY Allanach:2001kg (); Allanach:2009bv (); Allanach:2011de (); Allanach:2013kza (); Allanach:2014nba (). SpecBit also carries out vacuum stability calculations and perturbativity checks, which have been validated against existing results in the literature. See SDPBit () for full details.

DecayBit

calculates decay rates of all relevant particles in the BSM theory under investigation, and contains decay data for all SM particles. Theory calculations can make use of interfaces to FeynHiggs Bahl:2017aev (); Bahl:2016brp (); Hahn:2013ria (); Frank:2006yh (); Degrassi:2002fi (); Heinemeyer:1998np (); Heinemeyer:1998yj () and an improved version of SUSY-HIT Djouadi:2006bz (); Muhlleitner:2003vg (); Djouadi:2002ze (); Djouadi:1997yw (), validated against direct SLHA communication with the same codes. DecayBit supports the MSSM and scalar singlet models. See SDPBit ().

PrecisionBit

calculates model-dependent precision corrections to masses, couplings and other observables, as well as precision nuisance likelihoods for e.g. Standard Model (SM) parameters. BSM calculations are presently limited to the MSSM, and can call on GM2Calc gm2calc (), FeynHiggs Bahl:2017aev (); Bahl:2016brp (); Hahn:2013ria (); Frank:2006yh (); Degrassi:2002fi (); Heinemeyer:1998np (); Heinemeyer:1998yj () and SuperIso Mahmoudi:2007vz (); Mahmoudi:2008tp (); Mahmoudi:2009zz (). See SDPBit ().

Physics modules are collections of module functions, each capable of calculating a single physical or mathematical quantity. This may be an observable, likelihood component or any intermediate quantity required for computing one or more observables or likelihoods.

Each module function is tagged with a D, which together with the associated D describes exactly what D it is capable of calculating. Module functions, rather than modules themselves, are the main building blocks of GAMBIT. The capability-type pairs associated with module functions are the threads that allow GAMBIT to automatically stitch together multiple functions into arbitrarily complicated physics calculations.

Individual module functions may have one or more dependencies on quantities that their own calculations depend on. At runtime, GAMBIT selects an appropriate module function to fulfil each dependency, by matching the declared capabilities of module functions with the declared dependencies of other module functions. This process also requires matching the declared return types of module functions with the types requested in each dependency.

A simple example is the W mass likelihood function in PrecisionBit, which has capability lnL_W_mass. This function calculates a basic \chi^{2} likelihood for the W mass, and is correspondingly named lnL_W_mass_chi2. To do its job, PrecisionBit::lnL_W_mass_chi2 must be provided with a predicted value for the W mass, by some other module function in GAMBIT. These aspects are declared

#define CAPABILITY lnL_W_mass
START_CAPABILITY
#define FUNCTION lnL_W_mass_chi2
START_FUNCTION(double)
DEPENDENCY(mw, triplet<double>)
#undef FUNCTION
#undef CAPABILITY

Here the DEPENDENCY on the W mass mw is explicitly declared, and the declaration demands that it must be provided as a set of three real numbers, corresponding to a central value with upper and lower uncertainties (a triplet<double>). lnL_W_mass_chi2 accesses these values in its actual source via a pointer named mw placed in a special namespace reserved for dependencies (Pipes::lnL_W_mass_chi2::Dep). It then uses the values to compute the likelihood, which it returns as its result:

/// W boson mass likelihood
const double mw_central_observed = 80.385;
const double mw_err_observed = 0.015;
void lnL_W_mass_chi2(double &result)
{
using namespace Pipes::lnL_W_mass_chi2;
double theory_uncert = std::max(Dep::mw->upper,
Dep::mw->lower);
result = Stats::gaussian_loglikelihood(
Dep::mw->central, mw_central_observed,
theory_uncert, mw_err_observed);
}

This module function has no concern for precisely where or how the W mass has been determined. This allows GAMBIT to choose for itself at runtime, on the basis of the model being scanned, whether it should provide e.g. an MSSM-corrected prediction (for an MSSM scan), or a different prediction (for a scan of a different model). This serves to illustrate the power of the modular design of GAMBIT, allowing different calculations to be automatically reused in myriad different physics scenarios, with essentially zero user intervention.

Section 3 covers declaring and writing module functions in detail.

#### 2.1.2 Backends

External software packages that might be useful for calculating specific quantities are referred to in GAMBIT as backends. Examples of these might be DarkSUSY darksusy () (for, e.g., relic density calculations), or FeynHiggs Heinemeyer:1998yj (); Heinemeyer:1998np (); Degrassi:2002fi (); Frank:2006yh (); Hahn:2013ria () (for, e.g., Higgs mass calculations). A full list of existing codes with which GAMBIT can communicate via the backend system, along with all relevant references, can be found in the file README.md included in the main distribution. All studies that make use of GAMBIT with a backend must cite all the literature associated with that backend, along with all relevant GAMBIT literature.

Although GAMBIT itself is written in C++, with a small admixture of Python for build abstraction, backends can in principle be written in any language. Module functions can directly call backend functions and access global backend variables from these codes. To do this, a module function must declare that it has a D, which is then matched at runtime to the declared capability of a function or variable from some backend. This mirrors the manner in which GAMBIT fills dependencies from amongst the available module functions.

Whilst module functions can have both dependencies (resolvable with other module functions) and backend requirements (resolvable with backend functions or variables), backend functions and variables cannot themselves have either dependencies nor backend requirements. This is illustrated in the example in Fig. 1: backend functions and variables feed into module functions, but nothing feeds into the backend functions nor variables themselves.

A simple example is the calculation in DarkBit of the rate at which DM is gravitationally captured by the Sun:

#define CAPABILITY capture_rate_Sun
START_CAPABILITY
#define FUNCTION capture_rate_Sun_const_xsec
START_FUNCTION(double)
DEPENDENCY(mwimp, double)
DEPENDENCY(sigma_SI_p, double)
DEPENDENCY(sigma_SD_p, double)
BACKEND_REQ(cap_Sun_v0q0_isoscalar, (), double,
(const double&, const double&, const double&))
#undef FUNCTION
#undef CAPABILITY

Here DarkBit::capture_rate_Sun_const_xsec depends on the DM mass and scattering cross-sections, and explicitly declares that it requires access to a function from a backend. It demands that the backend function be tagged with capability cap_Sun_v0q0_isoscalar, that it take three const double& arguments, and that it must return a double result. The declaration of a matching backend function (taken in this example from the interface to DarkSUSY 5.1.3) would then look like:

BE_FUNCTION(dsntcapsuntab, double, (const double&,
const double&, const double&), "dsntcapsuntab_",
"cap_Sun_v0q0_isoscalar")

The function DarkBit::capture_rate_Sun_const_xsec then accesses the backend function from its source via a similar alias system to the one used for dependencies:

// @\cpppragma{Capture rate in s$^{-1}$ of regular DM in the Sun}@
// @\cpppragma{($\implies$ $\sigma$ is neither $v$-dependent nor $q$-dependent),}@
// @\cpppragma{assuming isoscalar interactions ($\sigma_p = \sigma_n$)}@.
void capture_rate_Sun_const_xsec(double &result)
{
using namespace
Pipes::capture_rate_Sun_const_xsec;
result =
BEreq::cap_Sun_v0q0_isoscalar(*Dep::mwimp,
*Dep::sigma_SI_p, *Dep::sigma_SD_p);
}

Typically, the requirement cap_Sun_v0q0_isoscalar will be fulfilled by DarkSUSY, a Fortran code – but there is nothing about this particular example function nor its declaration that forces such a pairing. The only conditions are that the selected backend function fulfils the requirements laid out in the BACKEND_REQ declaration. This is another example of the power of the modular design of GAMBIT, allowing it to attach any matching function from any backend at runtime, and to adapt to the presence or absence of different versions of different backends present on any given user’s system.

There are many additional options and declarations available but not shown in this example, for constraining which versions of which backends are permitted to provide which backend requirement, under what model-dependent conditions and so on. Two additional features of note are not shown in Fig. 1: backend initialisation functions, which always run before any functions or variables in a backend are used, and backend convenience functions, which are agglomerations of functions and variables from one backend, presented to the rest of GAMBIT as if they are single backend functions.

Declaration of backend requirements is covered in detail in Section 3.1.3, and declaration of actual interfaces to backends is covered in Section 4.

#### 2.1.3 Models

The models already implemented in GAMBIT 1.0.0 are shown in Fig. 2, and described in detail in Sec. 5.4. Instructions for adding new models are given in Sections 5.1 and 11.1.

GAMBIT automatically activates or disables module and backend functions222and backend variables — but from here we will stop explicitly referring to backend functions and backend variables as different things except where it actually matters. according to their compatibility with the BSM model under investigation. It does this using a hierarchical model database, where each model is defined as a set of free parameters and a series of relations to other models. Models can be declared as children of existing models, which implies that there exists a mapping from the child parameter space to some subspace of the parent space. Each D comes with a function that defines the transformation required to take a parameter point in its space to a corresponding point in the parent parameter space. GAMBIT uses these transformations at runtime to deliver the same parameter point in different parameterisations to different module functions, according to their declared needs. Models can also have translations pathways defined to other so-called friend models outside their own family tree.

One important aspect of this arrangement is that models can be arbitrarily ‘bolted together’ for any given scan, so that multiple models can be scanned over simultaneously, and their parameter values delivered together to any module functions that need them. This allows for the SM parameters to be varied as nuisance parameters when doing an MSSM or other BSM scan, for example. It also means that in such a joint SM-MSSM scan, the same underlying SM model (and therefore the same SM calculations wherever possible) will be used as in any other joint SM-BSM scan.

When a user requests a scan of a particular BSM model, that model and its entire model ancestry are activated. This makes all module and backend functions that are compatible with any model in the activated ancestry available as valid building blocks of the scan. This provides maximum safety by forbidding any calculations that are not valid for the model under consideration, and maximum re-usability of modules, backends and their functions with new models, by providing certainty about which existing functions are ‘safe’ to use with new additions to the model hierarchy.

A basic example of model and backend function activation/deactivation can be seen in Fig. 1. Functions A1 and C2 have been specifically declared as model-dependent and therefore require activation or deactivation by the model database. Only functions that have been declared as model-dependent in this way are allowed to access the values of the underlying parameters in a scan. No other functions have any such declarations, so they are therefore valid for all models. Such functions must always work for any model, as all they need to do their job is to be confident that GAMBIT will deliver their declared dependencies and backend requirements in the form that they request – and GAMBIT guarantees precisely this for all module functions.

The two examples given in the previous subsections, of the W mass likelihood and the capture rate of DM by the Sun, are both examples of essentially model-independent calculations, where the module function does not need direct access to any of the underlying model parameters. These functions care only that their dependencies and backend requirements are available; if this is the case, they can do their jobs, irrespective of the underlying model actually being scanned.333Note the distinction between model-independent functions and model-independent results. Model-independent numerical results have the same values regardless of the physics model assumed. Model-independent functions act on input data according to the values of the data only, not according to the physics model that gave rise to the data. In general, the input data to model-independent functions are model-dependent quantities, leading to different results for different models. The W mass likelihood is a case in point: the predicted value of m_{W} and its likelihood are necessarily model-dependent quantities – but the function that computes the likelihood from a given value of m_{W} is not dependent on the model for which m_{W} has been computed.

An example of an explicitly model-dependent module function is the DarkBit likelihood associated with the nuclear matrix elements relevant for spin-independent DM-nucleon scattering:

// Likelihoods for nuclear parameters.
START_CAPABILITY
#define FUNCTION lnL_sigmas_sigmal
START_FUNCTION(double)
ALLOW_MODEL(nuclear_params_sigmas_sigmal)
#undef FUNCTION

Here the ALLOW_MODEL declaration is used to indicate that the module function can only be used when scanning the nuclear_params_sigmas_sigmal model (or one of its descendants – but it has none in this version of GAMBIT). This particular module function directly accesses the values of the model parameters, uses them to compute the joint likelihood and returns the result. In contrast, when the nuclear matrix elements are needed for calculating the physical DM-nucleon couplings in e.g., the scalar singlet Higgs portal model, they are instead upcast to the nuclear_params_fnq model (an ancestor of nuclear_params_sigmas_sigmal, cf. Fig. 2), and presented as such within the relevant module function:

#define FUNCTION DD_couplings_SingletDM
START_FUNCTION(DM_nucleon_couplings)
DEPENDENCY(SingletDM_spectrum, Spectrum)
ALLOW_JOINT_MODEL(nuclear_params_fnq, SingletDM)
#undef FUNCTION

Here the ALLOW_JOINT_MODEL declaration explicitly forbids GAMBIT from using this function except when scanning both the nuclear_params_fnq and SingletDM models, or some pairwise combination of their respective descendants.

The GAMBIT model database, its declarations and features are discussed in much more detail in Sec. 5.

After filtering out invalid module and backend functions by checking their compatibility with the model under investigation, GAMBIT works through the remaining functions to properly connect module functions to dependencies and backend functions to backend requirements. It starts with the quantities requested by the user (observables, likelihood components or other derived quantities), and then progressively resolves dependencies and backend requirements until it either reaches an impasse due to a mutual dependency between groups of module functions, or no outstanding needs remain. If all needs have been fulfilled, the result is a directed graph of dependencies, with no internal closed loops – a so-called directed acyclic graph. Directed acyclic graphs have the mathematical property that they possess an implied topological order. GAMBIT computes this ordering, and uses it to determine the optimal order in which to evaluate the module functions, such that each module function is guaranteed to run before any other function that depends on its results. GAMBIT further optimises the ordering beyond the constraint implied by this condition, considering the typical evaluation time of each function as a scan progresses, and its role in ruling out previous parameter combinations. We explain this overall D process in detail in Sec. 7.

With a specific module function evaluation order in hand, GAMBIT passes the problem of actually sampling the parameter space to ScannerBit (Sec. 8). ScannerBit engages whichever statistical scanning algorithm and output method a user has selected in their input file (see Sec. 6), choosing parameter combinations, calling the module functions in order, and sending the results to the GAMBIT printer system (Sec. 9). Functions log their activity via an extensive internal logging system (Sec. 10.2), and invalid parameter combinations, warnings and errors are identified using a dedicated exceptions system (Sec. 10.3).

This rather abstract formulation of the global fit problem enables a very high degree of automation, in turn providing flexibility and extendibility. By deferring the actual choice of the function that will provide the requisite physical inputs to each step of a calculation, GAMBIT makes it easy to confidently swap or add functions to existing scans. It also makes such scans efficient, as only the calculations needed for a given scan are actually activated, and each calculation is guaranteed to run only once for each parameter combination. Linking this to a hierarchical model database then provides the means for GAMBIT to automatically adapt existing likelihood and observable calculations to new models, to the largest extent theoretically possible. New components of course need to be added when different physics is to be considered for the first time, but the level of automation allows the user to immediately identify the precise gaps in the theoretical chain in need of new work, rather then wasting time by coding almost identical functions for every new model. This is facilitated by extensive and informative error messages presented when a scan is attempted but some link in the dependency chain cannot be fulfilled. These messages explain, for example, when a given dependency cannot be filled by any known function, if a requisite backend appears to be missing, if appropriate functions seem to exist but are not compatible with the model being scanned, if multiple permitted options exist for resolving a given dependency or backend requirement, and so on.

GAMBIT takes this flexibility and automatic adaptation even further by having the backend (Sec. 4) and build (Sec. 11) systems automatically add or disable modules, backends, models, printers and other components when new ones are defined, or when existing ones happen to be missing from a user’s system. GAMBIT also includes extensive command-line diagnostics, which the user can employ to obtain reports on the status and contents of its components at many different levels (Sec. 10.4).

### 2.3 Performance and parallelisation

Parallelisation in GAMBIT happens at two levels: at the scanner level via MPI MPI (), and at the level of module functions with OpenMP openmp (). This allows GAMBIT to easily scale to many thousands of cores, as most major external sampling packages employ MPI, and a number of external physics codes make use of OpenMP (e.g. nulike IC79_SUSY () and forthcoming versions of DarkSUSY darksusy ()). Users also have the option of implementing their own module functions using OpenMP natively in GAMBIT. In fact, GAMBIT can even automatically connect OpenMP-aware module functions and have other module functions run them in parallel using OpenMP. Sec. 3.1.4 explains how to achieve this. With this method, the total runtime for a single MSSM parameter combination, even including explicit LHC Monte Carlo simulation, can be reduced to a matter of a few seconds ColliderBit ().

The performance of GAMBIT is explored in detail in the ScannerBit paper ScannerBit ().

### 2.4 Available examples

In Sec. 12.1 we provide a series of examples showing how to run the full GAMBIT code. Any GAMBIT module can also be compiled with a basic driver into a standalone program. We also give a number of examples of module standalone drivers in Sec. 12.1, as well as dedicated examples for different modules included in first release DarkBit (); ColliderBit (); ScannerBit (); FlavBit (); SDPBit ().

A standalone driver program that calls a GAMBIT module needs to do a number of specific things:

• specify which model to work with,

• choose what the parameter values should be,

• indicate which module functions to run and what to do with the results,

• indicate which module functions to use to fulfil which dependencies,

• indicate which backend functions or variables to use to fulfil which backend requirements, and

• set input options that different module functions should run with.

These are all functions that are normally done automatically by GAMBIT. We provide a series of simple utility functions specifically designed for use in standalone driver programs though, allowing most of these operations to be completed in a single line each.

## 3 Modules

Other than the six physics and one scanning module in GAMBIT 1.0.0, behind the scenes GAMBIT also arranges backend initialisation functions into a virtual module known as BackendIniBit, and puts model parameter translation functions into effective modules of their own. These are discussed in detail in Secs. 4 and 5, respectively.

### 3.1 Module function declaration

GAMBIT modules and their functions are declared in a module’s so-called D, using a series of convenient macros.

A module called MyBit would be created simply by creating a header MyBit\_rollcall.hpp containing

#define MODULE @\metavar{MyBit}@
START_MODULE
#undef MODULE

and then rerunning the build configuration step in order to make GAMBIT locate the new file.444Re-running the configuration step is a generic requirement whenever adding new source or header files to GAMBIT. See Sec. 11 for details.

Creating a module function requires a user to write it as a standard C++ function in a source file, and add a corresponding declaration to the rollcall header. The function should have return type void, and take exactly one argument by reference: the result of the calculation that the function is supposed to perform. This result can be of any type.555At least, any type with a default constructor. Dealing in types without default constructors requires declaring objects internally in the module and returning pointers to them. Taking a double-precision floating point number as an example, the definition of a function function_name in module MyBit would look like

namespace @\metavar{MyBit}@
{
void @\metavar{function\_name}@(double& result)
{
result =  // something useful
}
}

This would traditionally be placed in a file called MyBit.cpp or similar.

The declaration must state the name of the function, the type of its result, and the capability to assign to it. Such a declaration would look like

#define MODULE @\metavar{MyBit}@
START_MODULE
#define CAPABILITY @\metavar{example\_capability}@
START_CAPABILITY
#define FUNCTION @\metavar{function\_name}@
START_FUNCTION(double)
#undef FUNCTION
#undef CAPABILITY
#undef MODULE

where example_capability is the name of the capability assigned to the function MyBit::function_name in this example.

The following examples in Secs. 3.1.13.1.3 will show other specific declarations that may be given between
START_FUNCTION and #undef FUNCTION.

#### 3.1.1 Model compatibility

In the absence of any specific declarations as to the model-dependency of the calculations in a module function, GAMBIT assumes that the function is completely model-independent. To instead declare that a module function may only be used with a single specific model model_a, one adds a declaration

ALLOW_MODEL(@\metavar{model\_a}@)

after calling START_FUNCTION. To declare that the function may be used with one or more models from a particular set, one instead writes

ALLOW_MODEL(@\metavar{model\_a}@)
ALLOW_MODEL(@\metavar{model\_b}@)

or just

ALLOW_MODELS(@\metavar{model\_a}@, @\metavar{model\_b}@, …)

where the ellipses indicate that the ALLOW_MODELS macro is variadic, and can take up to 10 specific models. Alternatively, to declare that all models from a given set must be in use, one declares

ALLOW_JOINT_MODEL(@\metavar{model\_$\gamma$}@, @\metavar{model\_$\delta$}@, …)

Declaring ALLOW_MODEL, ALLOW_MODELS or ALLOW_JOINT_MODEL also grants the module function access to the values of the parameters of the appropriate model(s) at runtime. Section 3.2.3 below deals with how to retrieve these parameter values.

GAMBIT is expressly designed for simultaneous scanning of multiple models, where the parameters of each model are varied independently. This allows for arbitrary combinations of different models, e.g. from including SM parameters as nuisances in a BSM scan, to varying cosmological and BSM parameters simultaneously in some early-Universe cosmological scenario. In these cases, module functions can be granted access to the parameters of multiple models at the same time, as long as the function is declared from the outset to need all of those parameters in order to operate correctly.

To set rules that constrain module functions’ validities to scans of specific combinations of models, rather than simply declaring valid combinations one by one with ALLOW_JOINT_MODEL, a more involved syntax is required. Here, the possible individual models involved in the combinations are first listed with ALLOW_MODEL_DEPENDENCE. They are then placed into one or more specific model groups. Each allowed model combination is then specified by setting allowed combinations of model groups. If a given scan includes one model from each group listed in an allowed combination, then the module function is deemed to be compatible with the given scan.

For example, to specify that a function may be used when either model_a or model_b is being scanned, but only if model_c is also being scanned at the same time, one must write

ALLOW_MODEL_DEPENDENCE(@\metavar{model\_a}@, @\metavar{model\_b}@, @\metavar{model\_c}@)
MODEL_GROUP(group1, (@\metavar{model\_a}@, @\metavar{model\_b}@))
MODEL_GROUP(group2, (@\metavar{model\_c}@))
ALLOW_MODEL_COMBINATION(group1, group2)

This reveals that ALLOW_JOINT_MODEL(model_\gamma, model_\delta, …) is simply a special case of this extended syntax, precisely equivalent to

ALLOW_MODEL_DEPENDENCE(@\metavar{model\_$\gamma$}@, @\metavar{model\_$\delta$}@, …)
MODEL_GROUP(group1, (@\metavar{model\_$\gamma$}@))
MODEL_GROUP(group2, (@\metavar{model\_$\delta$}@))
ALLOW_MODEL_COMBINATION(group1, group2, …)

Note that GAMBIT still deems a model to be in use even if its parameters are fixed to constant values during a scan. Declaring that a module function requires some model or model combination to be in use therefore merely demands that the model parameters have definite values during a scan, not that they are necessarily varied.

An explicit example of the syntax described in this section can be found in the declaration of the function DarkBit::DD_couplings_MicrOmegas in DarkBit/include/gambit/DarkBit/DarkBit_rollcall.hpp:

ALLOW_MODEL_DEPENDENCE(nuclear_params_fnq,
MSSM63atQ, SingletDM)
MODEL_GROUP(group1, (nuclear_params_fnq))
MODEL_GROUP(group2, (MSSM63atQ, SingletDM))
ALLOW_MODEL_COMBINATION(group1, group2)

This function computes couplings relevant for direct detection, using micrOMEGAs micromegas (). To do this, it needs the parameters of the nuclear matrix element model nuclear_params_fnq, plus the parameters of a dark matter model, which in GAMBIT 1.0.0 may be either the MSSM or the scalar singlet model.

#### 3.1.2 Dependencies

To indicate that a module function requires some specific quantity as input in order to carry out its own calculation, one must declare that it has a dependency upon the capability, and the corresponding type, of some other module function. Dependencies are explicitly defined in terms of capabilities, not specific functions: from the GAMBIT perspective functions do not depend on each other, they depend on each others’ capabilities. This is specifically designed to make module functions genuinely modular, by keeping the use of a module function’s result completely independent of its identity. This has the (entirely intentional) consequence of making it practically impossible to safely use global states for passing information between module functions.

The syntax for declaring that a module function function_name has a dependency on some capability capability is simply to add a line

DEPENDENCY(@\metavar{capability}@, @\metavar{type}@)

to the module function declaration. Here type is the actual C++ type of the capability that needs to be available for function_name to use in its function body.

Such a declaration ensures that at runtime, GAMBIT will arrange its D such that it

• only runs function_name after some other module function with capability capability and return type type has already run for the same parameter combination,

• delivers the result of the other module function to function_name, so that the latter can use it in its own calculation.

It is also possible to arrange conditional dependencies that only apply when specific conditions are met. The simplest form is a purely model-dependent conditional dependency,

MODEL_CONDITIONAL_DEPENDENCY(@\metavar{capability}@, @\metavar{type}@,
@\metavar{model\_$\alpha$}@, @\metavar{model\_$\beta$}@, …)

which would cause a function to depend on capability only when model_\alpha and/or model_\beta is being scanned. Here the ellipses again indicate that up to 10 models can be specified.

A concrete example of this is the declaration of the function FlavBit::SuperIso_modelinfo in FlavBit/include/gambit/FlavBit/FlavBit_rollcall.hpp. This function is responsible for constructing the data object that will be sent to SuperIso Mahmoudi:2007vz (); Mahmoudi:2008tp () to tell it the values of the relevant Lagrangian parameters. Its declaration includes the lines:

MODEL_CONDITIONAL_DEPENDENCY(MSSM_spectrum,
Spectrum, MSSM63atQ, MSSM63atMGUT)
MODEL_CONDITIONAL_DEPENDENCY(SM_spectrum,
Spectrum, WC)

These statements cause the function to have a dependency on an MSSM_spectrum when scanning the MSSM, but a dependency on an SM_spectrum when scanning a low-energy effective theory of flavour (WC; see Sec. 5.4.5).

An alternative formulation allows both model conditions and backend conditions to be specified:

#define CONDITIONAL_DEPENDENCY @\metavar{capability}@
START_CONDITIONAL_DEPENDENCY(@\metavar{type}@)
ACTIVATE_FOR_MODELS(@\metavar{model\_$\alpha$}@, @\metavar{model\_$\beta$}@, …)
ACTIVATE_FOR_BACKEND(@\metavar{requirement}@, @\metavar{be\_name1}@)
ACTIVATE_FOR_BACKEND(@\metavar{requirement}@, @\metavar{be\_name2}@)
#undef CONDITIONAL_DEPENDENCY

In this example, the dependency on capability would not only be activated if model_\alpha or model_\beta were in use, but also if either backend be_name1 or backend be_name2 were used to resolve the backend requirement requirement. In this case, the CONDITIONAL_DEPENDENCY declaration must appear after the corresponding backend requirement is declared. Declaration of backend requirements is covered in Sec. 3.1.3.

There is currently no way to specify more complicated arrangements like ‘dependency is activated only if scanning model_\alpha and using backend_name’ or ‘only if scanning both model_\alpha and model_\beta’. Wanting to use such complicated scenarios is usually a sign that the intended design of the module function is unnecessarily complicated, and the function would be better just split into multiple functions with different properties.

#### 3.1.3 Backend requirements

Backend requirements are declarations that a module function intends to use either a function or a global variable from a backend (external) code. Backend requirements are specified in a similar way to dependencies: by declaring the type and the capability of the required backend function or variable (not the name of a specific backend function). In contrast to dependencies, however, the type of a backend requirement may be an entire function signature, describing not just the return type, but also the types of an arbitrary number of arguments. Designating the capability of the backend variable required as var_requirement and its required type var_type, the declaration of a backend variable requirement is

BACKEND_REQ(@\metavar{var\_requirement}@, (@\metavar{tags}@), @\metavar{var\_type}@)

If a backend function is required, with capability fn_requirement, return type fn_return_type and function argument types arg1_type, arg2_type and so on, the declaration is instead

BACKEND_REQ(@\metavar{fn\_requirement}@, (@\metavar{tags}@), @\metavar{fn\_return\_type}@,
(@\metavar{arg1\_type}@, @\metavar{arg2\_type}@, …))

Note that the final argument of BACKEND_REQ should be absent for backend variable requirements, but should be explicitly specified as () for backend functions with no arguments — as is standard C/C++ syntax. The ellipses in the backend function example again indicate that the entry is variadic, so as many function arguments can be specified as required. If the backend function is itself required to be variadic (in the C-style sense that the function required must be able to take a variable number of arguments), then instead of the traditional ellipses used to declare such a function, one must use the keyword etc, as in

BACKEND_REQ(@\metavar{fn\_requirement}@, (@\metavar{tags}@), @\metavar{fn\_return\_type}@,
(@\metavar{arg1\_type}@, etc))

The tags entry in the declarations above allows one to specify a set of zero or more comma-separated tags, which can then be used to impose various conditions on how backend requirements can be filled. Consider the following example:

BACKEND_REQ(@\metavar{req\_A}@, (tag1), float, (int, int))
BACKEND_REQ(@\metavar{req\_B}@, (tag1, tag2), int, ())
BACKEND_REQ(@\metavar{req\_C}@, (tag3), int)
ACTIVATE_BACKEND_REQ_FOR_MODELS( (@\metavar{model\_$\alpha$}@,
@\metavar{model\_$\beta$}@), (tag1) )
BACKEND_OPTION( (@\metavar{be\_name1}@), (tag1) )
BACKEND_OPTION( (@\metavar{be\_name2}@, 1.2, 1.3, 1.5),
(tag2, tag3) )
FORCE_SAME_BACKEND(tag1)

In this example, the ACTIVATE_BACKEND_REQ_FOR_MODELS directive ensures that req_A and req_B only exist as backend requirements when model_\alpha and/or model_\beta are in use. FORCE_SAME_BACKEND creates a rule that at runtime, both req_A and req_B must be filled using functions from the same version of the same backend.

Further rules are given by the BACKEND_OPTION declarations. The first of these indicates that be_name1 is a valid backend from which to fill one or both of req_A and req_B. The second BACKEND_OPTION declaration indicates that req_B and req_C may each be filled from versions 1.2, 1.3 or 1.5 only of be_name2. Version numbers here are both optional and variadic. Failure to list any version is taken to imply that any version of the backend is permitted. Presently there is no mechanism for indicating that only specific ranges of version numbers are permitted, short of listing each one explicitly. Version numbers can actually be specified in the same way when ACTIVATE_FOR_BACKEND is specified within a CONDITIONAL_DEPENDENCY declaration.

When model_\alpha or model_\beta is being scanned, the rules in this particular snippet have the effect of forcing req_A to be filled from some version of be_name1 (due to the first BACKEND_OPTION declaration), which in turn forces req_B to be filled from the same version of be_name1 (due to the FORCE_SAME_BACKEND directive). If other models are scanned, req_A and req_B are simply ignored, and go unfilled. Req_C is forced to be filled from either version 1.2, 1.3 or 1.5 of be_name2, regardless of which models are scanned.

As with other GAMBIT rollcall header commands, the lists of models and tags in all backend requirement declarations are variadic. In this case there is practically no limit to the number of entries that a tag or model list may contain. Empty lists () are also permitted.

When a backend requirement has a rule imposed on it by one or more BACKEND_OPTION declarations, one of the stated options must be used. When none of the tags of a given backend requirement is mentioned in a BACKEND_OPTION command, any version of any backend is permitted as long as the capability and type match. Simply omitting BACKEND_OPTION altogether means that any matching function can be used, from any backend.

#### 3.1.4 Parallel module functions

GAMBIT can make effective use of OpenMP parallelistaion either at the backend level, or natively within its own module functions. The simplest way to use OpenMP at the module function level is to place OpenMP directives inside a single module function, keeping the OpenMP block(s) wholly contained within the module function. In this case no special declarations are needed at the level of the module’s rollcall header.

An alternative method is to have a single module function open and close an OpenMP block, and to call other module functions (indirectly) within that block, potentially very many times over for a single parameter combination. In this case we refer to the managing module function as a D and the functions it calls nested module functions. Loop managers are declared using the CAN_MANAGE_LOOPS switch

START_FUNCTION(@\metavar{type}@, CAN_MANAGE_LOOPS)

Unlike regular module functions, loop managers may have type = void. Nested functions need to declare the capability of the loop manager that they require with

NEEDS_MANAGER_WITH_CAPABILITY(@\metavar{management\_cap}@)

This declaration endows the function with a special dependency on management_cap that can only be fulfilled by a function that has been declared as a loop manager. The result type of the loop manager is ignored, i.e. loop managers of any return type are equally valid sources of this dependency.

This arrangement allows GAMBIT’s D to dynamically string together various nested module functions and instruct loop managers to run them in parallel. At runtime, nested functions are arranged into their own mini dependency trees, and pointers to ordered lists of them are handed out to the designated loop managers.

Other functions can depend on nested functions in the regular way. In this case they receive the final result of the function, the last time it is called by its loop manager for a given parameter combination. Loop managers are assigned hidden dependencies at runtime by the dependency resolver, on all quantities on which their designated nested functions depend. This ensures that a loop is not invoked until the dependencies of all functions in the loop have been satisfied.

The GAMBIT Core does not invoke any nested functions itself; this is the express responsibility of loop managers. The only exception to this rule occurs when for whatever reason a nested function’s loop manager executes zero iterations of the loop it manages, but some other module function outside the loop depends on one of the nested functions that never ran; in this case the nested function is run the first time the dependent function tries to retrieve its value (as are any other nested functions that the first nested function depends on).

#### 3.1.5 One-line module function declaration

It is also possible to declare a module function with its allowed models and even dependencies, in a single line:

QUICK_FUNCTION( @\metavar{module\_name}@,
@\metavar{example\_capability}@,
@\metavar{capability\_vintage}@,
@\metavar{function\_name}@,
@\metavar{function\_type}@,
(@\metavar{model\_$\alpha$}@, @\metavar{model\_$\beta$}@, …),
(@\metavar{dep\_cap1}@, @\metavar{dep\_type1}@),
(@\metavar{dep\_cap2}@, @\metavar{dep\_type2}@),
)

Here one gives the module name explicitly, meaning that the declaration can even be used after MODULE has been #undef-ed. The argument capability_vintage tells GAMBIT whether or not example_capability has been declared previously; this can be set to either NEW_CAPABILITY or OLD_CAPABILITY. As usual, the variadic allowed model list (model_\alpha, model_\beta, …) can take up to 10 entries. This can be followed by up to 10 dependencies, given as capability-type pairs. The model list and dependency entries are optional arguments; specifying dependencies but leaving the allowed models free requires giving () for the allowed model list.

### 3.2 Pipes

Module functions must be entirely self-contained for GAMBIT to safely place them in a dependency tree. They must not call each other directly, nor call functions from specific backends directly. They should also strongly avoid setting or reading any global variables, especially those where the order of read or write operations might matter at all. The only safe way for code inside module functions to communicate with the outside world is via the function’s own personal set of pipes.

At runtime, GAMBIT’s D (Sec. 7) connects each pipe to the relevant data stream that a module function is permitted to interact with. This might be the result of a module function deemed appropriate for fulfilling a dependency, a backend function fitting a backend requirement, or some other more specific utility.

Pipes are safe pointers, automatically declared when module functions themselves are declared. They and the data they point to can be set by the dependency resolver, but not by code inside module functions (except for the special case of data pointed to by a backend variable requirement pipe). They reside in the namespace Pipes::function_name.

Here we give a complete list of all the pipes that can be available to a module function, along with information on their usage and the circumstances under which they should be expected to exist.

#### 3.2.1 Accessing dependencies

A dependency on a capability of dep_type can be accessed at runtime through the safe pointer

Pipes::@\metavar{function\_name}@::Dep::@\metavar{capability}@

by simply dereferencing it, or calling some_member_function of class dep_type

using namespace Pipes::@\metavar{function\_name}@;
@\metavar{dep\_type}@ my_variable = *Dep::@\metavar{capability}@;
Dep::@\metavar{capability}@->@\metavar{some\_member\_function}@();

e.g. if the function decay_width had a double-precision dependency on mass, one would simply type

double m = *Pipes::decay_width::Dep::mass;

The actual host module, name, capability and type of the function providing a dependency can be ascertained from its pipe, e.g.

using namespace Pipes::decay_width;
std::string m_module    = Dep::mass->origin();
std::string m_function  = Dep::mass->name();
std::string m_capability= Dep::mass->capability();
std::string m_type      = Dep::mass->type();

#### 3.2.2 Accessing backend requirements

Backend requirements can be used or retrieved by way of the safe pointer

Pipes::@\metavar{function\_name}@::BEreq::@\metavar{requirement}@

Take the example of a double-precision backend variable with capability my_var_req, declared in function my_func with

BACKEND_REQUIREMENT(my_var_req, (), double)

This variable is accessed directly as

using namespace Pipes::my_func;
double y = 2.5 + *BEreq::my_var_req;
*BEreq::my_var_req = y*y;

In the case of a backend function, e.g. declared as

BACKEND_REQUIREMENT(my_fn_req1, (), double,
(double))

one can call the corresponding backend function by writing

using namespace Pipes::my_func;
double f_of_pi = BEreq::my_fn_req1(3.14159);

If necessary, the actual underlying function or variable pointer can be retrieved from a backend requirement pipe, by calling its pointer() method. This can be useful if a module or backend function requires a pointer to some function in order to perform its duties, as in the following example from DarkBit::nuyield_from_DS

// Hand back the pointer to the DarkSUSY
// neutrino yield function
result.pointer = BEreq::nuyield.pointer();

There is an important final subtlety to note here: because the arguments are forwarded through a number of different layers of indirection, in order to support the direct use of literals in calls to backend functions it is necessary to indicate explicitly if any non-literal parameters must be passed by value. The way to do this is to wrap such arguments in the helper function byVal(). For example, take a backend requirement of a function my_func declared as

BACKEND_REQUIREMENT(my_fn_req2, (), double,
(double, double&))

This can be safely called as

using namespace Pipes::my_func;
double x = 2.0;
double y = BEreq::my_fn_req2(3.0, x);

or

using namespace Pipes::my_func;
double x = 2.0;
double y = BEreq::my_fn_req2(byVal(x), x);

but will fail to compile if

using namespace Pipes::my_func;
double x = 2.0;
double y = BEreq::my_fn_req2(x, x);

is attempted. The backend requirement system in GAMBIT is entirely typesafe, so if the code compiles one can at least be confident that the types in calls to backend functions correctly match their declarations.

As with dependencies, the name, capability and type of the backend function fulfilling a backend requirement can be extracted from its pipe, along with the host backend and its version, e.g.

using namespace Pipes::my_func;
std::string r3_function    = BEreq::r3->name();
std::string r3_capability  =
BEreq::r3->capability();
std::string r3_type        = BEreq::r3->type();
std::string r3_backend     = BEreq::r3->origin();
std::string r3_bkend_versn = BEreq::r3->version();

#### 3.2.3 Accessing model parameters

Model parameters are only provided to module functions that have been explicitly declared as model-dependent, and then only for the models actually being used in a particular scan. A module function is model dependent if it features an ALLOWED_MODELS or ALLOW_MODEL_DEPENDENCE declaration, a model-conditional dependency, or a backend requirement activation rule that is conditional on some model. Once again, this is to enforce modularity; functions that claim to be model-independent through their (lack of) model declarations must operate only on dependencies and backend requirements, i.e. without using the values of the scanned parameters.

For module functions that are permitted access to the parameter values, all parameters of all models are delivered in a simple map of parameter names to their values. For such a function function_name, the value of a parameter parameter_name can then be retrieved with

double p = Pipes::@\metavar{function\_name}@::Param["@\metavar{parameter\_}@
@\metavar{name}@"];

Whether or not the Param map contains a given parameter depends on whether or not its model is actually being scanned. This can be checked with the funtion

bool Pipes::@\metavar{function\_name}@::ModelInUse(str);

which takes as input a string containing the model in question (str is just a typedef of std::string). Note that the models in use in different functions may not always be what one expects — the nature of the GAMBIT model hierarchy is such that if a module function declares that it can work with a model that is an ancestor of the actual model being scanned, the function will be permitted to run but will receive each parameter point delivered in terms of the parameters of the ancestor model, rather than directly in the parameters of the model actually being scanned.666Note that if a module function is explicitly declared to work with multiple ancestors of the model being scanned, then only the parameters of the least-distant ancestor will be delivered. These rules also apply for activation of model-dependent depedencies and backend requirements (cf. Secs. 3.1.2 and 3.1.3). This is an important feature, as it allows module functions to be re-used unaltered with models that may not have even been invented when the original module function was written.

Although it is possible to scan two models containing a parameter with a common name, it is not possible to retrieve both parameters from the Param map in the same module function. By default, GAMBIT raises a runtime error if models with common parameters are declared as allowed (by ALLOWED_MODELS or ALLOW_MODEL_DEPENDENCE) in a single module function, and then activated together in a scan. More adventurous users may wish to deactivate this error and allow such parameter clashes in some very specific circumstances (see Sec. 6.3.1).

#### 3.2.4 Accessing options from the input file

GAMBIT features an extensive system for specifying run options for module functions, discussed in detail in Sec. 6. Module functions access these options via a dedicated pipe, which connects to a miniature YAML structure generated by the dependency resolver from all the entries in the original input YAML file that actually apply to the module function in question.

The pipe is runOptions. It can be queried for the presence of a given option "my_option"

using namespace Pipes::@\metavar{function\_name}@;
{
// Do something exciting
}

or used to retrieve the value as a variable of type opt_type, either directly

using namespace Pipes::@\metavar{function\_name}@;
@\metavar{opt\_type}@ x = runOptions->getValue<@\metavar{opt\_type}@>
("my_option");

or with a default value default

using namespace Pipes::@\metavar{function\_name}@;
@\metavar{opt\_type}@ x = runOptions->getValueOrDef<@\metavar{opt\_type}@>
(@\metavar{default}@, "my_option");

#### 3.2.5 Managing parallel module functions

Running OpenMP loops containing GAMBIT module functions takes a little care, but it is ultimately one of the most efficient ways to speed up computationally challenging likelihood calculations.

A loop manager lpman is responsible for opening and closing the multi-threaded OpenMP block. Inside the block, it needs to use the void function

Pipes::@\metavar{lpman}@::Loop::executeIteration(long long)

to execute a single call to the chain of nested functions that it manages. Here the integer argument of the function is the iteration number, which is passed directly on to each nested function running inside the loop. A nested function nested_fn can access the iteration using the pipe iteration as

long long it = *Pipes::@\metavar{nested\_fn}@::Loop::iteration;

Internally, GAMBIT holds the results of each module function in memory, for efficiently handing over results as dependencies and so on. For nested functions, it holds the results in an array of size equal to the number of threads. Serial module functions access the first element of this array when retrieving dependencies, whereas nested module functions run by the same loop manager access the element corresponding to the thread number. This is what allows the nested module functions to run safely in parallel, in arbitrary dependency trees arranged by the dependency resolver at runtime.

A consequence of this setup is that any serial module function that depends on a nested module function will only read the result obtained in the last iteration of the first thread (i.e. of index 0). For this reason, it is generally advisable to run the final iteration of a GAMBIT OpenMP loop in serial, so as to properly sync the results for use further ‘downstream’. Likewise, it is desirable to run the first iteration in serial as well, to allow any nested module functions to initialise any local static variables and other data elements that they might share across threads. With this consideration in mind, a minimal example of an OpenMP loop implemented in a loop manager is

using namespace Pipes::@\metavar{lpman}@;
Loop::executeIteration(0);
#pragma omp for
for (int i = 1; i < 9; i++)
{
Loop::executeIteration(i);
}
Loop::executeIteration(9);

In this example, the first iteration of ten is run serially, the next 8 are done in parallel using however many threads are available, and the tenth and final iteration is again done serially.

The above example assumes that the number of required iterations is known at compile time. If this is not the case, one may call the void function pipe wrapup() from within a nested function, in order to signal to the loop manager that the loop can be terminated. When one of the nested module functions in one of the threads calls wrapup(), the boolean pipe

Pipes::@\metavar{lpman}@::Loop::done

in the function managing the loop is set to true, allowing it to cut the loop short. This allows constructions like

using namespace Pipes::@\metavar{lpman}@;
long long it = 0;
Loop::executeIteration(it);
#pragma omp parallel
{
#pragma omp atomic
it++;
while(not *Loop::done)
{
Loop::executeIteration(it);
}
}
Loop::executeIteration(it++);

to be used in loop managers. Note that using this pattern requires that it be safe for a few more iterations of the loop to be performed after the done flag has been raised, because calling wrapup() in one thread will not affect other threads until they at least complete their own iterations and return to re-evaluate the while condition. The final serial iteration should generally also still be run as well, after the loop has terminated.

The done flag is automatically reset to false in all nested functions for each new parameter point. If for whatever reason it needs to be reset manually during a calculation, this can be achieved with the void function pipe

Pipes::@\metavar{lpman}@::Loop::reset()

which is available in all loop managers.

## 4 Backends

GAMBIT interfaces with backends by using them as runtime plug-ins. Backends are compiled into shared libraries, which GAMBIT then dynamically loads with the POSIX-standard dl library. This approach allows for direct access to the functions of the backend library and efficient data communication via memory, while at the same time keeping the build process of GAMBIT separate from of that of the particular backends used.

The locations of backend shared libraries can be specified in a YAML file config/backend_locations.yaml, with entries of the form

@\metavar{backend\_name}@:
@\metavar{backend\_version}@:  @\metavar{path\_to\_shared\_library}@

Library paths can either be given as absolute paths, or relative to the main GAMBIT directory. If backend_locations.yaml does not exist, or if it is missing an entry for a given backend, GAMBIT will instead look for a path in the file config/backend_locations.yaml.default, which contains default library paths for all backends that GAMBIT has interfaces to.

Similar to module functions, functions in backend libraries are tagged with a D describing what they can calculate. The capability tags are used by GAMBIT to match backend functions to the backend requirements declared by module functions. The layer of abstraction introduced by these tags allows appropriately designed module functions to use different backends interchangeably, given that they calculate the same quantity.

GAMBIT can currently communicate with backends written in C, C++ and Fortran. However, we must pay some attention to the differences between these languages. In particular, using a Fortran backend requires translating between standard Fortran and C-family types, and using a C++ backend typically involves loading entirely new types from the C++ library. We return to these topics in Secs. 4.4 and 4.5.

The interface to a backend library is declared in a frontend header file, located in

Backends/include/gambit/Backends/frontends

and named after the backend. Thus, a backend called MyBackend would be traditionally interfaced with GAMBIT via a frontend header MyBackend.hpp. To differentiate multiple versions of the same backend, the version number can be appended to the header name, e.g. MyBackend\_1\_2.hpp for version 1.2 of MyBackend. Applications such as this, where the periods in the version number are replaced with underscores, make use of what we refer to as the D of a backend, i.e. a representation of the version number that is safe to use when periods would be syntactically hazardous. A frontend header starts by defining the name, version and safe version of the backend, then immediately calls the LOAD_LIBRARY macro, which takes care of loading the backend shared library:

#define BACKENDNAME MyBackend
#define VERSION 1.2
#define SAFE_VERSION 1@\_@2

### 4.1 Backend function declaration

The main pieces of information required to interface a backend function to GAMBIT are its return type, call signature and library symbol. The name mangling schemes of g++/gfortran and icpc/ifort (the two main compiler suites that GAMBIT supports; cf. Appendix B) are mostly consistent, so a single symbol name can usually be entered here for both compilers.777The symbols of a shared library, with names prepended by an additional underscore, can be obtained using the nm command. Functions within Fortran modules are an exception to the consistency of name mangling. The best way to deal with these is often to use the C-interoperability features of Fortran to explicitly choose a symbol name, taking the choice out of the hands of the compiler. An example of this can be seen in DDCalc DarkBit (). In future, GAMBIT will automatically determine the appropriate name mangling itself, according to the scheme of the selected compiler. In addition, the function must be assigned a name and a capability. This is all specified via the BE_FUNCTION macro. For instance, a C/C++ backend function with the declaration

double getMatrixElement(int, int);

could be registered in the frontend header as

BE_FUNCTION(getMatrixElement, double, (int, int),
"_Z13getMatrixElementii",
"rotation_matrix_element")

where "_Z13getMatrixElementii" is the library symbol and "rotation_matrix_element" is the capability we assign to this function.

The macro BE_VARIABLE used to interface global variables in a backend library follows a similar syntax. If the backend contains a global variable

double epsilon;

controlling the tolerance of some calculation, it can be registered as

BE_VARIABLE(epsilon, double, "_epsilon",
"tolerance")

with "_epsilon" the library symbol and "tolerance" the capability assigned to the variable.

Backend functions and variables can be declared as either model-independent or valid for use only with certain models, just like module functions can. The default is to treat everything as model-independent. To declare an alternative default that applies to an entire backend, one places

BE_ALLOW_MODELS(@\metavar{model\_$\alpha$}@, @\metavar{model\_$\beta$}@, …)

directly after LOAD_LIBRARY. This has the effect of allowing the entire backend to be used only if one or more of the listed models is involved in a scan. This default can be further overridden at the level of individual backend variables and backend functions, by adding additional model arguments to their declarations:

BE_FUNCTION(getMatrixElement, double, (int,int),
"_Z13getMatrixElementii",
"rotation_matrix_element",
(@\metavar{model\_$\alpha$}@, @\metavar{model\_$\beta$}@, …) )
BE_VARIABLE(epsilon, double,
"_epsilon",
"tolerance",
(@\metavar{model\_$\alpha$}@, @\metavar{model\_$\beta$}@, …) )

### 4.2 Convenience functions

If several backend function calls or variable manipulations are commonly performed together, it may be useful to combine these into a single backend convenience function. Althought technically defined inside GAMBIT, this function will appear to the rest of GAMBIT as if it were simply another function in the backend library. Convenience functions are registered in the frontend header with the BE_CONV_FUNCTION macro. The syntax is identical to that of BE_FUNCTION except that there is no need to specify a library symbol, as the convenience function is not actually part of the backend library.

BE_CONV_FUNCTION(getMatrix, Matrix<double,2,2>,
(), "full_rotation_matrix")

The definition of the convenience function can then either be given directly in the frontend header, or in a separate source file named after the backend, e.g., MyBackend.cpp, and placed in the directory

Backends/src/frontends

In either case, the function definition must be placed inside a designated namespace Gambit::Backends::backend_name_safe_version, automatically generated with the BE_NAMESPACE and END_BE_NAMESPACE macros.

BE_NAMESPACE
{
Matrix<double,2,2> getMatrix()
{
// Call getMatrixElement four times
// and return a complete matrix.
}
}
END_BE_NAMESPACE

All backend functions and variables registered with the
BE_FUNCTION and BE_VARIABLE macros (in the same frontend) can be accessed directly in convenience functions, as long as the body of the convenience function appears after their declarations. This also applies to calling convenience functions from each other.

Just like backend variables and regular backend functions, backend convenience functions can be declared as model-dependent, e.g.

BE_CONV_FUNCTION(getMatrix, Matrix<double,2,2>,
(), "full_rotation_matrix", (@\metavar{model\_$\alpha$}@,
@\metavar{model\_$\beta$}@, …) )

### 4.3 Backend initialisation functions

A backend library will usually have to be initialised in some way before any calculations can be performed. For instance, variables storing masses and couplings may have to be reset for every new parameter point. For this purpose, the user can define a backend initialisation function. This is a special kind of convenience function that automatically runs prior to any other backend operations. An initialisation function is registered by enclosing it within BE_INI_FUNCTION and END_BE_INI_FUNCTION. These macros automatically set up a void function taking no input arguments, so the user only has to supply the function body. As for backend convenience functions, this function definition can be placed either in the frontend header file or in the corresponding source file.

BE_INI_FUNCTION
{
// Point-level initialisation.
}
END_BE_INI_FUNCTION

If some part of the initialisation only has to happen once for an entire scan, this can be accomplished by using a static flag:

BE_INI_FUNCTION
{
static bool scan_level = true;
if(scan_level)
{
// Scan-level initialisation.
}
scan_level = false;
// Point-level initialisation.
}
END_BE_INI_FUNCTION

As with convenience functions, all registered backend functions and variables from the same backend are directly accessible from within the body of initialisation functions, so long as the body appears after the functions and variables have been declared.

To help with scan-level initialisation, GAMBIT provides a flag for every registered backend function, variable and convenience function, indicating whether or not it will be used in the upcoming scan. These flags are accessible only from a backend’s initialisation function. The flags consist of pointers to boolean variables placed in the InUse namespace, i.e.

bool *InUse::@\metavar{name}@

where name is the name of the backend function, variable or convenience function as declared in the frontend header. Some example usage of the backend function InUse flags can be found in the fronted source files for nulike IC79_SUSY (); IC22Methods () and DDCalc DarkBit ().

Some backends write temporary files to disk during scan-level initialisation, which means that they cannot be safely initialised simultaneously in different MPI processes.888This is also to be discouraged on basic efficiency grounds. For such cases we provide a simple locking utility (Utils::FileLock) that can be employed to force serial execution of any block of code; example usage can be seen in the frontends to HiggsBounds and HiggsSignals Bechtle:2008jh (); Bechtle:2011sb (); Bechtle:2013wla ().

In fact, backend initialisation functions are actually promoted to module function status, and associated with a special GAMBIT-internal module called BackendIniBit. This is how GAMBIT ensures that they always run before any other functions from their backend are used. This also allows backend initialisation functions to depend on input from other GAMBIT module functions. This is declared using the BE_INI_DEPENDENCY and BE_INI_CONDITIONAL_DEPENDENCY macros. These follow exactly the same syntax as the DEPENDENCY and MODEL_CONDITIONAL_DEPENDENCY macros for module functions (Sec. 3.1.2):

BE_INI_DEPENDENCY(@\metavar{capability}@, @\metavar{type}@)
BE_INI_CONDITIONAL_DEPENDENCY(@\metavar{capability}@, @\metavar{type}@, @\metavar{model\_$\alpha$}@, @\metavar{model\_$\beta$}@, …)

Thus, a backend initialisation function that needs to know the particle spectrum for the given parameter point could declare a dependency similar to

BE_INI_DEPENDENCY(particle_spectrum, Spectrum)

This will be fulfilled if some module function can provide the capability particle_spectrum of type Spectrum. The dependency can then be accessed from within the function body of the initialisation function,

const Spectrum& my_spec = *Dep::particle_spectrum;

This is similar to the way module functions access their dependencies (Sec. 3.2.1), except that for backend initialisation functions there is no need to specify the namespace Pipes::function_name.

### 4.4 Backend types

Backend functions and variables will often require types that are not known to GAMBIT, and which therefore need to be defined. For C and Fortran backends, these types are typically structs or typedefs involving only built-in C types. In this case the required definitions can be placed directly in a designated backend types header, named after the backend and placed in

Backends/include/gambit/Backends/backend_types

The types must live within the Gambit namespace, e.g.,

namespace Gambit
{
struct Triplet
{
double x, y, z;
};
}

but additional sub-namespaces can of course be used.

To ease the process of generating these type declarations and the BE_FUNCTION and BE_VARIABLE declarations that use them, GAMBIT ships with a simple utility for parsing Fortran backend code: CBGB, the Common Block harvester for GAMBIT Backends. CBGB automatically generates GAMBIT code that declares the necessary backend types, functions and variables, according to the list of functions and common blocks that a user chooses to interface with GAMBIT. CBGB is written in Python and can be found in Backends/scripts/CBGB.

CBGB takes a single configuration file as input. This file is written in Python syntax and must be placed in Backends/scripts/CBGB/configs. An annotated example detailing all options and variables can be found in

Backends/scripts/CBGB/configs/example.py.

The most important variables to set in the configuration file are the three lists input_files, load_functions and load_common_blocks. We illustrate their use with a simple example, assuming a Fortran backend FortranBE v1.1:

input_files =
["../../installed/FortranBE/1.1/src/main.f90"]

Here CBGB would parse the Fortran file main.f90 and generate the BE_FUNCTION declarations needed to load the functions/subroutines f1 and f2, as well as the type and BE_VARIABLE declarations required to load the common block cb. The file paths in input_files must either be absolute paths or relative to the Backends/scripts/CBGB directory. To ensure that the library symbol names used in BE_FUNCTION and BE_VARIABLE match those in the backend shared library, CBGB must also know which name mangling scheme to use. This is specified via the variable name_mangling, which can be set to either "gfortran", "ifort" or "g77".

Once the configuration file is ready, CBGB can be run by passing in this file as a command line argument, e.g.

python cbgb.py configs/FortranBE.py

The generated GAMBIT code is stored in the output files backend_types_code.hpp and frontend_code.hpp. In this example, the code in backend_types_code.hpp should be used in the backend types header Backends/include/ gambit/Backends/backend_types/FortranBE_1_1.hpp, while the code in frontend_code.hpp should go in the frontend header Backends/include/gambit/Backends/ frontends/FortranBE_1_1.hpp.

As GAMBIT itself is written in C++, interfacing with a Fortran backend requires translation between the Fortran types used in the backend and the corresponding C-family types. Therefore, GAMBIT provides several Fortran-equivalent types and typedefs for use in communicating with Fortran backends, with names indicating which Fortran type they correspond to:

Flogical
Flogical1
Finteger
Finteger2
Finteger4
Finteger8
Freal
Freal4
Freal8
Freal16
Fdouble
Fdoubleprecision
Fcomplex
Fcomplex8
Fcomplex16
Fdouble_complex
Flongdouble_complex
Fcharacter

These are the types that CBGB makes use of in the generated GAMBIT code. In cases where CBGB fails to correctly parse the Fortran code, the user must manually specify type, BE_VARIABLE and BE_FUNCTION declarations using the above Fortran-equivalent types.

There are important differences in how arrays are treated in Fortran compared to C/C++. First, the lower array index in Fortran is by default 1, in contrast to C/C++ arrays, which count from 0. More generally, Fortran allows the user to specify arbitrary index ranges, something that is not allowed in C/C++. In the case of multidimensional arrays, C/C++ arrays are stored in memory in row-major order, whereas Fortran arrays use column-major ordering, and the two types of arrays are therefore effectively transposed with respect to each other. To save the user from having to deal with these complexities, GAMBIT provides an Farray class for working with Fortran arrays. This class provides basic Fortran array semantics directly in C++ code. The class is templated on the array type and index ranges. Thus, a two-dimensional integer array with index ranges 1–3 and 1–4 can be declared as

Farray<Finteger,1,3,1,4> my_f_array;

We also provide a special Fstring class for working with Fortran strings. It takes the string length as a template argument

Fstring<4> my_f_string;

Similar to regular Fortran strings, any string longer than the specified length will be truncated, and shorter strings will be padded with trailing spaces.

More information about the GAMBIT Fortran compatibility types can be found in the in-code GAMBIT documentation (cf. Sec. 10.7), and in Utils/include/gambit/Utils/util_types.hpp.

Most physics tools written in C or Fortran are fundamentally just collections of functions and variables of standard types. In contrast, C++ tools typically define a number of new classes for the user to work with. Unfortunately, there exists no standard way of loading an arbitrary C++ class from a shared library at runtime. The dl library, itself written in C, only provides access to functions and global variables. This limitation can be overcome if the main application has a predefined class interface that classes in the shared library are forced to adhere to; this is the so-called ‘factory’ pattern. This is unproblematic as long as all plug-ins are developed after the main application, which is normally the case. In GAMBIT, however, we face the reverse problem of turning already existing C++ physics tools into plug-ins for GAMBIT. To solve this problem we have developed the Python-based Backend-On-a-Stick Script (BOSS), which we describe here.

Strategies for runtime loading of classes are essentially always based on the C++ concept of polymorphism. One constructs a class interface from a base class containing a set of virtual member functions. These are functions for which the signature is defined, but where the actual implementation is expected to be overridden by classes that inherit from the base class. The idea can be illustrated by considering a base class Polygon containing a virtual member function calculateArea. From this base class two derived classes Triangle and Rectangle can be defined. Both classes should contain a calculateArea member function, but their implementations of this function would differ.

In plug-in, i.e. factory-based, systems, the main application defines the base class, while the plug-ins provide the specialized classes deriving from the base class. The main application can then be designed with the assumption that any future class passed in from a plug-in will have the predefined set of member functions, whose implementations live in the shared library that is loaded at runtime. The shared library also contains factory functions, one for each class it provides. These are functions that return a pointer to a newly created instance of a plug-in class. When a new class instance is required, the main application calls the correct factory function and interprets the pointer it receives as pointing to an instance of the known base class.

The purpose of BOSS is to reverse-engineer such a plug-in system for every backend class that is to be used from GAMBIT. Starting from a class X defined in the backend library, BOSS must generate source code for a base class with matching pure virtual member functions, as well as code for factory functions corresponding to the constructors X(…). The generated base class is called Abstract\_X, as classes containing pure virtual member functions are generally referred to as abstract classes. The source code for Abstract\_X is added to both the backend source code and to GAMBIT. On the backend side, some additional source code is also inserted in the original class X, most importantly adding Abstract\_X to the inheritance list of X. If class X originally inherits from a parent class Y, the abstract classes generated by BOSS mirror this structure. The resulting ‘ladder pattern’ is illustrated in Fig. 3.

When the ladder structure is complete, the basic ingredients for a plug-in system are in place. However, from the user perspective there are several limitations and inconveniences inherrent in such a minimal system. For example, the factory functions must be called to create class instances, and class member variables cannot be accessed directly. To overcome such limitations, BOSS generates an additional layer in the form of an interface class, which mimics the user interface of the original class. It is this interface class that a user interacts with from within GAMBIT. The generated class is placed in a namespace constructed from the backend name and version, so if our example class X is part of MyBackend v1.2 the full name of the interface class will be MyBackend_1_2::X. However, from within a GAMBIT module function using this class, the shorter name X can be used.

Fundamentally, the interface class is just a wrapper for a pointer to the abstract class. Through a factory function, this pointer is initialised to point to an instance of the orginal class, thus establishing the connection between GAMBIT and the original class living in the backend library. In the example considered above, the class MyBackend_1_2::X would hold a pointer of type Abstract\_X, pointing to an instance of X. This system is illustrated in Fig. 4. Note that the source code for the interface class is also inserted into the backend library. This allows BOSS to generate wrapper functions for any global library functions where the original class appears in the declaration.

When a GAMBIT module function requires classes from a backend library, this must be specified in the function’s rollcall header entry by adding the macro

NEEDS_CLASSES_FROM(@\metavar{backend\_name}@, @\metavar{versions}@)

Here versions is an optional comma-separated list of permitted backend version numbers. If versions is left out or set to default, GAMBIT will use the default backend version specified in the header file Backends/include/ gambit/Backends/default_bossed_versions.hpp. Here a default version can be chosen by setting a precompiler variable Default\_backend_name to the desired safe version number, e.g.

#define Default_MyBackend 1@\_@2

BOSS itself is the stand-alone Python program

Backends/scripts/BOSS/boss.py

For parsing the backend library source code BOSS employs the open-source tool CastXML. The basic input to BOSS is a configuration file, written in Python, containing information about the backend library code that is to be ‘BOSSed’. The configuration file should be placed in the configs subdirectory of the main BOSS directory. Here we will briefly go through the most important parts of the configuration file. For a complete list of options and variables we refer the reader to the example

Backends/scripts/BOSS/configs/Example_1_234.py

First the name and version number that GAMBIT should associate with the BOSSed library is set via the two variables gambit_backend_name and gambit_backend_version.

gambit_backend_name    = "MyBackend"
gambit_backend_version = "1.2"

Then follows a set of path variables. All paths must be given either as absolute paths or relative to the main BOSS directory. Consider the following example:

input_files =
["../../installed/MyBackend/1.2/include/X.hpp"]
include_paths =
["../../installed/MyBackend/1.2/include"]
base_paths = ["../../installed/MyBackend/1.2"]

Here we assume that our example backend MyBackend 1.2 is located in

Backends/installed/MyBackend/1.2

The input_files variable is a list of the header files that contain the declarations for the classes and functions that are to be used from GAMBIT. Next, include_paths lists the paths where CastXML should search for any header files that are included from one of the input files. Finally, base_paths is a list of the base directories of the backend library. This is used by BOSS to differentiate between classes that are native to the backend and classes that are pulled in from external libraries.

BOSS generates a number of header and source files that must be included when the BOSSed backend is compiled into a shared library. The output paths for these files are set with the variables header_files_to and src_files_to, for instance

"../../installed/MyBackend/1.2/include"
src_files_to = "../../installed/MyBackend/1.2/src"

The next two variables, load_classes and load_functions, are lists containing the fully qualified names of the classes and functions to be loaded for use in GAMBIT. If we assume that in addition to the class X, MyBackend also contains a global function addX for adding two instances of X, we may have

Typically users will only need access to a subset of all the classes defined in the library, so only a subset of the available classes will be listed in load_classes. BOSS will then automatically limit the user interface of the BOSSed library to make sure that only functions and variables that make use of the loaded library classes and standard C++ types are accessible from GAMBIT. However, if the backend library includes some classes that are also independently included in GAMBIT, functions and variables relying on these classes should also be allowed as part of the BOSSed library interface. Such classes can be listed in the dictionary known_classes. Here the dictionary key is the class name and the corresponding value is the header file where the class is declared.

BOSS is run by passing in the configuration file as a command line argument. For instance, with a configuration file configs/MyBackend_1_2.py, the command is simply

python boss.py configs/MyBackend_1_2.py

When BOSS finishes, a short set of instructions on how to connect the BOSSed library with GAMBIT is printed to stdout. Several of the variables in the configuration file can also be set directly as command line arguments to BOSS. For a complete list of arguments with explanations, see the output of the command

python boss.py help

Although BOSS is able to provide runtime loading for most C++ classes and functions, there are some cases that the plug-in system generated by BOSS cannot handle yet. Most importantly, BOSS currently does not work with backend template classes, nor specialisations of C++ standard template library (STL) classes where the template parameter is a backend class. Further, the use of function pointers as function arguments or return types, and the use of C++11 features in function declarations, is only partially supported. When a limitation only affects a class member function or variable, BOSS will attempt to generate a limited class interface where the problematic element is excluded. Future versions of BOSS will improve on these limitations.

### 4.6 Backend information utility

Although most users will never have need to access it directly, we briefly point out here that a global backend information object exists in GAMBIT. It can be accessed by reference from any module function using the function Backends::backendInfo(). It provides a plethora of runtime information about which backends are presently connected, their versions, functions, classloading status and so on. The mostly likely use cases from within module functions for this object are to determine the folder in which a loaded backend resides:

std::string path_to_MyBackend_1_2 = Backends::
backendInfo().path_dir("MyBackend", "1.2");

or to get the default version of a BOSSed backend required by an unversioned NEEDS_CLASSES_FROM declaration:

std::string default_MyBackend = Backends::
backendInfo().default_version("MyBackend");

The full interface to this object can be found in Backends/include/gambit/Backends/backend_info.hpp.

## 5 Hierarchical model database

In GAMBIT, a D is defined to be a collection of named parameters. These parameters are intended to be sampled by some scanning algorithm, according to some chosen prior probability distribution.101010For frequentist sampling, the prior simply defines the distance measure on the parameter space to be used internally by the scanning algorithm when choosing new points. The physical meaning of these parameters is defined entirely by how they are interpreted by module functions. It is up to the writers of modules to ensure that parameters are used in a consistent manner. Consistent usage is facilitated by the GAMBIT model database that the D (Sec. 7) employs in order to automatically determine which module functions are compatible with which models. Module functions that are incompatible with the model(s) selected for scanning are disabled at runtime, and not considered during dependency resolution.

### 5.1 Model declaration

GAMBIT ships with a pre-defined selection of common models (Sec. 5.4). New models can be defined easily by adding an appropriate declaration in a new C++ header file located in the folder

Models/include/gambit/Models/models

When the GAMBIT build configuration is next re-run (see Sec. 11), the new model will be automatically detected and registered. The declarations of all the pre-defined models can also be found in this folder.

The syntax for declaring a simple two parameter model my_model with parameters my_par1 and my_par2 is:

#define MODEL @\metavar{my\_model}@
START_MODEL
DEFINEPARS(@\metavar{my\_par1}@, @\metavar{my\_par2}@)
#undef MODEL

The START_MODEL command creates a ModelParameters object for the given model, which will hold the values of the parameters chosen at runtime by ScannerBit, and communicate them to relevant module functions during a scan. The macro DEFINEPARS is variadic, and can take up to 64 parameters (or more, depending on the user’s version of Boost). If one prefers to break a long list of parameters into several pieces, this macro can be reused as many times as desired.

It is often the case that models will be subsets of a more general model, in the sense that a mapping from the general model to the more constrained model can be constructed. This hierarchical relationship between models is handled in GAMBIT by defining the general model to be a parent of the constrained model, with the constrained model being reciprocally defined as a child of that parent. The mapping from the child parameters to the parent parameters is encoded in a translation function, which GAMBIT will call automatically when needed. Each parent model may have multiple children, however, a child model has only one parent. The “family tree” of any given model is thus a directed rooted tree graph, with the root of the tree being the common ancestor of all other models in the graph. The complete model database consists of a disconnected set of such family trees, see Fig. 2. When assessing the compatibility of module function with the model(s) being scanned, the GAMBIT dependency resolver automatically treats all module functions that declare compatibility with a given model as also compatible with all descendents of that model.

To declare that a model has a parent model parent, and assign a function to_parent capable of performing the translation from the child to the parent parameter set, the model declaration can be expanded to the following:

#define PARENT @\metavar{parent}@
#define MODEL @\metavar{my\_model}@
START_MODEL
DEFINEPARS(@\metavar{my\_par1}@, @\metavar{my\_par2}@)
INTERPRET_AS_PARENT_FUNCTION(@\metavar{to\_parent}@)
#undef MODEL
#undef PARENT

If a model is declared to have a parent but no translation function, any attempt to use another function that depends on the translation will trigger a runtime error from the dependency resolver. Further details on declaring and defining translation functions can be found in Sec. 5.3. Note that we are only dealing with the abstract concept of translation functions between different model parameter spaces at this stage, not the actual physics of any translations in any given class of models. The actual translations between the models implemented in GAMBIT 1.0 are implied by the relations between parent and child models described in Sec. 5.4.

Putting these aspects together, complete model declarations can be very simple, as in the CMSSM:

// Must include models that are targets of
// translation functions
#include "gambit/Models/models/NUHM1.hpp"
#define MODEL CMSSM
#define PARENT NUHM1
START_MODEL
DEFINEPARS(M0,M12,A0,TanBeta,SignMu)
INTERPRET_AS_PARENT_FUNCTION(CMSSM_to_NUHM1)
// Translation functions defined in CMSSM.cpp
#undef PARENT
#undef MODEL

This declaration can be found in the model header Models/include/gambit/Models/models/CMSSM.hpp.

Directed cross-links between branches of a family tree, or even between trees, are also possible. Models related in this way are denoted as friend models, though the relationship is not automatically mutual. If a model my_model has a friend model friend, then a function to_friend must also exist that can translate the parameters of my_model into those of friend. To declare such a relationship, one inserts the following into the model declaration for my_model:

INTERPRET_AS_X_FUNCTION(@\metavar{friend}@, @\metavar{to\_friend}@)

With the addition of friend translations, the model hierarchy graph can become arbitrarily complicated. To avoid painful manual resolution of ambiguous translation pathways between models, it can be advisable to limit the number of friend links. Nevertheless, a large number of the possible ambiguities are automatically resolved by the default behaviour of the dependency resolver to prefer child-to-parent links over child-to-friend links. This behaviour can be disabled by switching the prefer\_model\_specific\_functions option in the KeyValues section of the initialisation file to false. Manual resolution of all translation pathway ambiguities will then be required. Alternatively, one can simply add a Rule that overrides the default in a specific case. See Sec. 6 for details.

In some cases the translation from child to parent model, or to a friend model, may require the result of a calculation from a module function. It is therefore possible to declare dependencies for translation functions, which are directly analogous to the dependencies declared by module functions.111111Internally, the translation functions actually are module functions, each belonging to a virtual module named after their source model.

In general, translation functions can depend on any other capability, which may be filled by functions from any module. The dependency resolution system ensures consistency of the requested and provided dependencies of all translation functions in such cases. For example, the translation functions might depend on some aspect of the particle spectrum, and may involve translation of parameters from one renormalisation scheme to another, from a UV-complete theory to an EFT, or from one renormalisation scale to another. In these examples, the dependencies would be most naturally resolved from SpecBit, if it possesses the relevant capability for the model in question; we refer readers to Ref. SDPBit () for details of the functionalities available from this module.

To declare a dependency on some capability with C++ type for a child-to-parent translation function, one adds the following to the model declaration for the child:

INTERPRET_AS_PARENT_DEPENDENCY(@\metavar{capability}@, @\metavar{type}@)

To declare such a dependency for a translate-to-friend function, one instead adds:

INTERPRET_AS_X_DEPENDENCY(@\metavar{friend}@, @\metavar{capability}@, @\metavar{type}@)

where friend is the name of the target friend model. These declarations must appear after the declaration of the corresponding translation function.

The full machinery for declaring dependencies with complicated conditions on groups of models and backend choices — which is available for standard module functions — is not available for the dependencies of model translation functions. If this machinery is required, one should write a module function that uses it and returns a result associated with a new capability, which can then be made accessible in a translation function using the above declarations. In the most extreme case, this module function may perform the complete parameter translation and then simply store the results in a temporary ModelParameters object, which can then be retrieved by the “true” translation function via the above mechanism and simply copied into the target model ModelParameters object (see Sec. 5.3).

### 5.2 Model capabilities

In some cases a parameter in a D may directly correspond to a physically meaningful quantity. This quantity may be available already, computed in an alternate way, as the D of some existing D. One may wish to have the alternative of simply using the value of the parameter to satisfy the dependencies of other module functions on this quantity, rather than the module function calculation. It can therefore be convenient to directly inform GAMBIT of this correspondence when declaring a model. To declare this kind of relationship between a parameter my_par and a capability capability, one adds the following to the declaration of the model containing my_par:

MAP_TO_CAPABILITY(@\metavar{my\_par}@, @\metavar{capability}@)

Of course the same could be achieved by manually creating a trivial module function that takes the model parameters as input, and then directly outputs one of them as its capability. Internally, MAP_TO_CAPABILITY causes GAMBIT to create a virtual module function of precisely this kind, but it is convenient to have this task performed automatically.

The module function so created has the same name as the parameter being mapped, and lives in the module corresponding to the model to which it belongs. Take the example of the top mass, a parameter of the demo_A model found (commented out) in Models/include/gambit/Models/models/demo.hpp:

MAP_TO_CAPABILITY(Mstop, Mstop_obs)

This declaration creates a new module function called Mstop, with capability Mstop_obs and return type double, and places it within the module named after demo_A. The function demo_A::Mstop simply returns the value of the Mstop parameter as it varies during a scan of demo_A.

This convenience facility exists for the simplest case only. In the case where the correspondence is not direct — for example, if a factor of two or a change of units is required, or if a dependency on some other calculation exists — then manually adding an additional module function to do the transformation is the only option.

### 5.3 Defining translation functions

In Sec. 5.1 we discussed how to declare a translation pathway between two models; we now turn to how to define the functions that actually perform the translation. These may or may not involve calculations relating to the spectrum (as in the example the referee is thinking of). , so in this case, they would depend on functions from SpecBit. The full details of how those functions work is provided in the SpecBit, DecayBit and PrecisionBit paper (1705.07936). In particular, this includes translations between pole and running masses in different schemes and EFTs.

The function definition can either be placed directly into the header file in which the source model is declared, or into a separate source file that includes the header. In the former case, the function body must appear after the INTERPRET\_AS macro that declares it. In the latter case, the source file should be placed in

Models/src/models

to be properly auto-detected by the GAMBIT build system. Some extra headers providing additional helper macros should be included, and the names of the model and its parent redefined in order for the helpers to work properly. A basic template for such a file is:

#include "gambit/Models/model_macros.hpp"
#include "gambit/Models/model_helpers.hpp"
#include "gambit/Models/models/@\metavar{my\_model}@.hpp"
#define MODEL  @\metavar{my\_model}@
#define PARENT @\metavar{parent}@
// function definition
#undef PARENT
#undef MODEL

Consider the following example function definition:

void MODEL_NAMESPACE::@\metavar{to\_parent}@(const
ModelParameters& myparams, ModelParameters&
parentparams)
{
double x = myparams["@\metavar{my\_par}@"];
parentparams.setValue("@\metavar{parent\_par}@", 2*x);
}

Although this example is a child-to-parent translation function, the syntax is the same for child-to-friend functions. The translation function must return void, and take two arguments by reference: the source model parameters (which are const), and the target model parameters (of either the parent or friend model). The helper macro MODEL\_NAMESPACE places the function in the correct namespace (Gambit::Models::MODEL), and relies on MODEL having been defined appropriately. On the first line of the function body, a parameter my_par is retrieved from the ModelParameters object, which contains the parameters of the source model. The value of this parameter is stored in the variable x. This is then multiplied by two, and used to set the value of the target model parameter parent_par, completing the parameter translation.

This example assumes that the target model has only one parameter, parent_par. Often a source and target model will have many overlapping parameters, and it is convenient to have a mechanism for copying all of these automatically, without modification. This can be done using the setValues member function of the target ModelParameters object:

parentparams.setValues(myparams, true);

The second parameter is optional, and true by default. This triggers an error if any of the parameters in myparams (from my_model) are missing from parentparams (from parent), i.e. if the source model parameter names are not a subset of the target model parameter names. Setting this false causes matching parameters to be copied but unmatched parameters to be ignored.

A real-world example that make use of setValues is the the CMSSM-to-NUHM1 translation function (which was declared in Sec. 5.1):

#define MODEL CMSSM
void MODEL_NAMESPACE::CMSSM_to_NUHM1
(const ModelParameters &myP,
ModelParameters &targetP)
{
logger()<<"Running interpret_as_parent "
<<"calculations for CMSSM –> NUHM1."
<<LogTags::info<<EOM;
// Send all parameter values upstream
// to matching parameters in parent.
targetP.setValues(myP);
// Set NUHM1 parameter @\cpppragma{$m_H$}@ equal to @\cpppragma{$m_0$}@.
targetP.setValue("mH", myP["M0"]);
}
#undef MODEL

This function can be found in Models/src/models/ CMSSM.cpp.

To retrieve dependencies on externally-calculated quantities, one uses regular module function syntax

USE_MODEL_PIPE(@\metavar{target}@)
const @\metavar{type}@* my_variable = *Dep::@\metavar{capability}@;

where the USE\_MODEL\_PIPE macro simply expands to a using statement that brings the pipes for the translation function into the current namespace, making the Dep::capability pointer easily accessible. The argument should be the name of the target (parent or friend) model, i.e. USE_MODEL_PIPE(friend) or USE_MODEL_PIPE(PARENT) (remembering that PARENT is a macro holding the actual parent model, defined in the model header).

### 5.4 Models defined in GAMBIT1.0.0

Here we list the models already defined in the first release of GAMBIT, along with their parameters. The relationships between these models can be seen in Fig. 2.

#### 5.4.1 Standard Model

The SM exists in two parts within GAMBIT. The Higgs mass must be specified separately from the rest of the SM parameters, as it is often contained within the definition of BSM theories featuring BSM Higgs sectors. For those theories that do not include their own Higgs sector, e.g. SingletDM, we therefore provide additional models containing the Higgs mass as a parameter: StandardModel_Higgs and StandardModel_Higgs_running. Typically, one of these models should be scanned over in tandem with the rest of the SM (StandardModel_SLHA2) and the BSM theory in question. To investigate just the SM itself, one should perform a simultaneous scan of StandardModel_SLHA2 and either StandardModel_Higgs or StandardModel_Higgs_running.

StandardModel_SLHA2:

CKM_A, CKM_etabar, CKM_lambda, CKM_rhobar, GF, alpha1, alpha2, alphaS, alphainv, delta13, mBmB, mCmC, mD, mE, mMu, mNu1, mNu2, mNu3, mS, mT, mTau, mU, mZ, theta12, theta13, theta23.
This model contains the SM parameters defined in the SMINPUTS, VCKMIN and UPMNSIN blocks of the second SUSY Les Houches Accord (SLHA2; Allanach:2008qq ()). This includes the Z pole mass, the Fermi (weak) coupling G_{\mathrm{F}}, the strong and electromagnetic couplings at scale m_{Z} in the \overline{MS} renormalisation scheme, pole masses for leptons, neutrinos and the top quark, running masses for other quarks in the \overline{MS} scheme (at scale m_{b} for b, m_{c} for c and 2 GeV for u,d and s), the CKM mixing matrix in Wolfenstein parameterisation, and the PMNS matrix, characterised by three mixing angles and three CP-violating phases. To convert the Wolfenstein parameters into V_{\rm CKM} entries internally, we use the 9th-order expansions of Ref. CKMFitter (). More detailed definitions of these parameters can be found in Appendix C.

StandardModel_Higgs_running:

QEWSB, mH.
This model provides a description of the SM Higgs sector in terms of m^{2}_{H}, the bare Higgs mass parameter in the SM Lagrangian at scale m_{Z}. The vacuum expectation value of the SM Higgs field at m_{Z} can be obtained from the StandardModel_SLHA2 as v_{0}=(\sqrt{2}G_{\mathrm{F}})^{-1/2}. This model is intended for use in situations where the Higgs potential is run to different scales, e.g. for calculating pole masses or investigating vacuum stability. It therefore also contains one additional parameter: Q_{\rm EWSB}, the scale at which the electroweak symmetry-breaking (EWSB) consistency condition that the Higgs potential possess a tree-level minimum is imposed. Although in principle physical properties should not depend on its value, typically one prefers to take Q_{\rm EWSB}\sim m_{t} in order to minimise errors from neglecting higher-order loops. It is common to vary this parameter by a factor of a few in order to try to quantify the uncertainty in resulting pole masses from missing loop terms.

StandardModel_Higgs:

mH.
Unlike the StandardModel_Higgs_running model, the tree-level Higgs mass m_{h} is taken as the free parameter of StandardModel_Higgs, but interpreted directly as the pole mass for most calculations. This generally removes the need to calculate it via renormalisation group running in any higher-energy theory. For simple calculations, this allows a cut-down GAMBIT Spectrum object to be produced, with no ability to run, and the Higgs ‘pole’ mass extracted from it by simply accessing the value of the tree-level parameter for the given point in parameter space. When observables are to be calculated that genuinely need to use running parameters, the model point is up-translated to a parameter point in the StandardModel_Higgs_running (the parent model), where m^{2}_{H} at scale m_{Z} is set equal to the square of the tree-level mass, and Q_{\rm EWSB} is set to m_{t}. This is useful for more detailed calculations involving module functions that explicitly require the running mass parameter of StandardModel_Higgs_running, and/or functions that need accurate pole masses calculated by including the Higgs sector in renormalisation calculations.

#### 5.4.2 Scalar singlet

The scalar singlet is the simplest possible model for DM, consisting of a single additional scalar field S uncharged under the gauge symmetries of the SM, and stabilised by a \mathbb{Z}_{2} symmetry. The additional renormalisable Lagrangian terms permitted by general symmetry arguments are

 \mathcal{L}_{\mathrm{SS}}=\frac{1}{2}\mu_{S}^{2}S^{2}+\frac{1}{2}\lambda_{h% \scriptscriptstyle S}S^{2}|H|^{2}+\frac{1}{4}\lambda_{\scriptscriptstyle S}S^{% 4}+\frac{1}{2}\partial_{\mu}S\partial^{\mu}S. (1)

From left to right, these are: the bare S mass, the dimension-4 Higgs-portal coupling, the S quartic self-coupling, and the kinetic term. The latter plays no role in phenomenology, leaving three free parameters of the theory: \mu_{S}^{2}, \lambda_{h\scriptscriptstyle S} and \lambda_{\scriptscriptstyle S}. After EWSB, the singlet mass receives an additional contribution from the Higgs-portal term, leading to a tree-level mass of

 m_{S}=\sqrt{\mu_{S}^{2}+\frac{1}{2}{\lambda_{h\scriptscriptstyle S}v_{0}^{2}}}. (2)

This model has been subjected to global fits in Refs. Cheung:2012xb (); Cuoco:2016jqt (); SSDM ().

SingletDM_running:

lambda_S, lambda_hS, mS.
This model has the \overline{MS} couplings \lambda_{h\scriptscriptstyle S} and \lambda_{\scriptscriptstyle S} at scale m_{Z} as free parameters, as well as the tree-level mass m_{S}, which is matched internally to the \overline{MS} value of \mu_{S} at scale m_{Z} using \lambda_{h\scriptscriptstyle S}(m_{Z}) and Eq. 2. This allows full calculation of pole masses, renormalisation group running and vacuum stability.

SingletDM:

lambda_hS, mS.
The relationship between SingletDM and SingletDM_running is analogous to the one between StandardModel_Higgs and StandardModel_Higgs_running. SingletDM has m_{S} as a free parameter, leading to two use cases. The first is to interpret the model parameter directly as the pole mass for S and do phenomenology without any spectrum calculation; the second is to take the parameter m_{S} as the tree-level estimate of the mass, use Eq. 2 to recover \mu_{S}^{2} matched to the tree-level mass at scale m_{Z}, and calculate the pole mass accordingly in the parent model SingletDM_running. One chooses between these two options by selecting which function from SpecBit to obtain a Spectrum object from. SingletDM includes the Higgs-portal coupling \lambda_{h\scriptscriptstyle S} identically to the parent model, which we also set the running coupling at m_{Z} to when translating a SingletDM model point to a SingletDM_running point. It however does not include any description of the quartic coupling. This is because the S self-coupling term only plays a role in observables via RGE running, such as in the calculation of pole masses and analysis of Higgs vacuum stability. When translating to the parent model, we therefore explicitly choose the quartic coupling to be absent at scale m_{Z} (even though it will be regenerated at other scales under RGE flow):

 \displaystyle\lambda_{\scriptscriptstyle S}(m_{Z})=0. (3)

#### 5.4.3 Weak-scale MSSM

These models feature MSSM soft SUSY-breaking Lagrangian parameters defined at a chosen scale Q, typically set to something near the weak scale.

The MSSM is the version of SUSY containing the least additional field content beyond the SM. Its Lagrangian (see e.g. BaerTata ())

 \mathcal{L}_{\mathrm{MSSM}}=\mathcal{L}_{\textrm{SUSY-SM}}+\mathcal{L}_{% \mathrm{soft}}, (4)

is obtained by supersymmetrising the (pre-EWSB) SM Lagrangian to find \mathcal{L}_{\textrm{SUSY-SM}}, and augmenting it with all possible renormalisable soft SUSY-breaking terms that conserve both baryon (B) and lepton number (L). These soft terms are

 \displaystyle\mathcal{L}_{\mathrm{soft}}= \displaystyle-\frac{1}{2}\left[M_{1}\bar{\tilde{B}}^{0}\tilde{B}^{0}+M_{2}\bar% {\tilde{W}}_{A}\tilde{W}_{A}+M_{3}\bar{\tilde{g}}_{B}\tilde{g}_{B}\right] (5a) \displaystyle-\frac{i}{2}\left[M_{1}^{\prime}\bar{\tilde{B}}^{0}\gamma_{5}% \tilde{B}^{0}+M_{2}^{\prime}\bar{\tilde{W}}_{A}\gamma_{5}\tilde{W}_{A}+M_{3}^{% \prime}\bar{\tilde{g}}_{B}\gamma_{5}\tilde{g}_{B}\right] (5b) \displaystyle-\epsilon_{ab}\Big{[}b{H}^{a}_{u}{H}^{b}_{d}+\mathrm{h.c.}\Big{]}% -m^{2}_{H_{u}}|H_{u}|^{2}-m^{2}_{H_{d}}|H_{d}|^{2} (5c) \displaystyle+\textstyle\sum_{i,j=1,3}\left\{-\left[\tilde{Q}_{i}^{\dagger}(% \mathbf{m}^{\mathbf{2}}_{Q})_{ij}\tilde{Q}_{j}+\tilde{d}_{\mathrm{R}i}^{% \dagger}(\mathbf{m}^{\mathbf{2}}_{d})_{ij}\tilde{d}_{\mathrm{R}j}\right.\right. \displaystyle+\tilde{u}_{\mathrm{R}i}^{\dagger}(\mathbf{m}^{\mathbf{2}}_{u})_{% ij}\tilde{u}_{\mathrm{R}j}+\tilde{L}_{i}^{\dagger}(\mathbf{m}^{\mathbf{2}}_{L}% )_{ij}\tilde{L}_{j}+\tilde{e}_{\mathrm{R}i}^{\dagger}(\mathbf{m}^{\mathbf{2}}_% {e})_{ij}\tilde{e}_{\mathrm{R}j}\Big{]} (5d) \displaystyle-\epsilon_{ab}\left[(\mathbf{T}_{u})_{ij}\tilde{Q}^{a}_{i}H^{b}_{% u}\tilde{u}^{\dagger}_{\mathrm{R}j}-(\mathbf{T}_{d})_{ij}\tilde{Q}^{a}_{i}H^{b% }_{d}\tilde{d}^{\dagger}_{\mathrm{R}j}\right. \displaystyle         -\left.(\mathbf{T}_{e})_{ij}\tilde{L}^{a}_{i}H^{b}_{d}% \tilde{e}^{\dagger}_{\mathrm{R}j}+\mathrm{h.c.}\right] (5e) \displaystyle-\epsilon_{ab}\left[(\mathbf{C}_{u})_{ij}\tilde{Q}^{a}_{i}H^{*b}_% {d}\tilde{u}^{\dagger}_{\mathrm{R}j}-(\mathbf{C}_{d})_{ij}\tilde{Q}^{a}_{i}H^{% *b}_{u}\tilde{d}^{\dagger}_{\mathrm{R}j}\right. \displaystyle         -\left.\left.(\mathbf{C}_{e})_{ij}\tilde{L}^{a}_{i}H^{*b% }_{u}\tilde{e}^{\dagger}_{\mathrm{R}j}+\mathrm{h.c.}\right]\right\}. (5f)

Here we explicitly sum over the generation indices i and j, and imply summation over the gauge generator indices A=1\,..\,3 and B=1\,..\,8, as well as the SU(2)_{\mathrm{L}} indices a,b=1,2. Here \epsilon_{ab} is the two-dimensional completely antisymmetric tensor, defined such that \epsilon_{12}=-\epsilon_{21}=1. Superparticle fields are denoted by tilded operators (\tilde{Q}_{j}, \tilde{u}^{\dagger}_{\mathrm{R}j}, etc.), where \tilde{B}^{0}, \tilde{W}_{A} and \tilde{g}_{B} are the superpartners of the SM gauge bosons. Fields denoted with capital letters are SU(2)_{\mathrm{L}} doublets (Q_{i}\equiv(u_{\mathrm{L}i},d_{\mathrm{L}i})^{\mathrm{T}}, etc), whereas lowercase fields are SU(2)_{\mathrm{L}} singlets. The subscripts u and d refer to the two Higgs doublets, which give masses separately to up- and down-type quarks.

The first two terms in Eq. 5 (5a and 5b) are explicit gaugino masses associated with the real parameters M_{1},M_{2},M_{3} and M^{\prime}_{1},M^{\prime}_{2},M^{\prime}_{3}. The second set of these violates CP, so M^{\prime}_{1},M^{\prime}_{2} and M^{\prime}_{3} should be very small to agree with experiment. The Higgs sector (5c) includes explicit mass terms with real parameters m^{2}_{H_{u}} and m^{2}_{H_{d}}, as well as a bilinear coupling with complex parameter b. Explicit sfermion masses (5d) come from the five 3\times 3 Hermitian mass-squared matrices \mathbf{m}^{\mathbf{2}}_{Q}, \mathbf{m}^{\mathbf{2}}_{u}, \mathbf{m}^{\mathbf{2}}_{d}, \mathbf{m}^{\mathbf{2}}_{L} and \mathbf{m}^{\mathbf{2}}_{e}. The final two terms (5e and 5f) denote trilinear couplings between the Higgs and squarks or sleptons, with general Yukawa-type complex 3\times 3 matrices \mathbf{T}_{u},\mathbf{T}_{d},\mathbf{T}_{e} and \mathbf{C}_{u},\mathbf{C}_{d},\mathbf{C}_{e}. The \mathbf{C} terms are often omitted from the definition of the MSSM, as they end up strongly suppressed in many SUSY-breaking schemes. SUSY-breaking scenarios often imply universality relations between the Yukawa-scaled soft-breaking trilinear couplings \mathbf{A}_{u},\mathbf{A}_{d} and \mathbf{A}_{e}, which are defined as

where i and j run over all three generations, but summation is not implied.

\mathcal{L}_{\textrm{SUSY-SM}} contains derivatives of the superpotential

 \displaystyle\hat{W}= \displaystyle\epsilon_{ab}\left\{\textstyle\sum_{i,j=1,3}\left[(\mathbf{Y}_{u}% )_{ij}\hat{Q}^{a}_{i}\hat{H}^{b}_{u}\hat{U}^{c}_{j}-(\mathbf{Y}_{d})_{ij}\hat{% Q}^{a}_{i}\hat{H}^{b}_{d}\hat{D}^{c}_{j}\right.\right. (7) \displaystyle-\left.\left.(\mathbf{Y}_{e})_{ij}\hat{L}^{a}_{i}\hat{H}^{b}_{d}% \hat{E}^{c}_{j}\right]-\mu\hat{H}^{a}_{u}\hat{H}^{b}_{d}\right\}.

Here the indices i and j are again generation number, a and b are SU(2)_{\mathrm{L}} indices and \epsilon_{ab} is the two-dimensional antisymmetric tensor. Carets indicate superfields. The terms \hat{U}^{c}_{j}, \hat{D}^{c}_{j} and \hat{E}^{c}_{j} are the left chiral superfields containing the charge conjugates of the right-handed SU(2)_{\mathrm{L}} singlets: up-type (s)quarks, down-type (s)quarks and (s)electrons, respectively. Derivatives of \hat{W} with respect to its scalar fields give rise to all non-gauge interaction terms in \mathcal{L}_{\textrm{SUSY-SM}}. It plays a similar role to the non-gauge part of the scalar potential in non-supersymmetric theories, specifying the Higgs potential via the complex parameter \mu and the Higgs-fermion interactions and fermion masses via the complex 3\times 3 Yukawa coupling matrices \mathbf{Y}_{u}, \mathbf{Y}_{d} and \mathbf{Y}_{e}.

R parity is conserved in Eqs. 5 and 7 by construction, by virtue of B and L being conserved individually. This makes the lightest SUSY particle (LSP) absolutely stable; in general we impose the condition that this must be the lightest neutralino. Unless otherwise noted, we neglect the phenomenology of the gravitino, assuming it to be sufficiently heavy that it is not the LSP and its decays at early times are irrelevant.

MSSM63atQ:

Ad_11, Ad_12, Ad_13, Ad_21, Ad_22, Ad_23, Ad_31, Ad_32, Ad_33, Ae_11, Ae_12, Ae_13, Ae_21, Ae_22, Ae_23, Ae_31, Ae_32, Ae_33, Au_11, Au_12, Au_13, Au_21, Au_22, Au_23, Au_31, Au_32, Au_33, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, md2_11, md2_12, md2_13, md2_22, md2_23, md2_33, me2_11, me2_12, me2_13, me2_22, me2_23, me2_33, ml2_11, ml2_12, ml2_13, ml2_22, ml2_23, ml2_33, mq2_11, mq2_12, mq2_13, mq2_22, mq2_23, mq2_33, mu2_11, mu2_12, mu2_13, mu2_22, mu2_23, mu2_33.
This model contains 65 free parameters: the scale Q, the sign of the \mu parameter, and 63 parameters of the MSSM Lagrangian. Because of their usual irrelevance in (known) SUSY-breaking schemes, here we set the \mathbf{C} terms to zero. Apart from this omission, the MSSM63 is the most general formulation of the CP-conserving MSSM: here the CP-violating gaugino masses M^{\prime} and complex phases are all also explicitly set to zero. This leaves 3 free gaugino masses M_{1}, M_{2} and M_{3}, 6 real parameters each from the mass-squared matrices \mathbf{m}^{\mathbf{2}}_{Q}, \mathbf{m}^{\mathbf{2}}_{u}, \mathbf{m}^{\mathbf{2}}_{d}, \mathbf{m}^{\mathbf{2}}_{L} and \mathbf{m}^{\mathbf{2}}_{e} and a further 9 each from the trilinear couplings \mathbf{A}_{u},\mathbf{A}_{d} and \mathbf{A}_{e}. The final three parameters come from the Higgs sector, where we have m^{2}_{H_{u}} and m^{2}_{H_{d}}, and trade b and \mu for the sign of \mu and the ratio of the up-type to down-type Higgs vacuum expectation values \tan\beta\equiv v_{\mathrm{u}}/v_{\mathrm{d}}. All parameters are defined in the \overline{DR} scheme at the scale Q, except for \tan\beta, which is defined at m_{Z}.

Relative to the general MSSM, the additional constraints applied in this model are:

 \displaystyle M^{\prime}_{1}=M^{\prime}_{2}=M^{\prime}_{3}=0, (8) \displaystyle\mathbf{C}_{u}=\mathbf{C}_{d}=\mathbf{C}_{e}=\mathbf{0}, (9) \displaystyle\mathbf{m}^{\mathbf{2}}_{Q},\mathbf{m}^{\mathbf{2}}_{u},\mathbf{m% }^{\mathbf{2}}_{d},\mathbf{m}^{\mathbf{2}}_{L},\mathbf{m}^{\mathbf{2}}_{e},% \mathbf{A}_{u},\mathbf{A}_{d},\mathbf{A}_{e}\ \mathrm{all~{}real}. (10)
MSSM30atQ:

Ad_1, Ad_2, Ad_3, Ae_1, Ae_2, Ae_3, Au_1, Au_2, Au_3, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, md2_1, md2_2, md2_3, me2_1, me2_2, me2_3, ml2_1, ml2_2, ml2_3, mq2_1, mq2_2, mq2_3, mu2_1, mu2_2, mu2_3.
As per the MSSM63atQ, but with all off-diagonal elements in \mathbf{m}^{\mathbf{2}}_{Q}, \mathbf{m}^{\mathbf{2}}_{u}, \mathbf{m}^{\mathbf{2}}_{d}, \mathbf{m}^{\mathbf{2}}_{L}, \mathbf{m}^{\mathbf{2}}_{e}, \mathbf{A}_{u},\mathbf{A}_{d} and \mathbf{A}_{e} set to zero, in order to suppress flavour-changing neutral currents:

 \displaystyle\mathbf{m}^{\mathbf{2}}_{Q},\mathbf{m}^{\mathbf{2}}_{u},\mathbf{m% }^{\mathbf{2}}_{d},\mathbf{m}^{\mathbf{2}}_{L},\mathbf{m}^{\mathbf{2}}_{e},% \mathbf{A}_{u},\mathbf{A}_{d},\mathbf{A}_{e}\ \mathrm{diagonal}. (11)
MSSM25atQ:

Ad_3, Ae_12, Ae_3, Au_3, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, md2_1, md2_2, md2_3, me2_1, me2_2, me2_3, ml2_1, ml2_2, ml2_3, mq2_1, mq2_2, mq2_3, mu2_1, mu2_2, mu2_3.
This was the model investigated in Ref. Silverwood12 (). As per the MSSM30atQ, but with first and second-generation trilinear couplings degenerate in the slepton sector, and set to zero for squarks:

 \displaystyle(\mathbf{A}_{e})_{11}=(\mathbf{A}_{e})_{22}, (12) \displaystyle(\mathbf{A}_{u})_{11}=(\mathbf{A}_{u})_{22}=(\mathbf{A}_{d})_{11}% =(\mathbf{A}_{d})_{22}=0. (13)
MSSM24atQ:

Ad_3, Ae_3, Au_3, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, md2_1, md2_2, md2_3, me2_1, me2_2, me2_3, ml2_1, ml2_2, ml2_3, mq2_1, mq2_2, mq2_3, mu2_1, mu2_2, mu2_3.
As per the MSSM25atQ, but with first and second-generation trilinear couplings in the slepton sector also set to zero:

 \displaystyle(\mathbf{A}_{u})_{ii}=(\mathbf{A}_{d})_{ii}=(\mathbf{A}_{e})_{ii}% =0\hskip 5.690551pt\forall\ i\in\{1,2\}. (14)
MSSM20atQ:

Ad_3, Ae_12, Ae_3, Au_3, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, md2_12, md2_3, me2_12, me2_3, ml2_12, ml2_3, mq2_12, mq2_3, mu2_12, mu2_3.
As per the MSSM25atQ, but with degenerate first and second-generation sfermion mass parameters:

 \displaystyle(\mathbf{A}_{e})_{11}=(\mathbf{A}_{e})_{22}, (15) \displaystyle(\mathbf{A}_{u})_{11}=(\mathbf{A}_{u})_{22}=(\mathbf{A}_{d})_{11}% =(\mathbf{A}_{d})_{22}=0, (16) \displaystyle(\mathbf{m}^{\mathbf{2}}_{X})_{11}=(\mathbf{m}^{\mathbf{2}}_{X})_% {22}\hskip 5.690551pt\forall\ X\in\{Q,u,d,L,e\}. (17)
MSSM19atQ:

Ad_3, Ae_3, Au_3, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, md2_12, md2_3, me2_12, me2_3, ml2_12, ml2_3, mq2_12, mq2_3, mu2_12, mu2_3.
This is the model that is sometimes referred to as the “phenomenological” MSSM (pMSSM). It has been the focus of many non-statistical random parameter scans, e.g. Berger09 (); LATpMSSM (); Conley11 (); Arbey12 (); ATLAS15 (). As per the MSSM20atQ, but with first and second-generation trilinear couplings in the slepton sector also set to zero:

 \displaystyle(\mathbf{A}_{u})_{ii}=(\mathbf{A}_{d})_{ii}=(\mathbf{A}_{e})_{ii}% =0\hskip 5.690551pt\forall\ i\in\{1,2\}, (18) \displaystyle(\mathbf{m}^{\mathbf{2}}_{X})_{11}=(\mathbf{m}^{\mathbf{2}}_{X})_% {22}\hskip 5.690551pt\forall\ X\in\{Q,u,d,L,e\}. (19)
MSSM16atQ:

Ad_3, Ae_3, Au_3, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, md2_3, me2_3, ml2_12, ml2_3, mq2_12, mq2_3, mu2_3.
As per the MSSM19atQ, but with all first and second generation squark mass parameters degenerate, and all first and second generation slepton mass parameters degenerate:

 \displaystyle(\mathbf{m}^{\mathbf{2}}_{Q})_{ii}=(\mathbf{m}^{\mathbf{2}}_{u})_% {jj}=(\mathbf{m}^{\mathbf{2}}_{d})_{kk}\hskip 5.690551pt\forall\ i,j,k\in\{1,2\}, (20) \displaystyle(\mathbf{m}^{\mathbf{2}}_{L})_{ii}=(\mathbf{m}^{\mathbf{2}}_{e})_% {jj}\hskip 5.690551pt\forall\ i,j\in\{1,2\}. (21)
MSSM15atQ:

A0, At, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, md2_3, me2_3, ml2_12, ml2_3 mq2_12, mq2_3, mu2_3.
This is the model explored in Ref. Strege15 (), up to reparameterisation of the Higgs sector. As per the MSSM16atQ, but with down-type and sleptonic trilinear couplings degenerate:

 \displaystyle(\mathbf{A}_{d})_{33}=(\mathbf{A}_{e})_{33}. (22)
MSSM11atQ:

Ad_3, Ae_3, Au_3, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, ml2, mq2.
As per the MSSM16atQ/MSSM19atQ, but with universal squark (m_{\tilde{q}}^{2}) and slepton (m_{\tilde{l}}^{2}) mass parameters:

 \displaystyle(\mathbf{m}^{\mathbf{2}}_{X})_{ii}\equiv m_{\tilde{q}}^{2}\hskip 5% .690551pt\forall\ i\in\{1..3\},X\in\{Q,u,d\}, (23) \displaystyle(\mathbf{m}^{\mathbf{2}}_{Y})_{ii}\equiv m_{\tilde{l}}^{2}\hskip 5% .690551pt\forall\ i\in\{1..3\},Y\in\{L,e\}. (24)
MSSM10atQ:

Ad_3, Au_3, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, ml2, mq2.
As per the MSSM11atQ, but with no sleptonic trilinear coupings:

 \displaystyle(\mathbf{A}_{e})_{33}=0. (25)
MSSM10batQ:

Ad_3, Ae_3, Au_3, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, mf2.
As per the MSSM11atQ, but with a universal sfermion mass parameter m_{\tilde{f}}^{2}:

 \displaystyle m_{\tilde{q}}^{2}=m_{\tilde{l}}^{2}\equiv m_{\tilde{f}}^{2}. (26)
MSSM10catQ:

A0, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, ml2, mq2_12, mq2_3.
This is the model explored in Ref. MasterCodeMSSM10 (), up to reparameterisation of the Higgs sector. As per the MSSM15atQ, but with a universal trilinear coupling A_{0}, 3rd generation squark mass (m_{\tilde{q}3}^{2}) and slepton mass (m_{\tilde{l}}^{2}) parameters:

 \displaystyle(\mathbf{A}_{u})_{33}=(\mathbf{A}_{d})_{33}=(\mathbf{A}_{e})_{33}% \equiv A_{0}, (27) \displaystyle(\mathbf{m}^{\mathbf{2}}_{Q})_{33}=(\mathbf{m}^{\mathbf{2}}_{u})_% {33}=(\mathbf{m}^{\mathbf{2}}_{d})_{33}\equiv m_{\tilde{q}3}^{2}, (28) \displaystyle(\mathbf{m}^{\mathbf{2}}_{L})_{ii}=(\mathbf{m}^{\mathbf{2}}_{e})_% {jj}\equiv m_{\tilde{l}}^{2}\hskip 5.690551pt\forall\ i,j\in\{1..3\}. (29)
MSSM9atQ:

Ad_3, Au_3, M1, M2, M3, Qin, SignMu, TanBeta, mHd2, mHu2, mf2 As per the MSSM11atQ, but with both the approximations introduced in the MSSM10atQ and MSSM10batQ, i.e. universal sfermion masses and no sleptonic trilinear couplings:

 \displaystyle(\mathbf{A}_{e})_{33}=0, (30) \displaystyle m_{\tilde{q}}^{2}=m_{\tilde{l}}^{2}\equiv m_{\tilde{f}}^{2}. (31)
MSSM7atQ:

Ad_3, Au_3, M2, Qin, SignMu, TanBeta, mHd2, mHu2, mf2.
This model has been used extensively in DarkSUSY papers, e.g. BergstromGondolo96 (); darksusy (); BMSSM (). As per the MSSM9atQ, but assuming a Grand Unified Theory (GUT)-inspired relationship between the gaugino masses.

 \displaystyle\frac{3}{5}\cos^{2}\theta_{\mathrm{W}}M_{1}=\sin^{2}\theta_{% \mathrm{W}}M_{2}=\frac{\alpha}{\alpha_{\mathrm{s}}}M_{3}. (32)

When implementing this relationship, we use \sin^{2}\theta_{\mathrm{W}} at the Z pole mass scale, which we calculate directly from the StandardModel_SLHA2 parameters G_{\mathrm{F}}, m_{Z} (pole) and \alpha^{-1}_{\overline{\rm MS}}(m_{Z}).

#### 5.4.4 GUT-scale MSSM

These models feature MSSM soft SUSY-breaking Lagrangian parameters defined at the scale of gauge coupling unification, typically referred to as the GUT scale.

MSSM63atMGUT:

Ad_11, Ad_12, Ad_13, Ad_21, Ad_22, Ad_23, Ad_31, Ad_32, Ad_33, Ae_11, Ae_12, Ae_13, Ae_21, Ae_22, Ae_23, Ae_31, Ae_32, Ae_33, Au_11, Au_12, Au_13, Au_21, Au_22, Au_23, Au_31, Au_32, Au_33, M1, M2, M3, SignMu, TanBeta, mHd2, mHu2, md2_11, md2_12, md2_13, md2_22, md2_23, md2_33, me2_11, me2_12, me2_13, me2_22, me2_23, me2_33, ml2_11, ml2_12, ml2_13, ml2_22, ml2_23, ml2_33, mq2_11, mq2_12, mq2_13, mq2_22, mq2_23, mq2_33, mu2_11, mu2_12, mu2_13, mu2_22, mu2_23, mu2_33.
As per the MSSM63atQ, but with Q set to the GUT scale. Translation to MSSM63atQ requires having already solved the renormalisation group equations (RGEs) for the model, in order to determine the value of the GUT scale.

MSSM30atMGUT:

Ad_1, Ad_2, Ad_3, Ae_1, Ae_2, Ae_3, Au_1, Au_2, Au_3, M1, M2, M3, SignMu, TanBeta, mHd2, mHu2, md2_1, md2_2, md2_3, me2_1, me2_2, me2_3, ml2_1, ml2_2, ml2_3, mq2_1, mq2_2, mq2_3, mu2_1, mu2_2, mu2_3.
This is the MSSM30atQ with Q=M_{\mathrm{GUT}}; as per the MSSM63atMGUT, but with all off-diagonal elements in \mathbf{m}^{\mathbf{2}}_{Q}, \mathbf{m}^{\mathbf{2}}_{u}, \mathbf{m}^{\mathbf{2}}_{d}, \mathbf{m}^{\mathbf{2}}_{L}, \mathbf{m}^{\mathbf{2}}_{e}, \mathbf{A}_{u},\mathbf{A}_{d} and \mathbf{A}_{e} set to zero, in order to suppress flavour-changing neutral currents:

 \displaystyle\mathbf{m}^{\mathbf{2}}_{Q},\mathbf{m}^{\mathbf{2}}_{u},\mathbf{m% }^{\mathbf{2}}_{d},\mathbf{m}^{\mathbf{2}}_{L},\mathbf{m}^{\mathbf{2}}_{e},% \mathbf{A}_{u},\mathbf{A}_{d},\mathbf{A}_{e}\ \mathrm{diagonal}. (33)
NUHM2:

A0, M0, M12, SignMu, TanBeta, mHd, mHu.
The second Non-Universal Higgs Mass model. Descended from the MSSM63atMGUT. All off-diagonal elements in \mathbf{m}^{\mathbf{2}}_{Q}, \mathbf{m}^{\mathbf{2}}_{u}, \mathbf{m}^{\mathbf{2}}_{d}, \mathbf{m}^{\mathbf{2}}_{L} and \mathbf{m}^{\mathbf{2}}_{e} are set to zero, and all diagonal elements are set equal to a universal sfermion mass m_{0}. All gaugino masses are set to the universal mass m_{1/2}, and all entries in \mathbf{A}_{u}, \mathbf{A}_{d} and \mathbf{A}_{e} are set to a universal trilinear coupling A_{0}. Global fits of this model have been performed in Refs. arXiv:1405.4289 (); Buchmueller:2014yva (); CMSSM ().

 \displaystyle\mathbf{m}^{\mathbf{2}}_{Q},\mathbf{m}^{\mathbf{2}}_{u},\mathbf{m% }^{\mathbf{2}}_{d},\mathbf{m}^{\mathbf{2}}_{L},\mathbf{m}^{\mathbf{2}}_{e}\ % \mathrm{diagonal}, (34) \displaystyle M_{1}=M_{2}=M_{3}\equiv m_{1/2}, (35) \displaystyle(\mathbf{m}^{\mathbf{2}}_{X})_{ii}\equiv m_{0}^{2}\hskip 4.267913% pt\forall\ i\in\{1..3\},X\in\{Q,u,d,L,e\}, (36) \displaystyle(\mathbf{A}_{Y})_{ij}\equiv A_{0}\hskip 5.690551pt\forall\ i,j\in% \{1..3\},Y\in\{u,d,e\}. (37)
NUHM1:

A0, M0, M12, SignMu, TanBeta, mH.
The first Non-Universal Higgs Mass model, fitted in Refs. Buchmueller09 (); Mastercode12b (); Strege13 (); MastercodeCMSSM (); CMSSM (). As per the NUHM2, but with a single Higgs mass parameter m_{H}:

 \displaystyle m^{2}_{H_{u}}=m^{2}_{H_{d}}\equiv(m_{H})^{2}. (38)
CMSSM:

A0, M0, M12, SignMu, TanBeta.
The Constrained MSSM, most notably fitted in recent years in Refs. Fittinocoverage (); MastercodeCMSSM (); Han:2016gvr (); CMSSM (). As per the NUHM1, but with m_{0} playing the role of a fully universal scalar mass parameter:

 \displaystyle m_{H}=m_{0}. (39)
mSUGRA:

A0, M0, M12, SignMu, TanBeta.
The most common definition of the minimal supergravity model; just a pseudonym for the CMSSM.121212Other authors define mSUGRA as a smaller subspace of the CMSSM; see Ref. Dudas:2012hx () for discussion and further references.

#### 5.4.5 Flavour EFT

The study of rare meson decays is typically done within the framework of effective field theory (EFT), where squared matrix elements for decays from initial states i to final states f are calculated from |\langle f|{\cal H}_{\rm eff}|i\rangle|^{2}, using an interaction Hamiltonian

 \mathcal{H}_{\rm eff}=-\frac{4G_{F}}{\sqrt{2}}V_{tb}V_{ts}^{*}\sum_{x}C_{x}(% \mu)\mathcal{O}_{x}(\mu)\;. (40)

Here \mu specifies the scale of the process, V is the CKM matrix and G_{\text{F}} is the Fermi constant. \mathcal{H}_{\rm eff} is decomposed into a linear combination of effective interactions \mathcal{O}_{x} with Wilson coefficients C_{x}. Some such interactions exist already in the SM, e.g.

 \displaystyle\mathcal{O}_{7}=\frac{e}{(4\pi)^{2}}m_{b}(\overline{s}\sigma^{\mu% \nu}P_{R}b)F_{\mu\nu}\;, \displaystyle\mathcal{O}_{9}=\frac{e^{2}}{(4\pi)^{2}}(\overline{s}\gamma^{\mu}% P_{L}b)(\bar{\ell}\gamma_{\mu}\ell)\;, \displaystyle\mathcal{O}_{10}=\frac{e^{2}}{(4\pi)^{2}}(\overline{s}\gamma^{\mu% }P_{L}b)(\bar{\ell}\gamma_{\mu}\gamma_{5}\ell)\;, (41)

whereas others, such as

 \displaystyle\mathcal{Q}_{1} \displaystyle=\frac{e^{2}}{(4\pi)^{2}}(\bar{s}P_{R}b)(\bar{\ell}\,\ell)\;, \displaystyle\mathcal{Q}_{2} \displaystyle=\frac{e^{2}}{(4\pi)^{2}}(\bar{s}P_{R}b)(\bar{\ell}\gamma_{5}\ell% )\;, (42)

are almost exclusively the purvey of new physics. In general, the interesting quantities for new physics are therefore the differences between the expected SM and BSM values,

 \displaystyle\Delta C_{x}\equiv C_{x,\text{BSM}}-C_{x,\text{SM}}. (43)

More details can be found in the FlavBit paper FlavBit () and Ref. Mahmoudi:2008tp ().

WC:

Re_DeltaC7, Im_DeltaC7, Re_DeltaC9,
Im_DeltaC9, Re_DeltaC10, Im_DeltaC10,
Re_DeltaCQ1, Im_DeltaCQ1, Re_DeltaCQ2,
Im_DeltaCQ2.

This model incorporates enhancements and suppressions to the real and imaginary parts of the Wilson coefficients of the effective operators \mathcal{O}_{7}, \mathcal{O}_{9}, \mathcal{O}_{10}, \mathcal{Q}_{1} and \mathcal{Q}_{2} (Eqs. 5.4.5 and 5.4.5).

#### 5.4.6 Nuisance parameters

These models contain values with significant uncertainties that can be essential for calculating signal rates (particularly in DM searches), but which are not part of a BSM model or the Standard Model.

Halo_gNFW:

alpha, beta, gamma, r_sun, rho0, rhos, rs, v0, vesc, vrot.
This as well as all other halo models specify the radial dark matter distribution \rho(r) in the Milky Way and the local properties of dark matter relevant for direct detection and capture in the Sun. Specifically, this model corresponds to the generalized NFW profile

 \rho(r)=\frac{2^{(\beta-\gamma)/\alpha}\rho_{s}}{(r/r_{s})^{\gamma}\left[1+(r/% r_{s})^{\alpha}\right]^{(\beta-\gamma)/\alpha}}\,, (44)

where \gamma (\beta) describes the inner (outer) slope of the profile, \alpha is the shape in the transition region around the scale radius r=r_{s}, and \rho_{s}\equiv\rho(r_{s}) is the scale density. Furthermore, the local properties of dark matter are described by means of the local density \rho_{0} as well as a Maxwell-Boltzmann velocity distribution boosted to the rest frame of the Earth,

 f(\mathbf{u})=\frac{e^{-\left(\frac{\mathbf{u}+\mathbf{v}_{\rm LSR}+v_{\rm% \odot,pec}+V_{\oplus}}{v_{0}}\right)^{2}}}{\pi^{3/2}v_{0}^{3}\operatorname{erf% }\left(\frac{v_{\rm esc}}{v_{0}}\right)-2\pi v_{0}^{2}v_{\rm esc}e^{-\left(% \frac{v_{\rm esc}}{v_{0}}\right)^{2}}}. (45)

Here, v_{0} is the most probable speed of a DM particle with respect to the galactic halo, while v_{\rm esc} denotes the local escape velocity Akrami:2010dn (). The remaining parameters describe the relative motion of the Earth and the Galactic rest frame: \mathbf{v}_{\rm LSR}=(0,v_{\rm rot},0) is the motion of the Local Standard of Rest in Galactic coordinates, with v_{\rm rot} being the local disk circular velocity, \mathbf{v}_{\rm\odot,pec}=(11,12,7) km s{}^{-1} is the peculiar velocity of the Sun Schoenrich:2009bx (), and V_{\oplus}=29.78 km {}^{-1} is the Keplerian velocity of the Earth around the Sun. Notice that in this halo model the scale density \rho_{s} and the local density \rho_{0} are treated as independent parameters.

Halo_gNFW_rho0:

alpha, beta, gamma, r_sun, rho0, rs, v0, vesc, vrot.
Same as Halo_gNFW, but deriving the scale density \rho_{s}\equiv\rho(r_{s}) from a given value of the local density \rho_{0}\equiv\rho(r_{\rm sun}) via Eq. 44. Here, r_{\rm sun} denotes the distance from the solar system to the Galactic center.

Halo_gNFW_rhos:

alpha, beta, gamma, r_sun, rhos, rs, v0, vesc, vrot.
Same as Halo_gNFW, but deriving the local density \rho_{0}\equiv\rho(r_{\rm sun}) from a given value of the scale density \rho_{s}\equiv\rho(r_{s}) via Eq. 44.

Halo_Einasto:

alpha, r_sun, rho0, rhos, rs, v0, vesc, vrot.
Same as Halo_gNFW, but assuming instead the Einasto profile for the radial distribution of dark matter in the Milky Way:

 \rho(r)=\rho_{s}\exp\left\{-\frac{2}{\alpha}\left[\left(\frac{r}{r_{s}}\right)% ^{\alpha}-1\right]\right\}\,, (46)

with r_{s} referring to the scale radius, \rho_{s} to the scale density, and \alpha describing the shape of the profile.

Halo_Einasto_rho0:

alpha, r_sun, rho0, rs, v0, vesc, vrot.
Same as Halo_gNFW_rho0, but using the Einasto profile given by Eq. 46.

Halo_Einasto_rhos:

alpha, r_sun, rhos, rs, v0, vesc, vrot.
Same as Halo_gNFW_rhos, but using the Einasto profile given by Eq. 46.

nuclear_params_fnq:

deltad, deltas, deltau, fnd, fns, fnu, fpd, fps, fpu.
This model contains the nuclear matrix elements that parameterise the quark content of protons and neutrons, f^{(N)}_{T_{q}}, defined by

 m_{N}f^{(N)}_{T_{q}}\equiv\langle N|m_{q}\bar{q}q|N\rangle\,, (47)

where N\in\{p,n\} and q\in\{u,d,s\} Ellis:2008hf (). The model also contains the parameters \Delta^{(p)}_{q} that describe the spin content of the proton.

nuclear_params_sigma0_sigmal:

The same as nuclear_params_fnq, but with the 6 f^{(N)}_{T_{q}} parameters replaced by the light quark content of the nucleon \sigma_{l} and the quantity \sigma_{0}, defined as

 \displaystyle\sigma_{l} \displaystyle\equiv m_{l}\langle N|\bar{u}u+\bar{d}d|N\rangle\,, (48) \displaystyle\sigma_{0} \displaystyle\equiv m_{l}\langle N|\bar{u}u+\bar{d}d-2\bar{s}s|N\rangle\,, (49)

where m_{l}\equiv(1/2)(m_{u}+m_{d}). We take \sigma_{l} and \sigma_{0} to be the same for protons and neutrons Young:2013nn ().

nuclear_params_sigmas_sigmal:

The same as nuclear_params_fnq, but with the 6 f^{(N)}_{T_{q}} parameters replaced by \sigma_{0} from Eq. 49 and the strange quark content of the nucleon \sigma_{s}, which is defined as

 \sigma_{s}\equiv m_{s}\langle N|\bar{s}s|N\rangle\,. (50)

Again, \sigma_{0} and \sigma_{s} are assumed to be the same for protons and neutrons Young:2013nn ().

#### 5.4.7 Toys

NormalDist:

mu, sigma.
A simple test model consisting of two parameters: the width and central value of a Gaussian distribution. This model is used in most of the toy examples discussed in this paper.

TestModel1D:

x.
A one-dimensional test model, typically used for debugging simple prior transformations, or when a dummy model is required (as in the external model example of the ColliderBit paper ColliderBit ()).

demo_A, demo_B, etc:

These are additional example models available in the same header as NormalDist and TestModel1D, but commented out in order to keep from cluttering up the model hierarchy with fake models.

## 6 User interface and input file

In this section we describe the general user interface of GAMBIT. This includes a description of the available command line switches as well as a detailed walk-through of the structure and content of the main initialisation file. Further details about the functionality of the dependency resolver, printers and scanners are given in the following sections.

### 6.1 Command line switches and general usage

GAMBIT is run by executing the gambit executable. The canonical way to launch a scan is to specify an initialisation file myfile.yaml with the -f switch, as in

gambit -f @\metavar{myfile.yaml}@

The full set of command-line switches available is:

version
Print the GAMBIT version number and exit.

-h/–help
Display usage information and exit.

-f file
Use instructions in file to start a scan.

-v/–verbose
Run with full verbose output.

-d/–dryrun
Perform a dry run of a scan. GAMBIT will resolve all dependencies and backend requirements, then list the function evaluation order to stdout, but won’t actually start the scan. It will also produce necessary files and instructions for plotting the D (see Sec. 7). Requires -f.

-r/–restart
Restart a scan, overwriting any existing output. Requires -f. If -r is not specified and previous output exists matching the instructions in file, GAMBIT will attempt to resume scanning based on that output.

GAMBIT also has various diagnostic modes that provide information about its current configuration from the command line. See Sec. 10.4 for further information.

### 6.2 The master initialisation file

The master initialisation file of GAMBIT is written in the YAML format.131313See http://www.yaml.org for a definition of the standard. A compact introduction can be found at http://en.wikipedia.org/wiki/YAML. Note that GAMBIT is also fully compatible at the module level with the SLHA1 Skands:2003cj () and SLHA2 Allanach:2008qq () formats for SUSY models; see Refs. SDPBit (); DarkBit (); ColliderBit (); FlavBit () for details. YAML is a ‘human-friendly, cross-language, Unicode-based data serialization language’ that provides a general framework for setting up nested structures of common native data types. The format is reminiscent of Python. As such, leading whitespace (i.e. the indentation level) matters, and is part of the syntax.

The top node of the master initialisation file is a dictionary that contains eight entries.

Parameters describes the scan parameters for different models.

Priors describes the priors to be placed on the scan parameters.

ObsLikes describes observables and likelihoods that the user would like to be calculated in a scan.

Rules specifies additional rules to guide the resolution of dependencies and backend requirements.

Printer provides details about how and where to store the results of the scan.

Scanner provides information about the scanning algorithm to be adopted in a scan.

Logger chooses options for logging GAMBIT messages during the scan.

KeyValues is an additional global option section.

Any number of other YAML files can be imported to any section of the master initialisation file, using the !import other_file.yaml directive. Imported files may import files of their own, and so on.

### 6.3 Model and parameters

#### 6.3.1 General setup and fast priors

Selecting models to scan and setting options for their parameters is done in the Parameters section of the master YAML file, using the syntax:

Parameters:
@\metavar{model\_1}@:
@\metavar{parameter\_1}@:
# optional fast prior statements
@\metavar{parameter\_2}@:
# optional fast prior statements

@\metavar{model\_2}@:
# content as above
@\metavar{model\_3}@:

For example, in the scalar singlet YAML file that ships with GAMBIT, yaml_files/SingletDM.yaml, this looks like:

Parameters:
# SM non-Higgs parameters.
StandardModel_SLHA2: !import
@\yamlvalue{include/StandardModel\_SLHA2\_scan.yaml}@
# Nuclear matrix parameters.
nuclear_params_sigmas_sigmal:
sigmas:
range: [19, @\yamlvalue{67}@]
sigmal:
range: [31, @\yamlvalue{85}@]
deltau:  0.842
deltas:  -0.085
# SM Higgs-sector parameters
StandardModel_Higgs:
mH:
range: [124.1, @\yamlvalue{127.3}@]
# Scalar singlet dark matter parameters
SingletDM:
mS:
range: [45., @\yamlvalue{10000.}@]
prior_type: log
lambda_hS:
range: [0.0001, @\yamlvalue{10.00}@]
prior_type: log
# Dark matter halo parameters
Halo_gNFW_rho0:
rho0:
range: [0.2, @\yamlvalue{0.8}@]
v0: 235.0
vesc: 550.0
vrot: 235.0
rs: 20.0
r_sun: 8.5
alpha: 1
beta: 3
gamma: 1

Here we see that the SM parameters are imported from the YAML fragment yaml_files/include/ StandardModel_SLHA2_scan.yaml.

As this layout suggests, multiple models can be scanned simultaneously; for example a particle physics model, plus a DM halo model, plus a set of nuclear physics parameters. This allows for arbitrary physics models to be combined easily and fluidly. This makes it simple to add new observables to existing scans even if they bring ‘baggage’ in the form of additional free parameters. The typical example is that of nuisance parameters. Adding an observable that depends not only on the particle physics scenario, but also the assumed value of the top mass, for example, is easy: one adds the new observable to the ObsLikes section, and adds the value or range of top masses to consider when calculating that observable to the Parameters section. Broader examples of the utility of this arrangement include observables with dual implications for both particle physics and cosmology, or for both BSM and neutrino physics.

The subsection following each parameter is an optional ‘fast prior’ definition. For the purposes of sampling parameter values, a prior is the portion of the probability distribution function for choosing parameter values that is independent of the likelihood, i.e. the sampling distribution determined prior to any contact with data. Many sampling algorithms (indeed, essentially all useful ones) apply additional conditions designed to preferentially sample points that constitute better fits to data — but one must always choose what initial prior to employ, independent of the sampling algorithm to be employed. The simplest example would be assigning independent flat distributions for each parameter, viz. ‘flat priors’. When paired with a naive random scanner, this would lead to simple uniform sampling of the parameter values.

Using the Prior section (see Sec. 6.3.2 and Ref. ScannerBit ()), GAMBIT makes it possible to use any arbitrary prior in a scan — but in most cases a very simple prior will suffice. The fast prior subsection provides a streamlined way to directly set such simple priors in the Parameters section, for each parameter.

Note that every parameter of every model mentioned in the Parameters section must be associated with some prior, either in the Priors section or via a fast prior in the Parameters section. This applies even if the parameter is not actually used in a given scan. In this case, the parameter should normally simply be set to some arbitrary constant value in the YAML file.

In it’s simplest form, the fast prior section can just specify such a value to fix a parameter to during a scan (a so-called ‘delta-function prior’):

@\metavar{model\_1}@:
@\metavar{parameter\_1}@: 125.0
@\metavar{parameter\_2}@: 750.

The same thing can be achieved with

@\metavar{model\_1}@:
@\metavar{parameter\_1}@:
fixed_value: 125.0
@\metavar{parameter\_2}@:
fixed_value: 750.

This syntax naturally extends to specifying an ordered set of points to cycle through, e.g.

@\metavar{model\_1}@:
@\metavar{parameter\_1}@: [@\yamlvalue{125.0, 142.5, 119.0}@]
@\metavar{parameter\_2}@:
fixed_value: [@\yamlvalue{750.0, 2015.0, 38.0}@]

There may be cases where parameters spanning multiple models are equivalent and should thus be described as a single parameter. GAMBIT allows model parameters to be combined using the same_as keyword. Thus, parameter_1 of model_1 can be set to be equal to parameter_2 of model_2 via a fast prior entry such as

@\metavar{model\_1}@:
@\metavar{parameter\_1}@:
same_as: @\metavar{model\_2}@::@\metavar{parameter\_2}@
scale: @\metavar{scale}@
shift: @\metavar{shift}@

Here, model_1::parameter_1 will be automatically set from the value assigned to model_2::parameter_2 at each point in the scan. The keywords scale and shift can also be optionally specified; these scale the parameter by an amount scale and shift it by shift. Thus, in the above example,

 \displaystyle\textit{\color[rgb]{0,0.66796875,0}\definecolor{pgfstrokecolor}{% rgb}{0,0.66796875,0}\pgfsys@color@rgb@stroke{0}{0.66796875}{0}% \pgfsys@color@rgb@fill{0}{0.66796875}{0}\footnotesize{model\_1}}::\textit{% \color[rgb]{0,0.66796875,0}\definecolor{pgfstrokecolor}{rgb}{0,0.66796875,0}% \pgfsys@color@rgb@stroke{0}{0.66796875}{0}\pgfsys@color@rgb@fill{0}{0.66796875% }{0}\footnotesize{parameter\_1}}= (51) \displaystyle\quad\textit{\color[rgb]{0,0.66796875,0}\definecolor{% pgfstrokecolor}{rgb}{0,0.66796875,0}\pgfsys@color@rgb@stroke{0}{0.66796875}{0}% \pgfsys@color@rgb@fill{0}{0.66796875}{0}\footnotesize{shift}}+\textit{\color[% rgb]{0,0.66796875,0}\definecolor{pgfstrokecolor}{rgb}{0,0.66796875,0}% \pgfsys@color@rgb@stroke{0}{0.66796875}{0}\pgfsys@color@rgb@fill{0}{0.66796875% }{0}\footnotesize{scale}}*\textit{\color[rgb]{0,0.66796875,0}\definecolor{% pgfstrokecolor}{rgb}{0,0.66796875,0}\pgfsys@color@rgb@stroke{0}{0.66796875}{0}% \pgfsys@color@rgb@fill{0}{0.66796875}{0}\footnotesize{model\_2}}::\textit{% \color[rgb]{0,0.66796875,0}\definecolor{pgfstrokecolor}{rgb}{0,0.66796875,0}% \pgfsys@color@rgb@stroke{0}{0.66796875}{0}\pgfsys@color@rgb@fill{0}{0.66796875% }{0}\footnotesize{parameter\_2}}.

When two models being scanned have parameter names in common, extra care needs to be taken. ScannerBit treats each parameter of each model as fully separate by default, but any module functions that declare both models as allowed (either individually or in combination) will trigger a runtime error when GAMBIT attempts to add the values of all parameters in both models to the Params pipe (cf. Sec. 3.2.3). Usually this indicates poor module function design, although there are some use cases, where the same_as directive is in use, when it may be simplest to proceed without worrying which of the two models’ common parameters appears in the Params pipe. Users wishing to hack their way through such a situation can set the ALLOW_DUPLICATES_IN_PARAMS_MAP precompiler variable in Elements/include/gambit/Elements/ module\_macros\_incore.hpp to 1.

Other fast priors can be chosen via the prior_type keyword, which can be set to flat, log (uniform in the log of the parameter value), or various trigonometric functions (cos, sin, tan or cot), as in

@\metavar{model\_1}@:
@\metavar{parameter\_1}@:
prior_type: @\metavar{chosen\_prior}@
range: [@\metavar{low}@@\yamlvalue{,}@ @\metavar{high}@]
@\metavar{parameter\_2}@:
prior_type: log
range: [@\yamlvalue{5, 75}@]

The allowed values of the parameters are given by setting range. The scale and shift parameters also work with prior_type, in just that same way as with same_as.

If no fixed value is given for a parameter, and both prior_type and same_as are absent but range is given, a flat prior is assumed.

Additional custom priors can be be written as plugins for ScannerBit, and accessed by setting prior_type: plugin; details can be found in Ref. ScannerBit ().

#### 6.3.2 More involved priors

Certain priors introduce correlations between parameters. This makes specifying a separate, unique prior for each parameter impossible. Such multidimensional priors, operating on multiple parameters simultaneously, can only be declared in a separate Prior section of the main YAML file.

Priors:
@\metavar{prior\_name}@:
parameters: [@\metavar{model\_1}@::@\metavar{param1}@, @\metavar{model\_1}@::@\metavar{param2}@,
…]
prior_type: @\metavar{prior\_type\_1}@
@\metavar{options}@
@\metavar{other\_prior\_name}@:
parameters: [@\metavar{model\_2}@::@\metavar{paramA}@, @\metavar{model\_2}@::@\metavar{paramB}@,
…]
prior_type: @\metavar{prior\_type\_2}@
@\metavar{options}@

A multidimensional prior is defined under a new user-defined key such as prior_name. Each prior declared in this way must specify a vector of input parameters, a prior type, and any options required by the prior. A list of prior types and their options can be obtained with the GAMBIT diagnostic gambit priors (see Sec. 10.4.7). Available multidimensional priors include Gaussian and Cauchy distributions, as well as the ability to specify any additional ScannerBit prior plugin present on a user’s system; these are discussed in detail in Ref. ScannerBit ().

### 6.4 ObsLikes: Target observables and likelihoods

Entries in this section determine what is calculated during a scan. Each entry lists a likelihood contribution or an observable that should be calculated during the scan. (Likelihood functions and observables are largely the same within GAMBIT, the main difference being that the former are used to drive the scan, whereas the latter are simply recorded.) The minimal allowed entry has the form

ObsLikes:
- capability: @\metavar{example\_capability}@
purpose: @\metavar{example\_purpose}@
-

Here, example_capability is the capability of the likelihood or observable to be calculated, while example_purpose is its role in the scan. The latter determines its treatment by the scanner and the printer system. In the simplest cases, purpose will be set to either LogLike or Observable.141414Alternative purposes are relatively easy to arrange, but these are the conventional ones. See Sec. 8 for further discussion. In the case of a LogLike, the calculated quantity will be used as one of the likelihoods in the scan. As a convention in GAMBIT, all likelihoods are given in terms of \log\mathcal{L}=\ln(likelihood). In the case of an Observable, the calculated quantity will be simply written as additional output and will be available for later post-processing.

For example, the following entries from yaml_files/ SingletDM.yaml ensure that the likelihood from the dark matter relic density is included in the overall likelihood function, and that the value of the relic density itself is saved in the output of the scan, for every valid combination of model parameters:

ObsLikes:
# Relic density likelihood contribution
- capability: lnL_oh2
purpose:    LogLike
# Relic density prediction
- capability: RD_oh2
purpose:    Observable

It will often happen that several module functions can provide the same capability. In order to remove such ambiguities, it is possible to specify the requested quantity further by adding one or more of the following optional arguments

ObsLikes:
- capability: @\metavar{capability}@
purpose: @\metavar{purpose}@
type: @\metavar{type}@
function: @\metavar{function}@
module: @\metavar{module}@
-

Here, type specifies the C++ type of the module function that should be used to fulfil the requested capability, function explicitly gives the name of a module function, and module demands that the function must come from a specific module. These additional specifications in the ObsLikes section are in fact just a convenient shortcut for setting up the most common rules for dependency resolution. Dependency resolution rules can be set up in far more generality in the separate Rules section, which we discuss below.

In the case of the purpose LogLike, the type of the module function selected must be double, float, std::vector<double> or std::vector<float>, as the result will be sent to the D to contribute to the total likelihood function. (This applies regardless of whether the user has specified the type explicitly, or left it to the dependency resolver to work out.) In the case of vectors, the likelihood container automatically sums all entries.

Finally, the additional option printme can be set for each ObsLikes entry, for example

ObsLikes:
- capability: @\metavar{example\_capability}@
purpose: @\metavar{example\_purpose}@
printme: true
-

This option is true by default, meaning that by default GAMBIT will attempt to record to disk (i.e. ‘print’; see Sec. 9) the computed result of the each of the target observables/likelihoods. This is the behaviour that one almost always wants during a production scan, however by setting printme to false the user can tell GAMBIT not to try to output the result of the thusly-flagged computation. It is useful to do this when testing and debugging new module functions, for example, because these often produce results that are not of a printable C++ type (and so attempting to print them would cause a runtime error, see Sec 9.3), yet one will often want to set these functions as ObsLikes targets just to ensure that GAMBIT will run them.

### 6.5 Rules: Dependency resolution and module options

Entries in the Rules section determine the details of how the likelihoods and observables listed in the ObsLikes section are calculated in the scan. In the rather common case that several different module functions can provide a capability requested in the ObsLikes section, or several module functions can provide the neccessary capability-type pair requested in another module function’s D, then further specifications in the Rules section are required to fully define the scan. The Rules section can likewise be used to control the resolution of backend requirements, and to set options for individual module functions, modules and backend initialisation functions.

#### 6.5.1 Module function dependencies

In the rather common case that several different module functions provide the same requested quantity, further rules are necessary to define the scan. Note that with quantity, we refer here specifically to capability/type pairs, quantity \equiv (capability, type). These rules can be specified in the Rules section of the initialisation file. Furthermore, this section is used to control the resolution of backend dependencies, and to set options for individual module functions, modules and backend initialisation functions. In this sense, the rules determine how an individual point is calculated during the scan.

In the simplest case, a rule has the form

Rules:
- capability: @\metavar{capability}@
type: @\metavar{type}@
function: @\metavar{function}@
module: @\metavar{module}@

where capability is required, type is optional, and one or both of the entries function and module must be given. This entry translates into the rule: Any capability with C++ type type should be resolved by module function function from the module module. Assigning the empty string "" or the wildcard character "*" to an entry is equivalent to omitting it. If regex is activated (this is not the default; see Sec. 6.9), all entries are actually treated as regular expressions, allowing rules to be made arbitrarily complex.151515For details about regular expressions we refer the reader to https://en.wikipedia.org/wiki/Regular_expression.

A simple example of such a rule is the one in yaml_files/SingletDM.yaml that specifies that the observed relic density should be treated as an upper limit only when computing the likelihood. This allows for the possibility that some of the dark matter is not in the form of scalar singlet particles.

# Choose to implement the relic density likelihood
# as an upper bound, not a detection
- capability: lnL_oh2
function: lnL_oh2_upperlimit

This rule says that wherever the capability lnL_oh2 is needed in a scan, GAMBIT must use a function with the name lnL_oh2_upperlimit. As it turns out, there is only one function with such a name in GAMBIT 1.0.0, and it lives in DarkBit – so this rule forces DarkBit::lnL_oh2_upperlimit to be used.

The simple form shown above applies a rule to the resolution of dependencies of any module functions matching the specified capability and type. In order to set up rules that only affect the dependency resolution of a specific module function, one can add a dedicated dependencies subsection, and optionally omit any of the top-level keys capability, type, function and module (or equivalently, set them to "" or "*").

Rules:
- capability: @\metavar{capability}@
type: @\metavar{type}@
function: @\metavar{function}@
module: @\metavar{module}@
dependencies:
- {capability: @\metavar{cap\_A}@, type: @\metavar{type\_A}@,
function: @\metavar{func\_A}@, module: @\metavar{mod\_A}@}
- {capability: @\metavar{cap\_B}@, type: @\metavar{type\_B}@,
function: @\metavar{func\_B}@, module: @\metavar{mod\_B}@}
-
-

If regex is activated, the values are treated as regular expressions. The entry translates into the following rule: when resolving dependencies of module function function in module module, which provides capability capability with C++ type type, apply the rules listed under the keyword dependencies.

If conflicting rules are found during dependency resolution, GAMBIT will throw an error. This is intended to reduce side effects that changes in some parts of the initialisation file can have on other parts. However, rules can be explicitly declared as weak and over-rideable, by using the flag weak!, as per

Rules:
- !weak
capability: @\metavar{capability}@
type: @\metavar{type}@
function: @\metavar{function}@
module: @\metavar{module}@
-

Note that the flag affects the entire rule for which it is set, not only specific nearby keywords.

A special case can occur if several module functions depend on the same quantity as they provide. In this case these module functions can be chained, and setting up such chains in the rules section is simplified by using the keyword functionChain. This is illustrated in the following example, where func1, func2 and func3 are supposed to provide as well as depend on capability with type. These functions will be chained together, with func1 fulfulling the depenencies of func2 etc.

Rules:
- capability: @\metavar{capability}@
type: @\metavar{type}@
functionChain: [@\metavar{func1}@, @\metavar{func2}@, @\metavar{func3}@]
module: @\metavar{module}@

Finally, when performing type matching, the dependency resolver takes all type equivalences defined in config/resolution\_type\_equivalency\_classes.yaml into account. We discuss this type equivalency database for dependency resolution in more detail in Sec. 10.5.

#### 6.5.2 Backend requirements

After a module function has been selected to take part in a scan, its backend requirements are resolved. This process can be guided and controlled using rules for backend requirements, which have the form:

Rules:
- capability: @\metavar{capability}@
type: @\metavar{type}@
function: @\metavar{function}@
module: @\metavar{module}@
backends:
- {capability: @\metavar{cap\_A}@, type: @\metavar{type\_A}@,
function: @\metavar{func\_A}@, backend: @\metavar{backend\_A}@,
version: @\metavar{backend\_A\_version\_number}@}
- {capability: @\metavar{cap\_B}@, type: @\metavar{type\_B}@,
function: @\metavar{func\_B}@, backend: @\metavar{backend\_B}@,
version: @\metavar{backend\_B\_version\_number}@}
-

The usage is essentially identical to the one discussed above for dependencies, except that backend may be specified rather than module, and a specific version of a backend may be requested, as e.g.

- capability: Higgs_Couplings
backends:
- {backend: FeynHiggs, version: 2.11.3}

There are also a number of other restrictions that can be applied via rules declared in the module function’s rollcall header entry (Sec 3.1.3). These include backend requirements that are only activated for specific models (analogous to model-conditional dependencies of module functions), restricted lists of permitted backends and versions, and the condition that certain combinations of backend requirements must be resolved by the same version of the same backend.

#### 6.5.3 Options for module functions

Besides setting rules for the resolution of dependencies and backend requirements, the Rules section can also be used to set options for module functions. This is done with the options keyword, as

Rules:
- capability: @\metavar{capability}@
type: @\metavar{type}@
function: @\metavar{function}@
module: @\metavar{module}@
options:
@\metavar{key\_A}@: @\metavar{value\_A}@
@\metavar{key\_B}@: @\metavar{value\_B}@

-

This rule sets the option key_A to value_A and option key_B to value_B, for any module function that matches the indicated capability, type, function and module. Any of these keywords can be omitted; if regex is activated, they are treated as regular expressions. This allows, for instance, module-wide options to be set using just the name of the module, whilst omitting the other three keywords or setting them to wildcards:

Rules:
- module: DarkBit
options:

Here, the key DM_is_made_of is accessible by all module functions in the module DarkBit.

This last example is a bit glib, as in reality DM_is_made_of is not a recognised option of any functions in DarkBit, so setting it doesn’t actually have any effect in GAMBIT 1.0.0. A more realistic example is:

Rules:
# Use the DarkBit native calculator
# to compute the relic density
- capability: RD_oh2
function: RD_oh2_general
options:
fast: 1

This can be seen in e.g. yaml_files/SingletDM.yaml. This rule specifically selects the RD_oh2_general function from DarkBit for calculating capability RD_oh2 (i.e. the relic density), and passes it the option fast = 1, to set the accuracy required when solving the Boltzmann Equation for the thermal relic density of scalar singlet particles.

The key-value pairs specified in this way are easily accessed by any module function that matches a given rule, using runOptions->getValue (cf. Sec. 3.2.4).

In most cases, module functions will interpret option values as simple C++ types (commonly float, int, bool or std::string), but composite types like std::vector<double> can also be set. The necessary syntax for doing this is defined by the YAML standard. Options can also be easily nested, with the C++ type of the top-level option to be retrieved itself a YAML::Node161616This class is defined in the contributed package yaml-cpp, which ships with GAMBIT. Documentation is available at http://github.com/jbeder/yaml-cpp., from which lower-level options can then be retrieved.

Information about what options are available for which module function can be found in the module function documentation. Options that are never requested by module functions at runtime are silently ignored.

In case of ambiguity, such as when an option requested by a module function is listed in several matching rules, GAMBIT throws an error during initialisation.

### 6.6 Printer

The GAMBIT “printer” system handles the output of all scan results, whether to disk, a network resource or any other output stream. This system allows all GAMBIT output to be handled in an abstract way throughout the code, with the actual format of the output being decided by the choice of an output plugin (a D) at runtime, via the master YAML file. Therefore, setting up GAMBIT output consists primarily of choosing a printer and setting options for it. In this section we describe how to do this; full details of the printer system can be found in Sec. 9.

Note that output handled by the GAMBIT printer system is essentially independent of other output that might be created by any backend or scanner codes. This allows the output to remain as uniform as possible, regardless of the scanning algorithm and external codes being used.

GAMBIT 1.0.0 ships with two printers: ascii and hdf5. The ascii printer outputs data as a simple ASCII table, whereas the hdf5 printer writes data to a binary file in HDF5 format. The former format is useful for its simplicity, however the latter is far superior when dealing with large datasets, particularly in terms of disk usage and read/write speed. We have also upgraded the external analysis tool pippi pippi () to accept GAMBIT input in these formats; it can be easily retrieved via the GAMBIT build system (Sec. 11.3).

Most options that affect the output system are entered in the Printer section of the master YAML file. The basic layout of this section is:

Printer:
printer: @\metavar{plugin\_name}@
options:
@\metavar{option\_1}@: @\metavar{value\_1}@
@\metavar{option\_2}@: @\metavar{value\_2}@

That is, one chooses a plugin plugin_name and sets its options, which vary with the plugin. In the next sections we describe the options available in each printer.

#### 6.6.1 Common options

These options are common to both the ascii and hdf5 printers:

options:
output_path: @\metavar{default\_output\_path}@
output_file: @\metavar{filename}@
output_path

specifies the directory in which the printer output will be stored. By default it is set to the value of default_output_path as set in the KeyValues section of the input YAML file (see Sec. 6.9), however if a value is set here it will override that default.

output_file

specifies the name of the file in which to store data generated during the run. If it does not exist then it will be created.

#### 6.6.2 Specific options: ascii printer

The only specific option for this plugin is buffer_length, which defaults to a value of 100:

Printer:
printer: ascii
options:
buffer_length: 10

This specifies the size of the internal buffer used by the printer. A value of N will cause output to be written to disk every N model points. If model points are slow to evaluate, it can be useful (particularly during testing) to set buffer_length to 1 so that output is generated frequently. However, if model points are evaluated extremely rapidly then frequent writing of output will create a significant bottleneck, and a high value of buffer_length will be more appropriate.

#### 6.6.3 Specific options: hdf5 printer

There are three specific options for this plugin:

Printer:
printer: hdf5
options:
group: "/"
delete_file_on_restart: false

The first is group, which defaults to "/". This option specifies the name of the group within the host HDF5 output_file in which data will be stored. HDF5 files are structured similarly to a filesystem (i.e. hierarchically) and a ‘group’ is analogous to a directory. Various objects (such as datasets, and other groups) are then stored within groups181818See https://www.hdfgroup.org/HDF5/doc/Glossary.html for further description of ‘groups’ and ‘datasets’ in HDF5. The default value of "/" specifies the root group, and this option should rarely need to be set to anything else. A deeper-layer group can be specified e.g. as "/group1/group2/etc/". Absent groups at any layer will be automatically created.

The second option is delete_file_on_restart. This option is mainly a convenience for performing repeated test scans, and causes the file specified by output_file to be deleted if it already exists when a run restarts (i.e. if the -r command line flag is used, see Sec. 6.1). By default this is false, meaning that if a HDF5 file already exists matching the name given in output_file then GAMBIT will attempt to add the data for the run to this pre-existing file.

Further details of the HDF5 objects that GAMBIT writes to disk via this printer can be found in Sec. 9. Note that results from several runs can be stored inside the same HDF5 file by storing the data in different groups, however it is safer to use separate files because HDF5 files are vulnerable to corruption from write errors (which in principle can occur if GAMBIT terminates abnormally; see Sec. 10.8 for safe early shutdown methods), and data recovery is difficult. If delete_file_on_restart is false and the chosen group already exists, GAMBIT will throw a runtime error telling you to choose a different group or overwrite the whole file. Groups can be deleted, however the disk space they occupy cannot be reclaimed without copying the entire contents of the HDF5 file into a new file, e.g. using the h5repack command line tool. We leave these kind of file manipulations to the user.

#### 6.6.4 Output selection

The outputs handled by the printer system are simply the results of module function evaluations. However, not all module function results are of a C++ type that can be ‘printed’ with every printer (see Sec. 9.3 for the restrictions), so GAMBIT cannot automatically output all results. To instruct GAMBIT to write the result of a calculation to an output stream, the module function that computes a result must be selected to fulfil one of the capabilities requested in the ObsLikes section of the master YAML file. Intermediate results, computed by functions run by the dependency resolver only in order to fulfil dependencies of other functions, are not output.

### 6.7 Scanner

GAMBIT ships with a variety of scanner plugins that can be used in a “plug and play” manner. A full list of scanner plugins can be obtained from the GAMBIT scanners diagnostic (Sec. 10.4.5). A scanner is selected by specifying one of these plugins and any plugin-specific options in the Scanner section of the YAML file, e.g.

Scanner:
use_scanner: nested_sampler
scanners:
nested_sampler:
plugin: MultiNest
like:  LogLike
nlive: 4000
tol: 0.5
mmodal: 1
other_sampler:
plugin:

The Scanner section can contain multiple scanner definitions with user-defined names, such as nested_sampler and other_sampler in the above example. The scanner that will actually be used in a given scan is specified with the use_scanner key. Within the YAML scanner definitions, the plugin option must be set to a valid scanner plugin known to GAMBIT, and any necessary/desired options for that scanner should also be set. Note that a typical scanner plugin requires a D to use for its objective function, such as LogLike or Observable; this is provided by setting the like option in the example of the MultiNest plugin. Valid and required plugin options, plugin descriptions, and the status of a plugin can be obtained through the GAMBIT free-form diagnostic (see Sec. 10.4.8),

gambit @\metavar{plugin\_name}@

where plugin_name is the name of the scanner plugin.

GAMBIT also ships with a number of simple objective test functions, which can be used as objective functions for a scan in place of the regular GAMBIT D output, for testing scanners and other parts of the code. These exist as test function plugins in ScannerBit, and are accessed from the main YAML file with similar syntax to scanners, e.g.

Scanner:
use_objectives: my_test_function
objectives:
my_test_function:
plugin: uniform
parameter_A: 10
parameter_B: false
other_test_function:
plugin:

As the use_objectives directive suggests, multiple test functions can be specified with the regular YAML [x,y] syntax if desired, in which case all the listed objectives will be multiplied to form the actual objective function to be used in the scan. Details of the available test functions and their options can be found in the ScannerBit paper ScannerBit ().

### 6.8 Logger

The logging output of a scan can be directed to various output files. This is done using entries of the form:

Logger:
prefix: @\metavar{output\_path}@
redirection:
[Scanner, Warning] : "scanner_warnings.log"
[ExampleBit_A] : "ExampleBit_A.log"

Here prefix specifies the output location for log files (defaulting to default_output_path; cf. Sec. 6.9), and the entries in the redirection subsection dictate which logging messages go to which file. These options are discussed further in Sec. 10.2.

### 6.9 KeyValues: general purpose options

Most of the general behaviour of GAMBIT is controlled by various options in the KeyValues section. The syntax is the same as described above in the context of the module function options. We provide here a complete list of available options. Where we indicate concrete values, these are the default values that will be used if the option is omitted; where no default is indicated, the option is required.

KeyValues:
likelihood:
# The value of the log-likelihood to assign to
# invalid points.  Also the log-likelihood value
# below which an otherwise valid point is declared
# invalid.
model_invalid_for_lnlike_below: @\metavar{lnlike\_min}@
# Alternative value of the log-likelihood to
# assign to invalid points later in a scan (e.g.
# with the MultiNest scanner; see @\cite{ScannerBit}@).
model_invalid_for_lnlike_below_alt: #defaults to
# 0.5*@\metavar{lnlike\_min}@.
# Print likelihood debug information to stdout and
# logs, including parameter values and
# contributions of individual likelihood
# components. Set true automatically if the master
# debug flag (below) is true.
debug: false
exceptions:
# Set the fatality of different exceptions (see
# Sec.@\,\ref{exceptions}@).  By default, all
# errors are fatal and all warnings non-fatal.
core_warning: non-fatal
core_error: fatal
ExampleBit_A_warning: non-fatal
ExampleBit_A_error: non-fatal

dependency_resolution:
# If multiple module functions can resolve the
# same dependency, prefer the one that is more
# tailored for the scanned model.  See Sec.@\,\ref{depres_general}@.
prefer_model_specific_functions: true
# Interpret rules in terms of regular expressions
use_regex: false
# Print running average runtime for all functions
# in dependency resolver logs
log_runtime: false
# Print timing information into hdf5 output
print_timing_data: false
# Root prefix to use in all output paths. The
# default value is based on the input \YAML file
# name, with the (final) file extension removed.
default_output_path: "runs/@\metavar{inifile\_name}@/"
# Call MPI_ABORT when attempting to shut down. Many
# implementations of MPI_ABORT are buggy and do not
# abort other MPI processes properly; in these
# cases, set this option false to let GAMBIT try to
# abort things its own way.
use_mpi_abort: true
# Pick a random number generator engine.
# See Sec.@\,\ref{random numbers}@ for details.
rng: default # default = mt19937_64 in GAMBIT 1.0.0
# Turn on master debug mode. Implies
# Logger:debug=true and
# KeyValues:likelihood:debug=true
debug: false

## 7 Dependency Resolver

The D runs during the initialisation stage of a GAMBIT scan. It determines which module functions are required for a specific scan, infers their initial evaluation order, and connects their pipes. A major part of this plumbing exercise is constructing the D of a scan, a directed acyclic graph with dependency pipes as the connectors (‘edges’ in graph language) and module functions as the nodes. Roughly speaking, the dependency tree starts at its ‘top’ with the scanned models and their parameters, and terminates at the ‘bottom’ with functions that provide the likelihoods and observables requested in the ObsLikes section of the scan’s initialisation file (Sec. 6.4). An example can be seen in Fig. 5. The construction of a valid dependency tree will happen mostly automatically, and depends only on the declarations in the module and backend rollcall headers. However, it is rather common in GAMBIT that there are several ways to calculate the same thing, in which case additional rules have to be specified in the input file (Sec. 6.5).

### 7.1 General procedure

The steps of dependency resolution are:

1. Disable all module and backend functions not compatible with the models being scanned.

2. Based on the entries of the ObsLikes section, make a list of initially requested quantities; this is the initial dependency queue.

3. Pick an unresolved quantity from the dependency queue, along with a designated target. Entries in the initial dependency queue can be thought of as having the chosen printer as their target.

4. Make a list of module functions that can provide the requested quantity.

5. If the KeyValues entry prefer_model_specific_functions is true:

• If any module functions on the list are tailor-made for the scanned models, remove all other module functions from the list.

• If any module functions on the list are tailor-made for ancestors of the scanned models, keep only the module functions most closely related to the scanned models.

6. Adopt the Rules specified in the initialisation file (see Sec. 6.5), removing non-matching module functions from the list.

7. If exactly one module function is left on the list, resolve the quantity requested by the target function with the capability provided by that module function. This automatically connects the pipe of the target function to the result of the resolving function.

8. If the resolving function was not already activated for the scan, activate it and add its dependencies to the dependency queue (with the resolving function as new target function).

9. Resolve backend requirements, as described below.

10. Resolve module function options, as described below.

11. Repeat from step 3 until the dependency queue is empty.

### 7.2 Evaluation order

After building up the dependency tree of module functions, the dependency resolver determines the initial runtime ordering of its chosen module functions. An obvious minimal requirement is that if the output of module function \mathcal{A} is required by module function \mathcal{B}, then \mathcal{A} must be evaluated before \mathcal{B}. We do this by topologically sorting the directed dependency tree, using graph-theoretic methods from the Boost Graph Library.202020http://www.boost.org/doc/libs/1_63_0/libs/graph/doc/. The reader may wonder how mutually-dependent quantities should be dealt with, i.e. in cases where the values of \mathcal{A} and \mathcal{B} are defined by a set of equations that must be solved simultaneously, by means of iteration. Take the calculation of precision values of m_{W} and m_{h} in the MSSM for example, where each depends on the other. GAMBIT does not provide any option for doing such iterative calculations directly through the dependency tree. Generally the way to deal with such a situation is to either write a module function that can compute the two quantities simultaneously and self-consistently (i.e. that does the iteration internally), returning them both as its result, or use function pointers as return values of module functions. For option 2, take the Higgs mass example. If a module author wishes to permit the user to choose from two possible expressions for m_{h} that depend on m_{W}, they would first write the two expressions as functions of m_{W}. Call these expressions f(m_{W}) and g(m_{W}). The author would then write one or more module functions that return a pointer to f or g. The module function that computes m_{W} should then depend on a pointer to a Higgs mass function, and then just call it (either f or g, depending on which one the user chooses) whilst it does its iterative calculation of m_{W}. It should then return its final value of m_{W}. Another module function responsible for computing m_{h} should then depend on both the value of m_{W}, and the pointer to the same Higgs mass function (f or g). This module function then simply takes the previously computed value of m_{W}, passes it to the function pointed to by its dependency on the Higgs mass function pointer, retrieves the final value of the Higgs mass, and returns it as its own result.

In most cases, the evaluation order of the observables and likelihoods listed in the ObsLikes section (Sec. 6.4) remains unconstrained by the topological sorting. The dependency resolver first orders the likelihoods by estimating the expected evaluation time for each one, including all dependent module functions, along with the probability that each likelihood will invalidate a point. (A point may be invalidated if the likelihood is extremely close to zero, the point is unphysical, etc.) These estimates are based on the runtime and invalidation frequency of the previously calculated points, and updated on the fly during the scan. The dependency resolver then sorts the evaluation order of likelihoods such that the expected average time until a point is invalidated is minimised. In practice this means that, for instance, the relatively fast checks for consistency of a model with physicality constraints, such as perturbativity and the absence of tachyons, would be automatically performed before the often time-consuming evaluation of collider constraints. This gives a significant efficiency gain in a large scan, because expensive likelihoods are not even evaluated for points found to be invalid or sufficiently unlikely on the basis of faster likelihoods.

Observables not associated with likelihoods used to drive a scan (cf. 6.4) are always calculated after the likelihood components, as they do not have the power to completely invalidate a model point. Invalid observable calculations can still be flagged, but they will not trigger the termination of all remaining calculations for that point in the way that an invalid likelihood component will.

### 7.3 Resolution of backend requirements

Resolving backend requirements is in some sense a lot easier than resolving module function dependencies, in that backend requirements cannot themselves have explicit backend requirements nor dependencies, so there is no equivalent of the dependency tree to build. However, the ability to specify groups of backend functions from which only one requirement must be resolved, along with rules that apply to them (Sec. 3.1.3), especially the declaration that backend requirements that share a certain tag must be resolved from the same backend — without necessarily specifying which backend — makes backend resolution a uniquely challenging problem.

The dependency resolver employs an iterative approach to backend resolution. It performs multiple passes over the list of backend requirements, choosing to defer resolution of ambiguous requirements until resolution of other requirements makes it possible to uniquely resolve the initial requirements. The overall strategy proceeds as follows:

1. Create a new group of backend requirements, consisting of all requirements that were declared in the rollcall header without a group. This will be a special group; unlike declared groups, all requirements in this group must be resolved rather just one.

2. Create a queue of all groups of backend requirements.

3. Choose a group from the queue.

1. If the group is a regular group, iterate through all available backend functions and retain those that fulfil all rules of the group. If no backend function exists that satisfies all rules, throw a runtime error. If only one such function exists, resolve the group backend requirement with it. If multiple solutions are found, but one or more of them is subject to a rule linking it to another backend requirement, flag the group as one whose resolution should be deferred until other backends have been resolved.

2. If instead the group is the special one, iterate over all requirements in the group, attempting one by one to find a unique backend function that fulfils each requirement. Fail if no solution exists to any one of these requirements. If just one solution exists to a given requirement, resolve the requirement with it. If no unique solution is found for some requirement, but one or more candidates is subject to a rule linking it to another requirement, flag the group for deferral and come back to its unresolved members later.

4. If it has been flagged for deferral, add the group again to the end of the queue.

5. Repeat from step 3 until either

1. all groups have been fully resolved, or

2. the queue stagnates, i.e. a full iteration has been carried out through the entire queue of groups without any successful backend resolutions. In this case, disable the possibility to defer resolution, and try one last iteration through the queue, ultimately failing if any backend groups fail to resolve on the final attempt.

### 7.4 Resolution of loops and nested functions

As discussed in Sec. 3.1.4, it is possible to write special module functions (loop managers) that control the parallel execution of other module functions (nested module functions). Nested functions explicitly declare a dependency on a loop manager with a certain capability. The dependency resolution proceeds then as for non-nested module functions. The main difference is that loop managers have access to pointers to the nested module functions that they control. The dependency resolver generates a miniature dependency tree for each loop manager, consisting of all nested functions assigned to run inside the loop managed by that manager. The loop manager is then given responsibility for executing the nested functions, in the order provided to it by the dependency resolver. Further details can be found in Sec. 3.1.4.

### 7.5 Option resolution

Each time a module function is activated during the process of dependency resolution, the dependency resolver searches the Rules section of the initialisation file for relevant option entries (see Sec. 6.5.3 for the format of option entries). All options matching the characteristics of the activated module function are collected into a new object, which is then connected to the function’s runOptions pipe (cf. Sec. 3.2.4). If the same option is set to conflicting values in multiple entries in the Rules section of the initialisation file, the dependency resolver will throw an error.

## 8 Statistics and scanning

In this section we explain the statistical strategy employed by GAMBIT (Sec 8.1), how to obtain final inferences from its outputs (Sec 8.2), and the generic likelihood forms available within GAMBIT for use by module functions that do not define their own dedicated likelihoods (Sec 8.3).

### 8.1 The role of ScannerBit

To launch a GAMBIT run, a user requests a parameter scan of a certain model, specifying ranges and priors of the model parameters, how to sample them, and the quantities that should be calculated and included in the scan. The GAMBIT model database activates the relevant model ancestry, which the dependency resolver uses together with the capabilities and types of the user’s requested quantities to select and connect appropriate module and backend functions into a dependency tree. Choosing which values of the model parameters to run through this dependency tree is the job of ScannerBit, the sampling and statistics module ScannerBit (). ScannerBit applies any prior transformations requested by the user, and activates the appropriate D in order to run the requested sampling algorithm. ScannerBit presently contains plugins for nested sampling (MultiNest MultiNest ()), Markov Chain Monte Carlo (GreAT GreAT ()), a population-based Monte Carlo (T-Walk ScannerBit ()), differential evolution (Diver ScannerBit ()), and various grid, random and other toy samplers ScannerBit (). It also contains a dedicated postprocessor scanner plugin, which can be used for reprocessing samples obtained in a previous scan, either to recompute some output quantities or add new ones. See Ref. ScannerBit () for details.

When requesting a quantity in a scan, users are required to assign it a D in the context of that scan. The purpose may be Observable or Test, indicating that the quantity should be computed and output for every parameter combination sampled during a scan. Alternatively, a user can assign a purpose with a specific statistical meaning, such as LogLike or Likelihood. Interfaces to parameter sampling algorithms in ScannerBit allow the user to choose which purpose to associate with the objective function for the scanner at runtime. Following dependency resolution, GAMBIT creates a D from the module functions of the dependency tree that have been assigned the purpose(s) associated with the sampling algorithm. The likelihood container packages the module functions’ combined results into a simple objective function for the sampler to call. The sampler then chooses parameter combinations to sample, sends each to the likelihood container, and receives the final likelihood for the parameter combination in return.

The GAMBIT convention is to assign purpose: LogLike to each component of a fit that is to be associated with the scanner, and for the module functions in question to return the natural log of the likelihood \ln\mathcal{L}. The likelihood container then combines the results of all such module functions by simply summing their return values, returning the result to the scanner as the total log-likelihood. All sampling algorithms interfaced in ScannerBit 1.0.0 allow only a single designated purpose to drive a scan, although other scanners to be connected in future versions will make use of multiple, different purposes within a single scan, for example to split likelihood calculations into ‘fast’ and ‘slow’ subsets Lewis_slowfast ().

### 8.2 Analysing samples

As it samples different parameter values, ScannerBit ensures that those values are output using whichever generalised print stream the user has selected (see Sec. 9 for details), along with all requested observables and likelihood components. The final task of statistical interpretation then requires parsing the printed samples and processing them into meaningful statistical quantities, whether Bayesian (posterior probability distribution functions, credible intervals and/or evidence ratios) or frequentist (profile likelihoods, confidence intervals and/or p values). Depending on the sampler employed, not all of these options may be valid (we return to this discussion in more detail in Ref. ScannerBit ()).

Although processing the saved samples into statistical measures and producing corresponding plots are tasks technically outside the scope of GAMBIT itself, we specifically provide printer options that produce output compatible with common parsing and plotting software such as GetDist CosmoMC () and pippi pippi (). We also provide a simple installer for pippi from within the GAMBIT integrated build system (Sec. 11). This allows GAMBIT to effectively produce profile likelihoods, confidence intervals, posterior probability distributions and maximum-posterior-density credible intervals in situ, by outsourcing the final step to pippi. Bayesian evidences can also be obtained directly from relevant scanners (e.g. MultiNest), or calculated after the fact with pippi. Calculating p values requires the user to make their own ansatz for the distribution of the GAMBIT log-likelihood (or other test statistic that they might choose to employ in a GAMBIT scan), and then convert the best fit identified by pippi to p. Future versions of ScannerBit are planned to include features designed to aid in determining this distribution.

### 8.3 Available likelihood forms

GAMBIT ships with a number of centrally-implemented, general purpose Gaussian and log-normal likelihood functions. These can be found in Utils/src/statistics.cpp. These are intended for use with simple observables and uncorrelated data, for implementing, e.g., nuisance likelihoods corresponding to well-measured SM parameters (see SDPBit ()). Module functions responsible for more complicated likelihood calculations typically contain their own implementations of appropriate test statistics, and corresponding translations to a quantity that can be treated as equivalent to \ln\mathcal{L} in a scan (see the indirect detection likelihoods in DarkBit (), for example).

The centrally-implemented likelihoods come in a number of variants, allowing them to be used for detections, upper limits and lower limits. They deal with systematic uncertainties (theory errors, experimental systematics, related nuisance parameters, etc) by analytically profiling or marginalising over an assumed distribution for an auxiliary parameter \epsilon, which describes departures from a perfect mapping between model parameters and predicted values of observables. The module author must choose an appropriate central likelihood function to employ when computing a given likelihood. However, in every module function that uses one of following likelihoods, we choose to implement a boolean YAML option profile_systematics (default false) that selects at runtime whether systematics will be profiled or marginalised over.212121If the end user so desires, this can even be set differently for different module functions, although the resulting composite likelihood would arguably be inconsistent.

#### 8.3.1 Profiled Gaussian

The basic Gaussian likelihood for data measured with some mean x and standard deviation \sigma, given a prediction \mu, is

 \mathcal{L}_{\mathrm{G}}(x|\mu)=\frac{1}{\sqrt{2\pi}\sigma}\exp\left[-\frac{1}% {2}\frac{(x-\mu)^{2}}{\sigma^{2}}\right]. (52)

Here \mu may be a model parameter itself, or some complicated function of the true underlying model parameters. Taking \epsilon to be an additive offset in \mu induced by some source of error, and modelling its distribution as also Gaussian, centred on zero with standard deviation \sigma_{\epsilon}, the joint likelihood becomes

 \mathcal{L}_{\mathrm{G}}=\frac{1}{2\pi\sigma\sigma_{\epsilon}}\exp\left[-\frac% {1}{2}\frac{(x-\mu-\epsilon)^{2}}{\sigma^{2}}-\frac{1}{2}\frac{\epsilon^{2}}{% \sigma_{\epsilon}^{2}}\right]. (53)

Exactly how to denote \mathcal{L} on the left of this equation depends on whether \epsilon and \sigma_{\epsilon} are to be interpreted to result from an auxiliary, independent measurement (frequentist), or simply some input systematic, possibly theoretical (Bayesian). In the former case, \mathcal{L}=\mathcal{L}(x,\epsilon|\mu), and a final form of the likelihood for x alone can be obtained by profiling over the observed value of \epsilon. To do this, we determine the value of \epsilon that maximises \mathcal{L}(x,\epsilon|\mu), by differentiating Eq. 53 to find the root

 \hat{\epsilon}=\frac{\sigma_{\epsilon}^{2}}{\sigma^{2}+\sigma_{\epsilon}^{2}}(% x-\mu). (54)

Substituting back into Eq. 53, the profiled version of the Gaussian likelihood is

 \mathcal{L}_{\mathrm{G,prof}}(x|\mu)=\frac{1}{2\pi\sigma\sigma_{\epsilon}}\exp% \left[-\frac{1}{2}\frac{(x-\mu)^{2}}{\sigma^{2}+\sigma_{\epsilon}^{2}}\right]. (55)

#### 8.3.2 Marginalised Gaussian

If the quantity \epsilon in Eq. 53 is instead interpreted as a direct input from e.g. theory, its Gaussian distribution has the character of a prior and \mathcal{L}=\mathcal{L}(x|\mu,\epsilon,\sigma_{\epsilon}). Note that in this case, \sigma_{\epsilon} has the character of a model parameter (or a quantity derived from the model parameters), indicating that it may vary as a function of the underlying model across the parameter space, independent of any considerations from data.

In this case, the appropriate likelihood for x alone instead comes from marginalising Eq. 53 over the possible values of \epsilon, as

 \mathcal{L}_{\mathrm{G,marg}}(x|\mu,\sigma_{\epsilon})=\frac{1}{2\pi\sigma% \sigma_{\epsilon}}\int^{\infty}_{-\infty}e^{-\frac{(x-\mu-\epsilon)^{2}}{2% \sigma^{2}}-\frac{\epsilon^{2}}{2\sigma_{\epsilon}^{2}}}\,\mathrm{d}\epsilon, (56)

giving

 \mathcal{L}_{\mathrm{G,marg}}(x|\mu,\sigma_{\epsilon})=\frac{1}{\sqrt{2\pi(% \sigma^{2}+\sigma_{\epsilon}^{2})}}\exp\left[-\frac{1}{2}\frac{(x-\mu)^{2}}{% \sigma^{2}+\sigma_{\epsilon}^{2}}\right]. (57)

We compare the marginalised and profiled forms of the Gaussian likelihood for a toy problem with x=10 and \sigma=1 in the first panel of Fig. 6, assuming \sigma_{\epsilon}=0.5 or \sigma_{\epsilon}=2.

#### 8.3.3 Profiled Gaussian limits

The simplest reasonable approximation to the underlying likelihood associated with an upper limit on an observable \mu is to assume flatness below some canonical ‘observed’ or limiting value x, and to model the drop-off at \mu>x with a Gaussian of width \sigma. This defines the piecewise function

 \mathcal{L}_{\mathrm{G}\overline{\uparrow}}(x|\mu)=\begin{cases}\frac{1}{\sqrt% {2\pi}\sigma},&\mathrm{if}\ \mu\leq x\\ \frac{1}{\sqrt{2\pi}\sigma}\exp\left[-\frac{1}{2}\frac{(x-\mu)^{2}}{\sigma^{2}% }\right],&\mathrm{if}\ \mu\geq x.\end{cases} (58)

This treatment can be used to directly convert a measured value into a limit likelihood. An example is the relic density of dark matter \Omega_{\chi}h^{2}, which has been measured rather precisely, but may not consist exclusively of the dark matter candidate present in any particular BSM theory under investigation. The same treatment can also be used to implement likelihoods associated with published upper limits, but additional modelling is required to recover the equivalent central value x and falloff width \sigma from a published limit. Typically limits at two different CLs are needed to uniquely determine both x and \sigma.

Including an uncertainty from some auxiliary nuisance observable \epsilon proceeds similarly to the pure Gaussian case,

 \displaystyle\mathcal{L}_{\mathrm{G}\overline{\uparrow},\mathrm{prof}}(x|\mu)=% \frac{1}{2\pi\sigma\sigma_{\epsilon}}\max\left\{\max_{\epsilon\leq x-\mu}\exp% \left[-\frac{\epsilon^{2}}{2\sigma_{\epsilon}^{2}}\right],\right. \displaystyle               \left.\max_{\epsilon\geq x-\mu}\exp\left[-\frac{(x% -\mu-\epsilon)^{2}}{2\sigma^{2}}-\frac{\epsilon^{2}}{2\sigma_{\epsilon}^{2}}% \right]\right\}. (59)

Despite the need to carefully piecewise maximise in the different regimes, this leads to the simple result

 \mathcal{L}_{\mathrm{G}\overline{\uparrow},\mathrm{prof}}(x|\mu)=\begin{cases}% \frac{1}{2\pi\sigma\sigma_{\epsilon}},&\mathrm{if}\ \mu\leq x\\ \frac{1}{2\pi\sigma\sigma_{\epsilon}}\exp\left[-\frac{1}{2}\frac{(x-\mu)^{2}}{% \sigma^{2}+\sigma_{\epsilon}^{2}}\right],&\mathrm{if}\ \mu\geq x.\end{cases} (60)

The corresponding expression \mathcal{L}_{\mathrm{G}\underline{\downarrow},\mathrm{prof}}(x|\mu) for a lower limit is identical, except that the inequalities relating x and \mu are reversed.

The simplicity of Eq. 60 is somewhat beguiling. Incorrectly using this expression when \epsilon and \sigma_{\epsilon} are interpreted in a Bayesian manner can lead to behaviour of the test statistic that is undesirable in a frequentist analysis. For example, if \sigma_{\epsilon} varies over the parameter space, the likelihood function will not actually be flat for \mu\leq x, despite the fact that the data make no statement about neighbouring values of \mu in this region, and therefore neither should a sensible profile likelihood. An example of this behaviour can be seen in the second panel of Fig. 6. In such cases, it is important to carefully decide on the interpretation of \epsilon and \sigma_{\epsilon} from the outset. If they cannot be interpreted in a strict frequentist sense, then the marginalised variants of the likelihoods discussed here should be adopted instead, even when the final goal of a BSM scan is to produce profile likelihood results.

#### 8.3.4 Marginalised Gaussian limits

To produce the marginalised form of Eq. 58, we again integrate the joint likelihood over all possible \epsilon,

 \displaystyle\mathcal{L}_{\mathrm{G}\overline{\uparrow},\mathrm{marg}}(x|\mu,% \sigma_{\epsilon})=\frac{1}{2\pi\sigma\sigma_{\epsilon}}\int_{-\infty}^{x-\mu}% \exp\left[-\frac{\epsilon^{2}}{2\sigma_{\epsilon}^{2}}\right]\,\mathrm{d}\epsilon \displaystyle+\int_{x-\mu}^{\infty}\exp\left[-\frac{(x-\mu-\epsilon)^{2}}{2% \sigma^{2}}-\frac{\epsilon^{2}}{2\sigma_{\epsilon}^{2}}\right]\,\mathrm{d}\epsilon \displaystyle, (61)

 \displaystyle\mathcal{L}_{\mathrm{G}\overline{\uparrow},\mathrm{marg}}(x|\mu,% \sigma_{\epsilon})=\frac{1}{2^{3/2}\sqrt{\pi}}\left[\frac{1}{\sqrt{\sigma^{2}+% \sigma_{\epsilon}^{2}}}e^{-\frac{1}{2}\frac{(x-\mu)^{2}}{\sigma^{2}+\sigma_{% \epsilon}^{2}}}\right. \displaystyle\left.\times\,\mathrm{erfc}\left(\frac{\sigma}{\sigma_{\epsilon}}% \frac{x-\mu}{\sqrt{2(\sigma^{2}+\sigma_{\epsilon}^{2})}}\right)+\frac{1}{% \sigma}\mathrm{erfc}\left(\frac{\mu-x}{\sqrt{2}\sigma_{\epsilon}}\right)% \vphantom{\frac{e^{\frac{1}{2}\frac{(x-\mu)^{2}}{\sigma^{2}+\sigma_{\epsilon}^% {2}}}}{\sqrt{\sigma^{2}+\sigma_{\epsilon}^{2}}}}\right], (62)

where \mathrm{erfc}(x)=\operatorname{erf}(1-x) is the complementary error function. We can now see that

 \lim_{\mu\to-\infty}\mathcal{L}_{\mathrm{G}\overline{\uparrow},\mathrm{marg}}(% x|\mu,\sigma_{\epsilon})=\frac{1}{\sqrt{2\pi}\sigma}, (63)

regardless of \sigma_{\epsilon}, and precisely as one would prefer a sensibly-behaved profile likelihood to do. This behaviour can be seen in the second panel of Fig. 6.

The corresponding marginalised likelihood for a lower limit \mathcal{L}_{\mathrm{G}\underline{\downarrow},\mathrm{marg}}(x|\mu,\sigma_{% \epsilon}) is obtained by making the replacements x\rightarrow-x and \mu\rightarrow-\mu in Eq. 8.3.4.

#### 8.3.5 Profiled log-normal

A log-normal likelihood describes the situation where the distribution of the logarithm of some observation is expected to be Gaussian over repeated experiments. This may occur in cases where, for example, observations must return positive values by construction. The likelihood takes the form

 \mathcal{L}_{\mathrm{LN}}(x|\mu)=\frac{1}{\sqrt{2\pi}\sigma^{\prime}x}\exp% \left[-\frac{1}{2}\frac{(\ln\frac{x}{\mu})^{2}}{\sigma^{\prime 2}}\right]. (64)

Here x and \mu remain the observed and predicted values of the observable, and the Gaussian distribution for \ln x is centred on \ln\mu. The Gaussian width is \sigma^{\prime}, which is related to \sigma_{\mathrm{rel}}, the relative uncertainty on x, as

 \sigma^{\prime}\equiv\ln(1+\sigma_{\mathrm{rel}})=\ln(1+\sigma/x). (65)

This likelihood describes statistical variation in the scale of an observable, and is therefore most prone to the effects of systematics also able to impact that scale. In this case, \epsilon takes the form of an auxiliary multiplicative source of error, with the corresponding additive offset given by \ln\epsilon. It is therefore appropriate to model the distribution of \epsilon with a log-normal centred on 1. The corresponding width \sigma^{\prime}_{\epsilon} is then given by

 \sigma^{\prime}_{\epsilon}\equiv\ln(1+\sigma_{\epsilon,\mathrm{rel}})=\ln(1+% \sigma_{\epsilon}/\mu). (66)

The joint likelihood is then

 \mathcal{L}_{\mathrm{LN}}=\frac{1}{\sqrt{2\pi}\sigma^{\prime}\sigma^{\prime}_{% \epsilon}x\epsilon}\exp\left[-\frac{(\ln\frac{x}{\epsilon\mu})^{2}}{2\sigma^{% \prime 2}}-\frac{(\ln\epsilon)^{2}}{2\sigma^{\prime 2}_{\epsilon}}\right]. (67)

This has its maximum at

 \hat{\epsilon}=\exp\left[\frac{\sigma^{\prime 2}_{\epsilon}(\ln\frac{x}{\mu}-% \sigma^{\prime 2})}{\sigma^{\prime 2}+\sigma^{\prime 2}_{\epsilon}}\right], (68)

 \displaystyle\mathcal{L}_{\mathrm{LN,prof}}(x|\mu)= \displaystyle\frac{1}{x\sqrt{2\pi}\sigma^{\prime}\sigma^{\prime}_{\epsilon}}% \exp\left[-\frac{1}{2}\frac{\left(\ln\frac{x}{\epsilon\mu}\right)^{2}+\sigma^{% \prime 2}_{\epsilon}\ln\frac{x}{\mu}-\sigma^{\prime 2}\sigma^{\prime 2}_{% \epsilon}}{\sigma^{\prime 2}+\sigma^{\prime 2}_{\epsilon}}\right]. (69)

#### 8.3.6 Marginalised log-normal

Integrating Eq. 67 over \epsilon instead of maximising it gives the marginalised log-normal likelihood:

 \mathcal{L}_{\mathrm{LN,marg}}(x|\mu)=\frac{1}{x\sqrt{2\pi(\sigma^{\prime 2}+% \sigma^{\prime 2}_{\epsilon})}}\exp\left[-\frac{1}{2}\frac{(\ln\frac{x}{\mu})^% {2}}{\sigma^{\prime 2}+\sigma^{\prime 2}_{\epsilon}}\right]. (70)

In the lower panels of Fig. 6, we compare the marginalised and profiled forms of the log-normal likelihood, for the same toy problem as discussed previously (x=10 and \sigma=1). As in the Gaussian case, the profiled and marginalised versions show very similar behaviour, despite the fact that unlike the Gaussian case, they posses somewhat different functional forms. Here we also show the additional features that can be induced at low \mu if a constant value of the absolute systematic \sigma_{\epsilon} is employed with the log-normal likelihood, rather than a constant relative uncertainty \sigma_{\epsilon,\mathrm{rel}}.

## 9 Output

Output from GAMBIT scans is handled by the Printer subsystem, which generalises the writing of scan data to disk or any other output medium. It is designed so that the output format can be chosen at runtime with options in the master YAML file. Print commands within GAMBIT are issued via a general abstract interface, while the actual writing of data to the chosen output medium is handled by one of several derived classes, known as printers.

The actual print commands are automatically issued by GAMBIT whenever it runs a module function, so writers of new module functions need not concern themselves with how to send information to the printer system. Most users only need to know how to set up a printer via the master YAML file, and what the format of the output is. Sec. 6.6 covers the YAML setup. We deal with the main output format in Sec. 9.1, and the output formats of specific printers in 9.2.

There are three main scenarios that require additional knowledge of the printer system. One is writing a D, where one must use the printer interface class to output e.g. probability weights or likelihoods. We discuss this briefly in Sec. 9.2.1, but we refer readers to the ScannerBit paper ScannerBit () for a full exposition. Another is when a user wishes to make an existing printer emit a new C++ type, to e.g. allow a new module function returning a custom type to print its result. We deal with this in Sec. 9.3. The final scenario is writing a new printer, for outputting GAMBIT data in a new format. This is a straightforward but quite specialised task, requiring complete knowledge of the class structure of the printer subsystem. The requisite details are left to documentation shipped with the code (found in doc/writing_printers.pdf)

### 9.1 Overview of the output format

Other than in scanner plugin code (see Ref. ScannerBit ()), print commands are issued automatically to the GAMBIT printer system. This occurs after the evaluation of each module function that has been requested for printing from the master YAML file (see Sec. 6.6). Nonetheless, it useful to know how this system works when interpreting its output. The printer system receives print commands via functions with the signature

void _print(@\metavar{type}@ const& result,
const std::string& label,
const int IDcode,
const unsigned int MPIrank,
const unsigned long pointID);

These contain the following information:

result

The result computed by the module function (printable only if type is registered as printable and has an appropriate function overload defined; see Sec. 9.3).

label

A string describing the result of the module function. It typically has the format

"#*@\metavar{capability}@* @*@\metavar{module}@*::*@\metavar{function}@*"

where capability, module and function are respectively the D, host module and actual name of the module function that issued the print command. It is left to individual printers to decide what to do with this information (see Secs. 9.2.1 and 9.2.2).

IDcode

A unique integer automatically assigned to each module function for the duration of a scan. This allows printers to identify the origin of each print command without parsing the label string. Generally this number will not be passed on to the output file.

MPIrank

The process rank assigned by MPI. Along with pointID this is needed to identify which parameter space point triggered a given print command.

pointID

A unique integer automatically assigned to every parameter combination evaluated by a given MPI process in a scan. The pointID is not unique across processes, so both MPIrank and pointID need to be used in combination to obtain a globally unique identifier.

These arguments are the totality of information known to the printer at the time of each print command. It is then the job of the printer to assemble this information, from many print commands, into a coherent set of outputs.

Print commands can also be issued by ScannerBit or its plugins. By default, ScannerBit prints the final result returned to it for each model point (i.e. the total log-likelihood returned by the D).222222Technically, what is returned to the scanner is actually determined by the D(s) that the user has associated with their chosen scanner or test function plugin in the master YAML file (see Sec. 8). When using ScannerBit standalone however, anything can actually be connected to the scanner as its main objective function, and it will still be printed by default. However, scanners will often have other information that they want to record about each model point, and this can be added via manual calls to the print commands. Details can be found in the ScannerBit paper ScannerBit ().

In addition to the module function, likelihoood container and scanner plugin outputs sent to the printer, the MPIrank and pointID are also automatically printed for every point. This allows printers the option of writing new data back to previous points. For example, the MultiNest scanner plugin computes posterior probability weights for a subset of points, long after the likelihood function is evaluated at those points. With this setup, such information can be inserted directly into the existing output medium at the position associated with those points, rather than having to write an entirely new output stream, as occurs in the native MultiNest output. It is up to the individual printers exactly how they handle this; for example, the ascii printer will write out a new file as MultiNest itself does, but the hdf5 printer will automatically update existing HDF5 files with new data about old points.

### 9.2 Available printers

Here we give specific details of how print commands are translated into files on disk by the ascii and hdf5 printers. This is essential information for interpreting the output of each printer.

#### 9.2.1 ASCII output

The output file produced by the ascii printer (as named by the output_file option; see Sec. 6.6.1) consists of a simple whitespace-separated table of floating point numbers. The table is produced as follows. First, the GAMBIT module functions that are registered for printing issue print commands to the primary print stream, as they are each evaluated, and the result data is stored in a buffer. The print commands contain the MPIrank and pointID (see Sec. 9.1) identifying the model point that produced the data. By monitoring when these identifiers change, the printer detects when the scanner has moved to a new model point. Upon detecting a new point, the buffer begins a new line. Once the buffer is filled with a preset maximum number of lines, it is written to disk.

The structure of the ASCII output table (i.e. which data should be assigned to which column) is determined exclusively from the contents of the buffer immediately before the first dump. This imposes some extra restrictions on the data that the ascii printer can handle. For example, variable-length vectors of data can be printed, but at least one example with the maximum length expected in an entire scan must be sent to the printer before the first buffer dump, otherwise there will be insufficient space allocated in the output table to accommodate the longest such vectors in subsequent dumps.

To interpret the contents of the resulting ASCII file, an accompanying “info” file is produced at the time of the first buffer dump. The info file contains a list of labels identifying the columns of the output data file. If the data file is named output.data, then the info file will be output.data_info. When running GAMBIT via MPI, a separate output file will be produced for each process, with the rank of the host process appended to the root filename. An example info file describing output generated by fitting a normal distribution with MultiNest MultiNest ()232323See the ScannerBit paper ScannerBit () for details of the GAMBIT interface to MultiNest. is shown below:

Column 1: unitCubeParameters[0]
Column 2: unitCubeParameters[1]
Column 3: MPIrank
Column 4: pointID
Column 5: LogLikelihood
Column 6: #NormalDist_parameters \
@NormalDist::primary_parameters::mu
Column 7: #NormalDist_parameters \
@NormalDist::primary_parameters::sigma
Column 8: #normaldist_loglike \
@ExampleBit_A::normaldist_loglike

In this example the LogLikelihood (column 5) contains the global log-likelihood used to drive MultiNest. It consists of only one component, given in column 8: the log-likelihood returned by the normal distribution log-likelihood function normaldist_loglike from the module ExampleBit_A. Model parameter values are given in columns 6 and 7. The first two columns contain “unit hypercube” parameters, which are the raw unit-interval samples produced by MultiNest, before being transformed into the actual model parameter values by ScannerBit ScannerBit (). The MPIrank and pointID entries contain the model point identification data (Sec. 9.1).

Print statements originating from scanner plugins can be issued directly to the main printer — in which case they will be treated the same as module function output — or they can be issued to an auxiliary print stream if the data are not synchronised with the likelihood evaluations. Instructions for correctly handling this kind of data when writing scanner plugins are given elsewhere ScannerBit (). In the example above, unlike in the the native MultiNest output format, there are no posterior weights. These are issued to an auxiliary print stream in the MultiNest scanner plugin, so they end up in a different output file. The auxiliary file is also a plain ASCII table, and it comes with its own info file describing its contents:

Column 1: Posterior
Column 2: MPIrank
Column 3: pointID

The Posterior column contains the posterior weights, and the MPIrank and pointID contain the point identification data as before. Because MPIrank and pointID are shared between output files, they can be used to correlate Posterior weights with other data about the point during post-run analysis. GAMBIT could in principle perform this combination automatically at the end of a run, however it is currently left up to user’s preferred post-run analysis tools. Note that the hdf5 printer does automatically combine the auxiliary print stream data with the primary print stream data, so it is the more convenient format to use when working with auxiliary print data like posterior weights.

#### 9.2.2 HDF5 output

The output file produced by the hdf5 printer is set with the output_file option (Sec. 6.6.3). It contains a separate data record for every output quantity, each of length equal to the number of parameter space points evaluated during the scan. These datasets are located according to the group option (Sec. 6.6.3). The command-line utility h5ls (included in most HDF5 library distributions) can be used to probe the internal layout of an HDF5 file. This can be useful for