1 // ParticleData.cc is a part of the PYTHIA event generator.
2 // Copyright (C) 2012 Torbjorn Sjostrand.
3 // PYTHIA is licenced under the GNU GPL version 2, see COPYING for details.
4 // Please respect the MCnet Guidelines, see GUIDELINES for details.
6 // Function definitions (not found in the header) for the
7 // DecayChannel, ParticleDataEntry and ParticleData classes.
9 #include "ParticleData.h"
10 #include "StandardModel.h"
11 #include "SusyResonanceWidths.h"
13 // Allow string and character manipulation.
18 //==========================================================================
20 // DecayChannel class.
21 // This class holds info on a single decay channel.
23 //--------------------------------------------------------------------------
25 // Check whether id1 occurs anywhere in product list.
27 bool DecayChannel::contains(int id1) const {
30 for (int i = 0; i < nProd; ++i) if (prod[i] == id1) found1 = true;
35 //--------------------------------------------------------------------------
37 // Check whether id1 and id2 occur anywhere in product list.
38 // iF ID1 == ID2 then two copies of this particle must be present.
40 bool DecayChannel::contains(int id1, int id2) const {
44 for (int i = 0; i < nProd; ++i) {
45 if (!found1 && prod[i] == id1) {found1 = true; continue;}
46 if (!found2 && prod[i] == id2) {found2 = true; continue;}
48 return found1 && found2;
52 //--------------------------------------------------------------------------
54 // Check whether id1, id2 and id3 occur anywhere in product list.
55 // iF ID1 == ID2 then two copies of this particle must be present, etc.
57 bool DecayChannel::contains(int id1, int id2, int id3) const {
62 for (int i = 0; i < nProd; ++i) {
63 if (!found1 && prod[i] == id1) {found1 = true; continue;}
64 if (!found2 && prod[i] == id2) {found2 = true; continue;}
65 if (!found3 && prod[i] == id3) {found3 = true; continue;}
67 return found1 && found2 && found3;
71 //==========================================================================
73 // ParticleDataEntry class.
74 // This class holds info on a single particle species.
76 //--------------------------------------------------------------------------
78 // Constants: could be changed here if desired, but normally should not.
79 // These are of technical nature, as described for each.
81 // A particle is invisible if it has neither strong nor electric charge,
82 // and is not made up of constituents that have it. Only relevant for
83 // long-lived particles. This list may need to be extended.
84 const int ParticleDataEntry::INVISIBLENUMBER = 50;
85 const int ParticleDataEntry::INVISIBLETABLE[50] = { 12, 14, 16, 18, 23, 25,
86 32, 33, 35, 36, 39, 41, 1000012, 1000014, 1000016, 1000018, 1000022,
87 1000023, 1000025, 1000035, 1000045, 1000039, 2000012, 2000014, 2000016,
88 2000018, 4900012, 4900014, 4900016, 4900021, 4900022, 4900101, 4900102,
89 4900103, 4900104, 4900105, 4900106, 4900107, 4900108, 4900111, 4900113,
90 4900211, 4900213, 4900991, 5000039, 5100039, 9900012, 9900014, 9900016,
93 // For some particles we know it is necessary to switch off width,
94 // although they do have one, so do not warn.
95 const int ParticleDataEntry::KNOWNNOWIDTH[3] = {10313, 10323, 10333};
97 // Particles with a read-in tau0 (in mm/c) below this mayDecay by default.
98 const double ParticleDataEntry::MAXTAU0FORDECAY = 1000.;
100 // Particles with a read-in m0 above this isResonance by default.
101 const double ParticleDataEntry::MINMASSRESONANCE = 20.;
103 // Narrow states are assigned nominal mass.
104 const double ParticleDataEntry::NARROWMASS = 1e-6;
106 // Constituent quark masses (d, u, s, c, b, -, -, -, g).
107 const double ParticleDataEntry::CONSTITUENTMASSTABLE[10]
108 = {0., 0.325, 0.325, 0.50, 1.60, 5.00, 0., 0., 0., 0.7};
110 //--------------------------------------------------------------------------
112 // Destructor: delete any ResonanceWidths object.
114 ParticleDataEntry::~ParticleDataEntry() {
115 if (resonancePtr != 0) delete resonancePtr;
118 //--------------------------------------------------------------------------
120 // Set initial default values for some quantities.
122 void ParticleDataEntry::setDefaults() {
124 // A particle is a resonance if it is heavy enough.
125 isResonanceSave = (m0Save > MINMASSRESONANCE);
127 // A particle may decay if it is shortlived enough.
128 mayDecaySave = (tau0Save < MAXTAU0FORDECAY);
130 // A particle by default has no external decays.
131 doExternalDecaySave = false;
133 // A particle is invisible if in current table of such.
134 isVisibleSave = true;
135 for (int i = 0; i < INVISIBLENUMBER; ++i)
136 if (idSave == INVISIBLETABLE[i]) isVisibleSave = false;
138 // Normally a resonance should not have width forced to fixed value.
139 doForceWidthSave = false;
141 // Set up constituent masses.
142 setConstituentMass();
144 // No Breit-Wigner mass selection before initialized.
149 //--------------------------------------------------------------------------
151 // Find out if a particle is a hadron.
152 // Only covers normal hadrons, not e.g. R-hadrons.
154 bool ParticleDataEntry::isHadron() const {
156 if (idSave <= 100 || (idSave >= 1000000 && idSave <= 9000000)
157 || idSave >= 9900000) return false;
158 if (idSave == 130 || idSave == 310) return true;
159 if (idSave%10 == 0 || (idSave/10)%10 == 0 || (idSave/100)%10 == 0)
165 //--------------------------------------------------------------------------
167 // Find out if a particle is a meson.
168 // Only covers normal hadrons, not e.g. R-hadrons.
170 bool ParticleDataEntry::isMeson() const {
172 if (idSave <= 100 || (idSave >= 1000000 && idSave <= 9000000)
173 || idSave >= 9900000) return false;
174 if (idSave == 130 || idSave == 310) return true;
175 if (idSave%10 == 0 || (idSave/10)%10 == 0 || (idSave/100)%10 == 0
176 || (idSave/1000)%10 != 0) return false;
181 //--------------------------------------------------------------------------
183 // Find out if a particle is a baryon.
184 // Only covers normal hadrons, not e.g. R-hadrons.
186 bool ParticleDataEntry::isBaryon() const {
188 if (idSave <= 1000 || (idSave >= 1000000 && idSave <= 9000000)
189 || idSave >= 9900000) return false;
190 if (idSave%10 == 0 || (idSave/10)%10 == 0 || (idSave/100)%10 == 0
191 || (idSave/1000)%10 == 0) return false;
197 //--------------------------------------------------------------------------
199 // Extract the heaviest (= largest id) quark in a hadron.
201 int ParticleDataEntry::heaviestQuark(int idIn) const {
203 if (!isHadron()) return 0;
207 if ( (idSave/1000)%10 == 0 ) {
208 hQ = (idSave/100)%10;
209 if (idSave == 130) hQ = 3;
210 if (hQ%2 == 1) hQ = -hQ;
213 } else hQ = (idSave/1000)%10;
216 return (idIn > 0) ? hQ : -hQ;
220 //--------------------------------------------------------------------------
222 // Calculate three times baryon number, i.e. net quark - antiquark number.
224 int ParticleDataEntry::baryonNumberType(int idIn) const {
227 if (isQuark()) return (idIn > 0) ? 1 : -1;
230 if (isDiquark()) return (idIn > 0) ? 2 : -2;
233 if (isBaryon()) return (idIn > 0) ? 3 : -3;
240 //--------------------------------------------------------------------------
242 // Prepare the Breit-Wigner mass selection by precalculating
243 // frequently-used expressions.
245 void ParticleDataEntry::initBWmass() {
247 // Find Breit-Wigner mode for current particle.
248 modeBWnow = particleDataPtr->modeBreitWigner;
249 if ( mWidthSave < NARROWMASS || (mMaxSave > mMinSave
250 && mMaxSave - mMinSave < NARROWMASS) ) modeBWnow = 0;
251 if (modeBWnow == 0) return;
253 // Find atan expressions to be used in random mass selection.
255 atanLow = atan( 2. * (mMinSave - m0Save) / mWidthSave );
256 double atanHigh = (mMaxSave > mMinSave)
257 ? atan( 2. * (mMaxSave - m0Save) / mWidthSave ) : 0.5 * M_PI;
258 atanDif = atanHigh - atanLow;
260 atanLow = atan( (pow2(mMinSave) - pow2(m0Save))
261 / (m0Save * mWidthSave) );
262 double atanHigh = (mMaxSave > mMinSave)
263 ? atan( (pow2(mMaxSave) - pow2(m0Save)) / (m0Save * mWidthSave) )
265 atanDif = atanHigh - atanLow;
268 // Done if no threshold factor.
269 if (modeBWnow%2 == 1) return;
271 // Find average mass threshold for threshold-factor correction.
274 for (int i = 0; i < int(channels.size()); ++i)
275 if (channels[i].onMode() >= 0) {
276 bRatSum += channels[i].bRatio();
277 double mChannelSum = 0.;
278 for (int j = 0; j < channels[i].multiplicity(); ++j)
279 mChannelSum += particleDataPtr->m0( channels[i].product(j) );
280 mThrSum += channels[i].bRatio() * mChannelSum;
282 mThr = (bRatSum == 0.) ? 0. : mThrSum / bRatSum;
284 // Switch off Breit-Wigner if very close to threshold.
285 if (mThr + NARROWMASS > m0Save) {
287 bool knownProblem = false;
288 for (int i = 0; i < 3; ++i) if (idSave == KNOWNNOWIDTH[i])
291 ostringstream osWarn;
292 osWarn << "for id = " << idSave;
293 particleDataPtr->infoPtr->errorMsg("Warning in ParticleDataEntry::"
294 "initBWmass: switching off width", osWarn.str(), true);
300 //--------------------------------------------------------------------------
302 // Function to give mass of a particle, either at the nominal value
303 // or picked according to a (linear or quadratic) Breit-Wigner.
305 double ParticleDataEntry::mass() {
308 if (modeBWnow == 0) return m0Save;
311 // Mass according to a Breit-Wigner linear in m.
312 if (modeBWnow == 1) {
313 mNow = m0Save + 0.5 * mWidthSave
314 * tan( atanLow + atanDif * particleDataPtr->rndmPtr->flat() );
316 // Ditto, but make Gamma proportional to sqrt(m^2 - m_threshold^2).
317 } else if (modeBWnow == 2) {
318 double mWidthNow, fixBW, runBW;
319 double m0ThrS = m0Save*m0Save - mThr*mThr;
321 mNow = m0Save + 0.5 * mWidthSave
322 * tan( atanLow + atanDif * particleDataPtr->rndmPtr->flat() );
323 mWidthNow = mWidthSave * sqrtpos( (mNow*mNow - mThr*mThr) / m0ThrS );
324 fixBW = mWidthSave / (pow2(mNow - m0Save) + pow2(0.5 * mWidthSave));
325 runBW = mWidthNow / (pow2(mNow - m0Save) + pow2(0.5 * mWidthNow));
326 } while (runBW < particleDataPtr->rndmPtr->flat()
327 * particleDataPtr->maxEnhanceBW * fixBW);
329 // Mass according to a Breit-Wigner quadratic in m.
330 } else if (modeBWnow == 3) {
331 m2Now = m0Save*m0Save + m0Save * mWidthSave
332 * tan( atanLow + atanDif * particleDataPtr->rndmPtr->flat() );
333 mNow = sqrtpos( m2Now);
335 // Ditto, but m_0 Gamma_0 -> m Gamma(m) with threshold factor as above.
337 double mwNow, fixBW, runBW;
338 double m2Ref = m0Save * m0Save;
339 double mwRef = m0Save * mWidthSave;
340 double m2Thr = mThr * mThr;
342 m2Now = m2Ref + mwRef * tan( atanLow + atanDif
343 * particleDataPtr->rndmPtr->flat() );
344 mNow = sqrtpos( m2Now);
345 mwNow = mNow * mWidthSave
346 * sqrtpos( (m2Now - m2Thr) / (m2Ref - m2Thr) );
347 fixBW = mwRef / (pow2(m2Now - m2Ref) + pow2(mwRef));
348 runBW = mwNow / (pow2(m2Now - m2Ref) + pow2(mwNow));
349 } while (runBW < particleDataPtr->rndmPtr->flat()
350 * particleDataPtr->maxEnhanceBW * fixBW);
357 //--------------------------------------------------------------------------
359 // Function to calculate running mass at given mass scale.
361 double ParticleDataEntry::mRun(double mHat) {
363 // Except for six quarks return nominal mass.
364 if (idSave > 6) return m0Save;
365 double mQRun = particleDataPtr->mQRun[idSave];
366 double Lam5 = particleDataPtr->Lambda5Run;
368 // For d, u, s quarks start running at 2 GeV (RPP 2006 p. 505).
369 if (idSave < 4) return mQRun * pow ( log(2. / Lam5)
370 / log(max(2., mHat) / Lam5), 12./23.);
372 // For c, b and t quarks start running at respective mass.
373 return mQRun * pow ( log(mQRun / Lam5)
374 / log(max(mQRun, mHat) / Lam5), 12./23.);
378 //--------------------------------------------------------------------------
380 // Rescale all branching ratios to assure normalization to unity.
382 void ParticleDataEntry::rescaleBR(double newSumBR) {
384 // Sum up branching ratios. Find rescaling factor. Rescale.
385 double oldSumBR = 0.;
386 for ( int i = 0; i < int(channels.size()); ++ i)
387 oldSumBR += channels[i].bRatio();
388 double rescaleFactor = newSumBR / oldSumBR;
389 for ( int i = 0; i < int(channels.size()); ++ i)
390 channels[i].rescaleBR(rescaleFactor);
394 //--------------------------------------------------------------------------
396 // Prepare to pick a decay channel.
398 bool ParticleDataEntry::preparePick(int idSgn, double mHat, int idInFlav) {
400 // Reset sum of allowed widths/branching ratios.
403 // For resonances the widths are calculated dynamically.
404 if (isResonanceSave && resonancePtr != 0) {
405 resonancePtr->widthStore(idSgn, mHat, idInFlav);
406 for (int i = 0; i < int(channels.size()); ++i)
407 currentBRSum += channels[i].currentBR();
409 // Else use normal fixed branching ratios.
413 for (int i = 0; i < int(channels.size()); ++i) {
414 onMode = channels[i].onMode();
416 if ( idSgn > 0 && (onMode == 1 || onMode == 2) )
417 currentBRNow = channels[i].bRatio();
418 else if ( idSgn < 0 && (onMode == 1 || onMode == 3) )
419 currentBRNow = channels[i].bRatio();
420 channels[i].currentBR(currentBRNow);
421 currentBRSum += currentBRNow;
425 // Failure if no channels found with positive branching ratios.
426 return (currentBRSum > 0.);
430 //--------------------------------------------------------------------------
432 // Pick a decay channel according to branching ratios from preparePick.
434 DecayChannel& ParticleDataEntry::pickChannel() {
436 // Find channel in table.
437 int size = channels.size();
438 double rndmBR = currentBRSum * particleDataPtr->rndmPtr->flat();
440 do rndmBR -= channels[++i].currentBR();
441 while (rndmBR > 0. && i < size);
443 // Emergency if no channel found. Done.
444 if (i == size) i = 0;
449 //--------------------------------------------------------------------------
451 // Access methods stored in ResonanceWidths. Could have been
452 // inline in .h, except for problems with forward declarations.
454 void ParticleDataEntry::setResonancePtr(
455 ResonanceWidths* resonancePtrIn) {
456 if (resonancePtr == resonancePtrIn) return;
457 if (resonancePtr != 0) delete resonancePtr;
458 resonancePtr = resonancePtrIn;
461 void ParticleDataEntry::resInit(Info* infoPtrIn, Settings* settingsPtrIn,
462 ParticleData* particleDataPtrIn, Couplings* couplingsPtrIn) {
463 if (resonancePtr != 0) resonancePtr->init(infoPtrIn, settingsPtrIn,
464 particleDataPtrIn, couplingsPtrIn);
467 double ParticleDataEntry::resWidth(int idSgn, double mHat, int idIn,
468 bool openOnly, bool setBR) {
469 return (resonancePtr != 0) ? resonancePtr->width( idSgn, mHat,
470 idIn, openOnly, setBR) : 0.;
473 double ParticleDataEntry::resWidthOpen(int idSgn, double mHat, int idIn) {
474 return (resonancePtr != 0) ? resonancePtr->widthOpen( idSgn, mHat, idIn)
478 double ParticleDataEntry::resWidthStore(int idSgn, double mHat, int idIn) {
479 return (resonancePtr != 0) ? resonancePtr->widthStore( idSgn, mHat, idIn)
483 double ParticleDataEntry::resOpenFrac(int idSgn) {
484 return (resonancePtr != 0) ? resonancePtr->openFrac(idSgn) : 1.;
487 double ParticleDataEntry::resWidthRescaleFactor() {
488 return (resonancePtr != 0) ? resonancePtr->widthRescaleFactor() : 1.;
491 double ParticleDataEntry::resWidthChan(double mHat, int idAbs1,
493 return (resonancePtr != 0) ? resonancePtr->widthChan( mHat, idAbs1,
497 //--------------------------------------------------------------------------
499 // Constituent masses for (d, u, s, c, b) quarks and diquarks.
500 // Hardcoded in CONSTITUENTMASSTABLE so that they are not overwritten
501 // by mistake, and separated from the "normal" masses.
502 // Called both by setDefaults and setM0 so kept as separate method.
504 void ParticleDataEntry::setConstituentMass() {
506 // Equate with the normal masses as default guess.
507 constituentMassSave = m0Save;
509 // Quark masses trivial. Also gluon mass.
510 if (idSave < 6) constituentMassSave = CONSTITUENTMASSTABLE[idSave];
511 if (idSave == 21) constituentMassSave = CONSTITUENTMASSTABLE[9];
513 // Diquarks as simple sum of constituent quarks.
514 if (idSave > 1000 && idSave < 10000 && (idSave/10)%10 == 0) {
515 int id1 = idSave/1000;
516 int id2 = (idSave/100)%10;
517 if (id1 <6 && id2 < 6) constituentMassSave
518 = CONSTITUENTMASSTABLE[id1] + CONSTITUENTMASSTABLE[id2];
523 //--------------------------------------------------------------------------
525 // Convert string to lowercase for case-insensitive comparisons.
527 string ParticleDataEntry::toLower(const string& nameConv) {
529 string temp(nameConv);
530 for (int i = 0; i < int(temp.length()); ++i)
531 temp[i] = std::tolower(temp[i]);
536 //==========================================================================
538 // ParticleData class.
539 // This class holds a map of all ParticleDataEntries,
540 // each entry containing info on a particle species.
542 //--------------------------------------------------------------------------
544 // Get data to be distributed among particles during setup.
545 // Note: this routine is called twice. Firstly from init(...), but
546 // the data should not be used at that point, so is likely overkill.
547 // Secondly, from initWidths, after user has had time to change.
549 void ParticleData::initCommon() {
551 // Mass generation: fixed mass or linear/quadratic Breit-Wigner.
552 modeBreitWigner = settingsPtr->mode("ParticleData:modeBreitWigner");
554 // Maximum tail enhancement when adding threshold factor to Breit-Wigner.
555 maxEnhanceBW = settingsPtr->parm("ParticleData:maxEnhanceBW");
557 // Find initial MSbar masses for five light flavours.
558 mQRun[1] = settingsPtr->parm("ParticleData:mdRun");
559 mQRun[2] = settingsPtr->parm("ParticleData:muRun");
560 mQRun[3] = settingsPtr->parm("ParticleData:msRun");
561 mQRun[4] = settingsPtr->parm("ParticleData:mcRun");
562 mQRun[5] = settingsPtr->parm("ParticleData:mbRun");
563 mQRun[6] = settingsPtr->parm("ParticleData:mtRun");
565 // Find Lambda5 value to use in running of MSbar masses.
566 double alphaSvalue = settingsPtr->parm("ParticleData:alphaSvalueMRun");
568 alphaS.init( alphaSvalue, 1);
569 Lambda5Run = alphaS.Lambda5();
573 //--------------------------------------------------------------------------
575 // Initialize pointer for particles to the full database, the Breit-Wigners
576 // of normal hadrons and the ResonanceWidths of resonances. For the latter
577 // the order of initialization is essential to get secondary widths right.
579 void ParticleData::initWidths( vector<ResonanceWidths*> resonancePtrs) {
581 // Initialize some common data.
584 // Pointer to database and Breit-Wigner mass initialization for each
586 ResonanceWidths* resonancePtr = 0;
587 for (map<int, ParticleDataEntry>::iterator pdtEntry = pdt.begin();
588 pdtEntry != pdt.end(); ++pdtEntry) {
589 ParticleDataEntry& pdtNow = pdtEntry->second;
590 pdtNow.initPtr( this);
593 // Remove any existing resonances.
594 resonancePtr = pdtNow.getResonancePtr();
595 if (resonancePtr != 0) pdtNow.setResonancePtr(0);
598 // Begin set up new resonance objects.
599 // Z0, W+- and top are almost always needed.
600 resonancePtr = new ResonanceGmZ(23);
601 setResonancePtr( 23, resonancePtr);
602 resonancePtr = new ResonanceW(24);
603 setResonancePtr( 24, resonancePtr);
604 resonancePtr = new ResonanceTop(6);
605 setResonancePtr( 6, resonancePtr);
608 if (!settingsPtr->flag("Higgs:useBSM")) {
609 resonancePtr = new ResonanceH(0, 25);
610 setResonancePtr( 25, resonancePtr);
614 resonancePtr = new ResonanceH(1, 25);
615 setResonancePtr( 25, resonancePtr);
616 resonancePtr = new ResonanceH(2, 35);
617 setResonancePtr( 35, resonancePtr);
618 resonancePtr = new ResonanceH(3, 36);
619 setResonancePtr( 36, resonancePtr);
620 resonancePtr = new ResonanceHchg(37);
621 setResonancePtr( 37, resonancePtr);
624 // A fourth generation: b', t', tau', nu'_tau.
625 resonancePtr = new ResonanceFour(7);
626 setResonancePtr( 7, resonancePtr);
627 resonancePtr = new ResonanceFour(8);
628 setResonancePtr( 8, resonancePtr);
629 resonancePtr = new ResonanceFour(17);
630 setResonancePtr( 17, resonancePtr);
631 resonancePtr = new ResonanceFour(18);
632 setResonancePtr( 18, resonancePtr);
634 // New gauge bosons: Z', W', R.
635 resonancePtr = new ResonanceZprime(32);
636 setResonancePtr( 32, resonancePtr);
637 resonancePtr = new ResonanceWprime(34);
638 setResonancePtr( 34, resonancePtr);
639 resonancePtr = new ResonanceRhorizontal(41);
640 setResonancePtr( 41, resonancePtr);
643 resonancePtr = new ResonanceLeptoquark(42);
644 setResonancePtr( 42, resonancePtr);
648 for(int i = 1; i < 7; i++){
649 resonancePtr = new ResonanceSquark(1000000 + i);
650 setResonancePtr( 1000000 + i, resonancePtr);
651 resonancePtr = new ResonanceSquark(2000000 + i);
652 setResonancePtr( 2000000 + i, resonancePtr);
655 // - Sleptons and sneutrinos
656 for(int i = 1; i < 7; i++){
657 resonancePtr = new ResonanceSlepton(1000010 + i);
658 setResonancePtr( 1000010 + i, resonancePtr);
659 resonancePtr = new ResonanceSlepton(2000010 + i);
660 setResonancePtr( 2000010 + i, resonancePtr);
664 resonancePtr = new ResonanceGluino(1000021);
665 setResonancePtr( 1000021, resonancePtr);
668 resonancePtr = new ResonanceChar(1000024);
669 setResonancePtr( 1000024, resonancePtr);
670 resonancePtr = new ResonanceChar(1000037);
671 setResonancePtr( 1000037, resonancePtr);
674 resonancePtr = new ResonanceNeut(1000022);
675 setResonancePtr( 1000022, resonancePtr);
676 resonancePtr = new ResonanceNeut(1000023);
677 setResonancePtr( 1000023, resonancePtr);
678 resonancePtr = new ResonanceNeut(1000025);
679 setResonancePtr( 1000025, resonancePtr);
680 resonancePtr = new ResonanceNeut(1000035);
681 setResonancePtr( 1000035, resonancePtr);
682 resonancePtr = new ResonanceNeut(1000045);
683 setResonancePtr( 1000045, resonancePtr);
685 // Excited quarks and leptons.
686 for (int i = 1; i < 7; ++i) {
687 resonancePtr = new ResonanceExcited(4000000 + i);
688 setResonancePtr( 4000000 + i, resonancePtr);
690 for (int i = 11; i < 17; ++i) {
691 resonancePtr = new ResonanceExcited(4000000 + i);
692 setResonancePtr( 4000000 + i, resonancePtr);
695 // An excited graviton/gluon in extra-dimensional scenarios.
696 resonancePtr = new ResonanceGraviton(5100039);
697 setResonancePtr( 5100039, resonancePtr);
698 resonancePtr = new ResonanceKKgluon(5100021);
699 setResonancePtr( 5100021, resonancePtr);
701 // A left-right-symmetric scenario with new righthanded neutrinos,
702 // righthanded gauge bosons and doubly charged Higgses.
703 resonancePtr = new ResonanceNuRight(9900012);
704 setResonancePtr( 9900012, resonancePtr);
705 resonancePtr = new ResonanceNuRight(9900014);
706 setResonancePtr( 9900014, resonancePtr);
707 resonancePtr = new ResonanceNuRight(9900016);
708 setResonancePtr( 9900016, resonancePtr);
709 resonancePtr = new ResonanceZRight(9900023);
710 setResonancePtr( 9900023, resonancePtr);
711 resonancePtr = new ResonanceWRight(9900024);
712 setResonancePtr( 9900024, resonancePtr);
713 resonancePtr = new ResonanceHchgchgLeft(9900041);
714 setResonancePtr( 9900041, resonancePtr);
715 resonancePtr = new ResonanceHchgchgRight(9900042);
716 setResonancePtr( 9900042, resonancePtr);
718 // Attach user-defined external resonances and do basic initialization.
719 for (int i = 0; i < int(resonancePtrs.size()); ++i) {
720 int idNow = resonancePtrs[i]->id();
721 resonancePtrs[i]->initBasic(idNow);
722 setResonancePtr( idNow, resonancePtrs[i]);
725 // Set up lists to order resonances in ascending mass.
726 vector<int> idOrdered;
727 vector<double> m0Ordered;
729 // Put Z0 and W+- first, since known to be SM and often off-shell.
730 idOrdered.push_back(23);
731 m0Ordered.push_back(m0(23));
732 idOrdered.push_back(24);
733 m0Ordered.push_back(m0(24));
735 // Loop through particle table to find resonances.
736 for (map<int, ParticleDataEntry>::iterator pdtEntry = pdt.begin();
737 pdtEntry != pdt.end(); ++pdtEntry) {
738 ParticleDataEntry& pdtNow = pdtEntry->second;
739 int idNow = pdtNow.id();
741 // Set up a simple default object for uninitialized resonances.
742 if (pdtNow.isResonance() && pdtNow.getResonancePtr() == 0) {
743 resonancePtr = new ResonanceGeneric(idNow);
744 setResonancePtr( idNow, resonancePtr);
747 // Insert resonances in ascending mass, to respect decay hierarchies.
748 if (pdtNow.getResonancePtr() != 0 && idNow != 23 && idNow != 24) {
749 double m0Now = pdtNow.m0();
750 idOrdered.push_back(idNow);
751 m0Ordered.push_back(m0Now);
752 for (int i = int(idOrdered.size()) - 2; i > 1; --i) {
753 if (m0Ordered[i] < m0Now) break;
754 swap( idOrdered[i], idOrdered[i + 1]);
755 swap( m0Ordered[i], m0Ordered[i + 1]);
760 // Initialize the resonances in ascending mass order.
761 for (int i = 0; i < int(idOrdered.size()); ++i) resInit( idOrdered[i]);
765 //--------------------------------------------------------------------------
767 // Read in database from specific XML file (which may refer to others).
769 bool ParticleData::readXML(string inFile, bool reset) {
771 // Normally reset whole database before beginning.
772 if (reset) {pdt.clear(); isInit = false;}
774 // List of files to be checked.
775 vector<string> files;
776 files.push_back(inFile);
778 // Loop over files. Open them for read.
779 for (int i = 0; i < int(files.size()); ++i) {
780 const char* cstring = files[i].c_str();
781 ifstream is(cstring);
783 // Check that instream is OK.
785 infoPtr->errorMsg("Error in ParticleData::readXML:"
786 " did not find file", files[i]);
790 // Read in one line at a time.
793 while ( getline(is, line) ) {
795 // Get first word of a line.
796 istringstream getfirst(line);
800 // Check for occurence of a particle. Add any continuation lines.
801 if (word1 == "<particle") {
802 while (line.find(">") == string::npos) {
804 getline(is, addLine);
808 // Read in particle properties.
809 int idTmp = intAttributeValue( line, "id");
810 string nameTmp = attributeValue( line, "name");
811 string antiNameTmp = attributeValue( line, "antiName");
812 if (antiNameTmp == "") antiNameTmp = "void";
813 int spinTypeTmp = intAttributeValue( line, "spinType");
814 int chargeTypeTmp = intAttributeValue( line, "chargeType");
815 int colTypeTmp = intAttributeValue( line, "colType");
816 double m0Tmp = doubleAttributeValue( line, "m0");
817 double mWidthTmp = doubleAttributeValue( line, "mWidth");
818 double mMinTmp = doubleAttributeValue( line, "mMin");
819 double mMaxTmp = doubleAttributeValue( line, "mMax");
820 double tau0Tmp = doubleAttributeValue( line, "tau0");
822 // Erase if particle already exists.
823 if (isParticle(idTmp)) pdt.erase(idTmp);
825 // Store new particle. Save pointer, to be used for decay channels.
826 addParticle( idTmp, nameTmp, antiNameTmp, spinTypeTmp, chargeTypeTmp,
827 colTypeTmp, m0Tmp, mWidthTmp, mMinTmp, mMaxTmp, tau0Tmp);
828 particlePtr = particleDataEntryPtr(idTmp);
830 // Check for occurence of a decay channel. Add any continuation lines.
831 } else if (word1 == "<channel") {
832 while (line.find(">") == string::npos) {
834 getline(is, addLine);
838 // Read in channel properties - products so far only as a string.
839 int onMode = intAttributeValue( line, "onMode");
840 double bRatio = doubleAttributeValue( line, "bRatio");
841 int meMode = intAttributeValue( line, "meMode");
842 string products = attributeValue( line, "products");
844 // Read in decay products from stream. Must have at least one.
845 istringstream prodStream(products);
846 int prod0 = 0; int prod1 = 0; int prod2 = 0; int prod3 = 0;
847 int prod4 = 0; int prod5 = 0; int prod6 = 0; int prod7 = 0;
848 prodStream >> prod0 >> prod1 >> prod2 >> prod3 >> prod4 >> prod5
851 infoPtr->errorMsg("Error in ParticleData::readXML:"
852 " incomplete decay channel", line);
856 // Store new channel (if particle already known).
857 if (particlePtr == 0) {
858 infoPtr->errorMsg("Error in ParticleData::readXML:"
859 " orphan decay channel", line);
862 particlePtr->addChannel(onMode, bRatio, meMode, prod0, prod1,
863 prod2, prod3, prod4, prod5, prod6, prod7);
865 // Check for occurence of a file also to be read.
866 } else if (word1 == "<file") {
867 string file = attributeValue(line, "name");
869 infoPtr->errorMsg("Warning in ParticleData::readXML:"
870 " skip unrecognized file name", line);
871 } else files.push_back(file);
874 // End of loop over lines in input file and loop over files.
878 // All particle data at this stage defines baseline original.
879 if (reset) for (map<int, ParticleDataEntry>::iterator pdtEntry
880 = pdt.begin(); pdtEntry != pdt.end(); ++pdtEntry) {
881 particlePtr = &pdtEntry->second;
882 particlePtr->setHasChanged(false);
891 //--------------------------------------------------------------------------
893 // Print out complete database in numerical order as an XML file.
895 void ParticleData::listXML(string outFile) {
897 // Convert file name to ofstream.
898 const char* cstring = outFile.c_str();
899 ofstream os(cstring);
901 // Iterate through the particle data table.
902 for (map<int, ParticleDataEntry>::iterator pdtEntry
903 = pdt.begin(); pdtEntry != pdt.end(); ++pdtEntry) {
904 particlePtr = &pdtEntry->second;
906 // Print particle properties.
907 os << "<particle id=\"" << particlePtr->id() << "\""
908 << " name=\"" << particlePtr->name() << "\"";
909 if (particlePtr->hasAnti())
910 os << " antiName=\"" << particlePtr->name(-1) << "\"";
911 os << " spinType=\"" << particlePtr->spinType() << "\""
912 << " chargeType=\"" << particlePtr->chargeType() << "\""
913 << " colType=\"" << particlePtr->colType() << "\"\n";
914 // Pick format for mass and width based on mass value.
915 double m0Now = particlePtr->m0();
916 if (m0Now == 0 || (m0Now > 0.1 && m0Now < 1000.))
917 os << fixed << setprecision(5);
918 else os << scientific << setprecision(3);
919 os << " m0=\"" << m0Now << "\"";
920 if (particlePtr->mWidth() > 0.)
921 os << " mWidth=\"" << particlePtr->mWidth() << "\""
922 << " mMin=\"" << particlePtr->mMin() << "\""
923 << " mMax=\"" << particlePtr->mMax() << "\"";
924 if (particlePtr->tau0() > 0.) os << scientific << setprecision(5)
925 << " tau0=\"" << particlePtr->tau0() << "\"";
928 // Loop through the decay channel table for each particle.
929 if (particlePtr->sizeChannels() > 0) {
930 for (int i = 0; i < particlePtr->sizeChannels(); ++i) {
931 const DecayChannel& channel = particlePtr->channel(i);
932 int mult = channel.multiplicity();
934 // Print decay channel properties.
935 os << " <channel onMode=\"" << channel.onMode() << "\""
936 << fixed << setprecision(7)
937 << " bRatio=\"" << channel.bRatio() << "\"";
938 if (channel.meMode() > 0)
939 os << " meMode=\"" << channel.meMode() << "\"";
940 os << " products=\"";
941 for (int j = 0; j < mult; ++j) {
942 os << channel.product(j);
943 if (j < mult - 1) os << " ";
946 // Finish off line and loop over allowed decay channels.
951 // Finish off existing particle.
952 os << "</particle>\n\n";
958 //--------------------------------------------------------------------------
960 // Read in database from specific free format file.
962 bool ParticleData::readFF(string inFile, bool reset) {
964 // Normally reset whole database before beginning.
965 if (reset) {pdt.clear(); isInit = false;}
967 // Open file for read and check that instream is OK.
968 const char* cstring = inFile.c_str();
969 ifstream is(cstring);
971 infoPtr->errorMsg("Error in ParticleData::readFF:"
972 " did not find file", inFile);
976 // Read in one line at a time.
979 bool readParticle = false;
980 while ( getline(is, line) ) {
982 // Empty lines begins new particle.
983 if (line.find_first_not_of(" \n\t\v\b\r\f\a") == string::npos) {
988 // Prepare to use standard read from line.
989 istringstream readLine(line);
991 // Read in a line with particle information.
994 // Properties to be read.
996 string nameTmp, antiNameTmp;
997 int spinTypeTmp, chargeTypeTmp, colTypeTmp;
998 double m0Tmp, mWidthTmp, mMinTmp, mMaxTmp, tau0Tmp;
1002 readLine >> idTmp >> nameTmp >> antiNameTmp >> spinTypeTmp
1003 >> chargeTypeTmp >> colTypeTmp >> m0Tmp >> mWidthTmp
1004 >> mMinTmp >> mMaxTmp >> tau0Tmp;
1006 // Error printout if something went wrong.
1008 infoPtr->errorMsg("Error in ParticleData::readFF:"
1009 " incomplete particle", line);
1013 // Erase if particle already exists.
1014 if (isParticle(idTmp)) pdt.erase(idTmp);
1016 // Store new particle. Save pointer, to be used for decay channels.
1017 addParticle( idTmp, nameTmp, antiNameTmp, spinTypeTmp, chargeTypeTmp,
1018 colTypeTmp, m0Tmp, mWidthTmp, mMinTmp, mMaxTmp, tau0Tmp);
1019 particlePtr = particleDataEntryPtr(idTmp);
1020 readParticle = false;
1022 // Read in a line with decay channel information.
1025 // Properties to be read.
1029 int prod0 = 0; int prod1 = 0; int prod2 = 0; int prod3 = 0;
1030 int prod4 = 0; int prod5 = 0; int prod6 = 0; int prod7 = 0;
1032 // Read in data from stream. Need at least one decay product.
1033 readLine >> onMode >> bRatio >> meMode >> prod0;
1035 infoPtr->errorMsg("Error in ParticleData::readFF:"
1036 " incomplete decay channel", line);
1039 readLine >> prod1 >> prod2 >> prod3 >> prod4 >> prod5
1042 // Store new channel.
1043 if (particlePtr == 0) {
1044 infoPtr->errorMsg("Error in ParticleData::readFF:"
1045 " orphan decay channel", line);
1048 particlePtr->addChannel(onMode, bRatio, meMode, prod0, prod1,
1049 prod2, prod3, prod4, prod5, prod6, prod7);
1053 // End of while loop over lines in the file.
1063 //--------------------------------------------------------------------------
1065 // Print out complete database in numerical order as a free format file.
1067 void ParticleData::listFF(string outFile) {
1069 // Convert file name to ofstream.
1070 const char* cstring = outFile.c_str();
1071 ofstream os(cstring);
1073 // Iterate through the particle data table.
1074 for (map<int, ParticleDataEntry>::iterator pdtEntry
1075 = pdt.begin(); pdtEntry != pdt.end(); ++pdtEntry) {
1076 particlePtr = &pdtEntry->second;
1078 // Pick format for mass and width based on mass value.
1079 double m0Now = particlePtr->m0();
1080 if (m0Now == 0 || (m0Now > 0.1 && m0Now < 1000.))
1081 os << fixed << setprecision(5);
1082 else os << scientific << setprecision(3);
1084 // Print particle properties.
1085 os << "\n" << setw(8) << particlePtr->id() << " "
1086 << left << setw(16) << particlePtr->name() << " "
1087 << setw(16) << particlePtr->name(-1) << " "
1088 << right << setw(2) << particlePtr->spinType() << " "
1089 << setw(2) << particlePtr->chargeType() << " "
1090 << setw(2) << particlePtr->colType() << " "
1091 << setw(10) << particlePtr->m0() << " "
1092 << setw(10) << particlePtr->mWidth() << " "
1093 << setw(10) << particlePtr->mMin() << " "
1094 << setw(10) << particlePtr->mMax() << " "
1095 << scientific << setprecision(5)
1096 << setw(12) << particlePtr->tau0() << "\n";
1098 // Loop through the decay channel table for each particle.
1099 if (particlePtr->sizeChannels() > 0) {
1100 for (int i = 0; i < particlePtr->sizeChannels(); ++i) {
1101 const DecayChannel& channel = particlePtr->channel(i);
1102 os << " " << setw(6) << channel.onMode()
1103 << " " << fixed << setprecision(7) << setw(10)
1104 << channel.bRatio() << " "
1105 << setw(3) << channel.meMode() << " ";
1106 for (int j = 0; j < channel.multiplicity(); ++j)
1107 os << setw(8) << channel.product(j) << " ";
1116 //--------------------------------------------------------------------------
1118 // Read in updates from a character string, like a line of a file.
1119 // Is used by readString (and readFile) in Pythia.
1121 bool ParticleData::readString(string lineIn, bool warn, ostream& os) {
1123 // If empty line then done.
1124 if (lineIn.find_first_not_of(" \n\t\v\b\r\f\a") == string::npos) return true;
1126 // Take copy that will be modified.
1127 string line = lineIn;
1129 // If first character is not a digit then taken to be a comment.
1130 int firstChar = line.find_first_not_of(" \n\t\v\b\r\f\a");
1131 if (!isdigit(line[firstChar])) return true;
1133 // Replace colons and equal signs by blanks to make parsing simpler.
1134 for ( int j = 0; j < int(line.size()); ++ j)
1135 if (line[j] == ':' || line[j] == '=') line[j] = ' ';
1137 // Get particle id and property name.
1140 istringstream getWord(line);
1141 getWord >> idTmp >> property;
1142 property = toLower(property);
1144 // Check that valid particle.
1145 if ( (!isParticle(idTmp) && property != "all" && property != "new")
1147 if (warn) os << "\n Warning: input particle not found in Particle"
1148 << " Data Table; skip:\n " << lineIn << "\n";
1152 // Identify particle property and read + set its value, case by case.
1153 if (property == "name") {
1156 pdt[idTmp].setName(nameTmp);
1159 if (property == "antiname") {
1161 getWord >> antiNameTmp;
1162 pdt[idTmp].setAntiName(antiNameTmp);
1165 if (property == "names") {
1166 string nameTmp, antiNameTmp;
1167 getWord >> nameTmp >> antiNameTmp;
1168 pdt[idTmp].setNames(nameTmp, antiNameTmp);
1171 if (property == "spintype") {
1173 getWord >> spinTypeTmp;
1174 pdt[idTmp].setSpinType(spinTypeTmp);
1177 if (property == "chargetype") {
1179 getWord >> chargeTypeTmp;
1180 pdt[idTmp].setChargeType(chargeTypeTmp);
1183 if (property == "coltype") {
1185 getWord >> colTypeTmp;
1186 pdt[idTmp].setColType(colTypeTmp);
1189 if (property == "m0") {
1192 pdt[idTmp].setM0(m0Tmp);
1195 if (property == "mwidth") {
1197 getWord >> mWidthTmp;
1198 pdt[idTmp].setMWidth(mWidthTmp);
1201 if (property == "mmin") {
1204 pdt[idTmp].setMMin(mMinTmp);
1207 if (property == "mmax") {
1210 pdt[idTmp].setMMax(mMaxTmp);
1213 if (property == "tau0") {
1216 pdt[idTmp].setTau0(tau0Tmp);
1219 if (property == "isresonance") {
1221 getWord >> isresTmp;
1222 bool isResonanceTmp = boolString(isresTmp);
1223 pdt[idTmp].setIsResonance(isResonanceTmp);
1226 if (property == "maydecay") {
1229 bool mayDecayTmp = boolString(mayTmp);
1230 pdt[idTmp].setMayDecay(mayDecayTmp);
1233 if (property == "doexternaldecay") {
1235 getWord >> extdecTmp;
1236 bool doExternalDecayTmp = boolString(extdecTmp);
1237 pdt[idTmp].setDoExternalDecay(doExternalDecayTmp);
1240 if (property == "isvisible") {
1242 getWord >> isvisTmp;
1243 bool isVisibleTmp = boolString(isvisTmp);
1244 pdt[idTmp].setIsVisible(isVisibleTmp);
1247 if (property == "doforcewidth") {
1249 getWord >> doforceTmp;
1250 bool doForceWidthTmp = boolString(doforceTmp);
1251 pdt[idTmp].setDoForceWidth(doForceWidthTmp);
1255 // Addition or complete replacement of a particle.
1256 if (property == "all" || property == "new") {
1258 // Default values for properties to be read.
1259 string nameTmp = "void";
1260 string antiNameTmp = "void";
1261 int spinTypeTmp = 0;
1262 int chargeTypeTmp = 0;
1265 double mWidthTmp = 0.;
1266 double mMinTmp = 0.;
1267 double mMaxTmp = 0.;
1268 double tau0Tmp = 0.;
1270 // Read in data from stream.
1271 getWord >> nameTmp >> antiNameTmp >> spinTypeTmp >> chargeTypeTmp
1272 >> colTypeTmp >> m0Tmp >> mWidthTmp >> mMinTmp >> mMaxTmp
1275 // To keep existing decay channels, only overwrite particle data.
1276 if (property == "all" && isParticle(idTmp)) {
1277 setAll( idTmp, nameTmp, antiNameTmp, spinTypeTmp, chargeTypeTmp,
1278 colTypeTmp, m0Tmp, mWidthTmp, mMinTmp, mMaxTmp, tau0Tmp);
1280 // Else start over completely from scratch.
1282 if (isParticle(idTmp)) pdt.erase(idTmp);
1283 addParticle( idTmp, nameTmp, antiNameTmp, spinTypeTmp, chargeTypeTmp,
1284 colTypeTmp, m0Tmp, mWidthTmp, mMinTmp, mMaxTmp, tau0Tmp);
1289 // Set onMode of all decay channels in one go.
1290 if (property == "onmode") {
1293 getWord >> onModeIn;
1294 // For onMode allow the optional possibility of Bool input.
1295 if (isdigit(onModeIn[0])) {
1296 istringstream getOnMode(onModeIn);
1297 getOnMode >> onMode;
1298 } else onMode = (boolString(onModeIn)) ? 1 : 0;
1299 for (int i = 0; i < pdt[idTmp].sizeChannels(); ++i)
1300 pdt[idTmp].channel(i).onMode(onMode);
1304 // Selective search for matching decay channels.
1306 if (property == "offifany" || property == "onifany" ||
1307 property == "onposifany" || property == "onnegifany") matchKind = 1;
1308 if (property == "offifall" || property == "onifall" ||
1309 property == "onposifall" || property == "onnegifall") matchKind = 2;
1310 if (property == "offifmatch" || property == "onifmatch" ||
1311 property == "onposifmatch" || property == "onnegifmatch") matchKind = 3;
1312 if (matchKind > 0) {
1314 if (property == "onifany" || property == "onifall"
1315 || property == "onifmatch") onMode = 1;
1316 if (property == "onposifany" || property == "onposifall"
1317 || property == "onposifmatch") onMode = 2;
1318 if (property == "onnegifany" || property == "onnegifall"
1319 || property == "onnegifmatch") onMode = 3;
1321 // Read in particles to match.
1322 vector<int> idToMatch;
1326 if (!getWord) break;
1327 idToMatch.push_back(abs(idRead));
1329 int nToMatch = idToMatch.size();
1331 // Loop over all decay channels.
1332 for (int i = 0; i < pdt[idTmp].sizeChannels(); ++i) {
1333 int multi = pdt[idTmp].channel(i).multiplicity();
1335 // Look for any match at all.
1336 if (matchKind == 1) {
1337 bool foundMatch = false;
1338 for (int j = 0; j < multi; ++j) {
1339 int idNow = abs(pdt[idTmp].channel(i).product(j));
1340 for (int k = 0; k < nToMatch; ++k)
1341 if (idNow == idToMatch[k]) {foundMatch = true; break;}
1342 if (foundMatch) break;
1344 if (foundMatch) pdt[idTmp].channel(i).onMode(onMode);
1346 // Look for match of all products provided.
1348 int nUnmatched = nToMatch;
1349 if (multi < nToMatch);
1350 else if (multi > nToMatch && matchKind == 3);
1352 vector<int> idUnmatched;
1353 for (int k = 0; k < nToMatch; ++k)
1354 idUnmatched.push_back(idToMatch[k]);
1355 for (int j = 0; j < multi; ++j) {
1356 int idNow = abs(pdt[idTmp].channel(i).product(j));
1357 for (int k = 0; k < nUnmatched; ++k)
1358 if (idNow == idUnmatched[k]) {
1359 idUnmatched[k] = idUnmatched[--nUnmatched];
1362 if (nUnmatched == 0) break;
1365 if (nUnmatched == 0) pdt[idTmp].channel(i).onMode(onMode);
1371 // Rescale all branching ratios by common factor.
1372 if (property == "rescalebr") {
1375 pdt[idTmp].rescaleBR(factor);
1379 // Reset decay table in preparation for new input.
1380 if (property == "onechannel") pdt[idTmp].clearChannels();
1382 // Add or change a decay channel: get channel number and new property.
1383 if (property == "addchannel" || property == "onechannel"
1384 || isdigit(property[0])) {
1386 if (property == "addchannel" || property == "onechannel") {
1387 pdt[idTmp].addChannel();
1388 channel = pdt[idTmp].sizeChannels() - 1;
1391 istringstream getChannel(property);
1392 getChannel >> channel;
1393 getWord >> property;
1394 property = toLower(property);
1397 // Check that channel exists.
1398 if (channel < 0 || channel >= pdt[idTmp].sizeChannels()) return false;
1400 // Find decay channel property and value, case by case.
1401 // At same time also do case where all should be replaced.
1402 if (property == "onmode" || property == "all") {
1405 getWord >> onModeIn;
1406 // For onMode allow the optional possibility of Bool input.
1407 if (isdigit(onModeIn[0])) {
1408 istringstream getOnMode(onModeIn);
1409 getOnMode >> onMode;
1410 } else onMode = (boolString(onModeIn)) ? 1 : 0;
1411 pdt[idTmp].channel(channel).onMode(onMode);
1412 if (property == "onmode") return true;
1414 if (property == "bratio" || property == "all") {
1417 pdt[idTmp].channel(channel).bRatio(bRatio);
1418 if (property == "bratio") return true;
1420 if (property == "memode" || property == "all") {
1423 pdt[idTmp].channel(channel).meMode(meMode);
1424 if (property == "memode") return true;
1427 // Scan for products until end of line.
1428 if (property == "products" || property == "all") {
1430 for (int iProd = 0; iProd < 8; ++iProd) {
1433 if (!getWord) break;
1434 pdt[idTmp].channel(channel).product(iProd, idProd);
1437 for (int iProd = nProd; iProd < 8; ++iProd)
1438 pdt[idTmp].channel(channel).product(iProd, 0);
1439 pdt[idTmp].channel(channel).multiplicity(nProd);
1443 // Rescale an existing branching ratio.
1444 if (property == "rescalebr") {
1447 pdt[idTmp].channel(channel).rescaleBR(factor);
1452 // Return false if failed to recognize property.
1453 if (warn) os << "\n Warning: input property not found in Particle"
1454 << " Data Table; skip:\n " << lineIn << "\n";
1459 //--------------------------------------------------------------------------
1461 // Print out complete or changed table of database in numerical order.
1463 void ParticleData::list(bool changedOnly, bool changedRes, ostream& os) {
1465 // Table header; output for bool as off/on.
1467 os << "\n -------- PYTHIA Particle Data Table (complete) --------"
1468 << "------------------------------------------------------------"
1469 << "--------------\n \n";
1472 os << "\n -------- PYTHIA Particle Data Table (changed only) ----"
1473 << "------------------------------------------------------------"
1474 << "--------------\n \n";
1476 os << " id name antiName spn chg col m0"
1477 << " mWidth mMin mMax tau0 res dec ext "
1478 << "vis wid\n no onMode bRatio meMode products \n";
1480 // Iterate through the particle data table. Option to skip unchanged.
1482 for (map<int, ParticleDataEntry>::iterator pdtEntry
1483 = pdt.begin(); pdtEntry != pdt.end(); ++pdtEntry) {
1484 particlePtr = &pdtEntry->second;
1485 if ( !changedOnly || particlePtr->hasChanged() ||
1486 ( changedRes && particlePtr->getResonancePtr() != 0 ) ) {
1488 // Pick format for mass and width based on mass value.
1489 double m0Now = particlePtr->m0();
1490 if (m0Now == 0 || (m0Now > 0.1 && m0Now < 1000.))
1491 os << fixed << setprecision(5);
1492 else os << scientific << setprecision(3);
1494 // Print particle properties.
1496 string antiNameTmp = particlePtr->name(-1);
1497 if (antiNameTmp == "void") antiNameTmp = " ";
1498 os << "\n" << setw(8) << particlePtr->id() << " "
1499 << left << setw(16) << particlePtr->name() << " "
1500 << setw(16) << antiNameTmp << " "
1501 << right << setw(2) << particlePtr->spinType() << " "
1502 << setw(2) << particlePtr->chargeType() << " "
1503 << setw(2) << particlePtr->colType() << " "
1504 << setw(10) << particlePtr->m0() << " "
1505 << setw(10) << particlePtr->mWidth() << " "
1506 << setw(10) << particlePtr->mMin() << " "
1507 << setw(10) << particlePtr->mMax() << " "
1508 << scientific << setprecision(5)
1509 << setw(12) << particlePtr->tau0() << " " << setw(2)
1510 << particlePtr->isResonance() << " " << setw(2)
1511 << (particlePtr->mayDecay() && particlePtr->canDecay())
1512 << " " << setw(2) << particlePtr->doExternalDecay() << " "
1513 << setw(2) << particlePtr->isVisible()<< " "
1514 << setw(2) << particlePtr->doForceWidth() << "\n";
1516 // Loop through the decay channel table for each particle.
1517 if (particlePtr->sizeChannels() > 0) {
1518 for (int i = 0; i < int(particlePtr->sizeChannels()); ++i) {
1519 const DecayChannel& channel = particlePtr->channel(i);
1520 os << " " << setprecision(7)
1522 << setw(6) << channel.onMode()
1523 << fixed<< setw(12) << channel.bRatio()
1524 << setw(5) << channel.meMode() << " ";
1525 for (int j = 0; j < channel.multiplicity(); ++j)
1526 os << setw(8) << channel.product(j) << " ";
1534 // End of loop over database contents.
1535 if (changedOnly && nList == 0) os << "\n no particle data has been "
1536 << "changed from its default value \n";
1537 os << "\n -------- End PYTHIA Particle Data Table -----------------"
1538 << "--------------------------------------------------------------"
1539 << "----------\n" << endl;
1543 //--------------------------------------------------------------------------
1545 // Print out partial table of database in input order.
1547 void ParticleData::list(vector<int> idList, ostream& os) {
1549 // Table header; output for bool as off/on.
1550 os << "\n -------- PYTHIA Particle Data Table (partial) ---------"
1551 << "------------------------------------------------------------"
1552 << "--------------\n \n";
1553 os << " id name antiName spn chg col m0"
1554 << " mWidth mMin mMax tau0 res dec ext "
1555 << "vis wid\n no onMode bRatio meMode products \n";
1557 // Iterate through the given list of input particles.
1558 for (int i = 0; i < int(idList.size()); ++i) {
1559 particlePtr = particleDataEntryPtr(idList[i]);
1561 // Pick format for mass and width based on mass value.
1562 double m0Now = particlePtr->m0();
1563 if (m0Now == 0 || (m0Now > 0.1 && m0Now < 1000.))
1564 os << fixed << setprecision(5);
1565 else os << scientific << setprecision(3);
1567 // Print particle properties.
1568 string antiNameTmp = particlePtr->name(-1);
1569 if (antiNameTmp == "void") antiNameTmp = " ";
1570 os << "\n" << setw(8) << particlePtr->id() << " "
1571 << left << setw(16) << particlePtr->name() << " "
1572 << setw(16) << antiNameTmp << " "
1573 << right << setw(2) << particlePtr->spinType() << " "
1574 << setw(2) << particlePtr->chargeType() << " "
1575 << setw(2) << particlePtr->colType() << " "
1576 << setw(10) << particlePtr->m0() << " "
1577 << setw(10) << particlePtr->mWidth() << " "
1578 << setw(10) << particlePtr->mMin() << " "
1579 << setw(10) << particlePtr->mMax() << " "
1580 << scientific << setprecision(5)
1581 << setw(12) << particlePtr->tau0() << " " << setw(2)
1582 << particlePtr->isResonance() << " " << setw(2)
1583 << (particlePtr->mayDecay() && particlePtr->canDecay())
1584 << " " << setw(2) << particlePtr->doExternalDecay() << " "
1585 << setw(2) << particlePtr->isVisible() << " "
1586 << setw(2) << particlePtr->doForceWidth() << "\n";
1588 // Loop through the decay channel table for each particle.
1589 if (particlePtr->sizeChannels() > 0) {
1590 for (int j = 0; j < int(particlePtr->sizeChannels()); ++j) {
1591 const DecayChannel& channel = particlePtr->channel(j);
1592 os << " " << setprecision(7)
1594 << setw(6) << channel.onMode()
1595 << fixed<< setw(12) << channel.bRatio()
1596 << setw(5) << channel.meMode() << " ";
1597 for (int k = 0; k < channel.multiplicity(); ++k)
1598 os << setw(8) << channel.product(k) << " ";
1605 // End of loop over database contents.
1606 os << "\n -------- End PYTHIA Particle Data Table -----------------"
1607 << "--------------------------------------------------------------"
1608 << "----------\n" << endl;
1612 //--------------------------------------------------------------------------
1614 // Check that table makes sense: e.g. consistent names and mass ranges,
1615 // that branching ratios sum to unity, that charge is conserved and
1616 // that phase space is open in each channel.
1617 // verbosity = 0: mimimal amount of checks, e.g. that no channels open.
1618 // = 1: further warning if individual channels closed
1619 // (except for resonances).
1620 // = 2: also print branching-ratio-averaged threshold mass.
1621 // = 11, 12: as 1, 2, but include resonances in detailed checks.
1623 void ParticleData::checkTable(int verbosity, ostream& os) {
1626 os << "\n -------- PYTHIA Check of Particle Data Table ------------"
1630 // Loop through all particles.
1631 for (map<int, ParticleDataEntry>::iterator pdtEntry
1632 = pdt.begin(); pdtEntry != pdt.end(); ++pdtEntry) {
1633 particlePtr = &pdtEntry->second;
1635 // Extract some particle properties. Set some flags.
1636 int idNow = particlePtr->id();
1637 bool hasAntiNow = particlePtr->hasAnti();
1638 int spinTypeNow = particlePtr->spinType();
1639 int chargeTypeNow = particlePtr->chargeType();
1640 int baryonTypeNow = particlePtr->baryonNumberType();
1641 double m0Now = particlePtr->m0();
1642 double mMinNow = particlePtr->mMin();
1643 double mMaxNow = particlePtr->mMax();
1644 double mWidthNow = particlePtr->mWidth();
1645 double tau0Now = particlePtr->tau0();
1646 bool isResonanceNow = particlePtr->isResonance();
1647 bool hasPrinted = false;
1648 bool studyCloser = verbosity > 10 || !isResonanceNow;
1650 // Check that particle name consistent with charge information.
1651 string particleName = particlePtr->name(1);
1652 if (particleName.size() > 16) {
1653 os << " Warning: particle " << idNow << " has name " << particleName
1654 << " of length " << particleName.size() << "\n";
1660 for (int i = 0; i < int(particleName.size()); ++i) {
1661 if (particleName[i] == '+') ++nPos;
1662 if (particleName[i] == '-') ++nNeg;
1664 if ( (nPos > 0 && nNeg > 0) || ( nPos + nNeg > 0
1665 && 3 * (nPos - nNeg) != chargeTypeNow )) {
1666 os << " Warning: particle " << idNow << " has name " << particleName
1667 << " inconsistent with charge type " << chargeTypeNow << "\n";
1672 // Check that antiparticle name consistent with charge information.
1674 particleName = particlePtr->name(-1);
1675 if (particleName.size() > 16) {
1676 os << " Warning: particle " << idNow << " has name " << particleName
1677 << " of length " << particleName.size() << "\n";
1683 for (int i = 0; i < int(particleName.size()); ++i) {
1684 if (particleName[i] == '+') ++nPos;
1685 if (particleName[i] == '-') ++nNeg;
1687 if ( (nPos > 0 && nNeg > 0) || ( nPos + nNeg > 0
1688 && 3 * (nPos - nNeg) != -chargeTypeNow )) {
1689 os << " Warning: particle " << -idNow << " has name "
1690 << particleName << " inconsistent with charge type "
1691 << -chargeTypeNow << "\n";
1697 // Check that mass, mass range and width are consistent.
1698 if (particlePtr->useBreitWigner()) {
1699 if (mMinNow > m0Now) {
1700 os << " Error: particle " << idNow << " has mMin "
1701 << fixed << setprecision(5) << mMinNow
1702 << " larger than m0 " << m0Now << "\n";
1706 if (mMaxNow > mMinNow && mMaxNow < m0Now) {
1707 os << " Error: particle " << idNow << " has mMax "
1708 << fixed << setprecision(5) << mMaxNow
1709 << " smaller than m0 " << m0Now << "\n";
1713 if (mMaxNow > mMinNow && mMaxNow - mMinNow < mWidthNow) {
1714 os << " Warning: particle " << idNow << " has mMax - mMin "
1715 << fixed << setprecision(5) << mMaxNow - mMinNow
1716 << " smaller than mWidth " << mWidthNow << "\n";
1722 // Check that particle does not both have width and lifetime.
1723 if (mWidthNow > 0. && tau0Now > 0.) {
1724 os << " Warning: particle " << idNow << " has both nonvanishing width "
1725 << scientific << setprecision(5) << mWidthNow << " and lifetime "
1731 // Begin study decay channels.
1732 if (particlePtr->sizeChannels() > 0) {
1734 // Loop through all decay channels.
1735 double bRatioSum = 0.;
1736 double bRatioPos = 0.;
1737 double bRatioNeg = 0.;
1738 bool hasPosBR = false;
1739 bool hasNegBR = false;
1740 double threshMass = 0.;
1741 bool openChannel = false;
1742 for (int i = 0; i < particlePtr->sizeChannels(); ++i) {
1744 // Extract channel properties.
1745 int onMode = particlePtr->channel(i).onMode();
1746 double bRatio = particlePtr->channel(i).bRatio();
1747 int meMode = particlePtr->channel(i).meMode();
1748 int mult = particlePtr->channel(i).multiplicity();
1750 for (int j = 0; j < 8; ++j)
1751 prod[j] = particlePtr->channel(i).product(j);
1753 // Sum branching ratios. Include off-channels.
1754 if (onMode == 0 || onMode == 1) bRatioSum += bRatio;
1755 else if (onMode == 2) {bRatioPos += bRatio; hasPosBR = true;}
1756 else if (onMode == 3) {bRatioNeg += bRatio; hasNegBR = true;}
1758 // Error printout when unknown decay product code.
1759 for (int j = 0; j < 8; ++j) {
1760 if ( prod[j] != 0 && !isParticle(prod[j]) ) {
1761 os << " Error: unknown decay product for " << idNow
1762 << " -> " << prod[j] << "\n";
1769 // Error printout when no decay products or 0 interspersed.
1771 for (int j = 0; j < 8; ++j)
1772 if (prod[j] != 0) nLast = j + 1;
1773 if (mult == 0 || mult != nLast) {
1774 os << " Error: corrupted decay product list for "
1775 << particlePtr->id() << " -> ";
1776 for (int j = 0; j < 8; ++j) os << prod[j] << " ";
1783 // Check charge conservation and open phase space in decay channel.
1784 int chargeTypeSum = -chargeTypeNow;
1785 int baryonTypeSum = -baryonTypeNow;
1786 double avgFinalMass = 0.;
1787 double minFinalMass = 0.;
1788 bool canHandle = true;
1789 for (int j = 0; j < mult; ++j) {
1790 chargeTypeSum += chargeType( prod[j] );
1791 baryonTypeSum += baryonNumberType( prod[j] );
1792 avgFinalMass += m0( prod[j] );
1793 minFinalMass += m0Min( prod[j] );
1794 if (prod[j] == 81 || prod[j] == 82 || prod[j] == 83)
1797 threshMass += bRatio * avgFinalMass;
1799 // Error printout when charge or baryon number not conserved.
1800 if (chargeTypeSum != 0 && canHandle) {
1801 os << " Error: 3*charge changed by " << chargeTypeSum
1802 << " in " << idNow << " -> ";
1803 for (int j = 0; j < mult; ++j) os << prod[j] << " ";
1809 if ( baryonTypeSum != 0 && canHandle && particlePtr->isHadron() ) {
1810 os << " Error: 3*baryon number changed by " << baryonTypeSum
1811 << " in " << idNow << " -> ";
1812 for (int j = 0; j < mult; ++j) os << prod[j] << " ";
1819 // Begin check that some matrix elements are used correctly.
1820 bool correctME = true;
1822 // Check matrix element mode 0: recommended not into partons.
1823 if (meMode == 0 && !isResonanceNow) {
1824 bool hasPartons = false;
1825 for (int j = 0; j < mult; ++j) {
1826 int idAbs = abs(prod[j]);
1827 if ( idAbs < 10 || idAbs == 21 || idAbs == 81 || idAbs == 82
1828 || idAbs == 83 || (idAbs > 1000 && idAbs < 10000
1829 && (idAbs/10)%10 == 0) ) hasPartons = true;
1831 if (hasPartons) correctME = false;
1834 // Check matrix element mode 1: rho/omega -> pi+ pi- pi0.
1835 bool useME1 = ( mult == 3 && spinTypeNow == 3 && idNow > 100
1837 && particlePtr->channel(i).contains(211, -211, 111) );
1838 if ( meMode == 1 && !useME1 ) correctME = false;
1839 if ( meMode != 1 && useME1 ) correctME = false;
1841 // Check matrix element mode 2: polarization in V -> PS + PS.
1842 bool useME2 = ( mult == 2 && spinTypeNow == 3 && idNow > 100
1843 && idNow < 1000 && spinType(prod[0]) == 1
1844 && spinType(prod[1]) == 1 );
1845 if ( meMode == 2 && !useME2 ) correctME = false;
1846 if ( meMode != 2 && useME2 ) correctME = false;
1848 // Check matrix element mode 11, 12 and 13: Dalitz decay with
1849 // one or more particles in addition to the lepton pair,
1850 // or double Dalitz decay.
1851 bool useME11 = ( mult == 3 && !isResonanceNow
1852 && (prod[1] == 11 || prod[1] == 13 || prod[1] == 15)
1853 && prod[2] == -prod[1] );
1854 bool useME12 = ( mult > 3 && !isResonanceNow
1855 && (prod[mult - 2] == 11 || prod[mult - 2] == 13
1856 || prod[mult - 2] == 15) && prod[mult - 1] == -prod[mult - 2] );
1857 bool useME13 = ( mult == 4 && !isResonanceNow
1858 && (prod[0] == 11 || prod[0] == 13) && prod[1] == -prod[0]
1859 && (prod[2] == 11 || prod[2] == 13) && prod[3] == -prod[2] );
1860 if (useME13) useME12 = false;
1861 if ( meMode == 11 && !useME11 ) correctME = false;
1862 if ( meMode != 11 && useME11 ) correctME = false;
1863 if ( meMode == 12 && !useME12 ) correctME = false;
1864 if ( meMode != 12 && useME12 ) correctME = false;
1865 if ( meMode == 13 && !useME13 ) correctME = false;
1866 if ( meMode != 13 && useME13 ) correctME = false;
1868 // Check matrix element mode 21: tau -> nu_tau hadrons.
1869 bool useME21 = (idNow == 15 && mult > 2 && prod[0] == 16
1870 && abs(prod[1]) > 100);
1871 if ( meMode == 21 && !useME21 ) correctME = false;
1872 if ( meMode != 21 && useME21 ) correctME = false;
1874 // Check matrix element mode 22, but only for semileptonic decay.
1875 // For a -> b c d require types u = 2, ubar = -2, d = 1, dbar = -1.
1876 if ( isLepton(prod[0]) && isLepton(prod[1]) ) {
1877 bool useME22 = false;
1881 if (particlePtr->isLepton()) {
1882 typeA = (idNow > 0) ? 1 + (idNow-1)%2 : -1 - (1-idNow)%2;
1883 } else if (particlePtr->isHadron()) {
1884 int hQ = particlePtr->heaviestQuark();
1885 // Special case: for B_c either bbar or c decays.
1886 if (idNow == 541 && heaviestQuark(prod[2]) == -5) hQ = 4;
1887 typeA = (hQ > 0) ? 1 + (hQ-1)%2 : -1 - (1-hQ)%2;
1889 typeB = (prod[0] > 0) ? 1 + (prod[0]-1)%2 : -1 - (1-prod[0])%2;
1890 typeC = (prod[1] > 0) ? 1 + (prod[1]-1)%2 : -1 - (1-prod[1])%2;
1892 if ( (idNow == 130 || idNow == 310) && typeC * typeA < 0)
1894 if (mult == 3 && idNow == 2112 && prod[2] == 2212)
1896 if (mult == 3 && idNow == 3222 && prod[2] == 3122)
1898 if (mult > 2 && typeC == typeA && typeB * typeC < 0
1899 && (typeB + typeC)%2 != 0) useME22 = true;
1900 if ( meMode == 22 && !useME22 ) correctME = false;
1901 if ( meMode != 22 && useME22 ) correctME = false;
1904 // Check for matrix element mode 31.
1907 for (int j = 0; j < mult; ++j) if (prod[j] == 22) ++nGamma;
1908 if (nGamma != 1) correctME = false;
1911 // Check for unknown mode, or resonance-only mode.
1912 if ( !isResonanceNow && (meMode < 0 || (meMode > 2 && meMode <= 10)
1913 || (meMode > 13 && meMode <= 20) || (meMode > 23 && meMode <= 30)
1914 || (meMode > 31 && meMode <= 41) || meMode == 51 || meMode == 61
1915 || meMode == 71 || (meMode > 80 && meMode <= 90)
1916 || (!particlePtr->isOctetHadron() && meMode > 92) ) )
1919 // Print if incorrect matrix element mode.
1921 os << " Warning: meMode " << meMode << " used for "
1923 for (int j = 0; j < mult; ++j) os << prod[j] << " ";
1929 // Warning printout when no phase space for decay.
1930 if ( studyCloser && verbosity > 0 && canHandle && onMode > 0
1931 && particlePtr->m0Min() - minFinalMass < 0. ) {
1932 if (particlePtr->m0Max() - minFinalMass < 0.)
1933 os << " Error: decay never possible for ";
1934 else os << " Warning: decay sometimes not possible for ";
1935 os << idNow << " -> ";
1936 for (int j = 0; j < mult; ++j) os << prod[j] << " ";
1942 // End loop over decay channels.
1943 if (onMode > 0 && bRatio > 0.) openChannel = true;
1946 // Optional printout of threshold.
1947 if (verbosity%10 > 1 && particlePtr->useBreitWigner()) {
1948 threshMass /= bRatioSum;
1949 os << " Info: particle " << idNow << fixed << setprecision(5)
1950 << " has average mass threshold " << threshMass
1951 << " while mMin is " << mMinNow << "\n";
1955 // Error printout when no acceptable decay channels found.
1956 if (studyCloser && !openChannel) {
1957 os << " Error: no acceptable decay channel found for particle "
1963 // Warning printout when branching ratios do not sum to unity.
1964 if (studyCloser && (!hasAntiNow || (!hasPosBR && !hasNegBR))
1965 && abs(bRatioSum + bRatioPos - 1.) > 1e-8) {
1966 os << " Warning: particle " << idNow << fixed << setprecision(8)
1967 << " has branching ratio sum " << bRatioSum << "\n";
1970 } else if (studyCloser && hasAntiNow
1971 && (abs(bRatioSum + bRatioPos - 1.) > 1e-8
1972 || abs(bRatioSum + bRatioNeg - 1.) > 1e-8)) {
1973 os << " Warning: particle " << idNow << fixed << setprecision(8)
1974 << " has branching ratio sum " << bRatioSum + bRatioPos
1975 << " while its antiparticle has " << bRatioSum + bRatioNeg
1981 // End study of decay channels and loop over particles.
1983 if (hasPrinted) os << "\n";
1986 // Final output. Done.
1987 os << " Total number of errors and warnings is " << nErr << "\n";
1988 os << "\n -------- End PYTHIA Check of Particle Data Table --------"
1989 << "------\n" << endl;
1993 //--------------------------------------------------------------------------
1995 // Return the id of the sequentially next particle stored in table.
1997 int ParticleData::nextId(int idIn) {
1999 // Return 0 for negative or unknown codes. Return first for 0.
2000 if (idIn < 0 || (idIn > 0 && !isParticle(idIn))) return 0;
2001 if (idIn == 0) return pdt.begin()->first;
2003 // Find pointer to current particle and step up. Return 0 if impossible.
2004 map<int, ParticleDataEntry>::const_iterator pdtIn = pdt.find(idIn);
2005 if (pdtIn == pdt.end()) return 0;
2006 return (++pdtIn)->first;
2010 //--------------------------------------------------------------------------
2012 // Fractional width associated with open channels of one or two resonances.
2014 double ParticleData::resOpenFrac(int id1In, int id2In, int id3In) {
2020 if (isParticle(id1In)) answer = pdt[abs(id1In)].resOpenFrac(id1In);
2022 // Possibly second resonance.
2023 if (isParticle(id2In)) answer *= pdt[abs(id2In)].resOpenFrac(id2In);
2025 // Possibly third resonance.
2026 if (isParticle(id3In)) answer *= pdt[abs(id2In)].resOpenFrac(id3In);
2033 //--------------------------------------------------------------------------
2035 // Convert string to lowercase for case-insensitive comparisons.
2037 string ParticleData::toLower(const string& nameConv) {
2039 string temp(nameConv);
2040 for (int i = 0; i < int(temp.length()); ++i)
2041 temp[i] = std::tolower(temp[i]);
2046 //--------------------------------------------------------------------------
2048 // Allow several alternative inputs for true/false.
2050 bool ParticleData::boolString(string tag) {
2052 string tagLow = toLower(tag);
2053 return ( tagLow == "true" || tagLow == "1" || tagLow == "on"
2054 || tagLow == "yes" || tagLow == "ok" );
2058 //--------------------------------------------------------------------------
2060 // Extract XML value string following XML attribute.
2062 string ParticleData::attributeValue(string line, string attribute) {
2064 if (line.find(attribute) == string::npos) return "";
2065 int iBegAttri = line.find(attribute);
2066 int iBegQuote = line.find("\"", iBegAttri + 1);
2067 int iEndQuote = line.find("\"", iBegQuote + 1);
2068 return line.substr(iBegQuote + 1, iEndQuote - iBegQuote - 1);
2072 //--------------------------------------------------------------------------
2074 // Extract XML bool value following XML attribute.
2076 bool ParticleData::boolAttributeValue(string line, string attribute) {
2078 string valString = attributeValue(line, attribute);
2079 if (valString == "") return false;
2080 return boolString(valString);
2084 //--------------------------------------------------------------------------
2086 // Extract XML int value following XML attribute.
2088 int ParticleData::intAttributeValue(string line, string attribute) {
2089 string valString = attributeValue(line, attribute);
2090 if (valString == "") return 0;
2091 istringstream valStream(valString);
2093 valStream >> intVal;
2098 //--------------------------------------------------------------------------
2100 // Extract XML double value following XML attribute.
2102 double ParticleData::doubleAttributeValue(string line, string attribute) {
2103 string valString = attributeValue(line, attribute);
2104 if (valString == "") return 0.;
2105 istringstream valStream(valString);
2107 valStream >> doubleVal;
2112 //==========================================================================
2114 } // end namespace Pythia8