File: SimplePhaseSpace.cc

package info (click to toggle)
thepeg 1.8.0-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 9,312 kB
  • ctags: 11,509
  • sloc: cpp: 57,129; sh: 11,315; java: 3,212; lisp: 1,402; makefile: 830; ansic: 58; perl: 3
file content (92 lines) | stat: -rw-r--r-- 2,962 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// -*- C++ -*-
//
// SimplePhaseSpace.cc is a part of ThePEG - Toolkit for HEP Event Generation
// Copyright (C) 1999-2011 Leif Lonnblad
//
// ThePEG is licenced under version 2 of the GPL, see COPYING for details.
// Please respect the MCnet academic guidelines, see GUIDELINES for details.
//

#include "SimplePhaseSpace.h"

#ifdef ThePEG_TEMPLATES_IN_CC_FILE
#include "SimplePhaseSpace.tcc"
#endif

using namespace ThePEG;

Energy SimplePhaseSpace::getMagnitude(Energy2 s, Energy m1, Energy m2)
{
  const Energy2 eps = 10.0*s*Constants::epsilon;
  if ( m1 < ZERO && sqr(m1) < eps ) m1 = ZERO;
  if ( m2 < ZERO && sqr(m2) < eps ) m2 = ZERO;
  if ( m1 >= ZERO && m2 >= ZERO ) {
    Energy2 aa = s - sqr(m1+m2);
    if ( aa < ZERO && aa > -eps ) return ZERO;
    if ( aa < ZERO ) throw ImpossibleKinematics();
    return 0.5*sqrt(aa*(s-sqr(m1-m2))/s);
  }
  Energy2 m12 = m1 < ZERO? -sqr(m1): sqr(m1);
  Energy2 m22 = m2 < ZERO? -sqr(m2): sqr(m2);
  Energy2 r2 = 0.25*(sqr(m12) + sqr(m22 - s) -2.0*m12*(m22 + s))/s;
  if ( r2 < ZERO || r2 + m12 < ZERO || r2 + m22 < ZERO )
    throw ImpossibleKinematics();
  return sqrt(r2);
}

vector<LorentzMomentum> SimplePhaseSpace::
CMSn(Energy m0, const vector<Energy> & m)
{
  using Constants::pi;

  // Setup constants.
  int Np = m.size();
  vector<LorentzMomentum> ret(Np);
  Energy summ = std::accumulate(m.begin(), m.end(), Energy());
  if ( summ >= m0 ) throw ImpossibleKinematics();

  while ( true ) {
    // First get an ordered list of random numbers.
    vector<double> rndv(Np);
    rndv[0] = 1.0;
    rndv.back() = 0.0;
    for ( int i = 1; i < Np - 1; ++i ) rndv[i] = UseRandom::rnd();
    std::sort(rndv.begin() + 1, rndv.end() - 1, std::greater<double>());

    // Now setup masses of subsystems.
    vector<Energy> sm(Np);
    Energy tmass = m0 - summ;
    Energy tmp = summ;
    for ( int i = 0; i < Np; ++i ) {
      sm[i] = rndv[i]*tmass + tmp;
      tmp -= m[i];
    }

    // Now the magnitude of all the momenta can be calculated. This
    // gives the weight.
    double weight = 1.0;
    vector<Energy> p(Np);
    p[Np - 1] = getMagnitude(sqr(sm[Np - 2]), m[Np -2], sm[Np - 1]);
    for ( int i = Np - 2; i >= 0; --i )
      weight *= (p[i] = getMagnitude(sqr(sm[i]), m[i], sm[i + 1]))/sm[i];
    if ( weight > UseRandom::rnd() ) continue;

    // Now we just have to generate the angles.
    ret[Np - 1] = LorentzMomentum(ZERO, ZERO, ZERO, m[Np - 1]);
    for ( int i = Np - 2; i >= 0; --i ) {
      Momentum3 p3 = polar3Vector(p[i], 2.0*UseRandom::rnd() - 1.0,
				  2.0*pi*UseRandom::rnd());
      ret[i] = LorentzMomentum(-p3, sqrt(sqr(p[i]) + sqr(m[i])));
      if ( i == Np -2 ) {
	ret[Np - 1] = LorentzMomentum(p3, sqrt(sqr(m[Np - 1]) + p3.mag2()));
      } else {
	Boost bv = p3*(1.0/sqrt(sqr(p[i]) + sqr(sm[i + 1])));
	if ( bv.mag2() >= 1.0 ) throw ImpossibleKinematics();
	LorentzRotation r(bv);
	for ( int j = i + 1; j < Np; ++j ) ret[j]*=r.one();
      }
    }
    return ret;
  }
}