evtgen is hosted by Hepforge, IPPP Durham
EvtGen  2.0.0
Monte Carlo generator of particle decays, in particular the weak decays of heavy flavour particles such as B mesons.
EvtVub.cpp
Go to the documentation of this file.
1 
2 /***********************************************************************
3 * Copyright 1998-2020 CERN for the benefit of the EvtGen authors *
4 * *
5 * This file is part of EvtGen. *
6 * *
7 * EvtGen 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 * EvtGen 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 EvtGen. If not, see <https://www.gnu.org/licenses/>. *
19 ***********************************************************************/
20 
21 #include "EvtGenModels/EvtVub.hh"
22 
23 #include "EvtGenBase/EvtGenKine.hh"
24 #include "EvtGenBase/EvtPDL.hh"
26 #include "EvtGenBase/EvtPatches.hh"
27 #include "EvtGenBase/EvtRandom.hh"
28 #include "EvtGenBase/EvtReport.hh"
30 
32 
33 #include <stdlib.h>
34 #include <string>
35 using std::endl;
36 
37 std::string EvtVub::getName()
38 {
39  return "VUB";
40 }
41 
43 {
44  return new EvtVub;
45 }
46 
48 {
49  // check that there are at least 6 arguments
50 
51  if ( getNArg() < 6 ) {
52  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
53  << "EvtVub generator expected "
54  << " at least 6 arguments (mb,a,alpha_s,Nbins,m1,w1,...) but found: "
55  << getNArg() << endl;
56  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
57  << "Will terminate execution!" << endl;
58  ::abort();
59  }
60 
61  _mb = getArg( 0 );
62  _a = getArg( 1 );
63  _alphas = getArg( 2 );
64  _nbins = abs( (int)getArg( 3 ) );
65  _storeQplus = ( getArg( 3 ) < 0 ? 1 : 0 );
66  _masses = std::vector<double>( _nbins );
67  _weights = std::vector<double>( _nbins );
68 
69  if ( getNArg() - 4 != 2 * _nbins ) {
70  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
71  << "EvtVub generator expected " << _nbins
72  << " masses and weights but found: " << ( getNArg() - 4 ) / 2
73  << endl;
74  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
75  << "Will terminate execution!" << endl;
76  ::abort();
77  }
78  int i, j = 4;
79  double maxw = 0.;
80  for ( i = 0; i < _nbins; i++ ) {
81  _masses[i] = getArg( j++ );
82  if ( i > 0 && _masses[i] <= _masses[i - 1] ) {
83  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
84  << "EvtVub generator expected "
85  << " mass bins in ascending order!"
86  << "Will terminate execution!" << endl;
87  ::abort();
88  }
89  _weights[i] = getArg( j++ );
90  if ( _weights[i] < 0 ) {
91  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
92  << "EvtVub generator expected "
93  << " weights >= 0, but found: " << _weights[i] << endl;
94  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
95  << "Will terminate execution!" << endl;
96  ::abort();
97  }
98  if ( _weights[i] > maxw )
99  maxw = _weights[i];
100  }
101  if ( maxw == 0 ) {
102  EvtGenReport( EVTGEN_ERROR, "EvtGen" )
103  << "EvtVub generator expected at least one "
104  << " weight > 0, but found none! "
105  << "Will terminate execution!" << endl;
106  ::abort();
107  }
108  for ( i = 0; i < _nbins; i++ )
109  _weights[i] /= maxw;
110 
111  // the maximum dGamma*p2 value depends on alpha_s only:
112 
113  const double dGMax0 = 3.;
114  _dGMax = 0.21344 + 8.905 * _alphas;
115  if ( _dGMax < dGMax0 )
116  _dGMax = dGMax0;
117 
118  // for the Fermi Motion we need a B-Meson mass - but it's not critical
119  // to get an exact value; in order to stay in the phase space for
120  // B+- and B0 use the smaller mass
121 
122  EvtId BP = EvtPDL::getId( "B+" );
123  EvtId B0 = EvtPDL::getId( "B0" );
124 
125  double mB0 = EvtPDL::getMaxMass( B0 );
126  double mBP = EvtPDL::getMaxMass( BP );
127 
128  double mB = ( mB0 < mBP ? mB0 : mBP );
129 
130  const double xlow = -_mb;
131  const double xhigh = mB - _mb;
132  const int aSize = 10000;
133 
134  EvtPFermi pFermi( _a, mB, _mb );
135  // pf is the cumulative distribution
136  // normalized to 1.
137  _pf.resize( aSize );
138  for ( i = 0; i < aSize; i++ ) {
139  double kplus = xlow + (double)( i + 0.5 ) / ( (double)aSize ) *
140  ( xhigh - xlow );
141  if ( i == 0 )
142  _pf[i] = pFermi.getFPFermi( kplus );
143  else
144  _pf[i] = _pf[i - 1] + pFermi.getFPFermi( kplus );
145  }
146  for ( size_t index = 0; index < _pf.size(); index++ ) {
147  _pf[index] /= _pf[_pf.size() - 1];
148  }
149 
150  // static EvtHepRandomEngine myEngine;
151 
152  // _pFermi = new RandGeneral(myEngine,pf,aSize,0);
153  _dGamma = std::make_unique<EvtVubdGamma>( _alphas );
154 
155  // check that there are 3 daughters
156  checkNDaug( 3 );
157 }
158 
160 {
161  noProbMax();
162 }
163 
165 {
166  int j;
167  // B+ -> u-bar specflav l+ nu
168 
169  EvtParticle *xuhad( 0 ), *lepton( 0 ), *neutrino( 0 );
170  EvtVector4R p4;
171  // R. Faccini 21/02/03
172  // move the reweighting up , before also shooting the fermi distribution
173  double x, z, p2;
174  double sh = 0.0;
175  double mB, ml, xlow, xhigh, qplus;
176  double El = 0.0;
177  double Eh = 0.0;
178  double kplus;
179  const double lp2epsilon = -10;
180  bool rew( true );
181  while ( rew ) {
183 
184  xuhad = p->getDaug( 0 );
185  lepton = p->getDaug( 1 );
186  neutrino = p->getDaug( 2 );
187 
188  mB = p->mass();
189  ml = lepton->mass();
190 
191  xlow = -_mb;
192  xhigh = mB - _mb;
193 
194  // Fermi motion does not need to be computed inside the
195  // tryit loop as m_b in Gamma0 does not need to be replaced by (m_b+kplus).
196  // The difference however should be of the Order (lambda/m_b)^2 which is
197  // beyond the considered orders in the paper anyway ...
198 
199  // for alpha_S = 0 and a mass cut on X_u not all values of kplus are
200  // possible. The maximum value is mB/2-_mb + sqrt(mB^2/4-_masses[0]^2)
201  kplus = 2 * xhigh;
202 
203  while ( kplus >= xhigh || kplus <= xlow ||
204  ( _alphas == 0 &&
205  kplus >= mB / 2 - _mb +
206  sqrt( mB * mB / 4 - _masses[0] * _masses[0] ) ) ) {
207  kplus = findPFermi(); //_pFermi->shoot();
208  kplus = xlow + kplus * ( xhigh - xlow );
209  }
210  qplus = mB - _mb - kplus;
211  if ( ( mB - qplus ) / 2. <= ml )
212  continue;
213 
214  int tryit = 1;
215  while ( tryit ) {
216  x = EvtRandom::Flat();
217  z = EvtRandom::Flat( 0, 2 );
218  p2 = EvtRandom::Flat();
219  p2 = pow( 10.0, lp2epsilon * p2 );
220 
221  El = x * ( mB - qplus ) / 2;
222  if ( El > ml && El < mB / 2 ) {
223  Eh = z * ( mB - qplus ) / 2 + qplus;
224  if ( Eh > 0 && Eh < mB ) {
225  sh = p2 * pow( mB - qplus, 2 ) +
226  2 * qplus * ( Eh - qplus ) + qplus * qplus;
227  if ( sh > _masses[0] * _masses[0] &&
228  mB * mB + sh - 2 * mB * Eh > ml * ml ) {
229  double xran = EvtRandom::Flat();
230 
231  double y = _dGamma->getdGdxdzdp( x, z, p2 ) / _dGMax * p2;
232 
233  if ( y > 1 )
234  EvtGenReport( EVTGEN_WARNING, "EvtGen" )
235  << "EvtVub decay probability > 1 found: " << y
236  << endl;
237  if ( y >= xran )
238  tryit = 0;
239  }
240  }
241  }
242  }
243  // reweight the Mx distribution
244  if ( _nbins > 0 ) {
245  double xran1 = EvtRandom::Flat();
246  double m = sqrt( sh );
247  j = 0;
248  while ( j < _nbins && m > _masses[j] )
249  j++;
250  double w = _weights[j - 1];
251  if ( w >= xran1 )
252  rew = false;
253  } else {
254  rew = false;
255  }
256  }
257 
258  // o.k. we have the three kineamtic variables
259  // now calculate a flat cos Theta_H [-1,1] distribution of the
260  // hadron flight direction w.r.t the B flight direction
261  // because the B is a scalar and should decay isotropic.
262  // Then chose a flat Phi_H [0,2Pi] w.r.t the B flight direction
263  // and and a flat Phi_L [0,2Pi] in the W restframe w.r.t the
264  // W flight direction.
265 
266  double ctH = EvtRandom::Flat( -1, 1 );
267  double phH = EvtRandom::Flat( 0, 2 * EvtConst::pi );
268  double phL = EvtRandom::Flat( 0, 2 * EvtConst::pi );
269 
270  // now compute the four vectors in the B Meson restframe
271 
272  double ptmp, sttmp;
273  // calculate the hadron 4 vector in the B Meson restframe
274 
275  sttmp = sqrt( 1 - ctH * ctH );
276  ptmp = sqrt( Eh * Eh - sh );
277  double pHB[4] = {Eh, ptmp * sttmp * cos( phH ), ptmp * sttmp * sin( phH ),
278  ptmp * ctH};
279  p4.set( pHB[0], pHB[1], pHB[2], pHB[3] );
280  xuhad->init( getDaug( 0 ), p4 );
281 
282  if ( _storeQplus ) {
283  // cludge to store the hidden parameter q+ with the decay;
284  // the lifetime of the Xu is abused for this purpose.
285  // tau = 1 ps corresponds to ctau = 0.3 mm -> in order to
286  // stay well below BaBars sensitivity we take q+/(10000 GeV) which
287  // goes up to 0.0005 in the most extreme cases as ctau in mm.
288  // To extract q+ back from the StdHepTrk its necessary to get
289  // delta_ctau = Xu->anyDaughter->getVertexTime()-Xu->getVertexTime()
290  // where these pseudo calls refere to the StdHep time stored at
291  // the production vertex in the lab for each particle. The boost
292  // has to be reversed and the result is:
293  //
294  // q+ = delta_ctau * 10000 GeV/mm * Mass_Xu/Energy_Xu
295  //
296  xuhad->setLifetime( qplus / 10000. );
297  }
298 
299  // calculate the W 4 vector in the B Meson restrframe
300 
301  double apWB = ptmp;
302  double pWB[4] = {mB - Eh, -pHB[1], -pHB[2], -pHB[3]};
303 
304  // first go in the W restframe and calculate the lepton and
305  // the neutrino in the W frame
306 
307  double mW2 = mB * mB + sh - 2 * mB * Eh;
308  double beta = ptmp / pWB[0];
309  double gamma = pWB[0] / sqrt( mW2 );
310 
311  double pLW[4];
312 
313  ptmp = ( mW2 - ml * ml ) / 2 / sqrt( mW2 );
314  pLW[0] = sqrt( ml * ml + ptmp * ptmp );
315 
316  double ctL = ( El - gamma * pLW[0] ) / beta / gamma / ptmp;
317  if ( ctL < -1 )
318  ctL = -1;
319  if ( ctL > 1 )
320  ctL = 1;
321  sttmp = sqrt( 1 - ctL * ctL );
322 
323  // eX' = eZ x eW
324  double xW[3] = {-pWB[2], pWB[1], 0};
325  // eZ' = eW
326  double zW[3] = {pWB[1] / apWB, pWB[2] / apWB, pWB[3] / apWB};
327 
328  double lx = sqrt( xW[0] * xW[0] + xW[1] * xW[1] );
329  for ( j = 0; j < 2; j++ )
330  xW[j] /= lx;
331 
332  // eY' = eZ' x eX'
333  double yW[3] = {-pWB[1] * pWB[3], -pWB[2] * pWB[3],
334  pWB[1] * pWB[1] + pWB[2] * pWB[2]};
335  double ly = sqrt( yW[0] * yW[0] + yW[1] * yW[1] + yW[2] * yW[2] );
336  for ( j = 0; j < 3; j++ )
337  yW[j] /= ly;
338 
339  // p_lep = |p_lep| * ( sin(Theta) * cos(Phi) * eX'
340  // + sin(Theta) * sin(Phi) * eY'
341  // + cos(Theta) * eZ')
342  for ( j = 0; j < 3; j++ )
343  pLW[j + 1] = sttmp * cos( phL ) * ptmp * xW[j] +
344  sttmp * sin( phL ) * ptmp * yW[j] + ctL * ptmp * zW[j];
345 
346  double apLW = ptmp;
347 
348  // boost them back in the B Meson restframe
349  double appLB = beta * gamma * pLW[0] + gamma * ctL * apLW;
350 
351  ptmp = sqrt( El * El - ml * ml );
352  double ctLL = appLB / ptmp;
353 
354  if ( ctLL > 1 )
355  ctLL = 1;
356  if ( ctLL < -1 )
357  ctLL = -1;
358 
359  double pLB[4] = {El, 0, 0, 0};
360  double pNB[4] = {pWB[0] - El, 0, 0, 0};
361 
362  for ( j = 1; j < 4; j++ ) {
363  pLB[j] = pLW[j] + ( ctLL * ptmp - ctL * apLW ) / apWB * pWB[j];
364  pNB[j] = pWB[j] - pLB[j];
365  }
366 
367  p4.set( pLB[0], pLB[1], pLB[2], pLB[3] );
368  lepton->init( getDaug( 1 ), p4 );
369 
370  p4.set( pNB[0], pNB[1], pNB[2], pNB[3] );
371  neutrino->init( getDaug( 2 ), p4 );
372 
373  return;
374 }
375 
377 {
378  double ranNum = EvtRandom::Flat();
379  double oOverBins = 1.0 / ( float( _pf.size() ) );
380  int nBinsBelow = 0; // largest k such that I[k] is known to be <= rand
381  int nBinsAbove = _pf.size(); // largest k such that I[k] is known to be > rand
382  int middle;
383 
384  while ( nBinsAbove > nBinsBelow + 1 ) {
385  middle = ( nBinsAbove + nBinsBelow + 1 ) >> 1;
386  if ( ranNum >= _pf[middle] ) {
387  nBinsBelow = middle;
388  } else {
389  nBinsAbove = middle;
390  }
391  }
392 
393  double bSize = _pf[nBinsAbove] - _pf[nBinsBelow];
394  // binMeasure is always aProbFunc[nBinsBelow],
395 
396  if ( bSize == 0 ) {
397  // rand lies right in a bin of measure 0. Simply return the center
398  // of the range of that bin. (Any value between k/N and (k+1)/N is
399  // equally good, in this rare case.)
400  return ( nBinsBelow + .5 ) * oOverBins;
401  }
402 
403  double bFract = ( ranNum - _pf[nBinsBelow] ) / bSize;
404 
405  return ( nBinsBelow + bFract ) * oOverBins;
406 }
void initProbMax() override
Definition: EvtVub.cpp:159
double _alphas
Definition: EvtVub.hh:52
std::string getName() override
Definition: EvtVub.cpp:37
std::vector< double > _weights
Definition: EvtVub.hh:57
std::unique_ptr< EvtVubdGamma > _dGamma
Definition: EvtVub.hh:59
EvtDecayBase * clone() override
Definition: EvtVub.cpp:42
double getArg(unsigned int j)
std::ostream & EvtGenReport(EvtGenSeverity severity, const char *facility=0)
Definition: EvtReport.cpp:33
virtual void init(EvtId part_n, const EvtVector4R &p4)=0
void init() override
Definition: EvtVub.cpp:47
double getFPFermi(const double &kplus)
Definition: EvtPFermi.cpp:52
void set(int i, double d)
Definition: EvtVector4R.hh:167
void decay(EvtParticle *p) override
Definition: EvtVub.cpp:164
EvtId * getDaugs()
Definition: EvtDecayBase.hh:66
double _a
Definition: EvtVub.hh:51
Definition: EvtId.hh:27
double _dGMax
Definition: EvtVub.hh:53
static const double pi
Definition: EvtConst.hh:26
double findPFermi()
Definition: EvtVub.cpp:376
int _storeQplus
Definition: EvtVub.hh:55
std::vector< double > _masses
Definition: EvtVub.hh:56
double initializePhaseSpace(unsigned int numdaughter, EvtId *daughters, bool forceResetMasses=false, double poleSize=-1., int whichTwo1=0, int whichTwo2=1)
void checkNDaug(int d1, int d2=-1)
static double Flat()
Definition: EvtRandom.cpp:72
double abs(const EvtComplex &c)
Definition: EvtComplex.hh:201
static EvtId getId(const std::string &name)
Definition: EvtPDL.cpp:287
double mass() const
int getNDaug() const
Definition: EvtDecayBase.hh:65
EvtParticle * getDaug(int i)
Definition: EvtParticle.cpp:91
double _mb
Definition: EvtVub.hh:50
std::vector< double > _pf
Definition: EvtVub.hh:61
Definition: EvtVub.hh:37
int getNArg() const
Definition: EvtDecayBase.hh:68
int _nbins
Definition: EvtVub.hh:54
static double getMaxMass(EvtId i)
Definition: EvtPDL.cpp:337
EvtId getDaug(int i) const
Definition: EvtDecayBase.hh:67