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