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
EvtCPUtil.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"
30
31#include <assert.h>
32#include <stdio.h>
33#include <stdlib.h>
34using std::endl;
35
36EvtCPUtil::EvtCPUtil( int mixingType )
37{
38 m_enableFlip = false;
39 m_mixingType = mixingType;
40}
41
43{
44 static thread_local EvtCPUtil* theCPUtil = nullptr;
45
46 if ( !theCPUtil ) {
47 theCPUtil = new EvtCPUtil( 1 );
48 }
49
50 return theCPUtil;
51}
52
53//added two functions for finding the fraction of B0 tags for decays into
54//both CP eigenstates and non-CP eigenstates -- NK, Jan. 27th, 1998
55
56void EvtCPUtil::fractB0CP( EvtComplex Af, EvtComplex Abarf, double /*deltam*/,
57 double beta, double& fract )
58{
59 //This function returns the number of B0 tags for decays into CP-eigenstates
60 //(the "probB0" in the new EvtOtherB)
61
62 //double gamma_B = EvtPDL::getWidth(B0);
63 //double xd = deltam/gamma_B;
64 //double xd = 0.65;
65 double ratio = 1 / ( 1 + 0.65 * 0.65 );
66
67 EvtComplex rf, rbarf;
68
69 rf = EvtComplex( cos( 2.0 * beta ), sin( 2.0 * beta ) ) * Abarf / Af;
70 rbarf = EvtComplex( 1.0 ) / rf;
71
72 double A2 = real( Af ) * real( Af ) + imag( Af ) * imag( Af );
73 double Abar2 = real( Abarf ) * real( Abarf ) + imag( Abarf ) * imag( Abarf );
74
75 double rf2 = real( rf ) * real( rf ) + imag( rf ) * imag( rf );
76 double rbarf2 = real( rbarf ) * real( rbarf ) + imag( rbarf ) * imag( rbarf );
77
78 fract = ( Abar2 * ( 1 + rbarf2 + ( 1 - rbarf2 ) * ratio ) ) /
79 ( Abar2 * ( 1 + rbarf2 + ( 1 - rbarf2 ) * ratio ) +
80 A2 * ( 1 + rf2 + ( 1 - rf2 ) * ratio ) );
81 return;
82}
83
85 EvtComplex Abarfbar, double deltam, double beta,
86 int flip, double& fract )
87{
88 //this function returns the number of B0 tags for decays into non-CP eigenstates
89 //(the "probB0" in the new EvtOtherB)
90 //this needs more thought...
91
92 //double gamma_B = EvtPDL::getWidth(B0);
93 //EvtGenReport(EVTGEN_INFO,"EvtGen") << "gamma " << gamma_B<< endl;
94 //double xd = deltam/gamma_B;
95
96 //why is the width of B0 0 in PDL??
97
98 double xd = 0.65;
99 double gamma_B = deltam / xd;
100 double IAf, IAfbar, IAbarf, IAbarfbar;
101 EvtComplex rf, rfbar, rbarf, rbarfbar;
102 double rf2, rfbar2, rbarf2, rbarfbar2;
103 double Af2, Afbar2, Abarf2, Abarfbar2;
104
105 rf = EvtComplex( cos( 2.0 * beta ), sin( 2.0 * beta ) ) * Abarf / Af;
106 rfbar = EvtComplex( cos( 2.0 * beta ), sin( 2.0 * beta ) ) * Abarfbar / Afbar;
107 rbarf = EvtComplex( cos( -2.0 * beta ), sin( -2.0 * beta ) ) * Af / Abarf;
108 rbarfbar = EvtComplex( cos( -2.0 * beta ), sin( -2.0 * beta ) ) * Afbar /
109 Abarfbar;
110
111 rf2 = real( rf ) * real( rf ) + imag( rf ) * imag( rf );
112 rfbar2 = real( rfbar ) * real( rfbar ) + imag( rfbar ) * imag( rfbar );
113 rbarf2 = real( rbarf ) * real( rbarf ) + imag( rbarf ) * imag( rbarf );
114 rbarfbar2 = real( rbarfbar ) * real( rbarfbar ) +
115 imag( rbarfbar ) * imag( rbarfbar );
116
117 Af2 = real( Af ) * real( Af ) + imag( Af ) * imag( Af );
118 Afbar2 = real( Afbar ) * real( Afbar ) + imag( Afbar ) * imag( Afbar );
119 Abarf2 = real( Abarf ) * real( Abarf ) + imag( Abarf ) * imag( Abarf );
120 Abarfbar2 = real( Abarfbar ) * real( Abarfbar ) +
121 imag( Abarfbar ) * imag( Abarfbar );
122
123 //
124 //IAf = integral(gamma(B0->f)), etc.
125 //
126
127 IAf = ( Af2 / ( 2 * gamma_B ) ) * ( 1 + rf2 + ( 1 - rf2 ) / ( 1 + xd * xd ) );
128 IAfbar = ( Afbar2 / ( 2 * gamma_B ) ) *
129 ( 1 + rfbar2 + ( 1 - rfbar2 ) / ( 1 + xd * xd ) );
130 IAbarf = ( Abarf2 / ( 2 * gamma_B ) ) *
131 ( 1 + rbarf2 + ( 1 - rbarf2 ) / ( 1 + xd * xd ) );
132 IAbarfbar = ( Abarfbar2 / ( 2 * gamma_B ) ) *
133 ( 1 + rbarfbar2 + ( 1 - rbarfbar2 ) / ( 1 + xd * xd ) );
134
135 //flip specifies the relative fraction of fbar events
136
137 fract = IAbarf / ( IAbarf + IAf ) + flip * IAbarfbar / ( IAfbar + IAbarfbar );
138
139 return;
140}
141
142void EvtCPUtil::OtherB( EvtParticle* p, double& t, EvtId& otherb, double probB0 )
143{
145 OtherCoherentB( p, t, otherb, probB0 );
146
147 } else if ( m_mixingType == EvtCPUtil::Incoherent ) {
148 OtherIncoherentB( p, t, otherb, probB0 );
149 }
150}
151
152void EvtCPUtil::OtherCoherentB( EvtParticle* p, double& t, EvtId& otherb,
153 double probB0 )
154{
155 //Can not call this recursively!!!
156 static thread_local int entryCount = 0;
157 entryCount++;
158
159 //added by Lange Jan4,2000
160 static const EvtId B0B = EvtPDL::getId( "anti-B0" );
161 static const EvtId B0 = EvtPDL::getId( "B0" );
162 static const EvtId BSB = EvtPDL::getId( "anti-B_s0" );
163 static const EvtId BS = EvtPDL::getId( "B_s0" );
164
165 static const EvtId UPS4S = EvtPDL::getId( "Upsilon(4S)" );
166
167 int isB0 = EvtRandom::Flat( 0.0, 1.0 ) < probB0;
168
169 int idaug;
170
171 p->setLifetime();
172
173 // now get the time between the decay of this B and the other B!
174
175 EvtParticle* parent = p->getParent();
176
177 EvtParticle* other;
178
179 bool incoherentmix = false;
180
181 if ( ( parent != nullptr ) &&
182 ( parent->getId() == B0 || parent->getId() == B0B ||
183 parent->getId() == BS || parent->getId() == BSB ) ) {
184 incoherentmix = true;
185 }
186
187 if ( incoherentmix )
188 parent = parent->getParent();
189
190 if ( parent == nullptr || parent->getId() != UPS4S ) {
191 //Need to make this more general, but for now
192 //assume no parent. If we have parent of B we
193 //need to charge conj. full decay tree.
194
195 if ( parent != nullptr ) {
196 EvtGenReport( EVTGEN_INFO, "EvtGen" )
197 << "p=" << EvtPDL::name( p->getId() )
198 << " parent=" << EvtPDL::name( parent->getId() ) << endl;
199 }
200 assert( parent == 0 );
201 p->setLifetime();
202 t = p->getLifetime();
203 bool needToChargeConj = false;
204 if ( p->getId() == B0B && isB0 )
205 needToChargeConj = true;
206 if ( p->getId() == B0 && !isB0 )
207 needToChargeConj = true;
208 if ( p->getId() == BSB && isB0 )
209 needToChargeConj = true;
210 if ( p->getId() == BS && !isB0 )
211 needToChargeConj = true;
212
213 if ( needToChargeConj ) {
214 p->setId( EvtPDL::chargeConj( p->getId() ) );
215 if ( incoherentmix ) {
216 p->getDaug( 0 )->setId(
217 EvtPDL::chargeConj( p->getDaug( 0 )->getId() ) );
218 }
219 }
220 otherb = EvtPDL::chargeConj( p->getId() );
221
222 entryCount--;
223 return;
224 } else {
225 if ( parent->getDaug( 0 ) != p ) {
226 other = parent->getDaug( 0 );
227 idaug = 0;
228 } else {
229 other = parent->getDaug( 1 );
230 idaug = 1;
231 }
232 }
233
234 if ( parent != nullptr ) {
235 //if (entryCount>1){
236 // EvtGenReport(EVTGEN_INFO,"EvtGen") << "Double CP decay:"<<entryCount<<endl;
237 //}
238
239 //kludge!! Lange Mar21, 2003
240 // if the other B is an alias... don't change the flavor..
241 if ( other->getId().isAlias() ) {
242 OtherB( p, t, otherb );
243 entryCount--;
244 return;
245 }
246
247 if ( entryCount == 1 ) {
248 EvtVector4R p_init = other->getP4();
249 //int decayed=other->getNDaug()>0;
250 bool decayed = other->isDecayed();
251
252 other->deleteTree();
253
254 EvtScalarParticle* scalar_part;
255
256 scalar_part = new EvtScalarParticle;
257 if ( isB0 ) {
258 scalar_part->init( B0, p_init );
259 } else {
260 scalar_part->init( B0B, p_init );
261 }
262 other = (EvtParticle*)scalar_part;
263 // other->set_type(EvtSpinType::SCALAR);
264 other->setDiagonalSpinDensity();
265
266 parent->insertDaugPtr( idaug, other );
267
268 if ( decayed ) {
269 //EvtGenReport(EVTGEN_INFO,"EvtGen") << "In CP Util calling decay \n";
270 other->decay();
271 }
272 }
273
274 otherb = other->getId();
275
276 other->setLifetime();
277 t = p->getLifetime() - other->getLifetime();
278
279 otherb = other->getId();
280
281 } else {
282 EvtGenReport( EVTGEN_INFO, "EvtGen" )
283 << "We have an error here!!!!" << endl;
284 otherb = EvtId( -1, -1 );
285 }
286
287 entryCount--;
288 return;
289}
290
291// ========================================================================
293{
294 if ( !( p->getParent() ) )
295 return false;
296
297 static const EvtId BS0 = EvtPDL::getId( "B_s0" );
298 static const EvtId BSB = EvtPDL::getId( "anti-B_s0" );
299
300 if ( ( p->getId() != BS0 ) && ( p->getId() != BSB ) )
301 return false;
302
303 if ( ( p->getParent()->getId() == BS0 ) || ( p->getParent()->getId() == BSB ) )
304 return true;
305
306 return false;
307}
308
309// ========================================================================
311{
312 if ( !( p->getParent() ) )
313 return false;
314
315 static const EvtId B0 = EvtPDL::getId( "B0" );
316 static const EvtId B0B = EvtPDL::getId( "anti-B0" );
317
318 if ( ( p->getId() != B0 ) && ( p->getId() != B0B ) )
319 return false;
320
321 if ( ( p->getParent()->getId() == B0 ) || ( p->getParent()->getId() == B0B ) )
322 return true;
323
324 return false;
325}
326//============================================================================
327// Return the tag of the event (ie the anti-flavour of the produced
328// B meson). Flip the flavour of the event with probB probability
329//============================================================================
330void EvtCPUtil::OtherIncoherentB( EvtParticle* p, double& t, EvtId& otherb,
331 double probB )
332{
333 //std::cout<<"New routine running"<<endl;
334 //if(p->getId() == B0 || p->getId() == B0B)
335 //added by liming Zhang
336 enableFlip();
337 if ( ( isB0Mixed( p ) ) || ( isBsMixed( p ) ) ) {
338 p->getParent()->setLifetime();
339 t = p->getParent()->getLifetime();
340 } else {
341 p->setLifetime();
342 t = p->getLifetime();
343 }
344
345 if ( flipIsEnabled() ) {
346 //std::cout << " liming << flipIsEnabled " << std::endl;
347 // Flip the flavour of the particle with probability probB
348 bool isFlipped = ( EvtRandom::Flat( 0., 1. ) < probB );
349
350 if ( isFlipped ) {
351 if ( ( isB0Mixed( p ) ) || ( isBsMixed( p ) ) ) {
352 p->getParent()->setId(
354 p->setId( EvtPDL::chargeConj( p->getId() ) );
355 } else {
356 p->setId( EvtPDL::chargeConj( p->getId() ) );
357 }
358 }
359 }
360
361 if ( ( isB0Mixed( p ) ) || ( isBsMixed( p ) ) ) {
362 // if B has mixed, tag flavour is charge conjugate of parent of B-meson
363 otherb = EvtPDL::chargeConj( p->getParent()->getId() );
364 } else {
365 // else it is opposite flavour than this B hadron
366 otherb = EvtPDL::chargeConj( p->getId() );
367 }
368
369 return;
370}
371//============================================================================
372void EvtCPUtil::OtherB( EvtParticle* p, double& t, EvtId& otherb )
373{
374 static const EvtId BSB = EvtPDL::getId( "anti-B_s0" );
375 static const EvtId BS0 = EvtPDL::getId( "B_s0" );
376 static const EvtId B0B = EvtPDL::getId( "anti-B0" );
377 static const EvtId B0 = EvtPDL::getId( "B0" );
378 static const EvtId D0B = EvtPDL::getId( "anti-D0" );
379 static const EvtId D0 = EvtPDL::getId( "D0" );
380 static const EvtId UPS4 = EvtPDL::getId( "Upsilon(4S)" );
381
382 if ( p->getId() == BS0 || p->getId() == BSB ) {
383 static const double ctauL = EvtPDL::getctau( EvtPDL::getId( "B_s0L" ) );
384 static const double ctauH = EvtPDL::getctau( EvtPDL::getId( "B_s0H" ) );
385 static const double ctau = ctauL < ctauH ? ctauH : ctauL;
386 t = -log( EvtRandom::Flat() ) * ctau;
387 EvtParticle* parent = p->getParent();
388 if ( parent != nullptr &&
389 ( parent->getId() == BS0 || parent->getId() == BSB ) ) {
390 if ( parent->getId() == BS0 )
391 otherb = BSB;
392 if ( parent->getId() == BSB )
393 otherb = BS0;
394 parent->setLifetime( t );
395 return;
396 }
397 if ( p->getId() == BS0 )
398 otherb = BSB;
399 if ( p->getId() == BSB )
400 otherb = BS0;
401 p->setLifetime( t );
402 return;
403 }
404
405 if ( p->getId() == D0 || p->getId() == D0B ) {
406 static const double ctauL = EvtPDL::getctau( EvtPDL::getId( "D0L" ) );
407 static const double ctauH = EvtPDL::getctau( EvtPDL::getId( "D0H" ) );
408 static const double ctau = ctauL < ctauH ? ctauH : ctauL;
409 t = -log( EvtRandom::Flat() ) * ctau;
410 EvtParticle* parent = p->getParent();
411 if ( parent != nullptr &&
412 ( parent->getId() == D0 || parent->getId() == D0B ) ) {
413 if ( parent->getId() == D0 )
414 otherb = D0B;
415 if ( parent->getId() == D0B )
416 otherb = D0;
417 parent->setLifetime( t );
418 return;
419 }
420 if ( p->getId() == D0 )
421 otherb = D0B;
422 if ( p->getId() == D0B )
423 otherb = D0;
424 p->setLifetime( t );
425 return;
426 }
427
428 p->setLifetime();
429
430 // now get the time between the decay of this B and the other B!
431
432 EvtParticle* parent = p->getParent();
433
434 if ( parent == nullptr || parent->getId() != UPS4 ) {
435 //EvtGenReport(EVTGEN_ERROR,"EvtGen") <<
436 // "Warning CP violation with B having no parent!"<<endl;
437 t = p->getLifetime();
438 if ( p->getId() == B0 )
439 otherb = B0B;
440 if ( p->getId() == B0B )
441 otherb = B0;
442 if ( p->getId() == BS0 )
443 otherb = BSB;
444 if ( p->getId() == BSB )
445 otherb = BS0;
446 return;
447 } else {
448 if ( parent->getDaug( 0 ) != p ) {
449 otherb = parent->getDaug( 0 )->getId();
450 parent->getDaug( 0 )->setLifetime();
451 t = p->getLifetime() - parent->getDaug( 0 )->getLifetime();
452 } else {
453 otherb = parent->getDaug( 1 )->getId();
454 parent->getDaug( 1 )->setLifetime();
455 t = p->getLifetime() - parent->getDaug( 1 )->getLifetime();
456 }
457 }
458
459 return;
460}
461
462// No CP violation is assumed
463void EvtCPUtil::incoherentMix( const EvtId id, double& t, int& mix )
464{
465 int stdHepNum = EvtPDL::getStdHep( id );
466 stdHepNum = abs( stdHepNum );
467
468 EvtId partId = EvtPDL::evtIdFromStdHep( stdHepNum );
469
470 std::string partName = EvtPDL::name( partId );
471 std::string hname = partName + std::string( "H" );
472 std::string lname = partName + std::string( "L" );
473
474 EvtId lId = EvtPDL::getId( lname );
475 EvtId hId = EvtPDL::getId( hname );
476
477 const double ctauL = EvtPDL::getctau( lId );
478 const double ctauH = EvtPDL::getctau( hId );
479
480 // Bug Fixed: Corrected the average as gamma is the relevent parameter
481 const double ctau = 2.0 * ( ctauL * ctauH ) / ( ctauL + ctauH );
482 //double ctau=0.5*(ctauL+ctauH);
483
484 // Bug Fixed: ctau definition changed above
485 //double y=(ctauH-ctauL)/(2*ctau);
486 const double y = ( ctauH - ctauL ) / ( ctauH + ctauL );
487
488 //deltam and qoverp defined in DECAY.DEC
489
490 std::string qoverpParmName = std::string( "qoverp_incohMix_" ) + partName;
491 std::string mdParmName = std::string( "dm_incohMix_" ) + partName;
492 int ierr;
493 double qoverp = atof( EvtSymTable::get( qoverpParmName, ierr ).c_str() );
494 double x = atof( EvtSymTable::get( mdParmName, ierr ).c_str() ) * ctau /
496 double fac;
497
498 if ( id == partId ) {
499 fac = 1.0 / ( qoverp * qoverp );
500 } else {
501 fac = qoverp * qoverp;
502 }
503
504 double mixprob = ( x * x + y * y ) /
505 ( x * x + y * y + fac * ( 2.0 + x * x - y * y ) );
506
507 int mixsign;
508
509 mixsign = ( mixprob > EvtRandom::Flat( 0.0, 1.0 ) ) ? -1 : 1;
510
511 double prob;
512
513 // Find the longest of the two lifetimes
514 const double ctaulong = ctauL <= ctauH ? ctauH : ctauL;
515
516 // Bug fixed: Ensure cosine argument is dimensionless so /ctau
517 do {
518 t = -log( EvtRandom::Flat() ) * ctaulong;
519 prob = 1.0 + exp( -2.0 * fabs( y ) * t / ctau ) +
520 mixsign * 2.0 * exp( -fabs( y ) * t / ctau ) * cos( x * t / ctau );
521 } while ( prob < 4.0 * EvtRandom::Flat() );
522
523 mix = 0;
524
525 if ( mixsign == -1 )
526 mix = 1;
527
528 return;
529}
530
532{
533 int stdHepNum = EvtPDL::getStdHep( id );
534 stdHepNum = abs( stdHepNum );
535 EvtId partId = EvtPDL::evtIdFromStdHep( stdHepNum );
536
537 std::string partName = EvtPDL::name( partId );
538 std::string hname = partName + std::string( "H" );
539 std::string lname = partName + std::string( "L" );
540
541 EvtId lId = EvtPDL::getId( lname );
542 EvtId hId = EvtPDL::getId( hname );
543
544 double ctauL = EvtPDL::getctau( lId );
545 double ctauH = EvtPDL::getctau( hId );
546
547 double dGamma = ( 1 / ctauL - 1 / ctauH ) * EvtConst::c;
548 return dGamma;
549}
550
551double EvtCPUtil::getDeltaM( const EvtId id )
552{
553 int stdHepNum = EvtPDL::getStdHep( id );
554 stdHepNum = abs( stdHepNum );
555 EvtId partId = EvtPDL::evtIdFromStdHep( stdHepNum );
556
557 std::string partName = EvtPDL::name( partId );
558 std::string parmName = std::string( "dm_incohMix_" ) + partName;
559
560 int ierr;
561 double dM = atof( EvtSymTable::get( parmName, ierr ).c_str() );
562 return dM;
563}
564
566{
567 return m_enableFlip;
568}
570{
571 m_enableFlip = true;
572}
574{
575 m_enableFlip = false;
576}
double imag(const EvtComplex &c)
double real(const EvtComplex &c)
EvtComplex exp(const EvtComplex &c)
double abs(const EvtComplex &c)
std::ostream & EvtGenReport(EvtGenSeverity severity, const char *facility=nullptr)
Definition EvtReport.cpp:32
@ EVTGEN_INFO
Definition EvtReport.hh:52
bool isBsMixed(EvtParticle *)
int m_mixingType
Definition EvtCPUtil.hh:80
void OtherIncoherentB(EvtParticle *p, double &t, EvtId &otherb, double probB0)
static EvtCPUtil * getInstance()
Definition EvtCPUtil.cpp:42
void OtherCoherentB(EvtParticle *p, double &t, EvtId &otherb, double probB0)
bool flipIsEnabled()
void disableFlip()
void fractB0nonCP(EvtComplex Af, EvtComplex Abarf, EvtComplex Afbar, EvtComplex Abarfbar, double deltam, double beta, int flip, double &fract)
Definition EvtCPUtil.cpp:84
double getDeltaM(const EvtId id)
bool isB0Mixed(EvtParticle *)
EvtCPUtil(int mixingType)
Definition EvtCPUtil.cpp:36
bool m_enableFlip
Definition EvtCPUtil.hh:79
void enableFlip()
void fractB0CP(EvtComplex Af, EvtComplex Abarf, double deltam, double beta, double &fract)
Definition EvtCPUtil.cpp:56
void incoherentMix(const EvtId id, double &t, int &mix)
double getDeltaGamma(const EvtId id)
void OtherB(EvtParticle *p, double &t, EvtId &otherb)
static const double c
Definition EvtConst.hh:30
Definition EvtId.hh:27
static int getStdHep(EvtId id)
Definition EvtPDL.cpp:356
static EvtId evtIdFromStdHep(int stdhep)
Definition EvtPDL.cpp:241
static std::string name(EvtId i)
Definition EvtPDL.cpp:376
static EvtId chargeConj(EvtId id)
Definition EvtPDL.cpp:201
static double getctau(EvtId i)
Definition EvtPDL.cpp:351
static EvtId getId(const std::string &name)
Definition EvtPDL.cpp:283
void insertDaugPtr(int idaug, EvtParticle *partptr)
EvtId getId() const
void setLifetime(double tau)
EvtParticle * getDaug(const int i)
double getLifetime() const
void setId(EvtId id)
EvtParticle * getParent() const
static double Flat()
Definition EvtRandom.cpp:95
void init(EvtId part_n, double e, double px, double py, double pz)
static std::string get(const std::string &name, int &ierr)