Himalaya
Himalaya_LibraryLink.cpp
Go to the documentation of this file.
1 // ====================================================================
2 // This file is part of Himalaya.
3 //
4 // Himalaya is licenced under the GNU General Public License (GNU GPL)
5 // version 3.
6 // ====================================================================
7 
9 
12 
13 #include <iostream>
14 #include <sstream>
15 #include <string>
16 #include <tuple>
17 #include <vector>
18 
19 #include <mathlink.h>
20 #include <WolframLibrary.h>
21 
22 namespace himalaya {
23 namespace {
24 
25 /********************* put types *********************/
26 
27 inline void MLPut(MLINK link, const std::string& s)
28 {
29  MLPutSymbol(link, s.c_str());
30 }
31 
32 inline void MLPut(MLINK link, int c)
33 {
34  MLPutInteger(link, c);
35 }
36 
37 /*
38 inline void MLPut(MLINK link, double c)
39 {
40  MLPutReal(link, c);
41 }
42 */
43 
44 /*
45 inline void MLPut(MLINK link, std::complex<double> c)
46 {
47  if (std::imag(c) == 0.) {
48  MLPutReal(link, std::real(c));
49  } else {
50  MLPutFunction(link, "Complex", 2);
51  MLPutReal(link, std::real(c));
52  MLPutReal(link, std::imag(c));
53  }
54 }
55 */
56 
57 template <int M>
58 void MLPut(MLINK link, const Eigen::Array<double,M,1>& a)
59 {
60  double v[M];
61  for (int i = 0; i < M; i++)
62  v[i] = a(i);
63  MLPutRealList(link, static_cast<double*>(v), M);
64 }
65 
66 template <int M>
67 void MLPut(MLINK link, const Eigen::Matrix<double,M,1>& m)
68 {
69  const Eigen::Array<double,M,1> a(m.array());
70  MLPut(link, a);
71 }
72 
73 template <int M, int N>
74 void MLPut(MLINK link, const Eigen::Matrix<double,M,N>& m)
75 {
76  double mat[M][N];
77  for (int i = 0; i < M; i++)
78  for (int k = 0; k < N; k++)
79  mat[i][k] = m(i, k);
80 
81  long dims[] = { M, N };
82  MLPutDoubleArray(link, reinterpret_cast<double*>(mat), dims, nullptr, 2);
83 }
84 
85 template <int M>
86 void MLPut(MLINK link, const Eigen::Array<std::complex<double>,M,1>& a)
87 {
88  MLPutFunction(link, "List", M);
89  for (int i = 0; i < M; i++)
90  MLPut(link, a(i));
91 }
92 
93 template <int M>
94 void MLPut(MLINK link, const Eigen::Matrix<std::complex<double>,M,1>& m)
95 {
96  const Eigen::Array<std::complex<double>,M,1> a(m.array());
97  MLPut(link, a);
98 }
99 
100 template <int M, int N>
101 void MLPut(MLINK link, const Eigen::Matrix<std::complex<double>,M,N>& m)
102 {
103  MLPutFunction(link, "List", M);
104  for (int i = 0; i < M; i++) {
105  MLPutFunction(link, "List", N);
106  for (int k = 0; k < N; k++)
107  MLPut(link, m(i,k));
108  }
109 }
110 
111 template <class T>
112 void MLPut(MLINK link, const std::vector<T>& v)
113 {
114  MLPutFunction(link, "List", v.size());
115  for (std::size_t i = 0; i < v.size(); i++)
116  MLPut(link, v[i]);
117 }
118 
119 /********************* put rules to types *********************/
120 
121 void MLPutRule(MLINK link, const std::string& name)
122 {
123  MLPutFunction(link, "Rule", 2);
124  MLPutUTF8Symbol(link, reinterpret_cast<const unsigned char*>(name.c_str()), name.size());
125 }
126 
127 template <class T1>
128 void MLPutRuleTo(MLINK link, T1 t, const std::string& name)
129 {
130  MLPutRule(link, name);
131  MLPut(link, t);
132 }
133 
134 /******************************************************************/
135 
136 void put_message(MLINK link,
137  const std::string& message_function,
138  const std::string& message_str)
139 {
140  MLPutFunction(link, "CompoundExpression", 2);
141  MLPutFunction(link, message_function.c_str(), 1);
142  MLPutUTF8String(link, reinterpret_cast<const unsigned char*>(message_str.c_str()), message_str.size());
143 }
144 
145 /******************************************************************/
146 
147 class Redirect_output {
148 public:
149  explicit Redirect_output(MLINK link_) noexcept
150  : link(link_)
151  , old_cout(std::cout.rdbuf(buffer.rdbuf()))
152  , old_cerr(std::cerr.rdbuf(buffer.rdbuf()))
153  {}
154  Redirect_output(const Redirect_output&) = delete;
155  Redirect_output(Redirect_output&&) noexcept = delete;
156  ~Redirect_output() {
157  std::cout.rdbuf(old_cout);
158  std::cerr.rdbuf(old_cerr);
159  flush();
160  }
161  Redirect_output& operator=(const Redirect_output&) = delete;
162  Redirect_output& operator=(Redirect_output&& other) noexcept = delete;
163 
164  void flush() {
165  std::string line;
166  while (std::getline(buffer, line)) {
167  put_message(link, "HimalayaInfoMessage", line);
168  }
169  }
170 
171 private:
172  MLINK link; ///< redirect to this link
173  std::stringstream buffer; ///< buffer caching stdout
174  std::streambuf* old_cout; ///< original stdout buffer
175  std::streambuf* old_cerr; ///< original stderr buffer
176 };
177 
178 /******************************************************************/
179 
180 long number_of_args(MLINK link, const std::string& head)
181 {
182  long argc = 0;
183 
184  if (!MLCheckFunction(link, head.c_str(), &argc))
185  std::cerr << "Error: argument is not a " << head << std::endl;
186 
187  return argc;
188 }
189 
190 /******************************************************************/
191 
192 bool check_number_of_args(MLINK link, long number_of_arguments,
193  const std::string& function_name)
194 {
195  const auto n_given = number_of_args(link, "List");
196  const bool ok = n_given == number_of_arguments;
197 
198  if (!ok) {
199  std::cerr << "Error: " << function_name << " expects "
200  << number_of_arguments << " argument ("
201  << n_given << " given)." << std::endl;
202  }
203 
204  return ok;
205 }
206 
207 /******************************************************************/
208 
209 std::vector<double> read_list(MLINK link)
210 {
211  int N = 0;
212 
213  if (!MLTestHead(link, "List", &N)) {
214  throw std::runtime_error("HimalayaCalculateDMh3L expects a list"
215  " as the only argument!");
216  }
217 
218  std::vector<double> vec(N, 0.);
219 
220  for (int i = 0; i < N; i++) {
221  double val = 0.;
222  if (!MLGetReal64(link, &val)) {
223  throw std::runtime_error("Cannot read " + std::to_string(i)
224  + "'th value of parameter list!");
225  }
226  vec[i] = val;
227  }
228 
229  if (!MLNewPacket(link))
230  throw std::runtime_error("Cannot create new packet!");
231 
232  return vec;
233 }
234 
235 /******************************************************************/
236 
237 struct Data {
239  bool bottom{false};
240  int loopOrder{3};
241  bool verbose{true};
242 };
243 
244 /******************************************************************/
245 
246 Data make_data(const std::vector<double>& parsvec)
247 {
248  const int N_input_parameters = 127; // number of Himalaya input parameters
249 
250  if (parsvec.size() != N_input_parameters) {
251  throw std::runtime_error("HimalayaCalculateDMh3L expects "
252  + std::to_string(N_input_parameters) + ", but "
253  + std::to_string(parsvec.size()) + " given!");
254  }
255 
256  int c = 0; // counter
257 
258  const bool bottom = parsvec.at(c++);
259  const int loopOrder = parsvec.at(c++);
260  const bool verbose = parsvec.at(c++);
261 
263  pars.scale = parsvec.at(c++);
264  pars.mu = parsvec.at(c++);
265  pars.g1 = parsvec.at(c++);
266  pars.g2 = parsvec.at(c++);
267  pars.g3 = parsvec.at(c++);
268  pars.vd = parsvec.at(c++);
269  pars.vu = parsvec.at(c++);
270  for (int i = 0; i < 3; i++)
271  for (int k = 0; k < 3; k++)
272  pars.mq2(i,k) = parsvec.at(c++);
273  for (int i = 0; i < 3; i++)
274  for (int k = 0; k < 3; k++)
275  pars.md2(i,k) = parsvec.at(c++);
276  for (int i = 0; i < 3; i++)
277  for (int k = 0; k < 3; k++)
278  pars.mu2(i,k) = parsvec.at(c++);
279  for (int i = 0; i < 3; i++)
280  for (int k = 0; k < 3; k++)
281  pars.ml2(i,k) = parsvec.at(c++);
282  for (int i = 0; i < 3; i++)
283  for (int k = 0; k < 3; k++)
284  pars.me2(i,k) = parsvec.at(c++);
285  for (int i = 0; i < 3; i++)
286  for (int k = 0; k < 3; k++)
287  pars.Au(i,k) = parsvec.at(c++);
288  for (int i = 0; i < 3; i++)
289  for (int k = 0; k < 3; k++)
290  pars.Ad(i,k) = parsvec.at(c++);
291  for (int i = 0; i < 3; i++)
292  for (int k = 0; k < 3; k++)
293  pars.Ae(i,k) = parsvec.at(c++);
294  for (int i = 0; i < 3; i++)
295  for (int k = 0; k < 3; k++)
296  pars.Yu(i,k) = parsvec.at(c++);
297  for (int i = 0; i < 3; i++)
298  for (int k = 0; k < 3; k++)
299  pars.Yd(i,k) = parsvec.at(c++);
300  for (int i = 0; i < 3; i++)
301  for (int k = 0; k < 3; k++)
302  pars.Ye(i,k) = parsvec.at(c++);
303  pars.MA = parsvec.at(c++);
304  pars.M1 = parsvec.at(c++);
305  pars.M2 = parsvec.at(c++);
306  pars.MG = parsvec.at(c++);
307 
308  const double MW = parsvec.at(c++);
309  const double MZ = parsvec.at(c++);
310  const double Mt = parsvec.at(c++);
311  const double Mb = parsvec.at(c++);
312  const double Mtau = parsvec.at(c++);
313 
314  if (MW > 0) pars.MW = MW;
315  if (MZ > 0) pars.MZ = MZ;
316  if (Mt > 0) pars.Mt = Mt;
317  if (Mb > 0) pars.Mb = Mb;
318  if (Mtau > 0) pars.Mtau = Mtau;
319 
320  Eigen::Vector2d MSt, MSb, MStau;
321  MSt(0) = parsvec.at(c++);
322  MSt(1) = parsvec.at(c++);
323  MSb(0) = parsvec.at(c++);
324  MSb(1) = parsvec.at(c++);
325  MStau(0) = parsvec.at(c++);
326  MStau(1) = parsvec.at(c++);
327  const double s2t = parsvec.at(c++);
328  const double s2b = parsvec.at(c++);
329  const double s2tau = parsvec.at(c++);
330 
331  if (MSt.minCoeff() > 0. && std::abs(s2t) <= 1.) {
332  pars.MSt = MSt;
333  pars.s2t = s2t;
334  }
335 
336  if (MSb.minCoeff() > 0. && std::abs(s2b) <= 1.) {
337  pars.MSb = MSb;
338  pars.s2b = s2b;
339  }
340 
341  if (MStau.minCoeff() > 0. && std::abs(s2tau) <= 1.) {
342  pars.MStau = MStau;
343  pars.s2tau = s2tau;
344  }
345 
346  pars.validate(verbose);
347 
348  if (c != N_input_parameters) {
349  throw std::runtime_error(
350  "Bug: Expecting to read " + std::to_string(N_input_parameters) +
351  " input parameters from input vector of size " +
352  std::to_string(parsvec.size()) + ", but only " + std::to_string(c) +
353  " parameters have been read.");
354  }
355 
356  return Data{pars, bottom, loopOrder, verbose};
357 }
358 
359 /******************************************************************/
360 
361 struct Results {
362  using Loop_corrections = std::tuple<double,double,double,double>;
363 
365  Loop_corrections eft{}; ///< fixed-order corrections for v^2 << MS^2
366  Loop_corrections fo{}; ///< fixed-order corrections
367  Loop_corrections fo_dom{}; ///< fixed-order corrections O(at*(at + as))
368 };
369 
370 /******************************************************************/
371 
372 Results calculate_results(const Data& data)
373 {
374  Results res;
375 
376  if (data.loopOrder > 2) {
377  himalaya::HierarchyCalculator hc(data.pars, data.verbose);
378  res.ho = hc.calculateDMh3L(data.bottom);
379 
380  const auto dmh2_eft_0l = res.ho.getDMh2EFTAt(0);
381  const auto dmh2_eft_1l = res.ho.getDMh2EFTAt(1);
382  const auto dmh2_eft_2l = res.ho.getDMh2EFTAt(2);
383  const auto dmh2_eft_3l = res.ho.getDMh2EFTAt(3);
384 
385  res.eft =
386  std::make_tuple(dmh2_eft_0l, dmh2_eft_1l, dmh2_eft_2l, dmh2_eft_3l);
387 
388  const auto dmh2_fo_0l = res.ho.getDMh2FO(0);
389  const auto dmh2_fo_1l = res.ho.getDMh2FO(1);
390  const auto dmh2_fo_2l = res.ho.getDMh2FO(2);
391  const auto dmh2_fo_3l = res.ho.getDMh2FO(3);
392 
393  const auto dmh2_fo_0l_at = res.ho.getDMh2FOAt(0);
394  const auto dmh2_fo_1l_at = res.ho.getDMh2FOAt(1);
395  const auto dmh2_fo_2l_at = res.ho.getDMh2FOAt(2);
396  const auto dmh2_fo_3l_at = res.ho.getDMh2FOAt(3);
397 
398  res.fo = std::make_tuple(dmh2_fo_0l, dmh2_fo_1l, dmh2_fo_2l, dmh2_fo_3l);
399  res.fo_dom =
400  std::make_tuple(dmh2_fo_0l_at, dmh2_fo_1l_at, dmh2_fo_2l_at, dmh2_fo_3l_at);
401  } else {
402  // calculate fixed-order corrections for v^2 << MS^2
403  himalaya::mh2_eft::Mh2EFTCalculator meft(data.pars);
404  const auto dmh2_eft_0l = meft.getDeltaMh2EFT0Loop();
405  const auto dmh2_eft_1l = meft.getDeltaMh2EFT1Loop(1,1);
406  const auto dmh2_eft_2l = meft.getDeltaMh2EFT2Loop(1,1);
407  const auto zero = 0.;
408 
409  res.eft = std::make_tuple(dmh2_eft_0l, dmh2_eft_1l, dmh2_eft_2l, 0.);
410 
411  // calculate fixed-order corrections
413  const auto dmh2_fo = mfo.calculate_Mh2(); // 0L, 1L, 2L
414 
415  // calculate fixed-order corrections O(at*(at + as))
416  himalaya::mh2_fo::MSSM_mass_eigenstates mfo_dom(data.pars, true);
417  const auto dmh2_fo_dom = mfo_dom.calculate_Mh2(); // 0L, 1L, 2L
418 
419  res.fo = std::tuple_cat(dmh2_fo, std::tie(zero));
420  res.fo_dom = std::tuple_cat(dmh2_fo_dom, std::tie(zero));
421  }
422 
423  return res;
424 }
425 
426 /******************************************************************/
427 
428 void put_result(const Results& res, MLINK link)
429 {
430  MLPutFunction(link, "List", 13);
431 
432  const auto& ho = res.ho;
433  const auto& eft = res.eft;
434  const auto& fo = res.fo;
435  const auto& fo_dom = res.fo_dom;
436 
437  const auto hierarchy = ho.getSuitableHierarchy();
438  const std::string msf = ho.getIsAlphab() ? "MsbottomMDRPrime" : "MstopMDRPrime";
439 
440  Eigen::Vector4d expansion_uncertainty;
441  expansion_uncertainty << 0., ho.getDMhExpUncertainty(1),
443 
444  Eigen::Vector4d lambda;
445  lambda << ho.getDLambda(0), ho.getDLambda(1),
446  ho.getDLambda(2), ho.getDLambda(3);
447 
448  Eigen::Vector4d lambda_uncertainty;
449  lambda_uncertainty << 0., 0., 0., ho.getDLambdaUncertainty(3);
450 
451  Eigen::Vector4d lambda_shift_DRp_to_MS;
452  lambda_shift_DRp_to_MS <<
457 
458  std::vector<Eigen::Matrix2d> Mh2;
459  Mh2.reserve(4);
460  for (int i = 0; i < 4; i++)
461  Mh2.emplace_back(ho.getDMh(i));
462 
463  std::vector<Eigen::Matrix2d> Mh2_shift_DRp_to_MDRp;
464  Mh2_shift_DRp_to_MDRp.reserve(4);
465  Mh2_shift_DRp_to_MDRp.emplace_back(Eigen::Matrix2d::Zero());
466  Mh2_shift_DRp_to_MDRp.emplace_back(Eigen::Matrix2d::Zero());
467  Mh2_shift_DRp_to_MDRp.emplace_back(Eigen::Matrix2d::Zero());
468  Mh2_shift_DRp_to_MDRp.emplace_back(ho.getDMhDRbarPrimeToMDRbarPrimeShift());
469 
470  std::vector<Eigen::Matrix2d> Mh2_shift_DRp_to_H3m;
471  Mh2_shift_DRp_to_H3m.reserve(4);
472  Mh2_shift_DRp_to_H3m.emplace_back(Eigen::Matrix2d::Zero());
473  Mh2_shift_DRp_to_H3m.emplace_back(Eigen::Matrix2d::Zero());
474  Mh2_shift_DRp_to_H3m.emplace_back(Eigen::Matrix2d::Zero());
475  Mh2_shift_DRp_to_H3m.emplace_back(ho.getDMhDRbarPrimeToH3mShift());
476 
477  Eigen::Vector4d Mh2_eft;
478  Mh2_eft << std::get<0>(eft), std::get<1>(eft),
479  std::get<2>(eft), std::get<3>(eft);
480 
481  Eigen::Vector4d Mh2_fo;
482  Mh2_fo << std::get<0>(fo), std::get<1>(fo),
483  std::get<2>(fo), std::get<3>(fo);
484 
485  Eigen::Vector4d Mh2_fo_dominant;
486  Mh2_fo_dominant << std::get<0>(fo_dom), std::get<1>(fo_dom),
487  std::get<2>(fo_dom), std::get<3>(fo_dom);
488 
489  MLPutRuleTo(link, hierarchy, "hierarchyID");
490  MLPutRuleTo(link, ho.getH3mHierarchyNotation(hierarchy), "hierarchyName");
491  MLPutRuleTo(link, ho.getMDRMasses(), msf);
492  MLPutRuleTo(link, Mh2, "Mh2");
493  MLPutRuleTo(link, Mh2_shift_DRp_to_MDRp, "Mh2ShiftDRbarPrimeToMDRPrime");
494  MLPutRuleTo(link, Mh2_shift_DRp_to_H3m, "Mh2ShiftDRbarPrimeToH3m");
495  MLPutRuleTo(link, expansion_uncertainty, "expansionUncertainty");
496  MLPutRuleTo(link, Mh2_eft, "Mh2EFTAt");
497  MLPutRuleTo(link, Mh2_fo, "Mh2FO");
498  MLPutRuleTo(link, Mh2_fo_dominant, "Mh2FOAt");
499  MLPutRuleTo(link, lambda, "lambda");
500  MLPutRuleTo(link, lambda_uncertainty, "lambdaUncertainty");
501  MLPutRuleTo(link, lambda_shift_DRp_to_MS, "lambdaShiftDRbarPrimeToMSbar");
502 
503  MLEndPacket(link);
504 }
505 
506 } // anonymous namespace
507 } // namespace himalaya
508 
509 extern "C" {
510 
511 /******************************************************************/
512 
514  WolframLibraryData /* libData */, MLINK link)
515 {
516  using namespace himalaya;
517 
518  if (!check_number_of_args(link, 1, "HimalayaCalculateDMh3L"))
519  return LIBRARY_TYPE_ERROR;
520 
521  try {
522  Redirect_output rd(link);
523 
524  const auto res = calculate_results(make_data(read_list(link)));
525 
526  rd.flush();
527 
528  put_result(res, link);
529  } catch (const std::exception& e) {
530  put_message(link, "HimalayaErrorMessage", e.what());
531  MLPutSymbol(link, "$Failed");
532  } catch (...) {
533  put_message(link, "HimalayaErrorMessage", "An unknown exception has been thrown.");
534  MLPutSymbol(link, "$Failed");
535  }
536 
537  return LIBRARY_NO_ERROR;
538 }
539 
540 /******************************************************************/
541 
543 {
544  return WolframLibraryVersion;
545 }
546 
547 /******************************************************************/
548 
549 DLLEXPORT int WolframLibrary_initialize(WolframLibraryData /* libData */)
550 {
551  return LIBRARY_NO_ERROR;
552 }
553 
554 } // extern "C"
Contains the definition of the MSSM_mass_eigenstates class.
Eigen::Matrix2d getDMhDRbarPrimeToMDRbarPrimeShift() const
double vu
VEV of up Higgs, with v = Sqrt[vu^2 + vd^2] ~ 246 GeV.
Definition: H3.cpp:14
RM33 Yu
up-type yukawa coupling matrix
RM33 Ad
trilinear down type squark-Higgs coupling matrix
Eigen::Vector2d getMDRMasses() const
double getDMhExpUncertainty(int loops) const
void validate(bool verbose)
validates the parameter set
double vd
VEV of down Higgs, with v = Sqrt[vu^2 + vd^2] ~ 246 GeV.
double g2
gauge coupling g2
RM33 Ae
trilinear electron type squark-Higgs coupling matrix
double s2b
sine of 2 times the sbottom mixing angle
Eigen::Matrix2d getDMhDRbarPrimeToH3mShift() const
std::string getH3mHierarchyNotation(int hierarchy) const
RM33 ml2
soft-breaking squared left-handed slepton mass parameters
double Mtau
tau lepton
double s2t
sine of 2 times the stop mixing angle
HierarchyObject calculateDMh3L(bool isAlphab)
double getDLambdaDRbarPrimeToMSbarShift(int loops) const
double mu
mu parameter, convention of [Phys.Rept. 117 (1985) 75-263]
RM33 mq2
soft-breaking squared left-handed squark mass parameters
RM33 Yd
down-type yukawa coupling matrix
RM33 mu2
soft-breaking squared right-handed up-squark mass parameters
double getDLambdaUncertainty(int loops) const
double scale
renormalization scale
This class performs a fixed-order calculation of the light CP-even Higgs mass up to 2-loop order...
RM33 md2
soft-breaking squared right-handed down-squark mass parameters
double MA
CP-odd Higgs.
double getDeltaMh2EFT2Loop(int omitSMLogs, int omitMSSMLogs) const
double g3
gauge coupling g3 SU(3)
double g1
GUT-normalized gauge coupling g1, with gY = g1*Sqrt[3/5].
Definition of EFT Higgs mass calculation class.
Eigen::Matrix2d getDMh(int loops) const
double s2tau
sine of 2 times the stau mixing angle
RM33 Ye
electron-type yukawa coupling matrix
double getDLambda(int loops) const
Definition of the HierarchyCalculator.
double getDeltaMh2EFT1Loop(int omitSMLogs, int omitMSSMLogs) const
RM33 me2
soft-breaking squared right-handed slepton mass parameters
std::tuple< double, double, double > calculate_Mh2() const
calculates squared Higgs masses
RM33 Au
trilinear up type squark-Higgs coupling matrix