BOSS 8.0.0
BESIII Offline Software System
Loading...
Searching...
No Matches
EvtVubHybrid.cc
Go to the documentation of this file.
1//---------------------------------------------------------------------------
2//
3// Environment:
4// This software is part of the EvtGen package developed jointly
5// for the BaBar and CLEO collaborations. If you use all or part
6// of it, please give an appropriate acknowledgement.
7//
8// Copyright Information:
9// Copyright (C) 1998 Caltech, UCSB
10//
11// Module: EvtVubHybrid.cc
12//
13// Description: Routine to decay a particle according to phase space.
14//
15// Modification history:
16//
17// Jochen Dingfelder February 1, 2005 Created Module as update of the
18// original module EvtVub by Sven Menke
19//---------------------------------------------------------------------------
20//
21#include "EvtVubHybrid.hh"
22#include "CLHEP/Random/RandGeneral.h"
30#include "EvtPFermi.hh"
31#include "EvtVubdGamma.hh"
32#include <stdlib.h>
33
34#include <fstream>
35#include <iostream>
36#include <string>
37
38typedef double HepDouble;
39// #include "CLHEP/config/CLHEP.h" //maqm add
40// #include "CLHEP/config/TemplateFunctions.h" //maqm add
41
42using std::cout;
43using std::endl;
44using std::ifstream;
45
46// _noHybrid will be set TRUE if the DECAY.DEC file has no binning or weights
47// _storeQplus should alwasy be TRUE: writes out Fermi motion parameter
48
50 : _noHybrid( false )
51 , _storeQplus( true )
52 , _mb( 4.62 )
53 , _a( 2.27 )
54 , _alphas( 0.22 )
55 , _dGMax( 3. )
56 , _nbins_mX( 0 )
57 , _nbins_q2( 0 )
58 , _nbins_El( 0 )
59 , _nbins( 0 )
60 , _masscut( 0.28 )
61 , _bins_mX( 0 )
62 , _bins_q2( 0 )
63 , _bins_El( 0 )
64 , _weights( 0 )
65 , _dGamma( 0 ) {}
66
68 delete _dGamma;
69 delete[] _bins_mX;
70 delete[] _bins_q2;
71 delete[] _bins_El;
72 delete[] _weights;
73}
74
75void EvtVubHybrid::getName( std::string& model_name ) { model_name = "VUBHYBRID"; }
76
78
80
81 // check that there are at least 3 arguments
82 if ( getNArg() < EvtVubHybrid::nParameters )
83 {
84 report( ERROR, "EvtVubHybrid" )
85 << "EvtVub generator expected "
86 << "at least " << EvtVubHybrid::nParameters << " arguments but found: " << getNArg()
87 << "\nWill terminate execution!" << endl;
88 ::abort();
89 }
90 else if ( getNArg() == EvtVubHybrid::nParameters )
91 {
92 report( WARNING, "EvtVubHybrid" ) << "EvtVub: generate B -> Xu l nu events "
93 << "without using the hybrid reweighting." << endl;
94 _noHybrid = true;
95 }
96 else if ( getNArg() < EvtVubHybrid::nParameters + EvtVubHybrid::nVariables )
97 {
98 report( ERROR, "EvtVubHybrid" ) << "EvtVub could not read number of bins for "
99 << "all variables used in the reweighting\n"
100 << "Will terminate execution!" << endl;
101 ::abort();
102 }
103
104 // check that there are 3 daughters
105 checkNDaug( 3 );
106
107 // read minimum required parameters from decay.dec
108 _mb = getArg( 0 );
109 _a = getArg( 1 );
110 _alphas = getArg( 2 );
111
112 // the maximum dGamma*p2 value depends on alpha_s only:
113 const double dGMax0 = 3.;
114 _dGMax = 0.21344 + 8.905 * _alphas;
115 if ( _dGMax < dGMax0 ) _dGMax = dGMax0;
116
117 // for the Fermi Motion we need a B-Meson mass - but it's not critical
118 // to get an exact value; in order to stay in the phase space for
119 // B+- and B0 use the smaller mass
120
121 static double mB0 = EvtPDL::getMaxMass( EvtPDL::getId( "B0" ) );
122 static double mBP = EvtPDL::getMaxMass( EvtPDL::getId( "B+" ) );
123 static double mB = ( mB0 < mBP ? mB0 : mBP );
124
125 const double xlow = -_mb;
126 const double xhigh = mB - _mb;
127 const int aSize = 10000;
128
129 EvtPFermi pFermi( _a, mB, _mb );
130 // pf is the cumulative distribution normalized to 1.
131 _pf.resize( aSize );
132 for ( int i = 0; i < aSize; i++ )
133 {
134 double kplus = xlow + (double)( i + 0.5 ) / ( (double)aSize ) * ( xhigh - xlow );
135 if ( i == 0 ) _pf[i] = pFermi.getFPFermi( kplus );
136 else _pf[i] = _pf[i - 1] + pFermi.getFPFermi( kplus );
137 }
138 for ( int i = 0; i < _pf.size(); i++ ) _pf[i] /= _pf[_pf.size() - 1];
139
140 _dGamma = new EvtVubdGamma( _alphas );
141
142 if ( _noHybrid ) return; // Without hybrid weighting, nothing else to do
143
144 _nbins_mX = abs( (int)getArg( 3 ) );
145 _nbins_q2 = abs( (int)getArg( 4 ) );
146 _nbins_El = abs( (int)getArg( 5 ) );
147
148 int nextArg = EvtVubHybrid::nParameters + EvtVubHybrid::nVariables;
149
150 _nbins = _nbins_mX * _nbins_q2 * _nbins_El; // Binning of weight table
151
152 int expectArgs = nextArg + _nbins_mX + _nbins_q2 + _nbins_El + _nbins;
153
154 if ( getNArg() < expectArgs )
155 {
156 report( ERROR, "EvtVubHybrid" )
157 << " finds " << getNArg() << " arguments, expected " << expectArgs
158 << ". Something is wrong with the tables of weights or thresholds."
159 << "\nWill terminate execution!" << endl;
160 ::abort();
161 }
162
163 // read bin boundaries from decay.dec
164 int i;
165
166 _bins_mX = new double[_nbins_mX];
167 for ( i = 0; i < _nbins_mX; i++, nextArg++ ) { _bins_mX[i] = getArg( nextArg ); }
168 _masscut = _bins_mX[0];
169
170 _bins_q2 = new double[_nbins_q2];
171 for ( i = 0; i < _nbins_q2; i++, nextArg++ ) { _bins_q2[i] = getArg( nextArg ); }
172
173 _bins_El = new double[_nbins_El];
174 for ( i = 0; i < _nbins_El; i++, nextArg++ ) { _bins_El[i] = getArg( nextArg ); }
175
176 // read in weights (and rescale to range 0..1)
177 readWeights( nextArg );
178}
179
181
183
184 int j;
185 // B+ -> u-bar specflav l+ nu
186
187 EvtParticle *xuhad, *lepton, *neutrino;
188 EvtVector4R p4;
189 // R. Faccini 21/02/03
190 // move the reweighting up , before also shooting the fermi distribution
191 double x, z, p2;
192 double sh = 0.0;
193 double mB, ml, xlow, xhigh, qplus;
194 double El = 0.0;
195 double Eh = 0.0;
196 double kplus;
197 double q2, mX;
198
199 const double lp2epsilon = -10;
200 bool rew( true );
201 while ( rew )
202 {
203
205
206 xuhad = p->getDaug( 0 );
207 lepton = p->getDaug( 1 );
208 neutrino = p->getDaug( 2 );
209
210 mB = p->mass();
211 ml = lepton->mass();
212
213 xlow = -_mb;
214 xhigh = mB - _mb;
215
216 // Fermi motion does not need to be computed inside the
217 // tryit loop as m_b in Gamma0 does not need to be replaced by (m_b+kplus).
218 // The difference however should be of the Order (lambda/m_b)^2 which is
219 // beyond the considered orders in the paper anyway ...
220
221 // for alpha_S = 0 and a mass cut on X_u not all values of kplus are
222 // possible. The maximum value is mB/2-_mb + sqrt(mB^2/4-_masscut^2)
223 kplus = 2 * xhigh;
224
225 while (
226 kplus >= xhigh || kplus <= xlow ||
227 ( _alphas == 0 && kplus >= mB / 2 - _mb + sqrt( mB * mB / 4 - _masscut * _masscut ) ) )
228 {
229 kplus = findPFermi(); //_pFermi->shoot();
230 kplus = xlow + kplus * ( xhigh - xlow );
231 }
232 qplus = mB - _mb - kplus;
233 if ( ( mB - qplus ) / 2. <= ml ) continue;
234
235 int tryit = 1;
236 while ( tryit )
237 {
238
239 x = EvtRandom::Flat();
240 z = EvtRandom::Flat( 0, 2 );
242 p2 = pow( 10, lp2epsilon * p2 );
243
244 El = x * ( mB - qplus ) / 2;
245 if ( El > ml && El < mB / 2 )
246 {
247
248 Eh = z * ( mB - qplus ) / 2 + qplus;
249 if ( Eh > 0 && Eh < mB )
250 {
251
252 sh = p2 * pow( mB - qplus, 2 ) + 2 * qplus * ( Eh - qplus ) + qplus * qplus;
253 if ( sh > _masscut * _masscut && mB * mB + sh - 2 * mB * Eh > ml * ml )
254 {
255
256 double xran = EvtRandom::Flat();
257
258 double y = _dGamma->getdGdxdzdp( x, z, p2 ) / _dGMax * p2;
259
260 if ( y > 1 )
261 report( WARNING, "EvtVubHybrid" )
262 << "EvtVubHybrid decay probability > 1 found: " << y << endl;
263 if ( y >= xran ) tryit = 0;
264 }
265 }
266 }
267 }
268
269 // compute all kinematic variables needed for reweighting (J. Dingfelder)
270 mX = sqrt( sh );
271 q2 = mB * mB + sh - 2 * mB * Eh;
272
273 // Reweighting in bins of mX, q2, El (J. Dingfelder)
274 if ( _nbins > 0 )
275 {
276 double xran1 = EvtRandom::Flat();
277 double w = 1.0;
278 if ( !_noHybrid ) w = getWeight( mX, q2, El );
279 if ( w >= xran1 ) rew = false;
280 }
281 else { rew = false; }
282 }
283
284 // o.k. we have the three kineamtic variables
285 // now calculate a flat cos Theta_H [-1,1] distribution of the
286 // hadron flight direction w.r.t the B flight direction
287 // because the B is a scalar and should decay isotropic.
288 // Then chose a flat Phi_H [0,2Pi] w.r.t the B flight direction
289 // and and a flat Phi_L [0,2Pi] in the W restframe w.r.t the
290 // W flight direction.
291
292 double ctH = EvtRandom::Flat( -1, 1 );
293 double phH = EvtRandom::Flat( 0, 2 * M_PI );
294 double phL = EvtRandom::Flat( 0, 2 * M_PI );
295
296 // now compute the four vectors in the B Meson restframe
297
298 double ptmp, sttmp;
299 // calculate the hadron 4 vector in the B Meson restframe
300
301 sttmp = sqrt( 1 - ctH * ctH );
302 ptmp = sqrt( Eh * Eh - sh );
303 double pHB[4] = { Eh, ptmp * sttmp * cos( phH ), ptmp * sttmp * sin( phH ), ptmp * ctH };
304 p4.set( pHB[0], pHB[1], pHB[2], pHB[3] );
305 xuhad->init( getDaug( 0 ), p4 );
306
307 if ( _storeQplus )
308 {
309 // cludge to store the hidden parameter q+ with the decay;
310 // the lifetime of the Xu is abused for this purpose.
311 // tau = 1 ps corresponds to ctau = 0.3 mm -> in order to
312 // stay well below BaBars sensitivity we take q+/(10000 GeV) which
313 // goes up to 0.0005 in the most extreme cases as ctau in mm.
314 // To extract q+ back from the StdHepTrk its necessary to get
315 // delta_ctau = Xu->anyDaughter->getVertexTime()-Xu->getVertexTime()
316 // where these pseudo calls refere to the StdHep time stored at
317 // the production vertex in the lab for each particle. The boost
318 // has to be reversed and the result is:
319 //
320 // q+ = delta_ctau * 10000 GeV/mm * Mass_Xu/Energy_Xu
321 //
322 xuhad->setLifetime( qplus / 10000. );
323 }
324
325 // calculate the W 4 vector in the B Meson restrframe
326
327 double apWB = ptmp;
328 double pWB[4] = { mB - Eh, -pHB[1], -pHB[2], -pHB[3] };
329
330 // first go in the W restframe and calculate the lepton and
331 // the neutrino in the W frame
332
333 double mW2 = mB * mB + sh - 2 * mB * Eh;
334 double beta = ptmp / pWB[0];
335 double gamma = pWB[0] / sqrt( mW2 );
336
337 double pLW[4];
338
339 ptmp = ( mW2 - ml * ml ) / 2 / sqrt( mW2 );
340 pLW[0] = sqrt( ml * ml + ptmp * ptmp );
341
342 double ctL = ( El - gamma * pLW[0] ) / beta / gamma / ptmp;
343 if ( ctL < -1 ) ctL = -1;
344 if ( ctL > 1 ) ctL = 1;
345 sttmp = sqrt( 1 - ctL * ctL );
346
347 // eX' = eZ x eW
348 double xW[3] = { -pWB[2], pWB[1], 0 };
349 // eZ' = eW
350 double zW[3] = { pWB[1] / apWB, pWB[2] / apWB, pWB[3] / apWB };
351
352 double lx = sqrt( xW[0] * xW[0] + xW[1] * xW[1] );
353 for ( j = 0; j < 2; j++ ) xW[j] /= lx;
354
355 // eY' = eZ' x eX'
356 double yW[3] = { -pWB[1] * pWB[3], -pWB[2] * pWB[3], pWB[1] * pWB[1] + pWB[2] * pWB[2] };
357 double ly = sqrt( yW[0] * yW[0] + yW[1] * yW[1] + yW[2] * yW[2] );
358 for ( j = 0; j < 3; j++ ) yW[j] /= ly;
359
360 // p_lep = |p_lep| * ( sin(Theta) * cos(Phi) * eX'
361 // + sin(Theta) * sin(Phi) * eY'
362 // + cos(Theta) * eZ')
363 for ( j = 0; j < 3; j++ )
364 pLW[j + 1] = sttmp * cos( phL ) * ptmp * xW[j] + sttmp * sin( phL ) * ptmp * yW[j] +
365 ctL * ptmp * zW[j];
366
367 double apLW = ptmp;
368 // calculate the neutrino 4 vector in the W restframe
369 // double pNW[4] = {sqrt(mW2)-pLW[0],-pLW[1],-pLW[2],-pLW[3]};
370
371 // boost them back in the B Meson restframe
372
373 double appLB = beta * gamma * pLW[0] + gamma * ctL * apLW;
374
375 ptmp = sqrt( El * El - ml * ml );
376 double ctLL = appLB / ptmp;
377
378 if ( ctLL > 1 ) ctLL = 1;
379 if ( ctLL < -1 ) ctLL = -1;
380
381 double pLB[4] = { El, 0, 0, 0 };
382 double pNB[4] = { pWB[0] - El, 0, 0, 0 };
383
384 for ( j = 1; j < 4; j++ )
385 {
386 pLB[j] = pLW[j] + ( ctLL * ptmp - ctL * apLW ) / apWB * pWB[j];
387 pNB[j] = pWB[j] - pLB[j];
388 }
389
390 p4.set( pLB[0], pLB[1], pLB[2], pLB[3] );
391 lepton->init( getDaug( 1 ), p4 );
392
393 p4.set( pNB[0], pNB[1], pNB[2], pNB[3] );
394 neutrino->init( getDaug( 2 ), p4 );
395
396 return;
397}
398
399double EvtVubHybrid::findPFermi() {
400
401 double ranNum = EvtRandom::Flat();
402 double oOverBins = 1.0 / ( float( _pf.size() ) );
403 int nBinsBelow = 0; // largest k such that I[k] is known to be <= rand
404 int nBinsAbove = _pf.size(); // largest k such that I[k] is known to be > rand
405 int middle;
406
407 while ( nBinsAbove > nBinsBelow + 1 )
408 {
409 middle = ( nBinsAbove + nBinsBelow + 1 ) >> 1;
410 if ( ranNum >= _pf[middle] ) { nBinsBelow = middle; }
411 else { nBinsAbove = middle; }
412 }
413
414 double bSize = _pf[nBinsAbove] - _pf[nBinsBelow];
415 // binMeasure is always aProbFunc[nBinsBelow],
416
417 if ( bSize == 0 )
418 {
419 // rand lies right in a bin of measure 0. Simply return the center
420 // of the range of that bin. (Any value between k/N and (k+1)/N is
421 // equally good, in this rare case.)
422 return ( nBinsBelow + .5 ) * oOverBins;
423 }
424
425 HepDouble bFract = ( ranNum - _pf[nBinsBelow] ) / bSize;
426
427 return ( nBinsBelow + bFract ) * oOverBins;
428}
429
430double EvtVubHybrid::getWeight( double mX, double q2, double El ) {
431
432 int ibin_mX = -1;
433 int ibin_q2 = -1;
434 int ibin_El = -1;
435
436 for ( int i = 0; i < _nbins_mX; i++ )
437 {
438 if ( mX >= _bins_mX[i] ) ibin_mX = i;
439 }
440 for ( int i = 0; i < _nbins_q2; i++ )
441 {
442 if ( q2 >= _bins_q2[i] ) ibin_q2 = i;
443 }
444 for ( int i = 0; i < _nbins_El; i++ )
445 {
446 if ( El >= _bins_El[i] ) ibin_El = i;
447 }
448 int ibin = ibin_mX + ibin_q2 * _nbins_mX + ibin_El * _nbins_mX * _nbins_q2;
449
450 if ( ( ibin_mX < 0 ) || ( ibin_q2 < 0 ) || ( ibin_El < 0 ) )
451 {
452 report( ERROR, "EvtVubHybrid" ) << "Cannot determine hybrid weight "
453 << "for this event "
454 << "-> assign weight = 0" << endl;
455 return 0.0;
456 }
457
458 return _weights[ibin];
459}
460
461void EvtVubHybrid::readWeights( int startArg ) {
462 _weights = new double[_nbins];
463
464 double maxw = 0.0;
465 for ( int i = 0; i < _nbins; i++, startArg++ )
466 {
467 _weights[i] = getArg( startArg );
468 if ( _weights[i] > maxw ) maxw = _weights[i];
469 }
470
471 if ( maxw == 0 )
472 {
473 report( ERROR, "EvtVubHybrid" ) << "EvtVub generator expected at least one "
474 << " weight > 0, but found none! "
475 << "Will terminate execution!" << endl;
476 ::abort();
477 }
478
479 // rescale weights (to be in range 0..1)
480 for ( int i = 0; i < _nbins; i++ ) { _weights[i] /= maxw; }
481}
double p2[4]
character *LEPTONflag integer iresonances real zeta5 real adp3 real large_3 real zeta5 common params adp3 common switch large_3 common lepton LEPTONflag common RESFIT IRESON common RES iresonances common alpgmu era0 common physparams ERMW common leptomass ml
DOUBLE_PRECISION xlow[20]
double w
ostream & report(Severity severity, const char *facility)
Definition EvtReport.cc:34
@ ERROR
Definition EvtReport.hh:49
@ WARNING
Definition EvtReport.hh:50
double HepDouble
Definition EvtVub.cc:37
#define M_PI
Definition TConstant.h:4
double getArg(int j)
void checkNDaug(int d1, int d2=-1)
EvtId * getDaugs()
EvtId getDaug(int i)
static double getMaxMass(EvtId i)
Definition EvtPDL.hh:55
static EvtId getId(const std::string &name)
Definition EvtPDL.cc:272
double getFPFermi(const double &kplus)
Definition EvtPFermi.cc:50
virtual void init(EvtId part_n, const EvtVector4R &p4)=0
void setLifetime(double tau)
EvtParticle * getDaug(int i)
double mass() const
double initializePhaseSpace(int numdaughter, EvtId *daughters, double poleSize=-1., int whichTwo1=0, int whichTwo2=1)
static double Flat()
Definition EvtRandom.cc:69
void set(int i, double d)
void readWeights(int startArg=0)
double getWeight(double mX, double q2, double El)
void decay(EvtParticle *p)
void getName(std::string &name)
virtual ~EvtVubHybrid()
EvtDecayBase * clone()