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