gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool
VectorSingletDM.cpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
26 
31 #include "boost/make_shared.hpp"
33 
34 namespace Gambit
35 {
36 
37  namespace DarkBit
38  {
39 
40  class VectorSingletDM
41  {
42  public:
44  VectorSingletDM(
45  TH_ProcessCatalog* const catalog,
46  double gammaH,
47  double vev,
48  double alpha_strong)
49  : Gamma_mh(gammaH), v0 (vev),
50  alpha_s (alpha_strong)
51  {
52  mh = catalog->getParticleProperty("h0_1").mass;
53  mb = catalog->getParticleProperty("d_3").mass;
54  mc = catalog->getParticleProperty("u_2").mass;
55  mtau = catalog->getParticleProperty("e-_3").mass;
56  mt = catalog->getParticleProperty("u_3").mass;
57  mZ0 = catalog->getParticleProperty("Z0").mass;
58  mW = catalog->getParticleProperty("W+").mass;
59  };
60  ~VectorSingletDM() {}
61 
63  double Dh2 (double s)
64  {
65  return 1/((s-mh*mh)*(s-mh*mh)+mh*mh*Gamma_mh*Gamma_mh);
66  }
67 
74  double sv(std::string channel, double lambda, double mass, double v)
75  {
76  // Note: Valid for mass > 45 GeV
77  double s = 4*mass*mass/(1-v*v/4);
78  double sqrt_s = sqrt(s);
79  if ( sqrt_s < 90 )
80  {
82  "VectorSingletDM sigmav called with sqrt_s < 90 GeV.");
83  return 0;
84  }
85 
86  if ( channel == "hh" )
87  {
88  if ( sqrt_s > mh*2 )
89  {
90  return sv_hh(lambda, mass, v);
91  }
92  else return 0;
93  }
94 
95  if ( channel == "bb" and sqrt_s < mb*2 ) return 0;
96  if ( channel == "cc" and sqrt_s < mc*2 ) return 0;
97  if ( channel == "tautau" and sqrt_s < mtau*2 ) return 0;
98  if ( channel == "tt" and sqrt_s < mt*2 ) return 0;
99  if ( channel == "ZZ" and sqrt_s < mZ0*2) return 0;
100  if ( channel == "WW" and sqrt_s < mW*2) return 0;
101 
102  if ( sqrt_s < 300 )
103  {
104  double br = virtual_SMHiggs_widths(channel,sqrt_s);
105  double Gamma_s = virtual_SMHiggs_widths("Gamma",sqrt_s);
106  double GeV2tocm3s1 = gev2cm2*s2cm;
107  double y = s/pow(mass, 2);
108 
109  // Explicitly close channel for off-shell top quarks
110  if ( channel == "tt" and sqrt_s < mt*2) return 0;
111 
112  double res = 2*lambda*lambda*v0*v0*(1-y/3 + pow(y,2)/12)/3/
113  sqrt_s*Dh2(s)*Gamma_s*GeV2tocm3s1*br;
114  return res;
115  }
116  else
117  {
118  if ( channel == "bb" ) return sv_ff(lambda, mass, v, mb, true);
119  if ( channel == "cc" ) return sv_ff(lambda, mass, v, mc, true);
120  if ( channel == "tautau" ) return sv_ff(lambda, mass, v, mtau, false);
121  if ( channel == "tt" ) return sv_ff(lambda, mass, v, mt, true);
122  if ( channel == "ZZ" ) return sv_ZZ(lambda, mass, v);
123  if ( channel == "WW" ) return sv_WW(lambda, mass, v);
124  }
125  return 0;
126  }
127 
128  // Annihilation into W bosons.
129  double sv_WW(double lambda, double mass, double v)
130  {
131  double s = 4*mass*mass/(1-v*v/4);
132  double x = pow(mW,2)/s;
133  double y = s/pow(mass, 2);
134  double GeV2tocm3s1 = gev2cm2*s2cm;
135  return pow(lambda,2)*s/24/M_PI*sqrt(1-4*x)*(1-y/3 + pow(y,2)/12)*
136  Dh2(s)*(1-4*x+12*pow(x,2))*GeV2tocm3s1;
137  }
138 
139  // Annihilation into Z bosons.
140  double sv_ZZ(double lambda, double mass, double v)
141  {
142  double s = 4*mass*mass/(1-v*v/4);
143  double x = pow(mZ0,2)/s;
144  double y = s/pow(mass, 2);
145  double GeV2tocm3s1 = gev2cm2*s2cm;
146  return pow(lambda,2)*s/48/M_PI*sqrt(1-4*x)*(1-y/3 + pow(y,2)/12)*
147  Dh2(s)*(1-4*x+12*pow(x,2))*GeV2tocm3s1;
148  }
149 
150  // Annihilation into fermions
151  double sv_ff(
152  double lambda, double mass, double v, double mf, bool is_quark)
153  {
154  double s = 4*mass*mass/(1-v*v/4);
155  double vf = sqrt(1-4*pow(mf,2)/s);
156  double y = s/pow(mass, 2);
157  double Xf = 1;
158  if ( is_quark ) Xf = 3 *
159  (1+(3/2*log(pow(mf,2)/s)+9/4)*4*alpha_s/3/M_PI);
160  double GeV2tocm3s1 = gev2cm2*s2cm;
161  return pow(lambda,2)*(1-y/3 + pow(y,2)/12)*
162  pow(mf,2)/12/M_PI*Xf*pow(vf,3) * Dh2(s) *GeV2tocm3s1;
163  }
164 
166  double sv_hh(double lambda, double mass, double v)
167  {
168  // Hardcode lower limit for velocity to avoid nan results.
169  v = std::max(v, 1e-6);
170  double GeV2tocm3s1 = gev2cm2*s2cm;
171  double s = 4*mass*mass/(1-v*v/4); // v is relative velocity
172  double xV = mass*mass/s;
173  double xH = mh*mh/s;
174  double xG = Gamma_mh*mh/s;
175  double beta = (s - 2*pow(mh,2))/sqrt((s - 4*pow(mh,2))*(s - 4*pow(mass,2)));
176  double vH = sqrt(1-4*xH);
177 
178  return GeV2tocm3s1*(vH*pow(lambda,2)*pow(s,-3)*pow(xV,-4)*pow(pow(xG,2) + pow(-1 + xH,2),-1)*
179  ((4*lambda*s*xV*(1 - 6*xV + xH*(2 + 4*xV))*pow(v0,2)*(1 + xH + pow(xG,2) - 2*pow(xH,2))*(xV - 4*xH*xV + pow(xH,2)) +
180  4*(1 + 4*xV*(-1 + 3*xV))*pow(s,2)*(xV - 4*xH*xV + pow(xH,2))*(pow(xG,2) + pow(1 + 2*xH,2))*pow(xV,2) +
181  pow(lambda,2)*pow(v0,4)*(pow(xG,2) + pow(-1 + xH,2))*(xV + (1 + 12*xV*(-1 + 4*xV))*pow(xH,2) + (4 - 32*xV)*pow(xH,3) + 6*pow(xH,4) - 64*xH*pow(xV,3) +
182  96*pow(xV,4)))*pow(xV - 4*xH*xV + pow(xH,2),-1) - 8*beta*lambda*(-1 + 4*xH)*atanh(1/beta)*pow(v0,2)*pow(1 - 2*xH,-1)*
183  (2*s*(-1 + 2*xH)*xV*((-1 + xH)*(1 + 2*xH) - pow(xG,2))*(2*xV*pow(-1 + xH,2) + pow(xH,2) - 4*(1 + 2*xH)*pow(xV,2) + 24*pow(xV,3)) -
184  lambda*pow(v0,2)*(pow(xG,2) + pow(-1 + xH,2))*(-8*xV*pow(xH,3) + 3*pow(xH,4) - pow(xH,2)*(1 + 8*pow(xV,2)) + 4*xH*(xV + 8*pow(xV,3)) -
185  2*xV*(1 - 2*xV + 24*pow(xV,3))))*pow(1 - 6*xH + 8*pow(xH,2),-1)))/(2304*M_PI);
186  }
187 
188  private:
189  double Gamma_mh, mh, v0, alpha_s, mb, mc, mtau, mt, mZ0, mW;
190  };
191 
192  void DarkMatter_ID_VectorSingletDM(std::string& result) { result = "V"; }
193  void DarkMatterConj_ID_VectorSingletDM(std::string& result) { result = "V"; }
194 
197  {
200  const SubSpectrum& he = spec.get_HE();
201  double mass = spec.get(Par::Pole_Mass,"V");
202  double lambda = he.get(Par::dimensionless,"lambda_hV");
203  double mh = spec.get(Par::Pole_Mass,"h0_1");
204 
205  // Expressions taken from Cline et al. (2013, PRD 88:055025, arXiv:1306.4710)
206  double fp = 2./9. + 7./9.*(*Param["fpu"] + *Param["fpd"] + *Param["fps"]);
207  double fn = 2./9. + 7./9.*(*Param["fnu"] + *Param["fnd"] + *Param["fns"]);
208 
209  result.gps = lambda*fp*m_proton/pow(mh,2)/mass/2;
210  result.gns = lambda*fn*m_neutron/pow(mh,2)/mass/2;
211  result.gpa = 0; // Only SI cross-section
212  result.gna = 0;
213 
214  logger() << LogTags::debug << "Vector DM DD couplings:" << std::endl;
215  logger() << " gps = " << result.gps << std::endl;
216  logger() << " gns = " << result.gns << std::endl;
217  logger() << " gpa = " << result.gpa << std::endl;
218  logger() << " gna = " << result.gna << EOM;
219 
220  } // function DD_couplings_VectorSingletDM_Z2
221 
224  {
226  using std::vector;
227  using std::string;
228 
229  // Initialize empty catalog
230  TH_ProcessCatalog catalog;
231  TH_Process process_ann("V", "V");
232 
233  // Explicitly state that Vector DM is self-conjugate
234  process_ann.isSelfConj = true;
235 
237  // Import particle masses and couplings
239 
240  // Convenience macros
241  #define getSMmass(Name, spinX2) \
242  catalog.particleProperties.insert(std::pair<string, TH_ParticleProperty> \
243  (Name , TH_ParticleProperty(SM.get(Par::Pole_Mass,Name), spinX2)));
244  #define addParticle(Name, Mass, spinX2) \
245  catalog.particleProperties.insert(std::pair<string, TH_ParticleProperty> \
246  (Name , TH_ParticleProperty(Mass, spinX2)));
247 
248  // Import Spectrum objects
250  const SubSpectrum& he = spec.get_HE();
251  const SubSpectrum& SM = spec.get_LE();
252  const SMInputs& SMI = spec.get_SMInputs();
253 
254  // Import couplings
255  double lambda = he.get(Par::dimensionless,"lambda_hV");
256  double v = he.get(Par::mass1,"vev");
257  double alpha_s = SMI.alphaS; // alpha_s(mZ)^MSbar
258 
259  // Get SM pole masses
260  getSMmass("e-_1", 1)
261  getSMmass("e+_1", 1)
262  getSMmass("e-_2", 1)
263  getSMmass("e+_2", 1)
264  getSMmass("e-_3", 1)
265  getSMmass("e+_3", 1)
266  getSMmass("Z0", 2)
267  getSMmass("W+", 2)
268  getSMmass("W-", 2)
269  getSMmass("g", 2)
270  getSMmass("gamma", 2)
271  getSMmass("u_3", 1)
272  getSMmass("ubar_3", 1)
273  getSMmass("d_3", 1)
274  getSMmass("dbar_3", 1)
275 
276  // Pole masses not available for the light quarks.
277  addParticle("u_1" , SMI.mU, 1) // mu(2 GeV)^MS-bar, not pole mass
278  addParticle("ubar_1", SMI.mU, 1) // mu(2 GeV)^MS-bar, not pole mass
279  addParticle("d_1" , SMI.mD, 1) // md(2 GeV)^MS-bar, not pole mass
280  addParticle("dbar_1", SMI.mD, 1) // md(2 GeV)^MS-bar, not pole mass
281  addParticle("u_2" , SMI.mCmC,1) // mc(mc)^MS-bar, not pole mass
282  addParticle("ubar_2", SMI.mCmC,1) // mc(mc)^MS-bar, not pole mass
283  addParticle("d_2" , SMI.mS, 1) // ms(2 GeV)^MS-bar, not pole mass
284  addParticle("dbar_2", SMI.mS, 1) // ms(2 GeV)^MS-bar, not pole mass
285 
286  // Masses for neutrino flavour eigenstates. Set to zero.
287  // (presently not required)
288  addParticle("nu_e", 0.0, 1)
289  addParticle("nubar_e", 0.0, 1)
290  addParticle("nu_mu", 0.0, 1)
291  addParticle("nubar_mu", 0.0, 1)
292  addParticle("nu_tau", 0.0, 1)
293  addParticle("nubar_tau",0.0, 1)
294 
295  // Higgs-sector masses
296  double mV = spec.get(Par::Pole_Mass,"V");
297  double mH = spec.get(Par::Pole_Mass,"h0_1");
298  addParticle("V", mV, 2) // Vector DM
299  addParticle("h0_1", mH, 0) // SM-like Higgs
300  addParticle("pi0", meson_masses.pi0, 0)
301  addParticle("pi+", meson_masses.pi_plus, 0)
302  addParticle("pi-", meson_masses.pi_minus, 0)
303  addParticle("eta", meson_masses.eta, 0)
304  addParticle("rho0", meson_masses.rho0, 1)
305  addParticle("rho+", meson_masses.rho_plus, 1)
306  addParticle("rho-", meson_masses.rho_minus, 1)
307  addParticle("omega", meson_masses.omega, 1)
308 
309  // Get rid of convenience macros
310  #undef getSMmass
311  #undef addParticle
312 
314  // Import Decay information
316 
317  // Import decay table from DecayBit
318  const DecayTable* tbl = &(*Dep::decay_rates);
319 
320  // Save Higgs width for later
321  double gammaH = tbl->at("h0_1").width_in_GeV;
322 
323  // Set of imported decays
324  std::set<string> importedDecays;
325 
326  // Minimum branching ratio to include
327  double minBranching = 0;
328 
329  // Import relevant decays (only Higgs and subsequent decays)
331  // Notes: Virtual Higgs decays into offshell W+W- final states are not
332  // imported. All other channels are correspondingly rescaled. Decay
333  // into VV final states is accounted for, leading to zero photons.
334  ImportDecays("h0_1", catalog, importedDecays, tbl, minBranching,
335  daFunk::vec<std::string>("Z0", "W+", "W-", "e+_2", "e-_2", "e+_3", "e-_3"));
336 
337  // Instantiate new VectorSingletDM_Z2 object
338  auto vectorDM = boost::make_shared<VectorSingletDM>(&catalog, gammaH, v, alpha_s);
339 
340  // Populate annihilation channel list and add thresholds to threshold
341  // list.
342  // (remark: the lowest threshold is here = 2*mV, whereas in DS-internal
343  // conventions, this lowest threshold is not listed)
344  process_ann.resonances_thresholds.threshold_energy.push_back(2*mV);
345  auto channel =
346  daFunk::vec<string>("bb", "WW", "cc", "tautau", "ZZ", "tt", "hh");
347  auto p1 =
348  daFunk::vec<string>("d_3", "W+", "u_2", "e+_3", "Z0", "u_3", "h0_1");
349  auto p2 =
350  daFunk::vec<string>("dbar_3","W-", "ubar_2","e-_3", "Z0", "ubar_3","h0_1");
351  {
352  for ( unsigned int i = 0; i < channel.size(); i++ )
353  {
354  double mtot_final =
355  catalog.getParticleProperty(p1[i]).mass +
356  catalog.getParticleProperty(p2[i]).mass;
357  // Include final states that are open for T~m/20
358  if ( mV*2 > mtot_final*0.5 )
359  {
360  daFunk::Funk kinematicFunction = daFunk::funcM(vectorDM,
361  &VectorSingletDM::sv, channel[i], lambda, mV, daFunk::var("v"));
362  TH_Channel new_channel(
363  daFunk::vec<string>(p1[i], p2[i]), kinematicFunction
364  );
365  process_ann.channelList.push_back(new_channel);
366  }
367  if ( mV*2 > mtot_final )
368  {
370  push_back(mtot_final);
371  }
372  }
373  }
374 
375  // Populate resonance list
376  if ( mH >= mV*2 ) process_ann.resonances_thresholds.resonances.
377  push_back(TH_Resonance(mH, gammaH));
378 
379  catalog.processList.push_back(process_ann);
380 
381  // Validate
382  catalog.validate();
383 
384  result = catalog;
385 
386  } // function TH_ProcessCatalog_VectorSingletDM_Z2
387  }
388 }
std::vector< TH_Channel > channelList
List of channels.
double get(const Par::Tags partype, const std::string &mass) const
Definition: spectrum.cpp:249
Simple function for returning SM Higgs partial and total widths as a function of virtuality, as read from data files from CERN Yellow Paper arXiv:1101.0593.
const double m_proton
std::vector< TH_Resonance > resonances
Entry & at(std::pair< int, int >)
Get entry in decay table for a give particle, throwing an error if particle is absent.
START_MODEL beta
Definition: Axions.hpp:36
void ImportDecays(std::string pID, TH_ProcessCatalog &catalog, std::set< std::string > &importedDecays, const DecayTable *tbl, double minBranching, std::vector< std::string > excludeDecays=std::vector< std::string >())
Funk funcM(O *obj, double(O::*f)(funcargs...), Args... args)
Definition: daFunk.hpp:861
const double s2cm
const double m_neutron
void TH_ProcessCatalog_VectorSingletDM_Z2(DarkBit::TH_ProcessCatalog &result)
Set up process catalog for the VectorSingletDM_Z2 model.
Simple reader for ASCII tables.
const double mt
Definition: topness.h:39
START_MODEL v0
Funk var(std::string arg)
Definition: daFunk.hpp:921
const double mW
Definition: topness.h:40
double virtual_SMHiggs_widths(str, double)
Higgs branching ratios and total width Gamma [GeV], as function of mass [GeV] (90 - 300 GeV) ...
Piped_invalid_point piped_invalid_point
Global instance of piped invalid point class.
Definition: exceptions.cpp:544
bool isSelfConj
Does the process contain self-conjugate DM? (accounting for correct factors of 1/2 in annihilation sp...
A single resonance of a given width at a given energy (both in GeV)
virtual double get(const Par::Tags, const str &, const SpecOverrideOptions=use_overrides, const SafeBool check_antiparticle=SafeBool(true)) const =0
TH_resonances_thresholds resonances_thresholds
List of resonances and thresholds.
double width_in_GeV
Total particle width (in GeV)
A container holding all annihilation and decay initial states relevant for DarkBit.
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
Header file that includes all GAMBIT headers required for a module source file.
EXPORT_SYMBOLS Logging::LogMaster & logger()
Function to retrieve a reference to the Gambit global log object.
Definition: logger.cpp:95
#define addParticle(Name, Mass, spinX2)
void DD_couplings_VectorSingletDM_Z2(DM_nucleon_couplings &result)
Direct detection couplings for the VectorSingletDM_Z2 model.
SubSpectrum & get_LE()
Standard getters Return references to internal data members.
Definition: spectrum.cpp:224
All data on a single annihilation or decay channel, e.g.
const double gev2cm2
double lambda(double x, double y, double z)
Definition: MSSM_H.hpp:38
Virtual base class for interacting with spectrum generator output.
Definition: subspectrum.hpp:87
Rollcall header for module DarkBit.
GAMBIT native decay table class.
Definition: decay_table.hpp:35
Spectrum Spectrum Spectrum Spectrum VectorSingletDM_Z2_spectrum
double pow(const double &a)
Outputs a^i.
Spectrum Spectrum Spectrum Spectrum Spectrum Spectrum mh
void request(std::string message)
Request an exception.
Definition: exceptions.cpp:471
void DarkMatter_ID_VectorSingletDM(std::string &result)
void DarkMatterConj_ID_VectorSingletDM(std::string &result)
A container for a single process.
#define getSMmass(Name, spinX2)
shared_ptr< FunkBase > Funk
Definition: daFunk.hpp:113
TODO: see if we can use this one:
Definition: Analysis.hpp:33
SubSpectrum & get_HE()
Definition: spectrum.cpp:225
"Standard Model" (low-energy) plus high-energy model container class
Definition: spectrum.hpp:110
SMInputs & get_SMInputs()
Definition: spectrum.cpp:226
Utility functions for DarkBit.
Container class for Standard Model input information (defined as in SLHA2)
Definition: sminputs.hpp:29