gambit is hosted by Hepforge, IPPP Durham
GAMBIT  v1.5.0-2191-ga4742ac
a Global And Modular Bsm Inference Tool
SpecBit_MSSM.cpp
Go to the documentation of this file.
1 // GAMBIT: Global and Modular BSM Inference Tool
2 // *********************************************
32 
33 #include <string>
34 #include <sstream>
35 #include <cmath>
36 #include <complex>
37 
43 #include "gambit/Utils/stream_overloads.hpp" // Just for more convenient output to logger
49 #include "gambit/SpecBit/model_files_and_boxes.hpp" // #includes lots of flexiblesusy headers and defines interface classes
50 #include "gambit/Printers/printermanager.hpp" // Needed by get_MSSM_spectrum_from_postprocessor to access reader object
51 #include "gambit/Printers/baseprinter.hpp" // Needed by get_MSSM_spectrum_from_postprocessor to use reader object
52 
53 // Flexible SUSY stuff (should not be needed by the rest of gambit)
54 #include "flexiblesusy/src/ew_input.hpp"
55 #include "flexiblesusy/src/lowe.h" // From softsusy; used by flexiblesusy
56 #include "flexiblesusy/src/numerics2.hpp"
57 //#include "flexiblesusy/src/mssm_twoloophiggs.hpp"
58 #include "flexiblesusy/src/spectrum_generator_settings.hpp"
59 
60 // Switch for debug mode
61 //#define SPECBIT_DEBUG
62 
63 namespace Gambit
64 {
65 
66  namespace SpecBit
67  {
68  using namespace LogTags;
69  using namespace flexiblesusy;
70 
71  // To check if a model is currently being scanned:
72  // bool Pipes::<fname>::ModelInUse(str model_name)
73 
75  // =======================================================================
76  // These are not known to Gambit, but they do basically all the real work.
77  // The Gambit module functions merely wrap the functions here and hook
78  // them up to their dependencies, and input parameters.
79 
81  // In GAMBIT there are THREE flexiblesusy MSSM spectrum generators currently in
82  // use, for each of three possible boundary condition types:
83  // - GUT scale input
84  // - Electroweak symmetry breaking scale input
85  // - Intermediate scale Q input
86  // These each require slightly different setup, but once that is done the rest
87  // of the code required to run them is the same; this is what is contained in
88  // the below template function.
89  // MI for Model Interface, as defined in model_files_and_boxes.hpp
90  template <class MI>
92  ( const typename MI::InputParameters& input
93  , const SMInputs& sminputs
94  , const Options& runOptions
95  , const std::map<str, safe_ptr<const double> >& input_Param
96  )
97  {
98  // SoftSUSY object used to set quark and lepton masses and gauge
99  // couplings in QEDxQCD effective theory
100  // Will be initialised by default using values in lowe.h, which we will
101  // override next.
102  softsusy::QedQcd oneset;
103 
104  // Fill QedQcd object with SMInputs values
105  setup_QedQcd(oneset,sminputs);
106 
107  // Run everything to Mz
108  //oneset.toMz();
109 
110  // Create spectrum generator object
111  typename MI::SpectrumGenerator spectrum_generator;
112 
113  // Spectrum generator settings
114  // Default options copied from flexiblesusy/src/spectrum_generator_settings.hpp
115  //
116  // | enum | possible values | default value |
117  // |----------------------------------|------------------------------|-----------------|
118  // | precision | any positive double | 1.0e-4 |
119  // | max_iterations | any positive double | 0 (= automatic) |
120  // | algorithm | 0 (two-scale) or 1 (lattice) | 0 (= two-scale) |
121  // | calculate_sm_masses | 0 (no) or 1 (yes) | 0 (= no) |
122  // | pole_mass_loop_order | 0, 1, 2 | 2 (= 2-loop) |
123  // | ewsb_loop_order | 0, 1, 2 | 2 (= 2-loop) |
124  // | beta_loop_order | 0, 1, 2 | 2 (= 2-loop) |
125  // | threshold_corrections_loop_order | 0, 1 | 1 (= 1-loop) |
126  // | higgs_2loop_correction_at_as | 0, 1 | 1 (= enabled) |
127  // | higgs_2loop_correction_ab_as | 0, 1 | 1 (= enabled) |
128  // | higgs_2loop_correction_at_at | 0, 1 | 1 (= enabled) |
129  // | higgs_2loop_correction_atau_atau | 0, 1 | 1 (= enabled) |
130 
131  Spectrum_generator_settings settings;
132  settings.set(Spectrum_generator_settings::precision, runOptions.getValueOrDef<double>(1.0e-4,"precision_goal"));
133  settings.set(Spectrum_generator_settings::max_iterations, runOptions.getValueOrDef<double>(0,"max_iterations"));
134  settings.set(Spectrum_generator_settings::calculate_sm_masses, runOptions.getValueOrDef<bool> (false, "calculate_sm_masses"));
135  settings.set(Spectrum_generator_settings::pole_mass_loop_order, runOptions.getValueOrDef<int>(2,"pole_mass_loop_order"));
136  settings.set(Spectrum_generator_settings::pole_mass_loop_order, runOptions.getValueOrDef<int>(2,"ewsb_loop_order"));
137  settings.set(Spectrum_generator_settings::beta_loop_order, runOptions.getValueOrDef<int>(2,"beta_loop_order"));
138  settings.set(Spectrum_generator_settings::threshold_corrections_loop_order, runOptions.getValueOrDef<int>(2,"threshold_corrections_loop_order"));
139  settings.set(Spectrum_generator_settings::higgs_2loop_correction_at_as, runOptions.getValueOrDef<int>(1,"higgs_2loop_correction_at_as"));
140  settings.set(Spectrum_generator_settings::higgs_2loop_correction_ab_as, runOptions.getValueOrDef<int>(1,"higgs_2loop_correction_ab_as"));
141  settings.set(Spectrum_generator_settings::higgs_2loop_correction_at_at, runOptions.getValueOrDef<int>(1,"higgs_2loop_correction_at_at"));
142  settings.set(Spectrum_generator_settings::higgs_2loop_correction_atau_atau, runOptions.getValueOrDef<int>(1,"higgs_2loop_correction_atau_atau"));
143  settings.set(Spectrum_generator_settings::top_pole_qcd_corrections, runOptions.getValueOrDef<int>(1,"top_pole_qcd_corrections"));
144  settings.set(Spectrum_generator_settings::beta_zero_threshold, runOptions.getValueOrDef<double>(1.000000000e-14,"beta_zero_threshold"));
145  settings.set(Spectrum_generator_settings::eft_matching_loop_order_up, runOptions.getValueOrDef<int>(1,"eft_matching_loop_order_up"));
146  settings.set(Spectrum_generator_settings::eft_matching_loop_order_down, runOptions.getValueOrDef<int>(1,"eft_matching_loop_order_down"));
147  settings.set(Spectrum_generator_settings::threshold_corrections, runOptions.getValueOrDef<int>(123111321,"threshold_corrections"));
148 
149 
150  spectrum_generator.set_settings(settings);
151 
152  // Generate spectrum
153  spectrum_generator.run(oneset, input);
154 
155  // Extract report on problems...
156  const typename MI::Problems& problems = spectrum_generator.get_problems();
157 
158  // Create Model_interface to carry the input and results, and know
159  // how to access the flexiblesusy routines.
160  // Note: Output of spectrum_generator.get_model() returns type, e.g. CMSSM.
161  // Need to convert it to type CMSSM_slha (which alters some conventions of
162  // parameters into SLHA format)
163  MI model_interface(spectrum_generator,oneset,input);
164 
165  // Create SubSpectrum object to wrap flexiblesusy data
166  // THIS IS STATIC so that it lives on once we leave this module function. We
167  // therefore cannot run the same spectrum generator twice in the same loop and
168  // maintain the spectrum resulting from both. But we should never want to do
169  // this.
170  // A pointer to this object is what gets turned into a SubSpectrum pointer and
171  // passed around Gambit.
172  //
173  // This object will COPY the interface data members into itself, so it is now the
174  // one-stop-shop for all spectrum information, including the model interface object.
175  MSSMSpec<MI> mssmspec(model_interface, "FlexibleSUSY", "2.0.beta");
176 
177  // Add extra information about the scales used to the wrapper object
178  // (last parameter turns on the 'allow_new' option for the override setter, which allows
179  // us to set parameters that don't previously exist)
180  mssmspec.set_override(Par::mass1,spectrum_generator.get_high_scale(),"high_scale",true);
181  mssmspec.set_override(Par::mass1,spectrum_generator.get_susy_scale(),"susy_scale",true);
182  mssmspec.set_override(Par::mass1,spectrum_generator.get_low_scale(), "low_scale", true);
183 
184 
185  // Has the user chosen to override any pole mass values?
186  // This will typically break consistency, but may be useful in some special cases
187  if (runOptions.hasKey("override_FS_pole_masses"))
188  {
189  std::vector<str> particle_names = runOptions.getNames("override_FS_pole_masses");
190  for (auto& name : particle_names)
191  {
192  double mass = runOptions.getValue<double>("override_FS_pole_masses", name);
193  mssmspec.set_override(Par::Pole_Mass, mass, name);
194  }
195  }
196 
197  // Add theory errors
198  static const MSSM_strs ms;
199 
200  static const std::vector<int> i12 = initVector(1,2);
201  static const std::vector<int> i123 = initVector(1,2,3);
202  static const std::vector<int> i1234 = initVector(1,2,3,4);
203  static const std::vector<int> i123456 = initVector(1,2,3,4,5,6);
204 
205  // 3% theory "error"
208  mssmspec.set_override_vector(Par::Pole_Mass_1srd_high, 0.03, ms.pole_mass_strs_1_6, i123456, true);
209  mssmspec.set_override_vector(Par::Pole_Mass_1srd_low, 0.03, ms.pole_mass_strs_1_6, i123456, true);
210  mssmspec.set_override_vector(Par::Pole_Mass_1srd_high, 0.03, "~chi0", i1234, true);
211  mssmspec.set_override_vector(Par::Pole_Mass_1srd_low, 0.03, "~chi0", i1234, true);
212  mssmspec.set_override_vector(Par::Pole_Mass_1srd_high, 0.03, ms.pole_mass_strs_1_3, i123, true);
213  mssmspec.set_override_vector(Par::Pole_Mass_1srd_low, 0.03, ms.pole_mass_strs_1_3, i123, true);
214  mssmspec.set_override_vector(Par::Pole_Mass_1srd_high, 0.03, ms.pole_mass_strs_1_2, i12, true);
215  mssmspec.set_override_vector(Par::Pole_Mass_1srd_low, 0.03, ms.pole_mass_strs_1_2, i12, true);
216 
217  // Do the lightest Higgs mass separately. The default in most codes is 3 GeV. That seems like
218  // an underestimate if the stop masses are heavy enough, but an overestimate for most points.
219  double rd_mh1 = 2.0 / mssmspec.get(Par::Pole_Mass, ms.h0, 1);
220  mssmspec.set_override(Par::Pole_Mass_1srd_high, rd_mh1, ms.h0, 1, true);
221  mssmspec.set_override(Par::Pole_Mass_1srd_low, rd_mh1, ms.h0, 1, true);
222 
223  // Do the W mass separately. Here we use 10 MeV based on the size of corrections from two-loop papers and advice from Dominik Stockinger.
224  double rd_mW = 0.01 / mssmspec.get(Par::Pole_Mass, "W+");
225  mssmspec.set_override(Par::Pole_Mass_1srd_high, rd_mW, "W+", true);
226  mssmspec.set_override(Par::Pole_Mass_1srd_low, rd_mW, "W+", true);
227 
228  // Save the input value of TanBeta
229  // Probably need to make it a full requirement of the MSSM SpectrumContents
230  if(input_Param.find("TanBeta") != input_Param.end())
231  {
232  mssmspec.set_override(Par::dimensionless, *input_Param.at("TanBeta"), "tanbeta(mZ)", true);
233  }
234 
235  // Create a second SubSpectrum object to wrap the qedqcd object used to initialise the spectrum generator
236  // Attach the sminputs object as well, so that SM pole masses can be passed on (these aren't easily
237  // extracted from the QedQcd object, so use the values that we put into it.)
238  QedQcdWrapper qedqcdspec(oneset,sminputs);
239 
240  // Deal with points where spectrum generator encountered a problem
241  #ifdef SPECBIT_DEBUG
242  std::cout<<"Problem? "<<problems.have_problem()<<std::endl;
243  #endif
244  if( problems.have_problem() )
245  {
246  if( runOptions.getValueOrDef<bool>(false,"invalid_point_fatal") )
247  {
250  std::ostringstream errmsg;
251  errmsg << "A serious problem was encountered during spectrum generation!; ";
252  errmsg << "Message from FlexibleSUSY below:" << std::endl;
253  problems.print_problems(errmsg);
254  problems.print_warnings(errmsg);
255  SpecBit_error().raise(LOCAL_INFO,errmsg.str());
256  }
257  else
258  {
261  std::ostringstream msg;
262  //msg << "";
263  //if( have_bad_mass() ) msg << "bad mass " << std::endl; // TODO: check which one
264  //if( have_tachyon() ) msg << "tachyon" << std::endl;
265  //if( have_thrown() ) msg << "error" << std::endl;
266  //if( have_non_perturbative_parameter() ) msg << "non-perturb. param" << std::endl; // TODO: check which
267  //if( have_failed_pole_mass_convergence() ) msg << "fail pole mass converg." << std::endl; // TODO: check which
268  //if( no_ewsb() ) msg << "no ewsb" << std::endl;
269  //if( no_convergence() ) msg << "no converg." << std::endl;
270  //if( no_perturbative() ) msg << "no pertub." << std::endl;
271  //if( no_rho_convergence() ) msg << "no rho converg." << std::endl;
272  //if( msg.str()=="" ) msg << " Unrecognised problem! ";
273 
275  problems.print_problems(msg);
276  invalid_point().raise(msg.str()); //TODO: This message isn't ending up in the logs.
277  }
278  }
279 
280  if( problems.have_warning() )
281  {
282  std::ostringstream msg;
283  problems.print_warnings(msg);
284  SpecBit_warning().raise(LOCAL_INFO,msg.str()); //TODO: Is a warning the correct thing to do here?
285  }
286 
287  // Write SLHA file (for debugging purposes...)
288  #ifdef SPECBIT_DEBUG
289  typename MI::SlhaIo slha_io;
290  slha_io.set_spinfo(problems);
291  slha_io.set_sminputs(oneset);
292  slha_io.set_minpar(input);
293  slha_io.set_extpar(input);
294  slha_io.set_spectrum(mssmspec.model_interface.model);
295  slha_io.write_to_file("SpecBit/initial_CMSSM_spectrum->slha");
296  #endif
297 
298  // Retrieve any mass cuts
299  static const Spectrum::mc_info mass_cut = runOptions.getValueOrDef<Spectrum::mc_info>(Spectrum::mc_info(), "mass_cut");
300  static const Spectrum::mr_info mass_ratio_cut = runOptions.getValueOrDef<Spectrum::mr_info>(Spectrum::mr_info(), "mass_ratio_cut");
301 
302  // Package QedQcd SubSpectrum object, MSSM SubSpectrum object, and SMInputs struct into a 'full' Spectrum object
303  return Spectrum(qedqcdspec,mssmspec,sminputs,&input_Param,mass_cut,mass_ratio_cut);
304  }
305 
306  //Version for 1.5.1 commented out because we should make it possible to support FS versions in parallel.
307 
308  // template <class MI>
309  // Spectrum run_FS1_5_1_spectrum_generator
310  // ( const typename MI::InputParameters& input
311  // , const SMInputs& sminputs
312  // , const Options& runOptions
313  // , const std::map<str, safe_ptr<const double> >& input_Param
314  // )
315  // {
316  // // SoftSUSY object used to set quark and lepton masses and gauge
317  // // couplings in QEDxQCD effective theory
318  // // Will be initialised by default using values in lowe.h, which we will
319  // // override next.
320  // softsusy::QedQcd oneset;
321 
322  // // Fill QedQcd object with SMInputs values
323  // setup_QedQcd(oneset,sminputs);
324 
325  // // Run everything to Mz
326  // oneset.toMz();
327 
328  // // Create spectrum generator object
329  // typename MI::SpectrumGenerator spectrum_generator;
330 
331  // // Spectrum generator settings
332  // // Default options copied from flexiblesusy/src/spectrum_generator_settings.hpp
333  // //
334  // // | enum | possible values | default value |
335  // // |----------------------------------|------------------------------|-----------------|
336  // // | precision | any positive double | 1.0e-4 |
337  // // | max_iterations | any positive double | 0 (= automatic) |
338  // // | algorithm | 0 (two-scale) or 1 (lattice) | 0 (= two-scale) |
339  // // | calculate_sm_masses | 0 (no) or 1 (yes) | 0 (= no) |
340  // // | pole_mass_loop_order | 0, 1, 2 | 2 (= 2-loop) |
341  // // | ewsb_loop_order | 0, 1, 2 | 2 (= 2-loop) |
342  // // | beta_loop_order | 0, 1, 2 | 2 (= 2-loop) |
343  // // | threshold_corrections_loop_order | 0, 1 | 1 (= 1-loop) |
344  // // | higgs_2loop_correction_at_as | 0, 1 | 1 (= enabled) |
345  // // | higgs_2loop_correction_ab_as | 0, 1 | 1 (= enabled) |
346  // // | higgs_2loop_correction_at_at | 0, 1 | 1 (= enabled) |
347  // // | higgs_2loop_correction_atau_atau | 0, 1 | 1 (= enabled) |
348 
349  // spectrum_generator.set_precision_goal (runOptions.getValueOrDef<double>(1.0e-4,"precision_goal"));
350  // spectrum_generator.set_max_iterations (runOptions.getValueOrDef<double>(0, "max_iterations"));
351  // spectrum_generator.set_calculate_sm_masses (runOptions.getValueOrDef<bool> (false, "calculate_sm_masses"));
352  // spectrum_generator.set_pole_mass_loop_order (runOptions.getValueOrDef<int> (2, "pole_mass_loop_order"));
353  // spectrum_generator.set_ewsb_loop_order (runOptions.getValueOrDef<int> (2, "ewsb_loop_order"));
354  // spectrum_generator.set_beta_loop_order (runOptions.getValueOrDef<int> (2, "beta_loop_order"));
355  // spectrum_generator.set_threshold_corrections_loop_order(runOptions.getValueOrDef<int> (2, "threshold_corrections_loop_order"));
356 
357  // // Higgs loop corrections are a little different... sort them out now
358  // Two_loop_corrections two_loop_settings;
359 
360  // // alpha_t alpha_s
361  // // alpha_b alpha_s
362  // // alpha_t^2 + alpha_t alpha_b + alpha_b^2
363  // // alpha_tau^2
364  // two_loop_settings.higgs_at_as = runOptions.getValueOrDef<bool>(true,"use_higgs_2loop_at_as");
365  // two_loop_settings.higgs_ab_as = runOptions.getValueOrDef<bool>(true,"use_higgs_2loop_ab_as");
366  // two_loop_settings.higgs_at_at = runOptions.getValueOrDef<bool>(true,"use_higgs_2loop_at_at");
367  // two_loop_settings.higgs_atau_atau = runOptions.getValueOrDef<bool>(true,"use_higgs_2loop_atau_atau");
368 
369  // spectrum_generator.set_two_loop_corrections(two_loop_settings);
370 
371  // // Generate spectrum
372  // spectrum_generator.run(oneset, input);
373 
374  // // Extract report on problems...
375  // const typename MI::Problems& problems = spectrum_generator.get_problems();
376 
377  // // Create Model_interface to carry the input and results, and know
378  // // how to access the flexiblesusy routines.
379  // // Note: Output of spectrum_generator.get_model() returns type, e.g. CMSSM.
380  // // Need to convert it to type CMSSM_slha (which alters some conventions of
381  // // parameters into SLHA format)
382  // MI model_interface(spectrum_generator,oneset,input);
383 
384  // // Create SubSpectrum object to wrap flexiblesusy data
385  // // THIS IS STATIC so that it lives on once we leave this module function. We
386  // // therefore cannot run the same spectrum generator twice in the same loop and
387  // // maintain the spectrum resulting from both. But we should never want to do
388  // // this.
389  // // A pointer to this object is what gets turned into a SubSpectrum pointer and
390  // // passed around Gambit.
391  // //
392  // // This object will COPY the interface data members into itself, so it is now the
393  // // one-stop-shop for all spectrum information, including the model interface object.
394  // MSSMSpec<MI> mssmspec(model_interface, "FlexibleSUSY", "1.5.1");
395 
396  // // Add extra information about the scales used to the wrapper object
397  // // (last parameter turns on the 'allow_new' option for the override setter, which allows
398  // // us to set parameters that don't previously exist)
399  // mssmspec.set_override(Par::mass1,spectrum_generator.get_high_scale(),"high_scale",true);
400  // mssmspec.set_override(Par::mass1,spectrum_generator.get_susy_scale(),"susy_scale",true);
401  // mssmspec.set_override(Par::mass1,spectrum_generator.get_low_scale(), "low_scale", true);
402 
403  // // Add theory errors
404  // static const MSSM_strs ms;
405 
406  // static const std::vector<int> i12 = initVector(1,2);
407  // static const std::vector<int> i123 = initVector(1,2,3);
408  // static const std::vector<int> i1234 = initVector(1,2,3,4);
409  // static const std::vector<int> i123456 = initVector(1,2,3,4,5,6);
410 
411  // // 3% theory "error"
412  // mssmspec.set_override_vector(Par::Pole_Mass_1srd_high, 0.03, ms.pole_mass_pred, true);
413  // mssmspec.set_override_vector(Par::Pole_Mass_1srd_low, 0.03, ms.pole_mass_pred, true);
414  // mssmspec.set_override_vector(Par::Pole_Mass_1srd_high, 0.03, ms.pole_mass_strs_1_6, i123456, true);
415  // mssmspec.set_override_vector(Par::Pole_Mass_1srd_low, 0.03, ms.pole_mass_strs_1_6, i123456, true);
416  // mssmspec.set_override_vector(Par::Pole_Mass_1srd_high, 0.03, "~chi0", i1234, true);
417  // mssmspec.set_override_vector(Par::Pole_Mass_1srd_low, 0.03, "~chi0", i1234, true);
418  // mssmspec.set_override_vector(Par::Pole_Mass_1srd_high, 0.03, ms.pole_mass_strs_1_3, i123, true);
419  // mssmspec.set_override_vector(Par::Pole_Mass_1srd_low, 0.03, ms.pole_mass_strs_1_3, i123, true);
420  // mssmspec.set_override_vector(Par::Pole_Mass_1srd_high, 0.03, ms.pole_mass_strs_1_2, i12, true);
421  // mssmspec.set_override_vector(Par::Pole_Mass_1srd_low, 0.03, ms.pole_mass_strs_1_2, i12, true);
422 
423  // // Do the lightest Higgs mass separately. The default in most codes is 3 GeV. That seems like
424  // // an underestimate if the stop masses are heavy enough, but an overestimate for most points.
425  // double rd_mh1 = 2.0 / mssmspec.get(Par::Pole_Mass, ms.h0, 1);
426  // mssmspec.set_override(Par::Pole_Mass_1srd_high, rd_mh1, ms.h0, 1, true);
427  // mssmspec.set_override(Par::Pole_Mass_1srd_low, rd_mh1, ms.h0, 1, true);
428 
429  // // Do the W mass separately. Here we use 10 MeV based on the size of corrections from two-loop papers and advice from Dominik Stockinger.
430  // double rd_mW = 0.01 / mssmspec.get(Par::Pole_Mass, "W+");
431  // mssmspec.set_override(Par::Pole_Mass_1srd_high, rd_mW, "W+", true);
432  // mssmspec.set_override(Par::Pole_Mass_1srd_low, rd_mW, "W+", true);
433 
434  // // Save the input value of TanBeta
435  // // Probably need to make it a full requirement of the MSSM SpectrumContents
436  // if(input_Param.find("TanBeta") != input_Param.end())
437  // {
438  // mssmspec.set_override(Par::dimensionless, *input_Param.at("TanBeta"), "tanbeta(mZ)", true);
439  // }
440 
441  // // Create a second SubSpectrum object to wrap the qedqcd object used to initialise the spectrum generator
442  // // Attach the sminputs object as well, so that SM pole masses can be passed on (these aren't easily
443  // // extracted from the QedQcd object, so use the values that we put into it.)
444  // QedQcdWrapper qedqcdspec(oneset,sminputs);
445 
446  // // Deal with points where spectrum generator encountered a problem
447  // #ifdef SPECBIT_DEBUG
448  // std::cout<<"Problem? "<<problems.have_problem()<<std::endl;
449  // #endif
450  // if( problems.have_problem() )
451  // {
452  // if( runOptions.getValueOrDef<bool>(false,"invalid_point_fatal") )
453  // {
454  // ///TODO: Need to tell gambit that the spectrum is not viable somehow. For now
455  // /// just die.
456  // std::ostringstream errmsg;
457  // errmsg << "A serious problem was encountered during spectrum generation!; ";
458  // errmsg << "Message from FlexibleSUSY below:" << std::endl;
459  // problems.print_problems(errmsg);
460  // problems.print_warnings(errmsg);
461  // SpecBit_error().raise(LOCAL_INFO,errmsg.str());
462  // }
463  // else
464  // {
465  // /// Check what the problem was
466  // /// see: contrib/MassSpectra/flexiblesusy/src/problems.hpp
467  // std::ostringstream msg;
468  // //msg << "";
469  // //if( have_bad_mass() ) msg << "bad mass " << std::endl; // TODO: check which one
470  // //if( have_tachyon() ) msg << "tachyon" << std::endl;
471  // //if( have_thrown() ) msg << "error" << std::endl;
472  // //if( have_non_perturbative_parameter() ) msg << "non-perturb. param" << std::endl; // TODO: check which
473  // //if( have_failed_pole_mass_convergence() ) msg << "fail pole mass converg." << std::endl; // TODO: check which
474  // //if( no_ewsb() ) msg << "no ewsb" << std::endl;
475  // //if( no_convergence() ) msg << "no converg." << std::endl;
476  // //if( no_perturbative() ) msg << "no pertub." << std::endl;
477  // //if( no_rho_convergence() ) msg << "no rho converg." << std::endl;
478  // //if( msg.str()=="" ) msg << " Unrecognised problem! ";
479 
480  // /// Fast way for now:
481  // problems.print_problems(msg);
482  // invalid_point().raise(msg.str()); //TODO: This message isn't ending up in the logs.
483  // }
484  // }
485 
486  // if( problems.have_warning() )
487  // {
488  // std::ostringstream msg;
489  // problems.print_warnings(msg);
490  // SpecBit_warning().raise(LOCAL_INFO,msg.str()); //TODO: Is a warning the correct thing to do here?
491  // }
492 
493  // // Write SLHA file (for debugging purposes...)
494  // #ifdef SPECBIT_DEBUG
495  // typename MI::SlhaIo slha_io;
496  // slha_io.set_spinfo(problems);
497  // slha_io.set_sminputs(oneset);
498  // slha_io.set_minpar(input);
499  // slha_io.set_extpar(input);
500  // slha_io.set_spectrum(mssmspec.model_interface.model);
501  // slha_io.write_to_file("SpecBit/initial_CMSSM_spectrum->slha");
502  // #endif
503 
504  // // Retrieve any mass cuts
505  // static const Spectrum::mc_info mass_cut = runOptions.getValueOrDef<Spectrum::mc_info>(Spectrum::mc_info(), "mass_cut");
506  // static const Spectrum::mr_info mass_ratio_cut = runOptions.getValueOrDef<Spectrum::mr_info>(Spectrum::mr_info(), "mass_ratio_cut");
507 
508  // // Package QedQcd SubSpectrum object, MSSM SubSpectrum object, and SMInputs struct into a 'full' Spectrum object
509  // return Spectrum(qedqcdspec,mssmspec,sminputs,&input_Param,mass_cut,mass_ratio_cut);
510  // }
511 
513  // Names must conform to convention "<parname>_ij"
514  Eigen::Matrix<double,3,3> fill_3x3_parameter_matrix(const std::string& rootname, const std::map<str, safe_ptr<const double> >& Param)
515  {
516  Eigen::Matrix<double,3,3> output;
517  for(int i=0; i<3; ++i) for(int j=0; j<3; ++j)
518  {
519  output(i,j) = *Param.at(rootname + "_" + std::to_string(i+1) + std::to_string(j+1));
520  }
521  return output;
522  }
523 
525  Eigen::Matrix<double,3,3> fill_3x3_symmetric_parameter_matrix(const std::string& rootname, const std::map<str, safe_ptr<const double> >& Param)
526  {
527  Eigen::Matrix<double,3,3> output;
528  for(int i=0; i<3; ++i) for(int j=0; j<3; ++j)
529  {
530  str parname = rootname + "_" + ( i < j ? std::to_string(i+1) + std::to_string(j+1) : std::to_string(j+1) + std::to_string(i+1));
531  output(i,j) = *Param.at(parname);
532  }
533  return output;
534  }
535 
538  template <class T>
539  void fill_MSSM63_input(T& input, const std::map<str, safe_ptr<const double> >& Param )
540  {
541  //double valued parameters
542  input.TanBeta = *Param.at("TanBeta");
543  input.MassBInput = *Param.at("M1");
544  input.MassWBInput = *Param.at("M2");
545  input.MassGInput = *Param.at("M3");
546 
547  // Sanity checks
548  if(input.TanBeta<0)
549  {
550  std::ostringstream msg;
551  msg << "Tried to set TanBeta parameter to a negative value ("<<input.TanBeta<<")! This parameter must be positive. Please check your inifile and try again.";
552  SpecBit_error().raise(LOCAL_INFO,msg.str());
553  }
554 
555  //3x3 matrices; filled with the help of a convenience function
556  input.mq2Input = fill_3x3_symmetric_parameter_matrix("mq2", Param);
557  input.ml2Input = fill_3x3_symmetric_parameter_matrix("ml2", Param);
558  input.md2Input = fill_3x3_symmetric_parameter_matrix("md2", Param);
559  input.mu2Input = fill_3x3_symmetric_parameter_matrix("mu2", Param);
560  input.me2Input = fill_3x3_symmetric_parameter_matrix("me2", Param);
561  input.Aeij = fill_3x3_parameter_matrix("Ae", Param);
562  input.Adij = fill_3x3_parameter_matrix("Ad", Param);
563  input.Auij = fill_3x3_parameter_matrix("Au", Param);
564 
565  #ifdef SPECBIT_DEBUG
566  #define INPUT(p) input.p
567  #define ostr std::cout
568  #define oend std::endl
569  ostr << "TanBeta = " << INPUT(TanBeta) << ", " << oend ;
570  ostr << "mq2Input = " << oend << INPUT(mq2Input) << ", " << oend;
571  ostr << "ml2Input = " << oend << INPUT(ml2Input) << ", " << oend;
572  ostr << "md2Input = " << oend << INPUT(md2Input) << ", " << oend;
573  ostr << "mu2Input = " << oend << INPUT(mu2Input) << ", " << oend;
574  ostr << "me2Input = " << oend << INPUT(me2Input) << ", " << oend;
575  ostr << "MassBInput = " << INPUT(MassBInput) << ", " << oend;
576  ostr << "MassWBInput = " << INPUT(MassWBInput) << ", " << oend;
577  ostr << "MassGInput = " << INPUT(MassGInput) << ", " << oend;
578  ostr << "Aeij = " << oend << INPUT(Aeij) << ", " << oend;
579  ostr << "Adij = " << oend << INPUT(Adij) << ", " << oend;
580  ostr << "Auij = " << oend << INPUT(Auij) << ", " << oend;
581  #undef INPUT
582  #undef ostr
583  #undef oend
584  #endif
585  }
586 
587 
588  // Similar to above, except this is for MSSMEFTHiggs spectrum
589  // generator and a few others where different names for inputs for many
590  // parameters are used. This should be standardised.
591 
592  template <class T>
593  void fill_MSSM63_input_altnames(T& input, const std::map<str, safe_ptr<const double> >& Param )
594  {
595  //double valued parameters
596  input.TanBeta = *Param.at("TanBeta");
597  input.M1Input = *Param.at("M1");
598  input.M2Input = *Param.at("M2");
599  input.M3Input = *Param.at("M3");
600 
601  // Sanity checks
602  if(input.TanBeta<0)
603  {
604  std::ostringstream msg;
605  msg << "Tried to set TanBeta parameter to a negative value ("<<input.TanBeta<<")! This parameter must be positive. Please check your inifile and try again.";
606  SpecBit_error().raise(LOCAL_INFO,msg.str());
607  }
608 
609  //3x3 matrices; filled with the help of a convenience function
610  input.mq2Input = fill_3x3_symmetric_parameter_matrix("mq2", Param);
611  input.ml2Input = fill_3x3_symmetric_parameter_matrix("ml2", Param);
612  input.md2Input = fill_3x3_symmetric_parameter_matrix("md2", Param);
613  input.mu2Input = fill_3x3_symmetric_parameter_matrix("mu2", Param);
614  input.me2Input = fill_3x3_symmetric_parameter_matrix("me2", Param);
615  input.AeInput = fill_3x3_parameter_matrix("Ae", Param);
616  input.AdInput= fill_3x3_parameter_matrix("Ad", Param);
617  input.AuInput = fill_3x3_parameter_matrix("Au", Param);
618 
619  #ifdef SPECBIT_DEBUG
620  #define INPUT(p) input.p
621  #define ostr std::cout
622  #define oend std::endl
623  ostr << "TanBeta = " << INPUT(TanBeta) << ", " << oend ;
624  ostr << "mq2Input = " << oend << INPUT(mq2Input) << ", " << oend;
625  ostr << "ml2Input = " << oend << INPUT(ml2Input) << ", " << oend;
626  ostr << "md2Input = " << oend << INPUT(md2Input) << ", " << oend;
627  ostr << "mu2Input = " << oend << INPUT(mu2Input) << ", " << oend;
628  ostr << "me2Input = " << oend << INPUT(me2Input) << ", " << oend;
629  ostr << "M1Input = " << INPUT(M1Input) << ", " << oend;
630  ostr << "M2Input = " << INPUT(M2Input) << ", " << oend;
631  ostr << "M3Input = " << INPUT(M3Input) << ", " << oend;
632  ostr << "AeInput = " << oend << INPUT(AeInput) << ", " << oend;
633  ostr << "AdInput = " << oend << INPUT(AdInput) << ", " << oend;
634  ostr << "AuInput = " << oend << INPUT(AuInput) << ", " << oend;
635  #undef INPUT
636  #undef ostr
637  #undef oend
638  #endif
639 
640  }
641 
642 
644 
645 
647  // =======================================================================
648  // These are wrapped up in Gambit functor objects according to the
649  // instructions in the rollcall header
650 
651  // Functions to change the capability associated with a Spectrum object to "SM_spectrum"
654  void convert_E6MSSM_to_SM (Spectrum &result) {result = *Pipes::convert_E6MSSM_to_SM::Dep::E6MSSM_spectrum;}
655 
657  {
658  namespace myPipe = Pipes::get_MSSM_spectrum_SPheno;
659  const SMInputs &sminputs = *myPipe::Dep::SMINPUTS;
660 
661  // Set up the input structure
662  Finputs inputs;
663  inputs.sminputs = sminputs;
664  inputs.param = myPipe::Param;
665  inputs.options = myPipe::runOptions;
666 
667  // Retrieve any mass cuts
668  static const Spectrum::mc_info mass_cut = myPipe::runOptions->getValueOrDef<Spectrum::mc_info>(Spectrum::mc_info(), "mass_cut");
669  static const Spectrum::mr_info mass_ratio_cut = myPipe::runOptions->getValueOrDef<Spectrum::mr_info>(Spectrum::mr_info(), "mass_ratio_cut");
670 
671  // Get the spectrum from the Backend
672  myPipe::BEreq::SPheno_MSSMspectrum(spectrum, inputs);
673 
674  // Only allow neutralino LSPs.
675  if (not has_neutralino_LSP(spectrum)) invalid_point().raise("Neutralino is not LSP.");
676 
677  // Drop SLHA files if requested
678  spectrum.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
679 
680  }
681 
682 
683  // Runs FlexibleSUSY MSSMEFTHiggs model spectrum generator with SUSY
684  // scale boundary conditions, ie accepts MSSM parameters at MSUSY,
685  // and has DRbar mA and mu as an input and mHu2 and mHd2 as EWSB
686  // outputs, so it is for the MSSMatMSUSY_mA model.
687  #if(FS_MODEL_MSSMatMSUSYEFTHiggs_mAmu_IS_BUILT)
688  void get_MSSMatMSUSY_mA_spectrum_FlexibleEFTHiggs (Spectrum& result)
689  {
690  // Access the pipes for this function to get model and parameter information
691  namespace myPipe = Pipes::get_MSSMatMSUSY_mA_spectrum_FlexibleEFTHiggs;
692 
693  // Get SLHA2 SMINPUTS values
694  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS;
695 
696  // Get input parameters (from flexiblesusy namespace)
697  MSSMatMSUSYEFTHiggs_mAmu_input_parameters input;
698  input.MuInput = *myPipe::Param.at("mu");
699  // This FS spectrum generator has mA as the parameter
700  input.mAInput = *myPipe::Param.at("mA");
701  fill_MSSM63_input_altnames(input,myPipe::Param); // Fill the rest
702  result = run_FS_spectrum_generator<MSSMatMSUSYEFTHiggs_mAmu_interface<ALGORITHM1>>(input,sminputs,*myPipe::runOptions,myPipe::Param);
703 
704  // Only allow neutralino LSPs.
705  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
706 
707  // Drop SLHA files if requested
708  result.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
709 
710  }
711  #endif
712 
713  // Runs FlexibleSUSY MSSMEFTHiggs model spectrum generator
714  // and has m3^2 and mu as EWSB outputs, so it is for the
715  // MSSMatQ_model.
716  #if(FS_MODEL_MSSMEFTHiggs_IS_BUILT)
717  void get_MSSMatQ_spectrum_FlexibleEFTHiggs (Spectrum& result)
718  {
719  // Access the pipes for this function to get model and parameter information
720  namespace myPipe = Pipes::get_MSSMatQ_spectrum_FlexibleEFTHiggs;
721 
722  // Get SLHA2 SMINPUTS values
723  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS;
724 
725  // Get input parameters (from flexiblesusy namespace)
726  MSSMEFTHiggs_input_parameters input;
727  // MSSMatQ also requires input scale to be supplied with name MSUSY
728  input.MSUSY = *myPipe::Param.at("Qin");
729  input.mHu2IN = *myPipe::Param.at("mHu2");
730  input.mHd2IN = *myPipe::Param.at("mHd2");
731  input.SignMu = *myPipe::Param.at("SignMu");
732  fill_MSSM63_input_altnames(input,myPipe::Param); // Fill the rest
733  result = run_FS_spectrum_generator<MSSMEFTHiggs_interface<ALGORITHM1>>(input,sminputs,*myPipe::runOptions,myPipe::Param);
734 
735  // Only allow neutralino LSPs.
736  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
737 
738  // Drop SLHA files if requested
739  result.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
740 
741  }
742  #endif
743 
744  // Runs FlexibleSUSY MSSMEFTHiggs_mAmu spectrum generator with
745  // boundary conditions at a user specified scale, ie accepts MSSM
746  // parameters at Q, and has DRbar mA and mu as an input and mHu2
747  // and mHd2 as EWSB outputs, so it is for the MSSMatMSUSY_mA model.
748  #if(FS_MODEL_MSSMEFTHiggs_mAmu_IS_BUILT)
749  void get_MSSMatQ_mA_spectrum_FlexibleEFTHiggs (Spectrum& result)
750  {
751  // Access the pipes for this function to get model and parameter information
752  namespace myPipe = Pipes::get_MSSMatQ_mA_spectrum_FlexibleEFTHiggs;
753 
754  // Get SLHA2 SMINPUTS values
755  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS;
756 
757  // Get input parameters (from flexiblesusy namespace)
758  MSSMEFTHiggs_mAmu_input_parameters input;
759  input.MuInput = *myPipe::Param.at("mu");
760  // This FS spectrum generator has mA as the parameter
761  input.mAInput = *myPipe::Param.at("mA");
762  // Note: Qin has been named MSUSY inside the spectrum generator
763  // but it is a user-input scale in this case.
764  input.MSUSY = *myPipe::Param.at("Qin");
765  // Fill the rest.
766  // Note: This particular spectrum generator has been created with
767  // different names for parameter inputs. We should standardise this
768  fill_MSSM63_input_altnames(input,myPipe::Param);
769  result = run_FS_spectrum_generator<MSSMEFTHiggs_mAmu_interface<ALGORITHM1>>(input,sminputs,*myPipe::runOptions,myPipe::Param);
770 
771  // Only allow neutralino LSPs.
772  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
773 
774  // Drop SLHA files if requested
775  result.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
776 
777  }
778  #endif
779 
780 
781 
782  // Runs FlexibleSUSY MSSM spectrum generator with CMSSM (GUT scale) boundary conditions
783  // In principle an identical spectrum can be obtained from the function
784  // get_MSSMatGUT_spectrum_FS
785  // by setting the input parameters to match the CMSSM assumptions
786  #if(FS_MODEL_CMSSM_IS_BUILT)
787  void get_CMSSM_spectrum_FS (Spectrum& result)
788  {
789 
790  // Access the pipes for this function to get model and parameter information
791  namespace myPipe = Pipes::get_CMSSM_spectrum_FS;
792 
793  // Get SLHA2 SMINPUTS values
794  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS;
795 
796  // Get input parameters (from flexiblesusy namespace)
797  CMSSM_input_parameters input;
798 
799  input.m0 = *myPipe::Param["M0"];
800  input.m12 = *myPipe::Param["M12"];
801  input.TanBeta = *myPipe::Param["TanBeta"];
802  input.SignMu = *myPipe::Param["SignMu"];
803  input.Azero = *myPipe::Param["A0"];
804 
805  // Sanity checks
806  if(input.TanBeta<0)
807  {
808  std::ostringstream msg;
809  msg << "Tried to set TanBeta parameter to a negative value ("<<input.TanBeta<<")! This parameter must be positive. Please check your inifile and try again.";
810  SpecBit_error().raise(LOCAL_INFO,msg.str());
811  }
812  if(input.SignMu!=-1 and input.SignMu!=1)
813  {
814  std::ostringstream msg;
815  msg << "Tried to set SignMu parameter to a value that is not a sign! ("<<input.SignMu<<")! This parameter must be set to either 1 or -1. Please check your inifile and try again.";
816  SpecBit_error().raise(LOCAL_INFO,msg.str());
817  }
818 
819  // Run spectrum generator
820  result = run_FS_spectrum_generator<CMSSM_interface<ALGORITHM1>>(input,sminputs,*myPipe::runOptions,myPipe::Param);
821 
822  // Only allow neutralino LSPs.
823  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
824 
825  // Drop SLHA files if requested
826  result.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
827 
828  }
829  #endif
830 
831  // Runs FlexibleSUSY MSSM spectrum generator with EWSB scale input (boundary conditions)
832  #if(FS_MODEL_MSSM_IS_BUILT)
833  void get_MSSMatQ_spectrum_FS (Spectrum& result)
834  {
835  using namespace softsusy;
836  namespace myPipe = Pipes::get_MSSMatQ_spectrum_FS;
837  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS;
838  MSSM_input_parameters input;
839  input.Qin = *myPipe::Param.at("Qin"); // MSSMatQ also requires input scale to be supplied
840  input.mHu2IN = *myPipe::Param.at("mHu2");
841  input.mHd2IN = *myPipe::Param.at("mHd2");
842  input.SignMu = *myPipe::Param.at("SignMu");
843  if(input.SignMu!=-1 and input.SignMu!=1)
844  {
845  std::ostringstream msg;
846  msg << "Tried to set SignMu parameter to a value that is not a sign! ("<<input.SignMu<<")! This parameter must be set to either 1 or -1. Please check your inifile and try again.";
847  SpecBit_error().raise(LOCAL_INFO,msg.str());
848  }
849  fill_MSSM63_input(input,myPipe::Param);
850  result = run_FS_spectrum_generator<MSSM_interface<ALGORITHM1>>(input,sminputs,*myPipe::runOptions,myPipe::Param);
851  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
852  result.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
853  }
854  #endif
855 
856  // Runs FlexibleSUSY MSSM spectrum generator with EWSB scale input (boundary conditions)
857  // but with mA and mu as parameters instead of mHu2 and mHd2
858  #if(FS_MODEL_MSSM_mAmu_IS_BUILT)
859  void get_MSSMatQ_mA_spectrum_FS (Spectrum& result)
860  {
861  using namespace softsusy;
862  namespace myPipe = Pipes::get_MSSMatQ_mA_spectrum_FS;
863  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS;
864  MSSM_mAmu_input_parameters input;
865  input.Qin = *myPipe::Param.at("Qin"); // MSSMatQ also requires input scale to be supplied
866  input.MuInput = *myPipe::Param.at("mu");
867  // Note this spectrum generator mA2 is the parameter.
868  // However this freedom is not used in GAMBIT
869  // and not needed as mA is a DRbar mass eigenstate for a scalar
870  double mA = *myPipe::Param.at("mA");
871  input.mA2Input = mA*mA;
872  fill_MSSM63_input(input,myPipe::Param); // Fill the rest
873  result = run_FS_spectrum_generator<MSSM_mAmu_interface<ALGORITHM1>>(input,sminputs,*myPipe::runOptions,myPipe::Param);
874  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
875  result.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
876  }
877  #endif
878 
879  // Runs FlexibleSUSY MSSM spectrum generator with GUT scale input (boundary conditions)
880  #if(FS_MODEL_MSSMatMGUT_IS_BUILT)
881  void get_MSSMatMGUT_spectrum_FS (Spectrum& result)
882  {
883  using namespace softsusy;
884  namespace myPipe = Pipes::get_MSSMatMGUT_spectrum_FS;
885  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS;
886  MSSMatMGUT_input_parameters input;
887  input.mHu2IN = *myPipe::Param.at("mHu2");
888  input.mHd2IN = *myPipe::Param.at("mHd2");
889  input.SignMu = *myPipe::Param.at("SignMu");
890  if(input.SignMu!=-1 and input.SignMu!=1)
891  {
892  std::ostringstream msg;
893  msg << "Tried to set SignMu parameter to a value that is not a sign! ("<<input.SignMu<<")! This parameter must be set to either 1 or -1. Please check your inifile and try again.";
894  SpecBit_error().raise(LOCAL_INFO,msg.str());
895  }
896  fill_MSSM63_input(input,myPipe::Param);
897  result = run_FS_spectrum_generator<MSSMatMGUT_interface<ALGORITHM1>>(input,sminputs,*myPipe::runOptions,myPipe::Param);
898  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
899  result.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
900  }
901  #endif
902 
903  // Runs FlexibleSUSY MSSMatMGUTEFTHiggs model spectrum generator
904  // and has m3^2 and mu as EWSB outputs, so it is for the
905  // MSSMatMGUT_model.
906  #if(FS_MODEL_MSSMatMGUTEFTHiggs_IS_BUILT)
907  void get_MSSMatMGUT_spectrum_FlexibleEFTHiggs (Spectrum& result)
908  {
909  // Access the pipes for this function to get model and parameter information
910  namespace myPipe = Pipes::get_MSSMatMGUT_spectrum_FlexibleEFTHiggs;
911 
912  // Get SLHA2 SMINPUTS values
913  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS;
914 
915  // Get input parameters (from flexiblesusy namespace)
916  MSSMatMGUTEFTHiggs_input_parameters input;
917  input.mHu2IN = *myPipe::Param.at("mHu2");
918  input.mHd2IN = *myPipe::Param.at("mHd2");
919  input.SignMu = *myPipe::Param.at("SignMu");
920  if(input.SignMu!=-1 and input.SignMu!=1)
921  {
922  std::ostringstream msg;
923  msg << "Tried to set SignMu parameter to a value that is not a sign! ("<<input.SignMu<<")! This parameter must be set to either 1 or -1. Please check your inifile and try again.";
924  SpecBit_error().raise(LOCAL_INFO,msg.str());
925  }
926 
927  fill_MSSM63_input(input,myPipe::Param); // Fill the rest
928  result = run_FS_spectrum_generator<MSSMatMGUTEFTHiggs_interface<ALGORITHM1>>(input,sminputs,*myPipe::runOptions,myPipe::Param);
929 
930  // Only allow neutralino LSPs.
931  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
932 
933  // Drop SLHA files if requested
934  result.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
935 
936  }
937  #endif
938 
939 
940  // Runs FlexibleSUSY MSSM spectrum generator with GUT scale input (boundary conditions)
941  // but with mA and mu as parameters instead of mHu2 and mHd2
942  #if(FS_MODEL_MSSMatMGUT_mAmu_IS_BUILT)
943  void get_MSSMatMGUT_mA_spectrum_FS (Spectrum& result)
944  {
945  using namespace softsusy;
946  namespace myPipe = Pipes::get_MSSMatMGUT_mA_spectrum_FS;
947  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS;
948  MSSMatMGUT_mAmu_input_parameters input;
949  input.MuInput = *myPipe::Param.at("mu");
950  // Note this spectrum generator mA2 is the parameter.
951  // However this freedom is not used in GAMBIT
952  // and not needed as mA is a DRbar mass eigenstate for a scalar
953  double mA = *myPipe::Param.at("mA");
954  input.mA2Input = mA*mA;
955  fill_MSSM63_input(input,myPipe::Param); // Fill the rest
956  result = run_FS_spectrum_generator<MSSMatMGUT_mAmu_interface<ALGORITHM1>>(input,sminputs,*myPipe::runOptions,myPipe::Param);
957  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
958  result.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
959  }
960  #endif
961 
962  // Runs FlexibleSUSY MSSMatMGUTEFTHiggs model spectrum generator
963  // and has m3^2 and mu as EWSB outputs, so it is for the
964  // MSSMatMGUT_model.
965  #if(FS_MODEL_MSSMatMGUTEFTHiggs_mAmu_IS_BUILT)
966  void get_MSSMatMGUT_mA_spectrum_FlexibleEFTHiggs (Spectrum& result)
967  {
968  // Access the pipes for this function to get model and parameter information
969  namespace myPipe = Pipes::get_MSSMatMGUT_mA_spectrum_FlexibleEFTHiggs;
970 
971  // Get SLHA2 SMINPUTS values
972  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS;
973 
974  // Get input parameters (from flexiblesusy namespace)
975  MSSMatMGUTEFTHiggs_mAmu_input_parameters input;
976  input.MuInput = *myPipe::Param.at("mu");
977  // Note this spectrum generator mA2 is the parameter.
978  // However this freedom is not used in GAMBIT
979  // and not needed as mA is a DRbar mass eigenstate for a scalar
980  double mA = *myPipe::Param.at("mA");
981  input.mA2Input = mA*mA;
982 
983  fill_MSSM63_input(input,myPipe::Param); // Fill the rest
984  result = run_FS_spectrum_generator<MSSMatMGUTEFTHiggs_mAmu_interface<ALGORITHM1>>(input,sminputs,*myPipe::runOptions,myPipe::Param);
985 
986  // Only allow neutralino LSPs.
987  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
988 
989  // Drop SLHA files if requested
990  result.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
991 
992  }
993  #endif
994 
995 
996  // Runs FlexibleSUSY MSSM spectrum generator with SUSY scale input (boundary conditions)
997  // but with mA and mu as parameters instead of mHu2 and mHd2
998  #if(FS_MODEL_MSSMatMSUSY_mAmu_IS_BUILT)
999  void get_MSSMatMSUSY_mA_spectrum_FS (Spectrum& result)
1000  {
1001  using namespace softsusy;
1002  namespace myPipe = Pipes::get_MSSMatMSUSY_mA_spectrum_FS;
1003  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS;
1004  MSSMatMSUSY_mAmu_input_parameters input;
1005  input.MuInput = *myPipe::Param.at("mu");
1006  // Note this spectrum generator mA2 is the parameter.
1007  // However this freedom is not used in GAMBIT
1008  // and not needed as mA is a DRbar mass eigenstate for a scalar
1009  double mA = *myPipe::Param.at("mA");
1010  input.mA2Input = mA*mA; // FS has mA^2 as the parameter
1011  fill_MSSM63_input(input,myPipe::Param); // Fill the rest
1012  result = run_FS_spectrum_generator<MSSMatMSUSY_mAmu_interface<ALGORITHM1>>(input,sminputs,*myPipe::runOptions,myPipe::Param);
1013  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
1014  result.drop_SLHAs_if_requested(myPipe::runOptions, "GAMBIT_unimproved_spectrum");
1015  }
1016  #endif
1017 
1018  void get_GUTMSSMB_spectrum (Spectrum &/*result*/)
1019  {
1020  // Placeholder
1021  }
1022 
1025 
1030  {
1032  const Spectrum& matched_spectra(*myPipe::Dep::unimproved_MSSM_spectrum);
1033  result = &matched_spectra.get_LE();
1034  }
1035 
1038  {
1040  }
1041 
1044  {
1046  }
1047 
1053  {
1054  // Static counter running in a loop over all filenames
1055  static unsigned int counter = 0;
1056  static long int ncycle = 1;
1057  SLHAstruct input_slha;
1058 
1059  namespace myPipe = Pipes::get_MSSM_spectrum_from_SLHAfile;
1060 
1061  // Read filename from yaml file
1062  std::vector<std::string> filenames =
1063  myPipe::runOptions->getValue<std::vector<std::string>>("filenames");
1064 
1065  // Check how many loop over the input files we are doing.
1066  long int cycles = myPipe::runOptions->getValueOrDef<int>(-1,"cycles");
1067 
1068  // Check if we have completed the requested number of cycles
1069  if(cycles>0 and ncycle>cycles)
1070  {
1071  std::ostringstream msg;
1072  msg << "Preset number of loops through input files reached! Stopping. (tried to start cycle "<<ncycle<<" of "<<cycles<<")";
1073  SpecBit_error().raise(LOCAL_INFO,msg.str());
1074  }
1075 
1076  std::string filename = filenames[counter];
1077 
1078  logger() << "Reading SLHA file: " << filename << EOM;
1079  std::ifstream ifs(filename.c_str());
1080  if(!ifs.good()){ SpecBit_error().raise(LOCAL_INFO,"ERROR: SLHA file not found."); }
1081  ifs >> input_slha;
1082  ifs.close();
1083  counter++;
1084  if( counter >= filenames.size() )
1085  {
1086  logger() << "Returning to start of input SLHA file list (finished "<<ncycle<<" cycles)" << EOM;
1087  counter = 0;
1088  ncycle++;
1089  }
1090 
1091  // Retrieve any mass cuts
1092  static const Spectrum::mc_info mass_cut = myPipe::runOptions->getValueOrDef<Spectrum::mc_info>(Spectrum::mc_info(), "mass_cut");
1093  static const Spectrum::mr_info mass_ratio_cut = myPipe::runOptions->getValueOrDef<Spectrum::mr_info>(Spectrum::mr_info(), "mass_ratio_cut");
1094 
1095  // Create Spectrum object from the slhaea object
1096  result = spectrum_from_SLHAea<MSSMSimpleSpec, SLHAstruct>(input_slha, input_slha, mass_cut, mass_ratio_cut);
1097 
1098  // Add getter for susy scale if option set for this
1099  bool add_susy_scale = myPipe::runOptions->getValueOrDef<bool>(false,"assume_Q_is_MSUSY");
1100  if(add_susy_scale)
1101  {
1102  result.get_HE().set_override(Par::mass1,result.get_HE().GetScale(),"susy_scale",true);
1103  }
1104 
1105  // No sneaking in charged LSPs via SLHA, jävlar.
1106  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
1107  }
1108 
1113  {
1114  namespace myPipe = Pipes::get_MSSM_spectrum_from_SLHAstruct;
1115  const SLHAstruct& input_slha_tmp = *myPipe::Dep::unimproved_MSSM_spectrum; // Retrieve dependency on SLHAstruct
1116 
1118  SLHAstruct input_slha(input_slha_tmp); // Copy struct (for demo adding of GAMBIT block only)
1119  // For example; add this to your input SLHAstruct:
1120  input_slha["GAMBIT"][""] << "BLOCK" << "GAMBIT";
1121  input_slha["GAMBIT"][""] << 1 << 1e99 << "# Input scale";
1122 
1123  // Retrieve any mass cuts
1124  static const Spectrum::mc_info mass_cut = myPipe::runOptions->getValueOrDef<Spectrum::mc_info>(Spectrum::mc_info(), "mass_cut");
1125  static const Spectrum::mr_info mass_ratio_cut = myPipe::runOptions->getValueOrDef<Spectrum::mr_info>(Spectrum::mr_info(), "mass_ratio_cut");
1126 
1127  // Create Spectrum object from the slhaea object
1128  result = spectrum_from_SLHAea<MSSMSimpleSpec, SLHAstruct>(input_slha, input_slha, mass_cut, mass_ratio_cut);
1129 
1130  // No sneaking in charged LSPs via SLHA, jävlar.
1131  if (not has_neutralino_LSP(result)) invalid_point().raise("Neutralino is not LSP.");
1132 
1133  // In order to translate from e.g. MSSM63atMGUT to MSSM63atQ, we need
1134  // to know that input scale Q. This is generally not stored in SLHA format,
1135  // but we need it, so if you want to produce a Spectrum object this way you
1136  // will need to add this information to your SLHAstruct:
1137  // BLOCK GAMBIT
1138  // 1 <high_scale> # Input scale of (upper) boundary conditions, e.g. GUT scale
1139 
1140  // Need to check if this information exists:
1141  SLHAstruct::const_iterator block = input_slha.find("GAMBIT");
1142  std::vector<std::string> key(1, "1");
1143  if(block == input_slha.end() or block->find(key) == block->end())
1144  {
1145  // Big problem
1146  std::ostringstream errmsg;
1147  errmsg << "Error constructing Spectrum object from a pre-existing SLHAstruct! " << endl
1148  << "The supplied SLHAstruct did not have the special GAMBIT block added. " << endl
1149  << "This block carries extra information from the spectrum generator " << endl
1150  << "that is usually thrown away, but which is needed for properly creating" << endl
1151  << "a Spectrum object. In whatever module function created the SLHAstruct " << endl
1152  << "that you want to use, please add code that adds the following " << endl
1153  << "information to the SLHAstruct (SLHAea::Coll): " << endl
1154  << " BLOCK GAMBIT " << endl
1155  << " 1 <high_scale> # Input scale of (upper) boundary conditions, e.g. GUT scale\n";
1156  SpecBit_error().raise(LOCAL_INFO,errmsg.str());
1157  }
1158 
1159  // OK the GAMBIT block exists, add the data to the MSSM SubSpectrum object.
1160  result.get_HE().set_override(Par::mass1,SLHAea::to<double>(input_slha.at("GAMBIT").at(1).at(1)), "high_scale", false);
1161  }
1162 
1168  {
1170  const SMInputs& sminputs = *myPipe::Dep::SMINPUTS; // Retrieve dependency on SLHAstruct
1171 
1172  // Retrieve the spectrum from whatever the point the global reader object is pointed at.
1173  // This should be the same point that the postprocessor has retrieved the
1174  // current set of ModelParameters from.
1175  // Will throw an error if no reader object exists, i.e. if the postprocessor is not
1176  // driving this scan.
1177 
1178  // Retrieve MSSM spectrum info into an SLHAea object
1179  MSSM_SLHAstruct mssm_in; // Special type to trigger specialised MSSM retrieve routine
1180  bool mssm_is_valid = get_pp_reader().retrieve(mssm_in,"MSSM_spectrum");
1181 
1182  // Retrieve SM spectrum info into an SLHAea object
1183  // (should really match SMINPUTS, but better to use what is actually in the reported output spectrum)
1184  SMslha_SLHAstruct sm_in;
1185  bool sm_is_valid = get_pp_reader().retrieve(sm_in,"MSSM_spectrum");
1186 
1187  // Check if a valid spectrum was retrived
1188  // (if the required datasets don't exist an error will be thrown,
1189  // so this is just checking that the spectrum was computed for
1190  // the current input point)
1191  if(not (mssm_is_valid and sm_is_valid)) invalid_point().raise("Postprocessor: precomputed spectrum was set 'invalid' for this point");
1192 
1193  // Dump spectrum to output for testing
1194  SLHAstruct mssm = mssm_in; // Only this type has stream overloads etc. defined
1195  SLHAstruct sm = sm_in;
1196 
1197  // Turns out we don't generically save tan_beta(mZ)_DRbar, so need to extract
1198  // this from model parameters (it is always an input, so we should have it in those)
1199  double tbmZ = *myPipe::Param.at("TanBeta");
1200  SLHAea_add(mssm, "MINPAR", 3, tbmZ, "tan beta (mZ)_DRbar");
1201  SLHAea_add(sm, "MINPAR", 3, tbmZ, "tan beta (mZ)_DRbar");
1202 
1203  // Retrieve any mass cuts (could just cut with postprocessor, but I
1204  // guess can leave this feature in for compatibility with usage
1205  // of other Spectrum objects.
1206  static const Spectrum::mc_info mass_cut = myPipe::runOptions->getValueOrDef<Spectrum::mc_info>(Spectrum::mc_info(), "mass_cut");
1207  static const Spectrum::mr_info mass_ratio_cut = myPipe::runOptions->getValueOrDef<Spectrum::mr_info>(Spectrum::mr_info(), "mass_ratio_cut");
1208 
1209  // Create HE simple SubSpectrum object from the SLHAea object
1210  MSSMSimpleSpec he(mssm);
1211 
1212  // Create SMSimpleSpec SubSpectrum object from SMInputs
1213  SMSimpleSpec le(sm);
1214 
1215  // Create full Spectrum object
1216  result = Spectrum(le,he,sminputs,NULL,mass_cut,mass_ratio_cut);
1217  }
1218 
1220  void FH_MSSMMasses(fh_MSSMMassObs &result)
1221  {
1222  using namespace Pipes::FH_MSSMMasses;
1223 
1224  #ifdef SPECBIT_DEBUG
1225  cout << "****** calling FH_MSSMMasses ******" << endl;
1226  #endif
1227 
1228  // zero if minimal, non-zero if non-minimal flavour violation
1229  int nmfv;
1230 
1231  // MSf(s,t,g) MFV squark masses with indices
1232  // s = 1..2 sfermion index
1233  // t = 1..5 sfermion type nu,e,u,d,?
1234  // g = 1..3 generation index
1236 
1237  // USf(s1,s2,t,g) MFV squark mixing matrices with indices
1238  // s1 = 1..2 sfermion index (mass eigenstates)
1239  // s2 = 1..2 sfermion index (gauge eigenstates, L/R)
1240  // t = 1..5 sfermion type nu,e,u,d,?
1241  // g = 1..3 generation index
1243 
1244  // NMFV squark masses, with indices
1245  // a = 1..6 extended sfermion index
1246  // t = 1..5 sfermion type
1248 
1249  // NMFV squark mixing matrices, with indices
1250  // a1 = 1..6 extended sfermion index (mass eigenstates)
1251  // a2 = 1..6 extended sfermion index (gauge eigenstates)
1252  // t = 1..5 sftermion type nu,e,u,d,?
1254 
1255  // chargino masses
1256  Farray<fh_real, 1,2> MCha;
1257 
1258  // chargino mixing matrices (mass,gauge) eigenstates (2 x 2)
1261 
1262  // neutralino masses
1263  Farray<fh_real, 1,4> MNeu;
1264 
1265  // neutralino mixing matrices (mass,gauge) eigenstates (4 x 4)
1267 
1268  // correction to bottom Yukawa coupling
1269  fh_complex DeltaMB;
1270 
1271  // gluino mass
1272  fh_real MGl;
1273 
1274  // tree-level Higgs masses (Mh, MH, MA, MHpm)
1275  Farray<fh_real, 1,4> MHtree;
1276 
1277  // tree-level Higgs mixing parameters sin alpha
1278  fh_real SAtree;
1279 
1280  #ifdef SPECBIT_DEBUG
1281  cout << "****** calling FHGetPara ******" << endl;
1282  #endif
1283 
1284  int error = 1;
1285  BEreq::FHGetPara(error, nmfv, MSf, USf, MASf, UASf,
1286  MCha, UCha, VCha, MNeu, ZNeu,
1287  DeltaMB, MGl, MHtree, SAtree);
1288  if (error != 0)
1289  {
1290  std::ostringstream err;
1291  err << "BEreq::FHGetPara raised error flag: " << error << ".";
1292  invalid_point().raise(err.str());
1293  }
1294 
1295  fh_MSSMMassObs MassObs;
1296  for(int i = 0; i < 2; i++)
1297  for(int j = 0; j < 5; j++)
1298  for(int k = 0; k < 3; k++)
1299  MassObs.MSf[i][j][k] = MSf(i+1,j+1,k+1);
1300  for(int i = 0; i < 2; i++)
1301  for(int j = 0; j < 2; j++)
1302  for(int k = 0; k < 5; k++)
1303  for(int l = 0; l < 3; l++)
1304  MassObs.USf[i][j][k][l] = USf(i+1,j+1,k+1,l+1);
1305  for(int i = 0; i < 6; i++)
1306  for(int j = 0; j < 5; j++)
1307  MassObs.MASf[i][j] = MASf(i+1,j+1);
1308  for(int i = 0; i < 36; i++)
1309  for(int j = 0; j < 5; j++)
1310  MassObs.UASf[i][j] = UASf(i+1,j+1);
1311  for(int i = 0; i < 2; i++)
1312  MassObs.MCha[i] = MCha(i+1);
1313  for(int i = 0; i < 4; i++)
1314  {
1315  MassObs.UCha[i] = UCha(i+1);
1316  MassObs.VCha[i] = VCha(i+1);
1317  }
1318  for(int i = 0; i < 4; i++)
1319  MassObs.MNeu[i] = MNeu(i+1);
1320  for(int i = 0; i < 16; i++)
1321  MassObs.ZNeu[i] = ZNeu(i+1);
1322  MassObs.deltaMB = DeltaMB;
1323  MassObs.MGl = MGl;
1324  for(int i = 0; i < 4; i++)
1325  MassObs.MHtree[i] = MHtree(i+1);
1326  MassObs.SinAlphatree = SAtree;
1327 
1328  result = MassObs;
1329  }
1330 
1331 
1333  void FH_AllHiggsMasses(fh_HiggsMassObs &result)
1334  {
1335  using namespace Pipes::FH_AllHiggsMasses;
1336 
1337  #ifdef SPECBIT_DEBUG
1338  cout << "****** calling FH_HiggsMasses ******" << endl;
1339  #endif
1340 
1341  // Higgs mass with
1342  // 0 - m1 (Mh in rMSSM)
1343  // 1 - m2 (MH in rMSSM)
1344  // 2 - m3 (MA in rMSSM)
1345  // 3 - MHpm
1346  Farray<fh_real, 1,4> MHiggs;
1347  Farray<fh_real, 1,4> DeltaMHiggs;
1348 
1349  // sine of effective Higgs mixing angle, alpha_eff
1350  fh_complex SAeff;
1351  fh_complex DeltaSAeff;
1352 
1353  // matrix needed to rotate Higgs
1354  // mass matrix to diagonal form
1356  Farray<fh_complex, 1,3, 1,3> DeltaUHiggs;
1357 
1358  // matrix of Z-factors needed to combine
1359  // amplitudes involving on-shell Higgs
1361  Farray<fh_complex, 1,3, 1,3> DeltaZHiggs;
1362 
1363  #ifdef SPECBIT_DEBUG
1364  cout << "****** calling FHHiggsCorr ******" << endl;
1365  #endif
1366 
1367  int error = 1;
1368  BEreq::FHHiggsCorr(error, MHiggs, SAeff, UHiggs, ZHiggs);
1369  if (error != 0)
1370  {
1371  std::ostringstream err;
1372  err << "BEreq::FHHiggsCorr raised error flag: " << error << ".";
1373  invalid_point().raise(err.str());
1374  }
1375 
1376  #ifdef SPECBIT_DEBUG
1377  cout << "****** calling FHUncertainties ******" << endl;
1378  #endif
1379 
1380  error = 1;
1381  BEreq::FHUncertainties(error, DeltaMHiggs, DeltaSAeff, DeltaUHiggs, DeltaZHiggs);
1382  if (error != 0)
1383  {
1384  std::ostringstream err;
1385  err << "BEreq::FHUncertainties raised error flag: " << error << ".";
1386  invalid_point().raise(err.str());
1387  }
1388 
1389  fh_HiggsMassObs HiggsMassObs;
1390  for(int i = 0; i < 4; i++)
1391  {
1392  HiggsMassObs.MH[i] = MHiggs(i+1);
1393  HiggsMassObs.deltaMH[i] = DeltaMHiggs(i+1);
1394  }
1395  HiggsMassObs.SinAlphaEff = SAeff;
1396  HiggsMassObs.deltaSinAlphaEff = DeltaSAeff;
1397  for(int i = 0; i < 3; i++)
1398  for(int j = 0; j < 3; j++)
1399  {
1400  HiggsMassObs.UH[i][j] = UHiggs(i+1,j+1);
1401  HiggsMassObs.deltaUH[i][j] = DeltaUHiggs(i+1,j+1);
1402  HiggsMassObs.ZH[i][j] = ZHiggs(i+1,j+1);
1403  HiggsMassObs.deltaZH[i][j] = DeltaZHiggs(i+1,j+1);
1404  }
1405 
1406  result = HiggsMassObs;
1407  }
1408 
1412 
1414  void FH_Couplings(fh_Couplings &result)
1415  {
1416  using namespace Pipes::FH_Couplings;
1417 
1418  #ifdef SPECBIT_DEBUG
1419  cout << "****** calling FH_Couplings ******" << endl;
1420  #endif
1421 
1422  // what to use for internal Higgs mixing
1423  // (ex. in couplings)
1424  // (default = 1)
1425  // 0 - no mixing
1426  // 1 - UHiggs
1427  // 2 - ZHiggs
1428  int uzint = 2;
1429  // what to use for external Higgs mixing
1430  // (ex. in decays)
1431  // (default = 2)
1432  // 0 - no mixing
1433  // 1 - UHiggs
1434  // 2 - ZHiggs
1435  int uzext = 2;
1436  // which effective bottom mass to use
1437  int mfeff = 1;
1438 
1439  #ifdef SPECBIT_DEBUG
1440  cout << "****** calling FHSelectUZ ******" << endl;
1441  #endif
1442 
1443  int error = 1;
1444  BEreq::FHSelectUZ(error, uzint, uzext, mfeff);
1445  if (error != 0)
1446  {
1447  std::ostringstream err;
1448  err << "BEreq::FHSelectUZ raised error flag: " << error << ".";
1449  invalid_point().raise(err.str());
1450  }
1451 
1452  Farray<fh_complex, 1,ncouplings> couplings; // MSSM Higgs couplings
1453  Farray<fh_complex, 1,ncouplingsms> couplings_sm; // SM Higgs couplings
1454  Farray<fh_real, 1,ngammas> gammas; // Higgs decay widths and BR's (MSSM)
1455  Farray<fh_real, 1,ngammasms> gammas_sm; // Higgs decay widths and BR's (SM)
1456  int fast = 1; // include off-diagonal fermion decays? (1 = no)
1457 
1458  #ifdef SPECBIT_DEBUG
1459  cout << "****** calling FHCouplings ******" << endl;
1460  #endif
1461 
1462  error = 1;
1463  BEreq::FHCouplings(error, couplings, couplings_sm,
1464  gammas, gammas_sm, fast);
1465  if (error != 0)
1466  {
1467  std::ostringstream err;
1468  err << "BEreq::FHCouplings raised error flag: " << error << ".";
1469  invalid_point().raise(err.str());
1470  }
1471 
1472  fh_Couplings Couplings;
1473  for(int i = 0; i < ncouplings; i++) Couplings.couplings[i] = couplings(i+1);
1474  for(int i = 0; i < ncouplingsms; i++) Couplings.couplings_sm[i] = couplings_sm(i+1);
1475  for(int i = 0; i < ngammas; i++) Couplings.gammas[i] = gammas(i+1);
1476  for(int i = 0; i < ngammasms; i++) Couplings.gammas_sm[i] = gammas_sm(i+1);
1477  Couplings.calculator = BEreq::FHCouplings.origin();
1478  Couplings.calculator_version = BEreq::FHCouplings.version();
1479 
1480  result = Couplings;
1481  }
1482 
1483 
1485  std::vector<std::pair<str,str>> get_invisibles(const SubSpectrum& spec)
1486  {
1487  // Get the lighter of the lightest neutralino and the lightest sneutrino
1488  std::pair<str,double> neutralino("~chi0_1", spec.get(Par::Pole_Mass,"~chi0",1));
1489  std::pair<str,double> sneutrino("~nu_1", spec.get(Par::Pole_Mass,"~nu",1));
1490  std::pair<str,double> lnp = (neutralino.second < sneutrino.second ? neutralino : sneutrino);
1491 
1492  // Work out if this is indeed the LSP, and if decays of at least one neutral higgs to it are kinematically possible.
1493  bool inv_lsp = spec.get(Par::Pole_Mass,"~chi+",1) > lnp.second and
1494  spec.get(Par::Pole_Mass,"~g") > lnp.second and
1495  spec.get(Par::Pole_Mass,"~d",1) > lnp.second and
1496  spec.get(Par::Pole_Mass,"~u",1) > lnp.second and
1497  spec.get(Par::Pole_Mass,"~e-",1) > lnp.second and
1498  (spec.get(Par::Pole_Mass,"h0",2) > 2.*lnp.second or
1499  spec.get(Par::Pole_Mass,"A0") > 2.*lnp.second);
1500 
1501  // Create a vector containing all invisible products of higgs decays.
1502  if (inv_lsp) return initVector<std::pair<str,str>>(std::make_pair(lnp.first,lnp.first));
1503  return std::vector<std::pair<str,str>>();
1504  }
1505 
1508  {
1509  using namespace Pipes::MSSM_higgs_couplings_pwid;
1510 
1511  // Retrieve spectrum contents
1512  const SubSpectrum& spec = Dep::MSSM_spectrum->get_HE();
1513 
1514  // Set up neutral Higgses
1515  static const std::vector<str> sHneut = initVector<str>("h0_1", "h0_2", "A0");
1516  result.set_n_neutral_higgs(3);
1517 
1518  // Set up charged Higgses
1519  result.set_n_charged_higgs(1);
1520 
1521  // Set the CP of the Higgs states. Note that this would need to be more sophisticated to deal with the complex MSSM!
1522  result.CP[0] = 1; //h0_1
1523  result.CP[1] = 1; //h0_2
1524  result.CP[2] = -1; //A0
1525 
1526  // Work out which SM values correspond to which SUSY Higgs
1527  int higgs = (SMlike_higgs_PDG_code(spec) == 25 ? 0 : 1);
1528  int other_higgs = (higgs == 0 ? 1 : 0);
1529 
1530  // Set the decays
1531  result.set_neutral_decays_SM(higgs, sHneut[higgs], *Dep::Reference_SM_Higgs_decay_rates);
1532  result.set_neutral_decays_SM(other_higgs, sHneut[other_higgs], *Dep::Reference_SM_other_Higgs_decay_rates);
1533  result.set_neutral_decays_SM(2, sHneut[2], *Dep::Reference_SM_A0_decay_rates);
1534  result.set_neutral_decays(0, sHneut[0], *Dep::Higgs_decay_rates);
1535  result.set_neutral_decays(1, sHneut[1], *Dep::h0_2_decay_rates);
1536  result.set_neutral_decays(2, sHneut[2], *Dep::A0_decay_rates);
1537  result.set_charged_decays(0, "H+", *Dep::H_plus_decay_rates);
1538  result.set_t_decays(*Dep::t_decay_rates);
1539 
1540  // Use them to compute effective couplings for all neutral higgses, except for hhZ.
1541  for (int i = 0; i < 3; i++)
1542  {
1543  result.C_WW2[i] = result.compute_effective_coupling(i, std::pair<int,int>(24, 0), std::pair<int,int>(-24, 0));
1544  result.C_ZZ2[i] = result.compute_effective_coupling(i, std::pair<int,int>(23, 0), std::pair<int,int>(23, 0));
1545  result.C_tt2[i] = result.compute_effective_coupling(i, std::pair<int,int>(6, 1), std::pair<int,int>(-6, 1));
1546  result.C_bb2[i] = result.compute_effective_coupling(i, std::pair<int,int>(5, 1), std::pair<int,int>(-5, 1));
1547  result.C_cc2[i] = result.compute_effective_coupling(i, std::pair<int,int>(4, 1), std::pair<int,int>(-4, 1));
1548  result.C_tautau2[i] = result.compute_effective_coupling(i, std::pair<int,int>(15, 1), std::pair<int,int>(-15, 1));
1549  result.C_gaga2[i] = result.compute_effective_coupling(i, std::pair<int,int>(22, 0), std::pair<int,int>(22, 0));
1550  result.C_gg2[i] = result.compute_effective_coupling(i, std::pair<int,int>(21, 0), std::pair<int,int>(21, 0));
1551  result.C_mumu2[i] = result.compute_effective_coupling(i, std::pair<int,int>(13, 1), std::pair<int,int>(-13, 1));
1552  result.C_Zga2[i] = result.compute_effective_coupling(i, std::pair<int,int>(23, 0), std::pair<int,int>(21, 0));
1553  result.C_ss2[i] = result.compute_effective_coupling(i, std::pair<int,int>(3, 1), std::pair<int,int>(-3, 1));
1554  }
1555 
1556  // Calculate hhZ effective couplings. Here we scale out the kinematic prefactor
1557  // of the decay width, assuming we are well above threshold if the channel is open.
1558  // If not, we simply assume SM couplings.
1559  const double mZ = Dep::MSSM_spectrum->get(Par::Pole_Mass,23,0);
1560  const double scaling = 8.*sqrt(2.)*pi/Dep::MSSM_spectrum->get_SMInputs().GF;
1561  for(int i = 0; i < 3; i++)
1562  for(int j = 0; j < 3; j++)
1563  {
1564  double mhi = spec.get(Par::Pole_Mass, sHneut[i]);
1565  double mhj = spec.get(Par::Pole_Mass, sHneut[j]);
1566  if (mhi > mhj + mZ and result.get_neutral_decays(i).has_channel(sHneut[j], "Z0"))
1567  {
1568  double gamma = result.get_neutral_decays(i).width_in_GeV*result.get_neutral_decays(i).BF(sHneut[j], "Z0");
1569  double k[2] = {(mhj + mZ)/mhi, (mhj - mZ)/mhi};
1570  for (int l = 0; l < 2; l++) k[l] = (1.0 - k[l]) * (1.0 + k[l]);
1571  double K = mhi*sqrt(k[0]*k[1]);
1572  result.C_hiZ2[i][j] = scaling / (K*K*K) * gamma;
1573  }
1574  else // If the channel is missing from the decays or kinematically disallowed, just return the SM result.
1575  {
1576  result.C_hiZ2[i][j] = 1.;
1577  }
1578  }
1579 
1580  // Work out which invisible decays are possible
1581  result.invisibles = get_invisibles(spec);
1582  }
1583 
1584 
1587  {
1588  using namespace Pipes::MSSM_higgs_couplings_FH;
1589 
1590  // Retrieve spectrum contents
1591  const SubSpectrum& spec = Dep::MSSM_spectrum->get_HE();
1592  const SMInputs& sminputs = Dep::MSSM_spectrum->get_SMInputs();
1593 
1594  // Set up neutral Higgses
1595  static const std::vector<str> sHneut = initVector<str>("h0_1", "h0_2", "A0");
1596 
1597  // Work out which SM values correspond to which SUSY Higgs
1598  int higgs = (SMlike_higgs_PDG_code(spec) == 25 ? 0 : 1);
1599  int other_higgs = (higgs == 0 ? 1 : 0);
1600 
1601  // Set the decays
1602  result.set_neutral_decays_SM(higgs, sHneut[higgs], *Dep::Reference_SM_Higgs_decay_rates);
1603  result.set_neutral_decays_SM(other_higgs, sHneut[other_higgs], *Dep::Reference_SM_other_Higgs_decay_rates);
1604  result.set_neutral_decays_SM(2, sHneut[2], *Dep::Reference_SM_A0_decay_rates);
1605  result.set_neutral_decays(0, sHneut[0], *Dep::Higgs_decay_rates);
1606  result.set_neutral_decays(1, sHneut[1], *Dep::h0_2_decay_rates);
1607  result.set_neutral_decays(2, sHneut[2], *Dep::A0_decay_rates);
1608  result.set_charged_decays(0, "H+", *Dep::H_plus_decay_rates);
1609  result.set_t_decays(*Dep::t_decay_rates);
1610 
1611  // Use the branching fractions to compute gluon, gamma/Z and second generation fermionic effective couplings
1612  for (int i = 0; i < 3; i++)
1613  {
1614  result.C_gg2[i] = result.compute_effective_coupling(i, std::pair<int,int>(21, 0), std::pair<int,int>(21, 0));
1615  result.C_gaga2[i] = result.compute_effective_coupling(i, std::pair<int,int>(22, 0), std::pair<int,int>(22, 0));
1616  result.C_Zga2[i] = result.compute_effective_coupling(i, std::pair<int,int>(23, 0), std::pair<int,int>(22, 0));
1617  result.C_mumu2[i] = result.compute_effective_coupling(i, std::pair<int,int>(13, 1), std::pair<int,int>(-13, 1));
1618  result.C_ss2[i] = result.compute_effective_coupling(i, std::pair<int,int>(3, 1), std::pair<int,int>(-3, 1));
1619  result.C_cc2[i] = result.compute_effective_coupling(i, std::pair<int,int>(4, 1), std::pair<int,int>(-4, 1));
1620  }
1621 
1622  // Use couplings to get effective third-generation couplings
1623  for(int i = 0; i < 3; i++)
1624  {
1625  // Compute effective couplings
1626  double g2_s[3], g2_p[3];
1627  for (int j = 0; j < 3; j++) // j=0,1,2 => tau, t, b
1628  {
1629  fh_complex fh_L = Dep::FH_Couplings_output->couplings[H0FF(i+1,j+2,3,3)-1];
1630  fh_complex fh_R = Dep::FH_Couplings_output->couplings[H0FF(i+1,j+2,3,3)+Roffset-1];
1631  fh_complex fh_SM_L = Dep::FH_Couplings_output->couplings_sm[H0FF(i+1,j+2,3,3)-1];
1632  fh_complex fh_SM_R = Dep::FH_Couplings_output->couplings_sm[H0FF(i+1,j+2,3,3)+RSMoffset-1];
1633  std::complex<double> L(fh_L.re,fh_L.im);
1634  std::complex<double> R(fh_R.re,fh_R.im);
1635  std::complex<double> SM_L(fh_SM_L.re,fh_SM_L.im);
1636  std::complex<double> SM_R(fh_SM_R.re,fh_SM_R.im);
1637  g2_s[j] = 0.25*pow(std::abs(R/SM_R + L/SM_L), 2.);
1638  g2_p[j] = 0.25*pow(std::abs(R/SM_R - L/SM_L), 2.);
1639  }
1640  result.C_tautau2[i] = g2_s[0] + g2_p[0];
1641  result.C_tt2[i] = g2_s[1] + g2_p[1];
1642  result.C_bb2[i] = g2_s[2] + g2_p[2];
1643 
1644  // Calculate CP of state
1645  if(g2_p[2] < 1e-10)
1646  result.CP[i] = 1;
1647  else if(g2_s[2] < 1e-10)
1648  result.CP[i] = -1;
1649  else
1650  result.CP[i] = 0.;
1651  }
1652 
1653  // Use couplings to get di-boson effective couplings
1654  for(int i = 0; i < 3; i++)
1655  {
1656  fh_complex c_gWW = Dep::FH_Couplings_output->couplings[H0VV(i+1,4)-1];
1657  fh_complex c_gWW_SM = Dep::FH_Couplings_output->couplings_sm[H0VV(i+1,4)-1];
1658  fh_complex c_gZZ = Dep::FH_Couplings_output->couplings[H0VV(i+1,3)-1];
1659  fh_complex c_gZZ_SM = Dep::FH_Couplings_output->couplings_sm[H0VV(i+1,3)-1];
1660  std::complex<double> WW(c_gWW.re,c_gWW.im);
1661  std::complex<double> WW_SM(c_gWW_SM.re,c_gWW_SM.im);
1662  std::complex<double> ZZ(c_gZZ.re,c_gZZ.im);
1663  std::complex<double> ZZ_SM(c_gZZ_SM.re,c_gZZ_SM.im);
1664  result.C_WW2[i] = pow(std::abs(WW/WW_SM), 2.);
1665  result.C_ZZ2[i] = pow(std::abs(ZZ/ZZ_SM), 2.);
1666  }
1667 
1668  // Use couplings to get hhZ effective couplings
1669  double norm = sminputs.GF*sqrt(2.)*sminputs.mZ*sminputs.mZ;
1670  for(int i = 0; i < 3; i++)
1671  for(int j = 0; j < 3; j++)
1672  {
1673  fh_complex c_gHV = Dep::FH_Couplings_output->couplings[H0HV(i+1,j+1)-1];
1674  double g2HV = c_gHV.re*c_gHV.re+c_gHV.im*c_gHV.im;
1675  result.C_hiZ2[i][j] = g2HV/norm;
1676  }
1677 
1678  // Work out which invisible decays are possible
1679  result.invisibles = get_invisibles(spec);
1680  }
1681 
1682 
1686 
1688  template<class Contents>
1689  void fill_map_from_subspectrum(std::map<std::string,double>&, const SubSpectrum&);
1690 
1692  void add_extra_MSSM_parameter_combinations(std::map<std::string,double>& specmap, const SubSpectrum& mssm)
1693  {
1694  double At = 0;
1695  double Ab = 0;
1696  const double Yt = mssm.get(Par::dimensionless, "Yu", 3, 3);
1697  const double Yb = mssm.get(Par::dimensionless, "Yd", 3, 3);
1698  if(std::abs(Yt) > 1e-12)
1699  {
1700  At = mssm.get(Par::mass1, "TYu", 3, 3) / Yt;
1701  }
1702  if(std::abs(Yb) > 1e-12)
1703  {
1704  Ab = mssm.get(Par::mass1, "TYd", 3, 3) / Yb;
1705  }
1706 
1707  const double MuSUSY = mssm.get(Par::mass1, "Mu");
1708  const double tb = mssm.get(Par::dimensionless, "tanbeta");
1709 
1710  specmap["Xt"] = At - MuSUSY / tb;
1711  specmap["Xb"] = Ab - MuSUSY * tb;
1713  str msf1, msf2;
1717  const static double tol = 0.5;
1718  const static bool pt_error = true;
1719  slhahelp::family_state_mix_matrix("~u", 3, msf1, msf2, mssm, tol,
1720  LOCAL_INFO, pt_error);
1721  specmap["mstop1"] = mssm.get(Par::Pole_Mass, msf1);
1722  specmap["mstop2"] = mssm.get(Par::Pole_Mass, msf2);
1723  slhahelp::family_state_mix_matrix("~d", 3, msf1, msf2, mssm, tol,
1724  LOCAL_INFO, pt_error);
1725  specmap["msbottom1"] = mssm.get(Par::Pole_Mass, msf1);
1726  specmap["msbottom2"] = mssm.get(Par::Pole_Mass, msf2);
1727  slhahelp::family_state_mix_matrix("~e-", 3, msf1, msf2, mssm, tol,
1728  LOCAL_INFO, pt_error);
1729  specmap["mstau1"] = mssm.get(Par::Pole_Mass, msf1);
1730  specmap["mstau2"] = mssm.get(Par::Pole_Mass, msf2);
1733  const str gs_suL = slhahelp::mass_es_from_gauge_es("~u_L", mssm, tol,
1734  LOCAL_INFO, pt_error);
1735  specmap["msupL"] = mssm.get(Par::Pole_Mass,gs_suL);
1736  const str gs_scL = slhahelp::mass_es_from_gauge_es("~c_L", mssm, tol,
1737  LOCAL_INFO, pt_error);
1738  specmap["mscharmL"] = mssm.get(Par::Pole_Mass,gs_scL);
1739  const str gs_sdL = slhahelp::mass_es_from_gauge_es("~d_L", mssm, tol,
1740  LOCAL_INFO, pt_error);
1741  specmap["msdownL"] = mssm.get(Par::Pole_Mass,gs_sdL);
1742  const str gs_ssL = slhahelp::mass_es_from_gauge_es("~s_L", mssm, tol,
1743  LOCAL_INFO, pt_error);
1744  specmap["msstrangeL"] = mssm.get(Par::Pole_Mass,gs_ssL);
1745  const str gs_suR = slhahelp::mass_es_from_gauge_es("~u_R", mssm, tol,
1746  LOCAL_INFO, pt_error);
1747  specmap["msupR"] = mssm.get(Par::Pole_Mass,gs_suR);
1748  const str gs_scR = slhahelp::mass_es_from_gauge_es("~c_R", mssm, tol,
1749  LOCAL_INFO, pt_error);
1750  specmap["mscharmR"] = mssm.get(Par::Pole_Mass,gs_scR);
1751  const str gs_sdR = slhahelp::mass_es_from_gauge_es("~d_R", mssm, tol,
1752  LOCAL_INFO, pt_error);
1753  specmap["msdownR"] = mssm.get(Par::Pole_Mass,gs_sdR);
1754  const str gs_ssR = slhahelp::mass_es_from_gauge_es("~s_R", mssm, tol,
1755  LOCAL_INFO, pt_error);
1756  specmap["msstrangeR"] = mssm.get(Par::Pole_Mass,gs_ssR);
1757  const str gs_seL = slhahelp::mass_es_from_gauge_es("~e_L", mssm, tol,
1758  LOCAL_INFO, pt_error);
1759  specmap["mselectronL"] = mssm.get(Par::Pole_Mass,gs_seL);
1760  const str gs_sMuL = slhahelp::mass_es_from_gauge_es("~mu_L", mssm, tol,
1761  LOCAL_INFO, pt_error);
1762  specmap["msmuonL"] = mssm.get(Par::Pole_Mass,gs_sMuL);
1763  const str gs_seR = slhahelp::mass_es_from_gauge_es("~e_R", mssm, tol,
1764  LOCAL_INFO, pt_error);
1765  specmap["mselectronR"] = mssm.get(Par::Pole_Mass,gs_seR);
1766  const str gs_sMuR = slhahelp::mass_es_from_gauge_es("~mu_R", mssm, tol,
1767  LOCAL_INFO, pt_error);
1768  specmap["msmuonR"] = mssm.get(Par::Pole_Mass,gs_sMuR);
1769  const str gs_snu1 = slhahelp::mass_es_from_gauge_es("~nu_e_L", mssm, tol,
1770  LOCAL_INFO, pt_error);
1771  specmap["msnue"] = mssm.get(Par::Pole_Mass,gs_snu1);
1772  const str gs_snu2 = slhahelp::mass_es_from_gauge_es("~nu_mu_L", mssm, tol,
1773  LOCAL_INFO, pt_error);
1774  specmap["msnumu"] = mssm.get(Par::Pole_Mass,gs_snu2);
1775  const str gs_snu3 = slhahelp::mass_es_from_gauge_es("~nu_tau_L", mssm, tol,
1776  LOCAL_INFO, pt_error);
1777  specmap["msnutau"] = mssm.get(Par::Pole_Mass,gs_snu3);
1778 
1779  }
1780 
1781  void get_MSSM_spectrum_as_map (std::map<std::string,double>& specmap)
1782  {
1783  namespace myPipe = Pipes::get_MSSM_spectrum_as_map;
1784  const Spectrum& mssmspec(*myPipe::Dep::MSSM_spectrum);
1785  try
1786  {
1787  fill_map_from_subspectrum<SpectrumContents::SM> (specmap, mssmspec.get_LE());
1788  }
1789  catch(const Gambit::exception&)
1790  {
1791  // The above will fail for the SimpleSpectrum versions of the MSSM spectrum
1792  // because it uses SM_slha rather than SM for the LE subspectrum
1793  // TODO: Would be better to do this in a more elegant way than with exception
1794  // handling
1795  fill_map_from_subspectrum<SpectrumContents::SM_slha> (specmap, mssmspec.get_LE());
1796  }
1797  fill_map_from_subspectrum<SpectrumContents::MSSM>(specmap, mssmspec.get_HE());
1798  add_extra_MSSM_parameter_combinations(specmap, mssmspec.get_HE());
1799  }
1800  void get_unimproved_MSSM_spectrum_as_map (std::map<std::string,double>& specmap)
1801  {
1802  namespace myPipe = Pipes::get_unimproved_MSSM_spectrum_as_map;
1804  try
1805  {
1806  fill_map_from_subspectrum<SpectrumContents::SM> (specmap, mssmspec.get_LE());
1807  }
1808  catch(const Gambit::exception&)
1809  {
1810  // The above will fail for the SimpleSpectrum versions of the MSSM spectrum
1811  // because it uses SM_slha rather than SM for the LE subspectrum
1812  // TODO: Would be better to do this in a more elegant way than with exception
1813  // handling
1814  fill_map_from_subspectrum<SpectrumContents::SM_slha> (specmap, mssmspec.get_LE());
1815  }
1816  fill_map_from_subspectrum<SpectrumContents::MSSM>(specmap, mssmspec.get_HE());
1817  add_extra_MSSM_parameter_combinations(specmap, mssmspec.get_HE());
1818  }
1820 
1822  template<class Contents>
1823  void fill_map_from_subspectrum(std::map<std::string,double>& specmap, const SubSpectrum& subspec)
1824  {
1826  static const Contents contents;
1827  static const std::vector<SpectrumParameter> required_parameters = contents.all_parameters();
1828 
1829  for(std::vector<SpectrumParameter>::const_iterator it = required_parameters.begin();
1830  it != required_parameters.end(); ++it)
1831  {
1832  const Par::Tags tag = it->tag();
1833  const std::string name = it->name();
1834  const std::vector<int> shape = it->shape();
1835 
1837 
1838  // Check scalar case
1839  if(shape.size()==1 and shape[0]==1)
1840  {
1841  std::ostringstream label;
1842  label << name <<" "<< Par::toString.at(tag);
1843  specmap[label.str()] = subspec.get(tag,name);
1844  // Check again ignoring overrides (if the value has an override defined)
1845  if(subspec.has(tag,name,overrides_only) and
1846  subspec.has(tag,name,ignore_overrides))
1847  {
1848  label << " (unimproved)";
1849  specmap[label.str()] = subspec.get(tag,name,ignore_overrides);
1850  }
1851  }
1852  // Check vector case
1853  else if(shape.size()==1 and shape[0]>1)
1854  {
1855  for(int i = 1; i<=shape[0]; ++i) {
1856  std::ostringstream label;
1857  label << name <<"_"<<i<<" "<< Par::toString.at(tag);
1858  specmap[label.str()] = subspec.get(tag,name,i);
1859  // Check again ignoring overrides
1860  if(subspec.has(tag,name,i,overrides_only) and
1861  subspec.has(tag,name,i,ignore_overrides))
1862  {
1863  label << " (unimproved)";
1864  specmap[label.str()] = subspec.get(tag,name,i,ignore_overrides);
1865  }
1866  }
1867  }
1868  // Check matrix case
1869  else if(shape.size()==2)
1870  {
1871  for(int i = 1; i<=shape[0]; ++i) {
1872  for(int j = 1; j<=shape[0]; ++j) {
1873  std::ostringstream label;
1874  label << name <<"_("<<i<<","<<j<<") "<<Par::toString.at(tag);
1875  specmap[label.str()] = subspec.get(tag,name,i,j);
1876  // Check again ignoring overrides
1877  if(subspec.has(tag,name,i,j,overrides_only) and
1878  subspec.has(tag,name,i,j,ignore_overrides))
1879  {
1880  label << " (unimproved)";
1881  specmap[label.str()] = subspec.get(tag,name,i,j,ignore_overrides);
1882  }
1883  }
1884  }
1885  }
1886  // Deal with all other cases
1887  else
1888  {
1889  // ERROR
1890  std::ostringstream errmsg;
1891  errmsg << "Error, invalid parameter received while converting SubSpectrum with contents \""<<contents.getName()<<"\" to map of strings! This should no be possible if the spectrum content verification routines were working correctly; they must be buggy, please report this.";
1892  errmsg << "Problematic parameter was: "<< tag <<", " << name << ", shape="<< shape;
1893  SpecBit_error().forced_throw(LOCAL_INFO,errmsg.str());
1894  }
1895  }
1896  // add the scale!
1897  specmap["scale(Q)"] = subspec.GetScale();
1898  }
1899 
1901  {
1902  using namespace Pipes::FH_HiggsMass;
1903  //FH indices: 0=h0_1, 1=h0_2
1904  int i = 0;
1905  const SubSpectrum& spec = Dep::unimproved_MSSM_spectrum->get_HE();
1906  int higgs = SMlike_higgs_PDG_code(spec);
1907  if (higgs == 25) i = 0;
1908  else if (higgs == 35) i = 1;
1909  else SpecBit_error().raise(LOCAL_INFO, "Urecognised SM-like Higgs PDG code!");
1910  result.central = Dep::FH_HiggsMasses->MH[i];
1911  result.upper = Dep::FH_HiggsMasses->deltaMH[i];
1912  result.lower = Dep::FH_HiggsMasses->deltaMH[i];
1913  }
1914 
1916  {
1917  using namespace Pipes::FH_HeavyHiggsMasses;
1918  const int neutrals[2] = {25, 35};
1919  int i = -1;
1920  const SubSpectrum& spec = Dep::unimproved_MSSM_spectrum->get_HE();
1921  int higgs = SMlike_higgs_PDG_code(spec);
1922  if (higgs == neutrals[0]) i = 1;
1923  else if (higgs == neutrals[1]) i = 0;
1924  else SpecBit_error().raise(LOCAL_INFO, "Urecognised SM-like Higgs PDG code!");
1925  result.clear();
1926  result[neutrals[i]].central = Dep::FH_HiggsMasses->MH[i];
1927  result[neutrals[i]].upper = Dep::FH_HiggsMasses->deltaMH[i];
1928  result[neutrals[i]].lower = Dep::FH_HiggsMasses->deltaMH[i];
1929  result[36].central = Dep::FH_HiggsMasses->MH[2];
1930  result[36].upper = Dep::FH_HiggsMasses->deltaMH[2];
1931  result[36].lower = Dep::FH_HiggsMasses->deltaMH[2];
1932  result[37].central = Dep::FH_HiggsMasses->MH[3];
1933  result[37].upper = Dep::FH_HiggsMasses->deltaMH[3];
1934  result[37].lower = Dep::FH_HiggsMasses->deltaMH[3];
1935  }
1936 
1938  {
1939  using namespace Pipes::SHD_HiggsMass;
1940 
1941  const Spectrum& fullspectrum = *Dep::unimproved_MSSM_spectrum;
1942  SLHAea::Coll slhaea = fullspectrum.getSLHAea(1);
1943 
1944  #ifdef SPECBIT_DEBUG
1945  cout << "****** calling SHD_HiggsMass ******" << endl;
1946  #endif
1947 
1948  MList<MReal> parameterList = {
1949  SLHAea::to<double>(slhaea.at("HMIX").at(2).at(1)), // tanbeta
1950  SLHAea::to<double>(slhaea.at("MSOFT").at(1).at(1)), // M1
1951  SLHAea::to<double>(slhaea.at("MSOFT").at(2).at(1)), // M2
1952  SLHAea::to<double>(slhaea.at("MSOFT").at(3).at(1)), // M3
1953  SLHAea::to<double>(slhaea.at("HMIX").at(1).at(1)), // mu
1954  SLHAea::to<double>(slhaea.at("AU").at(3).at(2)), // At
1955  SLHAea::to<double>(slhaea.at("MSOFT").at(43).at(1)), // mQ3
1956  SLHAea::to<double>(slhaea.at("MSOFT").at(46).at(1)), // mU3
1957  SLHAea::to<double>(slhaea.at("MSOFT").at(49).at(1)), // mD3
1958  SLHAea::to<double>(slhaea.at("MSOFT").at(42).at(1)), // mQ2
1959  SLHAea::to<double>(slhaea.at("MSOFT").at(45).at(1)), // mU2
1960  SLHAea::to<double>(slhaea.at("MSOFT").at(48).at(1)), // mD2
1961  SLHAea::to<double>(slhaea.at("MSOFT").at(41).at(1)), // mQ1
1962  SLHAea::to<double>(slhaea.at("MSOFT").at(44).at(1)), // mU1
1963  SLHAea::to<double>(slhaea.at("MSOFT").at(47).at(1)), // mD1
1964  SLHAea::to<double>(slhaea.at("MSOFT").at(33).at(1)), // mL3
1965  SLHAea::to<double>(slhaea.at("MSOFT").at(36).at(1)), // mE3
1966  SLHAea::to<double>(slhaea.at("MSOFT").at(32).at(1)), // mL2
1967  SLHAea::to<double>(slhaea.at("MSOFT").at(35).at(1)), // mE2
1968  SLHAea::to<double>(slhaea.at("MSOFT").at(31).at(1)), // mL1
1969  SLHAea::to<double>(slhaea.at("MSOFT").at(34).at(1)), // mE1
1970  sqrt(SLHAea::to<double>(slhaea.at("HMIX").at(4).at(1))) // mA
1971  };
1972 
1973  MReal MHiggs = BEreq::SUSYHD_MHiggs(parameterList);
1974 
1975  #ifdef SPECBIT_DEBUG
1976  cout << "****** calling SHD_DeltaHiggsMass ******" << endl;
1977  #endif
1978 
1979  MReal DeltaMHiggs = BEreq::SUSYHD_DeltaMHiggs(parameterList);
1980 
1981  result.central = MHiggs;
1982 
1983  bool use_SHD_uncertainty = runOptions->getValueOrDef<bool>(true, "use_SHD_uncertainty");
1984 
1985  if(use_SHD_uncertainty)
1986  {
1987  result.upper = DeltaMHiggs;
1988  result.lower = DeltaMHiggs;
1989  }
1990  else
1991  {
1992  result.upper = 0.0;
1993  result.lower = 0.0;
1994  }
1995 
1996  }
1997 
1998 
2000 
2001  } // end namespace SpecBit
2002 } // end namespace Gambit
2003 
void drop_SLHAs_if_requested(const safe_ptr< Options > &, const str &)
Helper function to drop SLHA files.
Definition: spectrum.cpp:452
std::vector< std::vector< double > > C_hiZ2
Define overloadings of the stream operator for various containers.
Array class that matches the memory structure and functionality of arrays in Fortran codes Syntax: Fa...
Definition: util_types.hpp:318
void MSSM_higgs_couplings_pwid(HiggsCouplingsTable &result)
Put together the Higgs couplings for the MSSM, from partial widths only.
std::vector< double > family_state_mix_matrix(str type, int generation, str &mass_es1, str &mass_es2, const SubSpectrum &mssm, double tol, str context, bool pterror)
Get the family mixing matrix and corresponding mass eigenstates, then check for interfamily mixing...
void MSSM_higgs_couplings_FH(HiggsCouplingsTable &result)
Put together the Higgs couplings for the MSSM, using FeynHiggs.
Helper function to determine which Higgs is most SM-like.
START_CAPABILITY NMSSM_spectrum
Rollcall header for module SpecBit.
double BF(const std::vector< std::pair< int, int > > &) const
Retrieve branching fraction for decay to a given final state.
General small utility macros.
Declarations of convenience (i.e.
MSSM derived version of SubSpectrum class.
void set_t_decays(const DecayTable::Entry &)
Assign decay entries to top.
void get_unimproved_MSSM_spectrum_as_map(std::map< std::string, double > &specmap)
void get_MSSM_spectrum_as_SLHAea_SLHA1(SLHAstruct &result)
Extract an SLHAea version of the spectrum contained in a Spectrum object, in SLHA1 format...
void FH_HeavyHiggsMasses(map_int_triplet_dbl &result)
This struct contains all the strings we will use for the MSSM in the maps.
const DecayTable::Entry & get_neutral_decays(int) const
Retrieve decays of a specific neutral Higgs, by index.
const std::vector< str > getNames(const args &... keys) const
Retrieve values from key-value pairs in options node.
#define LOCAL_INFO
Definition: local_info.hpp:34
SLHAstruct getSLHAea(int) const
SLHAea object getter First constructs an SLHAea object from the SMINPUTS object, then adds the info f...
Definition: spectrum.cpp:432
GAMBIT native higgs coupling table class.
virtual double GetScale() const
Returns the renormalisation scale of parameters.
void set_n_charged_higgs(int)
Set the number of charged Higgses.
void fill_MSSM63_input_altnames(T &input, const std::map< str, safe_ptr< const double > > &Param)
void get_MSSM_spectrum_from_postprocessor(Spectrum &result)
Get pre-computed MSSM spectrum from previous output file This function ONLY works when the scan is dr...
Helpers for making simple spectra from SLHAea objects.
Flexiblesusy model header includes for SpecBit.
void set_charged_decays(int, const str &, const DecayTable::Entry &)
Assign decay entries to charged higgses.
void get_MSSM_spectrum_from_SLHAstruct(Spectrum &result)
Get an MSSMSpectrum object from an SLHAstruct Wraps it up in MSSMSimpleSpec; i.e. ...
void SLHAea_add(SLHAstruct &slha, const str &block, const int index, const double value, const str &comment="", const bool overwrite=false)
Add an entry to an SLHAea object (if overwrite=false, only if it doesn&#39;t already exist) ...
Manager class for printers.
std::vector< std::pair< str, str > > invisibles
Particles that higgses can decay invisibly to.
void FH_AllHiggsMasses(fh_HiggsMassObs &result)
Higgs masses and mixings with theoretical uncertainties.
std::chrono::milliseconds ms
Printers::BaseReader & get_pp_reader()
bool hasKey(const args &... keys) const
Getters for key/value pairs (which is all the options node should contain)
void set_override_vector(const Par::Tags, const double, const std::vector< str > &, const bool allow_new=false, const bool decouple=false)
Vector override functions.
TYPE getValue(const args &... keys) const
static const std::vector< str > pole_mass_strs_1_3
pole mass strings with 1 index and three entries
void FH_MSSMMasses(fh_MSSMMassObs &result)
FeynHiggs SUSY masses and mixings.
SLHAea::Coll SLHAstruct
Less confusing name for SLHAea container class.
void get_GUTMSSMB_spectrum(Spectrum &)
GAMBIT error class.
Definition: exceptions.hpp:136
void setup_QedQcd(softsusy::QedQcd &oneset, const SMInputs &sminputs)
Non-Gambit helper functions.
Definition: SpecBit.cpp:51
int SMlike_higgs_PDG_code(const SubSpectrum &)
Determine which MSSM higgs is most SM-like.
static const std::vector< str > pole_mass_strs_1_2
pole mass strings with 1 index and two entries
virtual void raise(const std::string &)
Raise the exception, i.e. throw it. Exact override of base method.
Definition: exceptions.cpp:422
virtual double get(const Par::Tags, const str &, const SpecOverrideOptions=use_overrides, const SafeBool check_antiparticle=SafeBool(true)) const =0
void convert_NMSSM_to_SM(Spectrum &result)
const double pi
Eigen::Matrix< double, 3, 3 > fill_3x3_parameter_matrix(const std::string &rootname, const std::map< str, safe_ptr< const double > > &Param)
Helper function for setting 3x3 matrix-valued parameters.
double compute_effective_coupling(int index, const T &p1, const T &p2)
Compute a neutral higgs effective coupling from the current two-body neutral higgs decays...
double width_in_GeV
Total particle width (in GeV)
SM specialisation of SLHAea object wrapper version of SubSpectrum class.
void add_extra_MSSM_parameter_combinations(std::map< std::string, double > &specmap, const SubSpectrum &mssm)
Adds additional information from interesting combinations of MSSM parameters.
bool has_channel(const std::vector< std::pair< int, int > > &) const
Check if a given final state exists in this DecayTable::Entry.
static const std::vector< str > pole_mass_pred
void SHD_HiggsMass(triplet< double > &result)
bool has_neutralino_LSP(const Spectrum &result)
Check that the spectrum has a neutralino LSP.
Definition: SpecBit.cpp:75
const Logging::endofmessage EOM
Explicit const instance of the end of message struct in Gambit namespace.
Definition: logger.hpp:100
std::vector< double > C_WW2
Effective couplings for neutral higgses.
void fill_MSSM63_input(T &input, const std::map< str, safe_ptr< const double > > &Param)
Helper function for filling MSSM63-compatible input parameter objects Leaves out mHu2, mHd2, SignMu, (mA, mu) because we use two different parameterisations of these.
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
std::vector< std::pair< str, str > > get_invisibles(const SubSpectrum &spec)
Helper function to work out if the LSP is invisible, and if so, which particle it is...
Declaration and definition of printer base class.
std::vector< T > MList
Definition: util_types.hpp:663
std::string str
Shorthand for a standard string.
Definition: Analysis.hpp:35
void convert_E6MSSM_to_SM(Spectrum &result)
static const std::vector< str > pole_mass_strs_1_6
pole mass strings with 1 index and six entries
std::vector< T > initVector(std::vector< T > vector)
SubSpectrum & get_LE()
Standard getters Return references to internal data members.
Definition: spectrum.cpp:224
TYPE getValueOrDef(TYPE def, const args &... keys) const
void fill_map_from_subspectrum(std::map< std::string, double > &, const SubSpectrum &)
Convert MSSM type Spectrum object into a map, so it can be printed.
void set_n_neutral_higgs(int)
Set the number of neutral Higgses.
void get_MSSM_spectrum_as_SLHAea_SLHA2(SLHAstruct &result)
Extract an SLHAea version of the spectrum contained in a Spectrum object, in SLHA2 format...
Eigen::Matrix< double, 3, 3 > fill_3x3_symmetric_parameter_matrix(const std::string &rootname, const std::map< str, safe_ptr< const double > > &Param)
As above, but for symmetric input (i.e. 6 entries, assumed to be the upper triangle) ...
void convert_MSSM_to_SM(Spectrum &result)
Gambit module functions.
Virtual base class for interacting with spectrum generator output.
Definition: subspectrum.hpp:87
void get_MSSM_spectrum_from_SLHAfile(Spectrum &result)
Get an MSSMSpectrum object from an SLHA file Wraps it up in MSSMSimpleSpec; i.e.
bool retrieve(T &out, const std::string &label)
Reimplement overload for &#39;retrieve&#39; that uses the current point as the input for rank/pointID.
This class is used to wrap the QedQcd object used by SoftSUSY and FlexibleSUSY in a Gambit SubSpectru...
void FH_Couplings(fh_Couplings &result)
Call FH_Couplings from FeynHiggs and collect the output.
SLHAea helper functions using spectrum objects.
void set_neutral_decays(int, const str &, const DecayTable::Entry &)
Assign decay entries to neutral higgses.
double pow(const double &a)
Outputs a^i.
void set_override(const Par::Tags, const double, const str &, const bool allow_new=false, const bool decouple=false)
Parameter override functions.
double get(const Par::Tags, const str &, const SpecOverrideOptions=use_overrides, const SafeBool=SafeBool(true)) const
Definition: spec.hpp:72
std::vector< YAML::sdd > mc_info
Typedefs for making it easier to manipulate mass cut and mass ratio cut info.
Definition: spectrum.hpp:119
void set_neutral_decays_SM(int, const str &, const DecayTable::Entry &)
Assign decay entries to the various table components.
invalid_point_exception & invalid_point()
Invalid point exceptions.
MSSM specialisation of SLHAea object wrapper version of SubSpectrum class.
std::vector< double > CP
CP of neutral higgses.
void get_MSSM_spectrum_as_map(std::map< std::string, double > &specmap)
Spectrum run_FS_spectrum_generator(const typename MI::InputParameters &input, const SMInputs &sminputs, const Options &runOptions, const std::map< str, safe_ptr< const double > > &input_Param)
Definition: SpecBit_MDM.cpp:55
Spectrum Spectrum Spectrum Spectrum Spectrum Spectrum Spectrum Spectrum SMINPUTS
std::vector< YAML::ssdd > mr_info
Definition: spectrum.hpp:120
std::map< int, triplet< double > > map_int_triplet_dbl
Shorthand for an int-to-double triplet map.
Definition: util_types.hpp:135
str mass_es_from_gauge_es(str gauge_es, double &max_mixing, std::vector< double > &gauge_composition, const SubSpectrum &mssm)
indentifies the state with largest gauge_es content also fills largest max_mixing and full gauge_comp...
TODO: see if we can use this one:
Definition: Analysis.hpp:33
A small wrapper object for &#39;options&#39; nodes.
virtual bool has(const Par::Tags, const str &, const SpecOverrideOptions=use_overrides, const SafeBool check_antiparticle=SafeBool(true)) const =0
Getters/Setters etc.
double MReal
Definition: util_types.hpp:659
SubSpectrum & get_HE()
Definition: spectrum.cpp:225
"Standard Model" (low-energy) plus high-energy model container class
Definition: spectrum.hpp:110
void get_SM_SubSpectrum_from_MSSM_Spectrum(const SubSpectrum *&result)
Retrieve SubSpectrum* to SM LE model from Spectrum object DEPENDENCY(MSSM_spectrum, Spectrum)
Container class for Standard Model input information (defined as in SLHA2)
Definition: sminputs.hpp:29
void FH_HiggsMass(triplet< double > &result)
void get_MSSM_spectrum_SPheno(Spectrum &spectrum)