Hammer  1.0.0
Helicity Amplitude Module for Matrix Element Reweighting
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PhaseSpace.cc
Go to the documentation of this file.
1 ///
2 /// @file PhaseSpace.cc
3 /// @brief Phase space integrals
4 ///
5 
6 //**** This file is a part of the HAMMER library
7 //**** Copyright (C) 2016 - 2020 The HAMMER Collaboration
8 //**** HAMMER is licensed under version 3 of the GPL; see COPYING for details
9 //**** Please note the MCnet academic guidelines; see GUIDELINES for details
10 
11 // -*- C++ -*-
12 #include <boost/math/special_functions/ellint_1.hpp>
13 #include <boost/math/special_functions/ellint_2.hpp>
14 #include <boost/math/special_functions/ellint_3.hpp>
15 
16 #include "Hammer/Exceptions.hh"
18 #include "Hammer/Math/Constants.hh"
20 #include "Hammer/Math/Utils.hh"
21 
22 using namespace std;
23 
24 namespace Hammer {
25 
26  static BoundaryFunction makeMjFunction(double parentMass, vector<double> masses, size_t j){
27  return([parentMass, masses, j](const vector<double>& vals) -> pair<double, double> {
28  size_t N = masses.size();
29  double MjMin = 0;
30  double MjMax = 0;
31  if (j > 1 && j < N) { //j is number of particles in invariant mass
32  for(size_t idx = 0; idx < j; ++idx){
33  MjMin += masses[idx];
34  }
35  if (j < N-1){
36  //j = N-2 takes val[0] - masses[N-2] as upper range, etc
37  MjMax = vals[N-2-j] - masses[j];
38  } else {
39  //j = N-1 takes Parent - masses[N-1]
40  MjMax = parentMass - masses[j];
41  }
42  }
43  return make_pair(MjMin, MjMax);
44  });
45  }
46 
47  static double kStar(double mParent, double mk, double mSibling){
48  double EStar = (mParent*mParent - mSibling*mSibling + mk*mk)/(2.* mParent);
49  return sqrt(EStar*EStar - mk*mk);
50  }
51 
52  double phaseSpaceNBody(const double parentMass, const vector<double>& daughterMasses) {
53  size_t N = daughterMasses.size();
54  double res = 0.;
55  switch(N) {
56  case 1: {
57  throw Error("Implementing a 1->1 decay is perhaps a poor idea.");
58  }
59  case 2: {
60  res += kStar(parentMass, daughterMasses[1], daughterMasses[0])/(4.*pi*parentMass);
61  break;
62  }
63  default:
64  Integrator integ;
65  IntegrationBoundaries boundaries{};
66  for(size_t j = 2; j < N; ++j){
67  boundaries.push_back(makeMjFunction(parentMass, daughterMasses, N+1-j));
68  }
69  integ.applyRange(boundaries);
70  const EvaluationGrid& points = integ.getEvaluationPoints();
71  const EvaluationWeights& weights = integ.getEvaluationWeights();
72 
73  for (size_t i = 0; i < points.size(); ++i) {
74  double respart = kStar(parentMass, daughterMasses[N-1], points[i][0])*weights[i]/(4.*pi*parentMass);
75  for(size_t j = 0; j < N-3; ++j){
76  respart *= kStar(points[i][j], daughterMasses[N-2-j], points[i][j+1])/(4.*pi2);
77  }
78  respart *= kStar(points[i][N-3], daughterMasses[1], daughterMasses[0])/(4.*pi2);
79  res += respart;
80  }
81  break;
82  }
83  return res;
84  }
85 
86  static double phaseSpace2(const double m0, const double m1, const double m2) {
87  const double coeff = 1./(8.* pi);
88  const double m0sq = m0*m0;
89  const double m1sq = m1*m1;
90  const double m2sq = m2*m2;
91  const double kallen = m0sq*m0sq + m1sq*m1sq + m2sq*m2sq - 2.*(m0sq*m1sq + m1sq*m2sq + m0sq*m2sq);
92  const double result = coeff * sqrt(kallen) / m0sq;
93  return result;
94  }
95 
96 
97  // taken from http://cds.cern.ch/record/682356/files/0311075.pdf
98  static double phaseSpace3(const double m0, const double m1, const double m2, const double m3) {
99  const double coeff = 1./(128.* pi3);
100 
101  const double m0sq = m0*m0;
102  const double m1sq = m1*m1;
103  const double m2sq = m2*m2;
104  const double m3sq = m3*m3;
105 
106  const double sq0p3 = pow(m0 + m3, 2.);
107  const double sq0m3 = pow(m0 - m3, 2.);
108  const double sq1p2 = pow(m1 + m2, 2.);
109  const double sq1m2 = pow(m1 - m2, 2.);
110 
111  const double qpp = sq0p3 - sq1p2;
112  const double qpm = sq0p3 - sq1m2;
113  const double qmp = sq0m3 - sq1p2;
114  const double qmm = sq0m3 - sq1m2;
115 
116  const double Qplus = qpp * qmm;
117  const double Qminus = qmp * qpm;
118 
119  double k = regularize(sqrt(Qminus / Qplus), 1., 1.e-10, -1);
120 
121  const double alpha1sq = isZero(m1 + m2) ? 1. : regularize(qmp / qmm, 1., 1.e-10, -1);
122  const double alpha2sq = isZero(m1 + m2) ? 1. : sq1m2 / sq1p2 * alpha1sq;
123 
124 
125  // Boost elliptic ell_int1/2(k) and ellint_3(k,n) functions require -1 <= k <=1 and n < 1
126  const double ellipticE = boost::math::ellint_2(k);
127  const double ellipticK = boost::math::ellint_1(k);
128  const double ellipticPi1 = boost::math::ellint_3(k, alpha1sq);
129  const double ellipticPi2 = boost::math::ellint_3(k, alpha2sq);
130 
131  const double expr = 0.5 * Qplus * (m1sq + m2sq + m3sq + m0sq) * ellipticE +
132  4. * m1 * m2 * ((sq0m3 - sq1m2) * (sq0p3 - m3 * m0 + m1 * m2) * ellipticK +
133  2. * ((m1sq + m2sq) * (m3sq + m0sq) - 2. * (m1sq * m2sq + m3sq * m0sq)) * ellipticPi1 -
134  2. * pow(m0sq - m3sq, 2.) * ellipticPi2);
135 
136  const double result = coeff * expr / m0sq / sqrt(Qplus);
137 
138  return result;
139  }
140 
141 
142  double phaseSpaceN(const double parentMass, const vector<double>& daughterMasses) {
143  switch(daughterMasses.size()) {
144  case 2: {
145  return phaseSpace2(parentMass, daughterMasses[0], daughterMasses[1]);
146  }
147  case 3: {
148  return phaseSpace3(parentMass, daughterMasses[0], daughterMasses[1], daughterMasses[2]);
149  }
150  case 4: {
151  function<double(double)> f = [parentMass, daughterMasses](double m) -> double { const double f1 = phaseSpace3(m, daughterMasses[0], daughterMasses[1], daughterMasses[2]);
152  const double f2 = phaseSpace2(parentMass, m, daughterMasses[3]);
153  return 2*m*f1*f2/(2*pi);
154  };
155  return integrate(f, daughterMasses[0] + daughterMasses[1] + daughterMasses[2], parentMass - daughterMasses[3]);
156  }
157  case 5: {
158  function<double(double)> f = [parentMass, daughterMasses](double m) -> double { const double f1 = phaseSpace3(m, daughterMasses[0], daughterMasses[1], daughterMasses[2]);
159  const double f2 = phaseSpace3(parentMass, m, daughterMasses[3], daughterMasses[4]);
160  return 2*m*f1*f2/(2*pi);
161  };
162  return integrate(f, daughterMasses[0] + daughterMasses[1] + daughterMasses[2], parentMass - daughterMasses[3] - daughterMasses[4]);
163 
164  }
165  default:
166  throw Error("Unimplemented phase space integral: n>5");
167  }
168 
169  }
170 
171 } // namespace Hammer
double integrate(std::function< double(double)> &func, double low, double high)
integration function based on gaussian method
Definition: Integrator.cc:22
const EvaluationWeights & getEvaluationWeights() const
Definition: Integrator.cc:111
static constexpr double pi2
Definition: Constants.hh:24
const EvaluationGrid & getEvaluationPoints() const
returns the position of the evaluation points given an integration range
Definition: Integrator.cc:107
std::function< std::pair< double, double >(const std::vector< double > &)> BoundaryFunction
Definition: Integrator.fhh:24
double phaseSpaceNBody(const double parentMass, const vector< double > &daughterMasses)
Definition: PhaseSpace.cc:52
static constexpr double pi3
Definition: Constants.hh:25
Phase space integrals.
std::vector< BoundaryFunction > IntegrationBoundaries
Definition: Integrator.fhh:25
static double phaseSpace2(const double m0, const double m1, const double m2)
Definition: PhaseSpace.cc:86
Hammer exception definitions.
static double phaseSpace3(const double m0, const double m1, const double m2, const double m3)
Definition: PhaseSpace.cc:98
static double kStar(double mParent, double mk, double mSibling)
Definition: PhaseSpace.cc:47
double phaseSpaceN(const double parentMass, const vector< double > &daughterMasses)
Definition: PhaseSpace.cc:142
double regularize(const double regularVal, const double problematicValue, const double delta=std::numeric_limits< double >::min(), int direction=0)
Definition: Math/Utils.hh:59
Generic error class.
Definition: Exceptions.hh:23
bool isZero(const std::complex< double > val)
Definition: Math/Utils.hh:25
Various numerical constants.
Hammer numerical integration classes.
static BoundaryFunction makeMjFunction(double parentMass, vector< double > masses, size_t j)
Definition: PhaseSpace.cc:26
void applyRange(const IntegrationBoundaries &boundaries)
apply rescaling factor for the size of the interval from the canonical [-1,1] interval to the actual ...
Definition: Integrator.cc:120
std::vector< double > EvaluationWeights
Definition: Integrator.fhh:27
std::vector< std::vector< double >> EvaluationGrid
Definition: Integrator.fhh:26
Tensor integration class.
Definition: Integrator.hh:35
static constexpr double pi
Definition: Constants.hh:21