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
EvtDecayBase.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
23#include "EvtGenBase/EvtPDL.hh"
28
29#include <ctype.h>
30#include <fstream>
31#include <iostream>
32#include <stdlib.h>
33#include <vector>
34using std::endl;
35using std::fstream;
37{
38 int i;
39 int q = 0;
40 int qpar;
41
42 //If there are no daughters (jetset etc) then we do not
43 //want to do this test. Why? Because sometimes the parent
44 //will have a nonzero charge.
45
46 if ( m_ndaug != 0 ) {
47 for ( i = 0; i < m_ndaug; i++ ) {
48 q += EvtPDL::chg3( m_daug[i] );
49 }
50 qpar = EvtPDL::chg3( m_parent );
51
52 if ( q != qpar ) {
53 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
54 << m_modelname.c_str() << " generator expected "
55 << " charge to be conserved, found:" << endl;
56 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
57 << "Parent charge of " << ( qpar / 3 ) << endl;
58 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
59 << "Sum of daughter charge of " << ( q / 3 ) << endl;
60 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
61 << "The parent is " << EvtPDL::name( m_parent ).c_str() << endl;
62 for ( i = 0; i < m_ndaug; i++ ) {
63 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
64 << "Daughter " << EvtPDL::name( m_daug[i] ).c_str() << endl;
65 }
66 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
67 << "Will terminate execution!" << endl;
68
69 ::abort();
70 }
71 }
72}
73
74double EvtDecayBase::getProbMax( double prob )
75{
76 int i;
77
78 //diagnostics
79 m_sum_prob += prob;
80 if ( prob > m_max_prob )
81 m_max_prob = prob;
82
83 if ( m_defaultprobmax && m_ntimes_prob <= 500 ) {
84 //We are building up m_probmax with this iteration
85 m_ntimes_prob += 1;
86 if ( prob > m_probmax ) {
87 m_probmax = prob;
88 }
89 if ( m_ntimes_prob == 500 ) {
90 m_probmax *= 1.2;
91 }
92 return 1000000.0 * prob;
93 }
94
95 if ( prob > m_probmax * 1.0001 ) {
96 EvtGenReport( EVTGEN_INFO, "EvtGen" )
97 << "prob > probmax:(" << prob << ">" << m_probmax << ")";
98 EvtGenReport( EVTGEN_INFO, "" ) << "(" << m_modelname.c_str() << ") ";
100 << EvtPDL::name( m_parent ).c_str() << " -> ";
101 for ( i = 0; i < m_ndaug; i++ ) {
103 << EvtPDL::name( m_daug[i] ).c_str() << " ";
104 }
105 EvtGenReport( EVTGEN_INFO, "" ) << endl;
106
107 if ( m_defaultprobmax )
108 m_probmax = prob;
109 }
110
111 m_ntimes_prob += 1;
112
113 return m_probmax;
114
115} //getProbMax
116
117double EvtDecayBase::resetProbMax( double prob )
118{
119 EvtGenReport( EVTGEN_INFO, "EvtGen" ) << "Reseting prob max\n";
120 EvtGenReport( EVTGEN_INFO, "EvtGen" )
121 << "prob > probmax:(" << prob << ">" << m_probmax << ")";
122 EvtGenReport( EVTGEN_INFO, "" ) << "(" << m_modelname.c_str() << ")";
124
125 for ( int i = 0; i < m_ndaug; i++ ) {
126 EvtGenReport( EVTGEN_INFO, "" ) << EvtPDL::getStdHep( m_daug[i] ) << " ";
127 }
128 EvtGenReport( EVTGEN_INFO, "" ) << endl;
129
130 m_probmax = 0.0;
131 m_defaultprobmax = false;
132 m_ntimes_prob = 0;
133
134 return prob;
135}
136
138{
139 return std::string( "" );
140}
141
142void EvtDecayBase::command( std::string )
143{
144 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
145 << "Should never call EvtDecayBase::command" << endl;
146 ::abort();
147}
148
149std::string EvtDecayBase::getParamName( int i )
150{
151 switch ( i ) {
152 case 0:
153 return "param00";
154 case 1:
155 return "param01";
156 case 2:
157 return "param02";
158 case 3:
159 return "param03";
160 case 4:
161 return "param04";
162 case 5:
163 return "param05";
164 case 6:
165 return "param06";
166 case 7:
167 return "param07";
168 case 8:
169 return "param08";
170 case 9:
171 return "param09";
172 default:
173 return "";
174 }
175}
176
177std::string EvtDecayBase::getParamDefault( int /*i*/ )
178{
179 return "";
180}
181
183{
184 //This default version of init does nothing;
185 //A specialized version of this function can be
186 //supplied for each decay model to do initialization.
187
188 return;
189}
190
192{
193 //This function is called if the decay does not have a
194 //specialized initialization.
195 //The default is to set the maximum
196 //probability to 0 and the number of times called to 0
197 //and m_defaultprobmax to 'true' such that the decay will be
198 //generated many many times
199 //in order to generate a reasonable maximum probability
200 //for the decay.
201
202 m_defaultprobmax = true;
203 m_ntimes_prob = 0;
204 m_probmax = 0.0;
205
206} //initProbMax
207
208void EvtDecayBase::saveDecayInfo( EvtId ipar, int ndaug, const EvtId* daug,
209 int narg, std::vector<std::string>& args,
210 std::string name, double brfr )
211{
212 int i;
213
214 m_brfr = brfr;
215 m_ndaug = ndaug;
216 m_narg = narg;
217 m_parent = ipar;
218
219 m_dsum = 0;
220
221 if ( m_ndaug > 0 ) {
222 m_daug.resize( m_ndaug );
223 for ( i = 0; i < m_ndaug; i++ ) {
224 m_daug[i] = daug[i];
225 m_dsum += daug[i].getAlias();
226 }
227 } else {
228 m_daug.clear();
229 }
230
231 if ( m_narg > 0 ) {
232 m_args.resize( m_narg + 1 );
233 for ( i = 0; i < m_narg; i++ ) {
234 m_args[i] = args[i];
235 }
236 } else {
237 m_args.clear();
238 }
239
240 m_modelname = name;
241
242 this->init();
243 this->initProbMax();
244
245 if ( m_chkCharge ) {
246 this->checkQ();
247 }
248
249 if ( m_defaultprobmax ) {
250 EvtGenReport( EVTGEN_INFO, "EvtGen" ) << "No default probmax for ";
251 EvtGenReport( EVTGEN_INFO, "" ) << "(" << m_modelname.c_str() << ") ";
253 << EvtPDL::name( m_parent ).c_str() << " -> ";
254 for ( i = 0; i < m_ndaug; i++ ) {
256 << EvtPDL::name( m_daug[i] ).c_str() << " ";
257 }
258 EvtGenReport( EVTGEN_INFO, "" ) << endl;
260 << "This is fine for development, but must be provided for production."
261 << endl;
262 EvtGenReport( EVTGEN_INFO, "EvtGen" )
263 << "Never fear though - the decay will use the \n";
264 EvtGenReport( EVTGEN_INFO, "EvtGen" )
265 << "500 iterations to build up a good probmax \n";
266 EvtGenReport( EVTGEN_INFO, "EvtGen" )
267 << "before accepting a decay. " << endl;
268 }
269}
270
272{
273 if ( m_ntimes_prob > 0 ) {
274 EvtGenReport( EVTGEN_INFO, "EvtGen" )
275 << "Calls = " << m_ntimes_prob
276 << " eff: " << m_sum_prob / ( m_probmax * m_ntimes_prob )
277 << " frac. max:" << m_max_prob / m_probmax;
279 << " probmax:" << m_probmax << " max:" << m_max_prob << " : ";
280 }
281
282 printInfo();
283}
284
286{
287 EvtGenReport( EVTGEN_INFO, "" ) << EvtPDL::name( m_parent ).c_str() << " -> ";
288 for ( int i = 0; i < m_ndaug; i++ ) {
290 << EvtPDL::name( m_daug[i] ).c_str() << " ";
291 }
292 EvtGenReport( EVTGEN_INFO, "" ) << " (" << m_modelname.c_str() << ")" << endl;
293}
294
295void EvtDecayBase::setProbMax( double prbmx )
296{
297 m_defaultprobmax = false;
298 m_probmax = prbmx;
299}
300
302{
303 m_defaultprobmax = false;
304}
305
307{
308 double maxOkMass = EvtPDL::getMaxMass( p->getId() );
309
310 //protect against vphotons
311 if ( maxOkMass < 0.0000000001 )
312 return 10000000.;
313 //and against already determined masses
314 if ( p->hasValidP4() )
315 maxOkMass = p->mass();
316
317 EvtParticle* par = p->getParent();
318 if ( par ) {
319 double maxParMass = findMaxMass( par );
320 size_t i;
321 double minDaugMass = 0.;
322 for ( i = 0; i < par->getNDaug(); i++ ) {
323 EvtParticle* dau = par->getDaug( i );
324 if ( dau != p ) {
325 // it might already have a mass
326 if ( dau->isInitialized() || dau->hasValidP4() )
327 minDaugMass += dau->mass();
328 else
329 //give it a bit of phase space
330 minDaugMass += 1.000001 * EvtPDL::getMinMass( dau->getId() );
331 }
332 }
333 if ( maxOkMass > ( maxParMass - minDaugMass ) )
334 maxOkMass = maxParMass - minDaugMass;
335 }
336 return maxOkMass;
337}
338
339// given list of daughters ( by number ) returns a
340// list of viable masses.
341
343{
344 //Need to also check that this mass does not screw
345 //up the parent
346 //This code assumes that for the ith daughter, 0..i-1
347 //already have a mass
348 double maxOkMass = findMaxMass( p );
349
350 int count = 0;
351 double mass;
352 bool massOk = false;
353 size_t i;
354 while ( !massOk ) {
355 count++;
356 if ( count > 10000 ) {
357 EvtGenReport( EVTGEN_INFO, "EvtGen" )
358 << "Can not find a valid mass for: "
359 << EvtPDL::name( p->getId() ).c_str() << endl;
360 EvtGenReport( EVTGEN_INFO, "EvtGen" )
361 << "Now printing parent and/or grandparent tree\n";
362 if ( p->getParent() ) {
363 if ( p->getParent()->getParent() ) {
364 p->getParent()->getParent()->printTree();
365 EvtGenReport( EVTGEN_INFO, "EvtGen" )
366 << p->getParent()->getParent()->mass() << endl;
367 EvtGenReport( EVTGEN_INFO, "EvtGen" )
368 << p->getParent()->mass() << endl;
369 } else {
370 p->getParent()->printTree();
371 EvtGenReport( EVTGEN_INFO, "EvtGen" )
372 << p->getParent()->mass() << endl;
373 }
374 } else
375 p->printTree();
376 EvtGenReport( EVTGEN_INFO, "EvtGen" )
377 << "maxokmass=" << maxOkMass << " "
378 << EvtPDL::getMinMass( p->getId() ) << " "
379 << EvtPDL::getMaxMass( p->getId() ) << endl;
380 if ( p->getNDaug() ) {
381 for ( i = 0; i < p->getNDaug(); i++ ) {
382 EvtGenReport( EVTGEN_INFO, "EvtGen" )
383 << p->getDaug( i )->mass() << " ";
384 }
385 EvtGenReport( EVTGEN_INFO, "EvtGen" ) << endl;
386 }
387 if ( maxOkMass >= EvtPDL::getMinMass( p->getId() ) ) {
388 EvtGenReport( EVTGEN_INFO, "EvtGen" )
389 << "taking a default value\n";
390 p->setMass( maxOkMass );
391 return;
392 }
393 assert( 0 );
394 }
395 mass = EvtPDL::getMass( p->getId() );
396 //Just need to check that this mass is > than
397 //the mass of all daughters
398 double massSum = 0.;
399 if ( p->getNDaug() ) {
400 for ( i = 0; i < p->getNDaug(); i++ ) {
401 massSum += p->getDaug( i )->mass();
402 }
403 }
404 //some special cases are handled with 0 (stable) or 1 (k0->ks/kl) daughters
405 if ( p->getNDaug() < 2 )
406 massOk = true;
407 if ( p->getParent() ) {
408 if ( p->getParent()->getNDaug() == 1 )
409 massOk = true;
410 }
411 if ( !massOk ) {
412 if ( massSum < mass )
413 massOk = true;
414 if ( mass > maxOkMass )
415 massOk = false;
416 }
417 }
418
419 p->setMass( mass );
420}
421
423 const EvtId daugs[10], double masses[10] )
424{
425 int i;
426 double mass_sum;
427
428 int count = 0;
429
430 if ( !( p->firstornot() ) ) {
431 for ( i = 0; i < ndaugs; i++ ) {
432 masses[i] = p->getDaug( i )->mass();
433 } //for
434 } //if
435 else {
436 p->setFirstOrNot();
437 // if only one daughter do it
438
439 if ( ndaugs == 1 ) {
440 masses[0] = p->mass();
441 return;
442 }
443
444 //until we get a combo whose masses are less than the parent mass.
445 do {
446 mass_sum = 0.0;
447
448 for ( i = 0; i < ndaugs; i++ ) {
449 masses[i] = EvtPDL::getMass( daugs[i] );
450 mass_sum = mass_sum + masses[i];
451 }
452
453 count++;
454
455 if ( count == 10000 ) {
456 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
457 << "Decaying particle:" << EvtPDL::name( p->getId() ).c_str()
458 << " (m=" << p->mass() << ")" << endl;
459 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
460 << "To the following daugthers" << endl;
461 for ( i = 0; i < ndaugs; i++ ) {
462 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
463 << EvtPDL::name( daugs[i] ).c_str() << endl;
464 }
465 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
466 << "Has been rejected " << count
467 << " times, will now take minimal masses "
468 << " of daugthers" << endl;
469
470 mass_sum = 0.;
471 for ( i = 0; i < ndaugs; i++ ) {
472 masses[i] = EvtPDL::getMinMass( daugs[i] );
473 mass_sum = mass_sum + masses[i];
474 }
475 if ( mass_sum > p->mass() ) {
476 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
477 << "Parent mass=" << p->mass()
478 << "to light for daugthers." << endl
479 << "Will throw the event away." << endl;
480 //dont terminate - start over on the event.
482 mass_sum = 0.;
483 // ::abort();
484 }
485 }
486 } while ( mass_sum > p->mass() );
487 } //else
488
489 return;
490}
491
492void EvtDecayBase::checkNArg( int a1, int a2, int a3, int a4 )
493{
494 if ( m_narg != a1 && m_narg != a2 && m_narg != a3 && m_narg != a4 ) {
495 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
496 << m_modelname.c_str() << " generator expected " << endl;
497 EvtGenReport( EVTGEN_ERROR, "EvtGen" ) << a1 << endl;
498 ;
499 if ( a2 > -1 ) {
500 EvtGenReport( EVTGEN_ERROR, "EvtGen" ) << " or " << a2 << endl;
501 }
502 if ( a3 > -1 ) {
503 EvtGenReport( EVTGEN_ERROR, "EvtGen" ) << " or " << a3 << endl;
504 }
505 if ( a4 > -1 ) {
506 EvtGenReport( EVTGEN_ERROR, "EvtGen" ) << " or " << a4 << endl;
507 }
508 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
509 << " arguments but found:" << m_narg << endl;
510 printSummary();
511 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
512 << "Will terminate execution!" << endl;
513 ::abort();
514 }
515}
516void EvtDecayBase::checkNDaug( int d1, int d2 )
517{
518 if ( m_ndaug != d1 && m_ndaug != d2 ) {
519 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
520 << m_modelname.c_str() << " generator expected ";
521 EvtGenReport( EVTGEN_ERROR, "EvtGen" ) << d1;
522 if ( d2 > -1 ) {
523 EvtGenReport( EVTGEN_ERROR, "EvtGen" ) << " or " << d2;
524 }
525 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
526 << " daughters but found:" << m_ndaug << endl;
527 printSummary();
528 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
529 << "Will terminate execution!" << endl;
530 ::abort();
531 }
532}
533
535{
537 if ( parenttype != sp ) {
538 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
539 << m_modelname.c_str() << " did not get the correct parent spin\n";
540 printSummary();
541 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
542 << "Will terminate execution!" << endl;
543 ::abort();
544 }
545}
546
548{
550 if ( parenttype != sp ) {
551 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
552 << m_modelname.c_str()
553 << " did not get the correct daughter spin d=" << d1 << endl;
554 printSummary();
555 EvtGenReport( EVTGEN_ERROR, "EvtGen" )
556 << "Will terminate execution!" << endl;
557 ::abort();
558 }
559}
560
562{
563 if ( !m_argsD.empty() )
564 return m_argsD.data();
565 //The user has asked for a list of doubles - the arguments
566 //better all be doubles...
567 if ( m_narg == 0 )
568 return m_argsD.data();
569
570 m_argsD.resize( m_narg );
571 for ( int i = 0; i < m_narg; i++ ) {
572 char* tc;
573 m_argsD[i] = strtod( m_args[i].c_str(), &tc );
574 }
575 return m_argsD.data();
576}
577
578double EvtDecayBase::getArg( unsigned int j )
579{
580 // Verify string
581 const char* str = m_args[j].c_str();
582 int i = 0;
583 while ( str[i] != 0 ) {
584 if ( isalpha( str[i] ) && str[i] != 'e' ) {
585 EvtGenReport( EVTGEN_INFO, "EvtGen" )
586 << "String " << str << " is not a number" << endl;
587 assert( 0 );
588 }
589 i++;
590 }
591
592 char** tc = nullptr;
593 double result = strtod( m_args[j].c_str(), tc );
594
595 if ( m_storedArgs.size() < j + 1 ) { // then store the argument's value
596 m_storedArgs.push_back( result );
597 }
598
599 return result;
600}
601
603{
604 if ( m_ndaug != other.m_ndaug )
605 return false;
606 if ( m_parent != other.m_parent )
607 return false;
608
609 std::vector<int> useDs;
610 for ( int i = 0; i < m_ndaug; i++ )
611 useDs.push_back( 0 );
612
613 for ( int i = 0; i < m_ndaug; i++ ) {
614 bool foundIt = false;
615 for ( int j = 0; j < m_ndaug; j++ ) {
616 if ( useDs[j] == 1 )
617 continue;
618 if ( m_daug[i] == other.m_daug[j] &&
619 m_daug[i].getAlias() == other.m_daug[j].getAlias() ) {
620 foundIt = true;
621 useDs[j] = 1;
622 break;
623 }
624 }
625 if ( foundIt == false )
626 return false;
627 }
628 for ( int i = 0; i < m_ndaug; i++ )
629 if ( useDs[i] == 0 )
630 return false;
631
632 return true;
633}
const double a4
const double a3
const double a2
const double a1
std::ostream & EvtGenReport(EvtGenSeverity severity, const char *facility=nullptr)
Definition EvtReport.cpp:32
@ EVTGEN_INFO
Definition EvtReport.hh:52
@ EVTGEN_ERROR
Definition EvtReport.hh:49
void checkSpinDaughter(int d1, EvtSpinType::spintype sp)
EvtDecayBase()=default
void checkSpinParent(EvtSpinType::spintype sp)
double getArg(unsigned int j)
void printInfo() const
void saveDecayInfo(EvtId ipar, int ndaug, const EvtId *daug, int narg, std::vector< std::string > &args, std::string name, double brfr)
double resetProbMax(double prob)
void setProbMax(double prbmx)
static void findMasses(EvtParticle *p, int ndaugs, const EvtId daugs[10], double masses[10])
virtual std::string getParamName(int i)
virtual void init()
static void findMass(EvtParticle *p)
virtual bool matchingDecay(const EvtDecayBase &other) const
EvtId getParentId() const
static double findMaxMass(EvtParticle *p)
EvtId getDaug(int i) const
virtual void command(std::string cmd)
double * getArgs()
double getProbMax(double prob)
virtual std::string getParamDefault(int i)
void checkNDaug(int d1, int d2=-1)
std::vector< EvtId > m_daug
std::string m_modelname
std::vector< double > m_storedArgs
void checkNArg(int a1, int a2=-1, int a3=-1, int a4=-1)
virtual void initProbMax()
std::vector< std::string > m_args
virtual std::string commandName()
std::vector< double > m_argsD
void printSummary() const
Definition EvtId.hh:27
int getAlias() const
Definition EvtId.hh:43
static EvtSpinType::spintype getSpinType(EvtId i)
Definition EvtPDL.cpp:371
static int getStdHep(EvtId id)
Definition EvtPDL.cpp:356
static int chg3(EvtId i)
Definition EvtPDL.cpp:366
static double getMaxMass(EvtId i)
Definition EvtPDL.cpp:331
static double getMass(EvtId i)
Definition EvtPDL.cpp:311
static std::string name(EvtId i)
Definition EvtPDL.cpp:376
static double getMinMass(EvtId i)
Definition EvtPDL.cpp:336
void setMass(double m)
EvtId getId() const
bool hasValidP4()
void printTree() const
EvtParticle * getDaug(const int i)
bool isInitialized()
double mass() const
size_t getNDaug() const
int firstornot() const
EvtParticle * getParent() const
void setFirstOrNot()
static void setRejectFlag()
Definition EvtStatus.hh:26