StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
nBodyPhaseSpaceGen.h
1 //
3 // Copyright 2010
4 //
5 // This file is part of starlight.
6 //
7 // starlight is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation, either version 3 of the License, or
10 // (at your option) any later version.
11 //
12 // starlight is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with starlight. If not, see <http://www.gnu.org/licenses/>.
19 //
21 //
22 // File and Version Information:
23 // $Rev:: $: revision of last commit
24 // $Author: jwebb $: author of last commit
25 // $Date: 2012/11/27 22:27:32 $: date of last commit
26 //
27 // Description:
28 // calculates n-body phase space (constant matrix element) using various algorithms
29 //
30 // the n-body decay is split up into (n - 2) successive 2-body decays
31 // each 2-body decay is considered in its own center-of-mass frame thereby
32 // separating the mass from the (trivial) angular dependence
33 //
34 // the event is boosted into the same frame in which the n-body system is
35 // given
36 //
37 // based on:
38 // GENBOD (CERNLIB W515), see F. James, "Monte Carlo Phase Space", CERN 68-15 (1968)
39 // NUPHAZ, see M. M. Block, "Monte Carlo phase space evaluation", Comp. Phys. Commun. 69, 459 (1992)
40 // S. U. Chung, "Spin Formalism", CERN Yellow Report
41 // S. U. Chung et. al., "Diffractive Dissociation for COMPASS"
42 //
43 // index convention:
44 // - all vectors have the same size (= number of decay daughters)
45 // - index i corresponds to the respective value in the (i + 1)-body system: effective mass M, break-up momentum, angles
46 // - thus some vector elements are not used like breakupMom[0], theta[0], phi[0], ...
47 // this overhead is negligible compared to the ease of notation
48 //
49 // the following graph illustrates how the n-body decay is decomposed into a sequence of two-body decays
50 //
51 // n-body ... 3-body 2-body single daughter
52 //
53 // m[n - 1] m[2] m[1]
54 // ^ ^ ^
55 // | | |
56 // | | |
57 // M[n - 1] --> ... --> M[2] --> M[1] --> M [0] = m[0]
58 // theta[n - 1] ... theta[2] theta[1] theta[0] = 0 (not used)
59 // phi [n - 1] ... phi [2] phi [1] phi [0] = 0 (not used)
60 // mSum [n - 1] ... mSum [2] mSum [1] mSum [0] = m[0]
61 // = sum_0^(n - 1) m[i] = m[2] + m[1] + m[0] = m[1] + m[0]
62 // breakUpMom[n - 1] ... breakUpMom[2] breakUpMom[1] breakUpMom[0] = 0 (not used)
63 // = q(M[n - 1], m[n - 1], M[n - 2]) = q(M[2], m[2], M[1]) = q(M[1], m[1], m[0])
64 //
65 //
67 
68 
69 #ifndef NBODYPHASESPACEGEN_H
70 #define NBODYPHASESPACEGEN_H
71 
72 
73 #include <iostream>
74 #include <vector>
75 
76 #include "reportingUtils.h"
77 #include "lorentzvector.h"
78 #include "randomgenerator.h"
79 #include "starlightconstants.h"
80 
81 
82 // small helper functions
83 // calculates factorial
84 inline
85 unsigned int
86 factorial(const unsigned int n)
87 {
88  unsigned int fac = 1;
89  for (unsigned int i = 1; i <= n; ++i)
90  fac *= i;
91  return fac;
92 }
93 
94 
95 // computes breakup momentum of 2-body decay
96 inline
97 double
98 breakupMomentum(const double M, // mass of mother particle
99  const double m1, // mass of daughter particle 1
100  const double m2) // mass of daughter particle 2
101 {
102  if (M < m1 + m2)
103  return 0;
104  return sqrt((M - m1 - m2) * (M + m1 + m2) * (M - m1 + m2) * (M + m1 - m2)) / (2 * M);
105 }
106 
107 
109 
110 public:
111 
113  virtual ~nBodyPhaseSpaceGen();
114 
115  // generator setup
117  bool setDecay(const std::vector<double>& daughterMasses); // daughter particle masses
118  bool setDecay(const unsigned int nmbOfDaughters, // number of daughter particles
119  const double* daughterMasses); // array of daughter particle masses
120 
121  // random generator
122  void setSeed(const unsigned int seed) { _rnd.SetSeed(seed); }
123  double random () { return _rnd.Rndom(); }
124 
125  // high-level generator interface
127  double generateDecay (const lorentzVector& nBody); // Lorentz vector of n-body system in lab frame
130  bool generateDecayAccepted(const lorentzVector& nBody, // Lorentz vector of n-body system in lab frame
131  const double maxWeight = 0); // if positive, given value is used as maximum weight, otherwise _maxWeight
132 
133  void setMaxWeight (const double maxWeight) { _maxWeight = maxWeight; }
134  double maxWeight () const { return _maxWeight; }
135  double normalization () const { return _norm; }
136  double eventWeight () const { return _weight; }
137  double maxWeightObserved () const { return _maxWeightObserved; }
138  void resetMaxWeightObserved() { _maxWeightObserved = 0; }
139 
141  double estimateMaxWeight(const double nBodyMass, // sic!
142  const unsigned int nmbOfIterations = 10000); // number of generated events
143 
147  inline bool eventAccepted(const double maxWeight = 0);
148 
149  //----------------------------------------------------------------------------
150  // trivial accessors
151  const lorentzVector& daughter (const int index) const { return _daughters[index]; }
152  const std::vector<lorentzVector>& daughters () const { return _daughters; }
153  unsigned int nmbOfDaughters () const { return _n; }
154  double daughterMass (const int index) const { return _m[index]; }
155  double intermediateMass(const int index) const { return _M[index]; }
156  double breakupMom (const int index) const { return _breakupMom[index]; }
157  double cosTheta (const int index) const { return _cosTheta[index]; }
158  double phi (const int index) const { return _phi[index]; }
159 
160 
161  std::ostream& print(std::ostream& out = std::cout) const;
162  friend std::ostream& operator << (std::ostream& out,
163  const nBodyPhaseSpaceGen& gen)
164  { return gen.print(out); }
165 
166 private:
167 
168  //----------------------------------------------------------------------------
169  // low-level generator interface
171  void pickMasses(const double nBodyMass); // total energy of n-body system in its RF
172 
175  double calcWeight();
176 
178  inline void pickAngles();
179 
182  void calcEventKinematics(const lorentzVector& nBody); // Lorentz vector of n-body system in lab frame
183 
184  // external parameters
185  std::vector<double> _m;
186 
187  // internal variables
188  unsigned int _n;
189  std::vector<double> _M;
190  std::vector<double> _cosTheta;
191  std::vector<double> _phi;
192  std::vector<double> _mSum;
193  std::vector<double> _breakupMom;
194  std::vector<lorentzVector> _daughters;
195  double _norm;
196  double _weight;
197  double _maxWeightObserved;
198  double _maxWeight;
199 
200  randomGenerator _rnd;
201 
202 };
203 
204 
205 inline
206 void
207 nBodyPhaseSpaceGen::pickAngles()
208 {
209  for (unsigned int i = 1; i < _n; ++i) { // loop over 2- to n-bodies
210  _cosTheta[i] = 2 * random() - 1; // range [-1, 1]
211  _phi[i] = starlightConstants::twoPi * random(); // range [ 0, 2 pi]
212  }
213 }
214 
215 
216 inline
217 bool
218 nBodyPhaseSpaceGen::eventAccepted(const double maxWeight) // if maxWeight > 0, given value is used as maximum weight, otherwise _maxWeight
219 {
220  const double max = (maxWeight <= 0) ? _maxWeight : maxWeight;
221  if (max <= 0) {
222  printWarn << "maximum weight = " << max << " does not make sense. rejecting event." << std::endl;
223  return false;
224  }
225  if ((_weight / max) > random())
226  return true;
227  return false;
228 }
229 
230 
231 #endif // NBODYPHASESPACEGEN_H
const std::vector< lorentzVector > & daughters() const
returns Lorentz vectors of all daughters
unsigned int nmbOfDaughters() const
returns number of daughters
void resetMaxWeightObserved()
sets maximum observed weight back to zero
void setMaxWeight(const double maxWeight)
sets maximum weight used for hit-miss MC
const lorentzVector & daughter(const int index) const
returns Lorentz vector of daughter at index
bool generateDecayAccepted(const lorentzVector &nBody, const double maxWeight=0)
generates full event with certain n-body mass and momentum only when event is accepted (return value ...
double maxWeight() const
returns maximum weight used for hit-miss MC
double normalization() const
returns normalization used in weight calculation
double breakupMom(const int index) const
returns breakup momentum in (index + 1)-body RF
double random()
returns number from internal random generator
bool eventAccepted(const double maxWeight=0)
applies event weight in form of hit-miss MC assumes that event weight has been already calculated by ...
double eventWeight() const
returns weight of generated event
double intermediateMass(const int index) const
returns intermediate mass of (index + 1)-body system
std::ostream & print(std::ostream &out=std::cout) const
prints generator status
double phi(const int index) const
returns azimuth in (index + 1)-body RF
double maxWeightObserved() const
returns maximum observed weight since instantiation
double cosTheta(const int index) const
returns polar angle in (index + 1)-body RF
double daughterMass(const int index) const
returns invariant mass of daughter at index
double generateDecay(const lorentzVector &nBody)
generates full event with certain n-body mass and momentum and returns event weight ...
void setSeed(const unsigned int seed)
sets seed of random number generator
double estimateMaxWeight(const double nBodyMass, const unsigned int nmbOfIterations=10000)
estimates maximum weight for given n-body mass
bool setDecay(const std::vector< double > &daughterMasses)
sets decay constants and prepares internal variables