9 #include "Pythia8/ParticleData.h"
10 #include "Pythia8/ResonanceWidths.h"
11 #include "Pythia8/StandardModel.h"
12 #include "Pythia8/SusyResonanceWidths.h"
28 bool DecayChannel::contains(
int id1)
const {
31 for (
int i = 0; i < nProd; ++i)
if (prod[i] == id1) found1 =
true;
41 bool DecayChannel::contains(
int id1,
int id2)
const {
45 for (
int i = 0; i < nProd; ++i) {
46 if (!found1 && prod[i] == id1) {found1 =
true;
continue;}
47 if (!found2 && prod[i] == id2) {found2 =
true;
continue;}
49 return found1 && found2;
58 bool DecayChannel::contains(
int id1,
int id2,
int id3)
const {
63 for (
int i = 0; i < nProd; ++i) {
64 if (!found1 && prod[i] == id1) {found1 =
true;
continue;}
65 if (!found2 && prod[i] == id2) {found2 =
true;
continue;}
66 if (!found3 && prod[i] == id3) {found3 =
true;
continue;}
68 return found1 && found2 && found3;
85 const int ParticleDataEntry::INVISIBLENUMBER = 50;
86 const int ParticleDataEntry::INVISIBLETABLE[50] = { 12, 14, 16, 18, 23, 25,
87 32, 33, 35, 36, 39, 41, 1000012, 1000014, 1000016, 1000018, 1000022,
88 1000023, 1000025, 1000035, 1000045, 1000039, 2000012, 2000014, 2000016,
89 2000018, 4900012, 4900014, 4900016, 4900021, 4900022, 4900101, 4900102,
90 4900103, 4900104, 4900105, 4900106, 4900107, 4900108, 4900111, 4900113,
91 4900211, 4900213, 4900991, 5000039, 5100039, 9900012, 9900014, 9900016,
96 const int ParticleDataEntry::KNOWNNOWIDTH[3] = {10313, 10323, 10333};
99 const double ParticleDataEntry::MAXTAU0FORDECAY = 1000.;
102 const double ParticleDataEntry::MINMASSRESONANCE = 20.;
105 const double ParticleDataEntry::NARROWMASS = 1e-6;
108 const double ParticleDataEntry::CONSTITUENTMASSTABLE[10]
109 = {0., 0.325, 0.325, 0.50, 1.60, 5.00, 0., 0., 0., 0.7};
115 ParticleDataEntry::~ParticleDataEntry() {
116 if (resonancePtr != 0)
delete resonancePtr;
123 void ParticleDataEntry::setDefaults() {
126 isResonanceSave = (m0Save > MINMASSRESONANCE);
129 mayDecaySave = (tau0Save < MAXTAU0FORDECAY);
132 doExternalDecaySave =
false;
135 isVisibleSave =
true;
136 for (
int i = 0; i < INVISIBLENUMBER; ++i)
137 if (idSave == INVISIBLETABLE[i]) isVisibleSave =
false;
140 doForceWidthSave =
false;
143 setConstituentMass();
155 bool ParticleDataEntry::isHadron()
const {
157 if (idSave <= 100 || (idSave >= 1000000 && idSave <= 9000000)
158 || idSave >= 9900000)
return false;
159 if (idSave == 130 || idSave == 310)
return true;
160 if (idSave%10 == 0 || (idSave/10)%10 == 0 || (idSave/100)%10 == 0)
171 bool ParticleDataEntry::isMeson()
const {
173 if (idSave <= 100 || (idSave >= 1000000 && idSave <= 9000000)
174 || idSave >= 9900000)
return false;
175 if (idSave == 130 || idSave == 310)
return true;
176 if (idSave%10 == 0 || (idSave/10)%10 == 0 || (idSave/100)%10 == 0
177 || (idSave/1000)%10 != 0)
return false;
187 bool ParticleDataEntry::isBaryon()
const {
189 if (idSave <= 1000 || (idSave >= 1000000 && idSave <= 9000000)
190 || idSave >= 9900000)
return false;
191 if (idSave%10 == 0 || (idSave/10)%10 == 0 || (idSave/100)%10 == 0
192 || (idSave/1000)%10 == 0)
return false;
202 int ParticleDataEntry::heaviestQuark(
int idIn)
const {
204 if (!isHadron())
return 0;
208 if ( (idSave/1000)%10 == 0 ) {
209 hQ = (idSave/100)%10;
210 if (idSave == 130) hQ = 3;
211 if (hQ%2 == 1) hQ = -hQ;
214 }
else hQ = (idSave/1000)%10;
217 return (idIn > 0) ? hQ : -hQ;
225 int ParticleDataEntry::baryonNumberType(
int idIn)
const {
228 if (isQuark())
return (idIn > 0) ? 1 : -1;
231 if (isDiquark())
return (idIn > 0) ? 2 : -2;
234 if (isBaryon())
return (idIn > 0) ? 3 : -3;
246 void ParticleDataEntry::initBWmass() {
249 modeBWnow = particleDataPtr->modeBreitWigner;
250 if ( m0Save < NARROWMASS ) mWidthSave = 0.;
251 if ( mWidthSave < NARROWMASS || (mMaxSave > mMinSave
252 && mMaxSave - mMinSave < NARROWMASS) ) modeBWnow = 0;
253 if (modeBWnow == 0)
return;
257 atanLow = atan( 2. * (mMinSave - m0Save) / mWidthSave );
258 double atanHigh = (mMaxSave > mMinSave)
259 ? atan( 2. * (mMaxSave - m0Save) / mWidthSave ) : 0.5 * M_PI;
260 atanDif = atanHigh - atanLow;
262 atanLow = atan( (pow2(mMinSave) - pow2(m0Save))
263 / (m0Save * mWidthSave) );
264 double atanHigh = (mMaxSave > mMinSave)
265 ? atan( (pow2(mMaxSave) - pow2(m0Save)) / (m0Save * mWidthSave) )
267 atanDif = atanHigh - atanLow;
271 if (modeBWnow%2 == 1)
return;
276 for (
int i = 0; i < int(channels.size()); ++i)
277 if (channels[i].onMode() > 0) {
278 bRatSum += channels[i].bRatio();
279 double mChannelSum = 0.;
280 for (
int j = 0; j < channels[i].multiplicity(); ++j)
281 mChannelSum += particleDataPtr->m0( channels[i].product(j) );
282 mThrSum += channels[i].bRatio() * mChannelSum;
284 mThr = (bRatSum == 0.) ? 0. : mThrSum / bRatSum;
287 if (mThr + NARROWMASS > m0Save) {
289 bool knownProblem =
false;
290 for (
int i = 0; i < 3; ++i)
if (idSave == KNOWNNOWIDTH[i])
293 ostringstream osWarn;
294 osWarn <<
"for id = " << idSave;
295 particleDataPtr->infoPtr->errorMsg(
"Warning in ParticleDataEntry::"
296 "initBWmass: switching off width", osWarn.str(),
true);
307 double ParticleDataEntry::mSel() {
310 if (modeBWnow == 0 || mWidthSave < NARROWMASS)
return m0Save;
314 if (modeBWnow == 1) {
315 mNow = m0Save + 0.5 * mWidthSave
316 * tan( atanLow + atanDif * particleDataPtr->rndmPtr->flat() );
319 }
else if (modeBWnow == 2) {
320 double mWidthNow, fixBW, runBW;
321 double m0ThrS = m0Save*m0Save - mThr*mThr;
323 mNow = m0Save + 0.5 * mWidthSave
324 * tan( atanLow + atanDif * particleDataPtr->rndmPtr->flat() );
325 mWidthNow = mWidthSave * sqrtpos( (mNow*mNow - mThr*mThr) / m0ThrS );
326 fixBW = mWidthSave / (pow2(mNow - m0Save) + pow2(0.5 * mWidthSave));
327 runBW = mWidthNow / (pow2(mNow - m0Save) + pow2(0.5 * mWidthNow));
328 }
while (runBW < particleDataPtr->rndmPtr->flat()
329 * particleDataPtr->maxEnhanceBW * fixBW);
332 }
else if (modeBWnow == 3) {
333 m2Now = m0Save*m0Save + m0Save * mWidthSave
334 * tan( atanLow + atanDif * particleDataPtr->rndmPtr->flat() );
335 mNow = sqrtpos( m2Now);
339 double mwNow, fixBW, runBW;
340 double m2Ref = m0Save * m0Save;
341 double mwRef = m0Save * mWidthSave;
342 double m2Thr = mThr * mThr;
344 m2Now = m2Ref + mwRef * tan( atanLow + atanDif
345 * particleDataPtr->rndmPtr->flat() );
346 mNow = sqrtpos( m2Now);
347 mwNow = mNow * mWidthSave
348 * sqrtpos( (m2Now - m2Thr) / (m2Ref - m2Thr) );
349 fixBW = mwRef / (pow2(m2Now - m2Ref) + pow2(mwRef));
350 runBW = mwNow / (pow2(m2Now - m2Ref) + pow2(mwNow));
351 }
while (runBW < particleDataPtr->rndmPtr->flat()
352 * particleDataPtr->maxEnhanceBW * fixBW);
363 double ParticleDataEntry::mRun(
double mHat) {
366 if (idSave > 6)
return m0Save;
367 double mQRun = particleDataPtr->mQRun[idSave];
368 double Lam5 = particleDataPtr->Lambda5Run;
371 if (idSave < 4)
return mQRun * pow ( log(2. / Lam5)
372 / log(max(2., mHat) / Lam5), 12./23.);
375 return mQRun * pow ( log(mQRun / Lam5)
376 / log(max(mQRun, mHat) / Lam5), 12./23.);
384 void ParticleDataEntry::rescaleBR(
double newSumBR) {
387 double oldSumBR = 0.;
388 for (
int i = 0; i < int(channels.size()); ++ i)
389 oldSumBR += channels[i].bRatio();
390 double rescaleFactor = newSumBR / oldSumBR;
391 for (
int i = 0; i < int(channels.size()); ++ i)
392 channels[i].rescaleBR(rescaleFactor);
400 bool ParticleDataEntry::preparePick(
int idSgn,
double mHat,
int idInFlav) {
406 if (isResonanceSave && resonancePtr != 0) {
407 resonancePtr->widthStore(idSgn, mHat, idInFlav);
408 for (
int i = 0; i < int(channels.size()); ++i)
409 currentBRSum += channels[i].currentBR();
415 for (
int i = 0; i < int(channels.size()); ++i) {
416 onMode = channels[i].onMode();
418 if ( idSgn > 0 && (onMode == 1 || onMode == 2) )
419 currentBRNow = channels[i].bRatio();
420 else if ( idSgn < 0 && (onMode == 1 || onMode == 3) )
421 currentBRNow = channels[i].bRatio();
422 channels[i].currentBR(currentBRNow);
423 currentBRSum += currentBRNow;
428 return (currentBRSum > 0.);
436 DecayChannel& ParticleDataEntry::pickChannel() {
439 int size = channels.size();
440 double rndmBR = currentBRSum * particleDataPtr->rndmPtr->flat();
442 do rndmBR -= channels[++i].currentBR();
443 while (rndmBR > 0. && i < size);
446 if (i == size) i = 0;
456 void ParticleDataEntry::setResonancePtr(
457 ResonanceWidths* resonancePtrIn) {
458 if (resonancePtr == resonancePtrIn)
return;
459 if (resonancePtr != 0)
delete resonancePtr;
460 resonancePtr = resonancePtrIn;
463 void ParticleDataEntry::resInit(Info* infoPtrIn, Settings* settingsPtrIn,
464 ParticleData* particleDataPtrIn, Couplings* couplingsPtrIn) {
465 if (resonancePtr != 0) resonancePtr->init(infoPtrIn, settingsPtrIn,
466 particleDataPtrIn, couplingsPtrIn);
469 double ParticleDataEntry::resWidth(
int idSgn,
double mHat,
int idIn,
470 bool openOnly,
bool setBR) {
471 return (resonancePtr != 0) ? resonancePtr->width( idSgn, mHat,
472 idIn, openOnly, setBR) : 0.;
475 double ParticleDataEntry::resWidthOpen(
int idSgn,
double mHat,
int idIn) {
476 return (resonancePtr != 0) ? resonancePtr->widthOpen( idSgn, mHat, idIn)
480 double ParticleDataEntry::resWidthStore(
int idSgn,
double mHat,
int idIn) {
481 return (resonancePtr != 0) ? resonancePtr->widthStore( idSgn, mHat, idIn)
485 double ParticleDataEntry::resOpenFrac(
int idSgn) {
486 return (resonancePtr != 0) ? resonancePtr->openFrac(idSgn) : 1.;
489 double ParticleDataEntry::resWidthRescaleFactor() {
490 return (resonancePtr != 0) ? resonancePtr->widthRescaleFactor() : 1.;
493 double ParticleDataEntry::resWidthChan(
double mHat,
int idAbs1,
495 return (resonancePtr != 0) ? resonancePtr->widthChan( mHat, idAbs1,
506 void ParticleDataEntry::setConstituentMass() {
509 constituentMassSave = m0Save;
512 if (idSave < 6) constituentMassSave = CONSTITUENTMASSTABLE[idSave];
513 if (idSave == 21) constituentMassSave = CONSTITUENTMASSTABLE[9];
516 if (idSave > 1000 && idSave < 10000 && (idSave/10)%10 == 0) {
517 int id1 = idSave/1000;
518 int id2 = (idSave/100)%10;
519 if (id1 <6 && id2 < 6) constituentMassSave
520 = CONSTITUENTMASSTABLE[id1] + CONSTITUENTMASSTABLE[id2];
538 void ParticleData::initCommon() {
541 modeBreitWigner = settingsPtr->mode(
"ParticleData:modeBreitWigner");
544 maxEnhanceBW = settingsPtr->parm(
"ParticleData:maxEnhanceBW");
547 mQRun[1] = settingsPtr->parm(
"ParticleData:mdRun");
548 mQRun[2] = settingsPtr->parm(
"ParticleData:muRun");
549 mQRun[3] = settingsPtr->parm(
"ParticleData:msRun");
550 mQRun[4] = settingsPtr->parm(
"ParticleData:mcRun");
551 mQRun[5] = settingsPtr->parm(
"ParticleData:mbRun");
552 mQRun[6] = settingsPtr->parm(
"ParticleData:mtRun");
555 double alphaSvalue = settingsPtr->parm(
"ParticleData:alphaSvalueMRun");
557 alphaS.init( alphaSvalue, 1, 5,
false);
558 Lambda5Run = alphaS.Lambda5();
568 void ParticleData::initWidths( vector<ResonanceWidths*> resonancePtrs) {
575 ResonanceWidths* resonancePtr = 0;
576 for (map<int, ParticleDataEntry>::iterator pdtEntry = pdt.begin();
577 pdtEntry != pdt.end(); ++pdtEntry) {
578 ParticleDataEntry& pdtNow = pdtEntry->second;
582 resonancePtr = pdtNow.getResonancePtr();
583 if (resonancePtr != 0) pdtNow.setResonancePtr(0);
588 resonancePtr =
new ResonanceGmZ(23);
589 setResonancePtr( 23, resonancePtr);
590 resonancePtr =
new ResonanceW(24);
591 setResonancePtr( 24, resonancePtr);
592 resonancePtr =
new ResonanceTop(6);
593 setResonancePtr( 6, resonancePtr);
596 if (!settingsPtr->flag(
"Higgs:useBSM")) {
597 resonancePtr =
new ResonanceH(0, 25);
598 setResonancePtr( 25, resonancePtr);
602 resonancePtr =
new ResonanceH(1, 25);
603 setResonancePtr( 25, resonancePtr);
604 resonancePtr =
new ResonanceH(2, 35);
605 setResonancePtr( 35, resonancePtr);
606 resonancePtr =
new ResonanceH(3, 36);
607 setResonancePtr( 36, resonancePtr);
608 resonancePtr =
new ResonanceHchg(37);
609 setResonancePtr( 37, resonancePtr);
613 resonancePtr =
new ResonanceFour(7);
614 setResonancePtr( 7, resonancePtr);
615 resonancePtr =
new ResonanceFour(8);
616 setResonancePtr( 8, resonancePtr);
617 resonancePtr =
new ResonanceFour(17);
618 setResonancePtr( 17, resonancePtr);
619 resonancePtr =
new ResonanceFour(18);
620 setResonancePtr( 18, resonancePtr);
623 resonancePtr =
new ResonanceZprime(32);
624 setResonancePtr( 32, resonancePtr);
625 resonancePtr =
new ResonanceWprime(34);
626 setResonancePtr( 34, resonancePtr);
627 resonancePtr =
new ResonanceRhorizontal(41);
628 setResonancePtr( 41, resonancePtr);
631 resonancePtr =
new ResonanceLeptoquark(42);
632 setResonancePtr( 42, resonancePtr);
636 resonancePtr =
new ResonanceGmZ(93);
637 setResonancePtr( 93, resonancePtr);
638 resonancePtr =
new ResonanceW(94);
639 setResonancePtr( 94, resonancePtr);
643 for(
int i = 1; i < 7; i++){
644 resonancePtr =
new ResonanceSquark(1000000 + i);
645 setResonancePtr( 1000000 + i, resonancePtr);
646 resonancePtr =
new ResonanceSquark(2000000 + i);
647 setResonancePtr( 2000000 + i, resonancePtr);
651 for(
int i = 1; i < 7; i++){
652 resonancePtr =
new ResonanceSlepton(1000010 + i);
653 setResonancePtr( 1000010 + i, resonancePtr);
654 resonancePtr =
new ResonanceSlepton(2000010 + i);
655 setResonancePtr( 2000010 + i, resonancePtr);
659 resonancePtr =
new ResonanceGluino(1000021);
660 setResonancePtr( 1000021, resonancePtr);
663 resonancePtr =
new ResonanceChar(1000024);
664 setResonancePtr( 1000024, resonancePtr);
665 resonancePtr =
new ResonanceChar(1000037);
666 setResonancePtr( 1000037, resonancePtr);
669 resonancePtr =
new ResonanceNeut(1000022);
670 setResonancePtr( 1000022, resonancePtr);
671 resonancePtr =
new ResonanceNeut(1000023);
672 setResonancePtr( 1000023, resonancePtr);
673 resonancePtr =
new ResonanceNeut(1000025);
674 setResonancePtr( 1000025, resonancePtr);
675 resonancePtr =
new ResonanceNeut(1000035);
676 setResonancePtr( 1000035, resonancePtr);
677 resonancePtr =
new ResonanceNeut(1000045);
678 setResonancePtr( 1000045, resonancePtr);
681 for (
int i = 1; i < 7; ++i) {
682 resonancePtr =
new ResonanceExcited(4000000 + i);
683 setResonancePtr( 4000000 + i, resonancePtr);
685 for (
int i = 11; i < 17; ++i) {
686 resonancePtr =
new ResonanceExcited(4000000 + i);
687 setResonancePtr( 4000000 + i, resonancePtr);
691 resonancePtr =
new ResonanceGraviton(5100039);
692 setResonancePtr( 5100039, resonancePtr);
693 resonancePtr =
new ResonanceKKgluon(5100021);
694 setResonancePtr( 5100021, resonancePtr);
698 resonancePtr =
new ResonanceNuRight(9900012);
699 setResonancePtr( 9900012, resonancePtr);
700 resonancePtr =
new ResonanceNuRight(9900014);
701 setResonancePtr( 9900014, resonancePtr);
702 resonancePtr =
new ResonanceNuRight(9900016);
703 setResonancePtr( 9900016, resonancePtr);
704 resonancePtr =
new ResonanceZRight(9900023);
705 setResonancePtr( 9900023, resonancePtr);
706 resonancePtr =
new ResonanceWRight(9900024);
707 setResonancePtr( 9900024, resonancePtr);
708 resonancePtr =
new ResonanceHchgchgLeft(9900041);
709 setResonancePtr( 9900041, resonancePtr);
710 resonancePtr =
new ResonanceHchgchgRight(9900042);
711 setResonancePtr( 9900042, resonancePtr);
714 for (
int i = 0; i < int(resonancePtrs.size()); ++i) {
715 int idNow = resonancePtrs[i]->id();
716 resonancePtrs[i]->initBasic(idNow);
717 setResonancePtr( idNow, resonancePtrs[i]);
721 vector<int> idOrdered;
722 vector<double> m0Ordered;
725 idOrdered.push_back(23);
726 m0Ordered.push_back(m0(23));
727 idOrdered.push_back(24);
728 m0Ordered.push_back(m0(24));
731 for (map<int, ParticleDataEntry>::iterator pdtEntry = pdt.begin();
732 pdtEntry != pdt.end(); ++pdtEntry) {
733 ParticleDataEntry& pdtNow = pdtEntry->second;
734 int idNow = pdtNow.id();
737 if (pdtNow.isResonance() && pdtNow.getResonancePtr() == 0) {
738 resonancePtr =
new ResonanceGeneric(idNow);
739 setResonancePtr( idNow, resonancePtr);
743 if (pdtNow.getResonancePtr() != 0 && idNow != 23 && idNow != 24) {
744 double m0Now = pdtNow.m0();
745 idOrdered.push_back(idNow);
746 m0Ordered.push_back(m0Now);
747 for (
int i =
int(idOrdered.size()) - 2; i > 1; --i) {
748 if (m0Ordered[i] < m0Now)
break;
749 swap( idOrdered[i], idOrdered[i + 1]);
750 swap( m0Ordered[i], m0Ordered[i + 1]);
756 for (
int i = 0; i < int(idOrdered.size()); ++i) {
757 resInit( idOrdered[i]);
758 ParticleDataEntry* pdtPtrNow = particleDataEntryPtr( idOrdered[i]);
759 pdtPtrNow->initBWmass();
768 bool ParticleData::readXML(
string inFile,
bool reset) {
771 if (reset) {pdt.clear(); isInit =
false;}
774 vector<string> files;
775 files.push_back(inFile);
778 for (
int i = 0; i < int(files.size()); ++i) {
779 const char* cstring = files[i].c_str();
780 ifstream is(cstring);
784 infoPtr->errorMsg(
"Error in ParticleData::readXML:"
785 " did not find file", files[i]);
792 while ( getline(is, line) ) {
795 istringstream getfirst(line);
800 if (word1 ==
"<particle") {
801 while (line.find(
">") == string::npos) {
803 getline(is, addLine);
808 int idTmp = intAttributeValue( line,
"id");
809 string nameTmp = attributeValue( line,
"name");
810 string antiNameTmp = attributeValue( line,
"antiName");
811 if (antiNameTmp ==
"") antiNameTmp =
"void";
812 int spinTypeTmp = intAttributeValue( line,
"spinType");
813 int chargeTypeTmp = intAttributeValue( line,
"chargeType");
814 int colTypeTmp = intAttributeValue( line,
"colType");
815 double m0Tmp = doubleAttributeValue( line,
"m0");
816 double mWidthTmp = doubleAttributeValue( line,
"mWidth");
817 double mMinTmp = doubleAttributeValue( line,
"mMin");
818 double mMaxTmp = doubleAttributeValue( line,
"mMax");
819 double tau0Tmp = doubleAttributeValue( line,
"tau0");
822 if (isParticle(idTmp)) pdt.erase(idTmp);
825 addParticle( idTmp, nameTmp, antiNameTmp, spinTypeTmp, chargeTypeTmp,
826 colTypeTmp, m0Tmp, mWidthTmp, mMinTmp, mMaxTmp, tau0Tmp);
827 particlePtr = particleDataEntryPtr(idTmp);
830 }
else if (word1 ==
"<channel") {
831 while (line.find(
">") == string::npos) {
833 getline(is, addLine);
838 int onMode = intAttributeValue( line,
"onMode");
839 double bRatio = doubleAttributeValue( line,
"bRatio");
840 int meMode = intAttributeValue( line,
"meMode");
841 string products = attributeValue( line,
"products");
844 istringstream prodStream(products);
845 int prod0 = 0;
int prod1 = 0;
int prod2 = 0;
int prod3 = 0;
846 int prod4 = 0;
int prod5 = 0;
int prod6 = 0;
int prod7 = 0;
847 prodStream >> prod0 >> prod1 >> prod2 >> prod3 >> prod4 >> prod5
850 infoPtr->errorMsg(
"Error in ParticleData::readXML:"
851 " incomplete decay channel", line);
856 if (particlePtr == 0) {
857 infoPtr->errorMsg(
"Error in ParticleData::readXML:"
858 " orphan decay channel", line);
861 particlePtr->addChannel(onMode, bRatio, meMode, prod0, prod1,
862 prod2, prod3, prod4, prod5, prod6, prod7);
865 }
else if (word1 ==
"<file") {
866 string file = attributeValue(line,
"name");
868 infoPtr->errorMsg(
"Error in ParticleData::readXML:"
869 " skip unrecognized file name", line);
870 }
else files.push_back(file);
878 if (reset)
for (map<int, ParticleDataEntry>::iterator pdtEntry
879 = pdt.begin(); pdtEntry != pdt.end(); ++pdtEntry) {
880 particlePtr = &pdtEntry->second;
881 particlePtr->setHasChanged(
false);
894 void ParticleData::listXML(
string outFile) {
897 const char* cstring = outFile.c_str();
898 ofstream os(cstring);
901 for (map<int, ParticleDataEntry>::iterator pdtEntry
902 = pdt.begin(); pdtEntry != pdt.end(); ++pdtEntry) {
903 particlePtr = &pdtEntry->second;
906 os <<
"<particle id=\"" << particlePtr->id() <<
"\""
907 <<
" name=\"" << particlePtr->name() <<
"\"";
908 if (particlePtr->hasAnti())
909 os <<
" antiName=\"" << particlePtr->name(-1) <<
"\"";
910 os <<
" spinType=\"" << particlePtr->spinType() <<
"\""
911 <<
" chargeType=\"" << particlePtr->chargeType() <<
"\""
912 <<
" colType=\"" << particlePtr->colType() <<
"\"\n";
914 double m0Now = particlePtr->m0();
915 if (m0Now == 0 || (m0Now > 0.1 && m0Now < 1000.))
916 os << fixed << setprecision(5);
917 else os << scientific << setprecision(3);
918 os <<
" m0=\"" << m0Now <<
"\"";
919 if (particlePtr->mWidth() > 0.)
920 os <<
" mWidth=\"" << particlePtr->mWidth() <<
"\""
921 <<
" mMin=\"" << particlePtr->mMin() <<
"\""
922 <<
" mMax=\"" << particlePtr->mMax() <<
"\"";
923 if (particlePtr->tau0() > 0.) os << scientific << setprecision(5)
924 <<
" tau0=\"" << particlePtr->tau0() <<
"\"";
928 if (particlePtr->sizeChannels() > 0) {
929 for (
int i = 0; i < particlePtr->sizeChannels(); ++i) {
930 const DecayChannel& channel = particlePtr->channel(i);
931 int mult = channel.multiplicity();
934 os <<
" <channel onMode=\"" << channel.onMode() <<
"\""
935 << fixed << setprecision(7)
936 <<
" bRatio=\"" << channel.bRatio() <<
"\"";
937 if (channel.meMode() > 0)
938 os <<
" meMode=\"" << channel.meMode() <<
"\"";
939 os <<
" products=\"";
940 for (
int j = 0; j < mult; ++j) {
941 os << channel.product(j);
942 if (j < mult - 1) os <<
" ";
951 os <<
"</particle>\n\n";
961 bool ParticleData::readFF(
string inFile,
bool reset) {
964 if (reset) {pdt.clear(); isInit =
false;}
967 const char* cstring = inFile.c_str();
968 ifstream is(cstring);
970 infoPtr->errorMsg(
"Error in ParticleData::readFF:"
971 " did not find file", inFile);
978 bool readParticle =
false;
979 while ( getline(is, line) ) {
982 if (line.find_first_not_of(
" \n\t\v\b\r\f\a") == string::npos) {
988 istringstream readLine(line);
995 string nameTmp, antiNameTmp;
996 int spinTypeTmp, chargeTypeTmp, colTypeTmp;
997 double m0Tmp, mWidthTmp, mMinTmp, mMaxTmp, tau0Tmp;
1001 readLine >> idTmp >> nameTmp >> antiNameTmp >> spinTypeTmp
1002 >> chargeTypeTmp >> colTypeTmp >> m0Tmp >> mWidthTmp
1003 >> mMinTmp >> mMaxTmp >> tau0Tmp;
1007 infoPtr->errorMsg(
"Error in ParticleData::readFF:"
1008 " incomplete particle", line);
1013 if (isParticle(idTmp)) pdt.erase(idTmp);
1016 addParticle( idTmp, nameTmp, antiNameTmp, spinTypeTmp, chargeTypeTmp,
1017 colTypeTmp, m0Tmp, mWidthTmp, mMinTmp, mMaxTmp, tau0Tmp);
1018 particlePtr = particleDataEntryPtr(idTmp);
1019 readParticle =
false;
1028 int prod0 = 0;
int prod1 = 0;
int prod2 = 0;
int prod3 = 0;
1029 int prod4 = 0;
int prod5 = 0;
int prod6 = 0;
int prod7 = 0;
1032 readLine >> onMode >> bRatio >> meMode >> prod0;
1034 infoPtr->errorMsg(
"Error in ParticleData::readFF:"
1035 " incomplete decay channel", line);
1038 readLine >> prod1 >> prod2 >> prod3 >> prod4 >> prod5
1042 if (particlePtr == 0) {
1043 infoPtr->errorMsg(
"Error in ParticleData::readFF:"
1044 " orphan decay channel", line);
1047 particlePtr->addChannel(onMode, bRatio, meMode, prod0, prod1,
1048 prod2, prod3, prod4, prod5, prod6, prod7);
1066 void ParticleData::listFF(
string outFile) {
1069 const char* cstring = outFile.c_str();
1070 ofstream os(cstring);
1073 for (map<int, ParticleDataEntry>::iterator pdtEntry
1074 = pdt.begin(); pdtEntry != pdt.end(); ++pdtEntry) {
1075 particlePtr = &pdtEntry->second;
1078 double m0Now = particlePtr->m0();
1079 if (m0Now == 0 || (m0Now > 0.1 && m0Now < 1000.))
1080 os << fixed << setprecision(5);
1081 else os << scientific << setprecision(3);
1084 os <<
"\n" << setw(8) << particlePtr->id() <<
" "
1085 << left << setw(16) << particlePtr->name() <<
" "
1086 << setw(16) << particlePtr->name(-1) <<
" "
1087 << right << setw(2) << particlePtr->spinType() <<
" "
1088 << setw(2) << particlePtr->chargeType() <<
" "
1089 << setw(2) << particlePtr->colType() <<
" "
1090 << setw(10) << particlePtr->m0() <<
" "
1091 << setw(10) << particlePtr->mWidth() <<
" "
1092 << setw(10) << particlePtr->mMin() <<
" "
1093 << setw(10) << particlePtr->mMax() <<
" "
1094 << scientific << setprecision(5)
1095 << setw(12) << particlePtr->tau0() <<
"\n";
1098 if (particlePtr->sizeChannels() > 0) {
1099 for (
int i = 0; i < particlePtr->sizeChannels(); ++i) {
1100 const DecayChannel& channel = particlePtr->channel(i);
1101 os <<
" " << setw(6) << channel.onMode()
1102 <<
" " << fixed << setprecision(7) << setw(10)
1103 << channel.bRatio() <<
" "
1104 << setw(3) << channel.meMode() <<
" ";
1105 for (
int j = 0; j < channel.multiplicity(); ++j)
1106 os << setw(8) << channel.product(j) <<
" ";
1120 bool ParticleData::readString(
string lineIn,
bool warn, ostream& os) {
1123 if (lineIn.find_first_not_of(
" \n\t\v\b\r\f\a") == string::npos)
return true;
1126 string line = lineIn;
1129 int firstChar = line.find_first_not_of(
" \n\t\v\b\r\f\a");
1130 if (!isdigit(line[firstChar]))
return true;
1133 for (
int j = 0; j < int(line.size()); ++ j)
1134 if (line[j] ==
':' || line[j] ==
'=') line[j] =
' ';
1139 istringstream getWord(line);
1140 getWord >> idTmp >> property;
1141 property = toLower(property);
1144 if ( (!isParticle(idTmp) && property !=
"all" && property !=
"new")
1146 if (warn) os <<
"\n PYTHIA Error: input particle not found in Particle"
1147 <<
" Data Table:\n " << lineIn <<
"\n";
1148 readingFailedSave =
true;
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);
1256 if (property ==
"all" || property ==
"new") {
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.;
1271 getWord >> nameTmp >> antiNameTmp >> spinTypeTmp >> chargeTypeTmp
1272 >> colTypeTmp >> m0Tmp >> mWidthTmp >> mMinTmp >> mMaxTmp
1276 if (property ==
"all" && isParticle(idTmp)) {
1277 setAll( idTmp, nameTmp, antiNameTmp, spinTypeTmp, chargeTypeTmp,
1278 colTypeTmp, m0Tmp, mWidthTmp, mMinTmp, mMaxTmp, tau0Tmp);
1282 if (isParticle(idTmp)) pdt.erase(idTmp);
1283 addParticle( idTmp, nameTmp, antiNameTmp, spinTypeTmp, chargeTypeTmp,
1284 colTypeTmp, m0Tmp, mWidthTmp, mMinTmp, mMaxTmp, tau0Tmp);
1290 if (property ==
"onmode") {
1293 getWord >> onModeIn;
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);
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;
1322 vector<int> idToMatch;
1326 if (!getWord)
break;
1327 idToMatch.push_back(abs(idRead));
1329 int nToMatch = idToMatch.size();
1332 for (
int i = 0; i < pdt[idTmp].sizeChannels(); ++i) {
1333 int multi = pdt[idTmp].channel(i).multiplicity();
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);
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);
1372 if (property ==
"rescalebr") {
1375 pdt[idTmp].rescaleBR(factor);
1380 if (property ==
"onechannel") pdt[idTmp].clearChannels();
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);
1398 if (channel < 0 || channel >= pdt[idTmp].sizeChannels())
return false;
1402 if (property ==
"onmode" || property ==
"all") {
1405 getWord >> onModeIn;
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;
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);
1444 if (property ==
"rescalebr") {
1447 pdt[idTmp].channel(channel).rescaleBR(factor);
1453 if (warn) os <<
"\n PYTHIA Error: input property not found in Particle"
1454 <<
" Data Table:\n " << lineIn <<
"\n";
1455 readingFailedSave =
true;
1464 void ParticleData::list(
bool changedOnly,
bool changedRes, ostream& os) {
1468 os <<
"\n -------- PYTHIA Particle Data Table (complete) --------"
1469 <<
"------------------------------------------------------------"
1470 <<
"--------------\n \n";
1473 os <<
"\n -------- PYTHIA Particle Data Table (changed only) ----"
1474 <<
"------------------------------------------------------------"
1475 <<
"--------------\n \n";
1477 os <<
" id name antiName spn chg col m0"
1478 <<
" mWidth mMin mMax tau0 res dec ext "
1479 <<
"vis wid\n no onMode bRatio meMode products \n";
1483 for (map<int, ParticleDataEntry>::iterator pdtEntry
1484 = pdt.begin(); pdtEntry != pdt.end(); ++pdtEntry) {
1485 particlePtr = &pdtEntry->second;
1486 if ( !changedOnly || particlePtr->hasChanged() ||
1487 ( changedRes && particlePtr->getResonancePtr() != 0 ) ) {
1490 double m0Now = particlePtr->m0();
1491 if (m0Now == 0 || (m0Now > 0.1 && m0Now < 1000.))
1492 os << fixed << setprecision(5);
1493 else os << scientific << setprecision(3);
1497 os <<
"\n" << setw(8) << particlePtr->id() <<
" " << left;
1498 if (particlePtr->name(-1) ==
"void")
1499 os << setw(33) << particlePtr->name() <<
" ";
1500 else os << setw(16) << particlePtr->name() <<
" "
1501 << setw(16) << particlePtr->name(-1) <<
" ";
1502 os << right << setw(2) << particlePtr->spinType() <<
" "
1503 << setw(2) << particlePtr->chargeType() <<
" "
1504 << setw(2) << particlePtr->colType() <<
" "
1505 << setw(10) << particlePtr->m0() <<
" "
1506 << setw(10) << particlePtr->mWidth() <<
" "
1507 << setw(10) << particlePtr->mMin() <<
" "
1508 << setw(10) << particlePtr->mMax() <<
" "
1509 << scientific << setprecision(5)
1510 << setw(12) << particlePtr->tau0() <<
" " << setw(2)
1511 << particlePtr->isResonance() <<
" " << setw(2)
1512 << (particlePtr->mayDecay() && particlePtr->canDecay())
1513 <<
" " << setw(2) << particlePtr->doExternalDecay() <<
" "
1514 << setw(2) << particlePtr->isVisible()<<
" "
1515 << setw(2) << particlePtr->doForceWidth() <<
"\n";
1518 if (particlePtr->sizeChannels() > 0) {
1519 for (
int i = 0; i < int(particlePtr->sizeChannels()); ++i) {
1520 const DecayChannel& channel = particlePtr->channel(i);
1521 os <<
" " << setprecision(7)
1523 << setw(6) << channel.onMode()
1524 << fixed<< setw(12) << channel.bRatio()
1525 << setw(5) << channel.meMode() <<
" ";
1526 for (
int j = 0; j < channel.multiplicity(); ++j)
1527 os << setw(8) << channel.product(j) <<
" ";
1536 if (changedOnly && nList == 0) os <<
"\n no particle data has been "
1537 <<
"changed from its default value \n";
1538 os <<
"\n -------- End PYTHIA Particle Data Table -----------------"
1539 <<
"--------------------------------------------------------------"
1540 <<
"----------\n" << endl;
1548 void ParticleData::list(vector<int> idList, ostream& os) {
1551 os <<
"\n -------- PYTHIA Particle Data Table (partial) ---------"
1552 <<
"------------------------------------------------------------"
1553 <<
"--------------\n \n";
1554 os <<
" id name antiName spn chg col m0"
1555 <<
" mWidth mMin mMax tau0 res dec ext "
1556 <<
"vis wid\n no onMode bRatio meMode products \n";
1559 for (
int i = 0; i < int(idList.size()); ++i) {
1560 particlePtr = particleDataEntryPtr(idList[i]);
1563 double m0Now = particlePtr->m0();
1564 if (m0Now == 0 || (m0Now > 0.1 && m0Now < 1000.))
1565 os << fixed << setprecision(5);
1566 else os << scientific << setprecision(3);
1569 os <<
"\n" << setw(8) << particlePtr->id() <<
" " << left;
1570 if (particlePtr->name(-1) ==
"void")
1571 os << setw(33) << particlePtr->name() <<
" ";
1572 else os << setw(16) << particlePtr->name() <<
" "
1573 << setw(16) << particlePtr->name(-1) <<
" ";
1574 os << right << setw(2) << particlePtr->spinType() <<
" "
1575 << setw(2) << particlePtr->chargeType() <<
" "
1576 << setw(2) << particlePtr->colType() <<
" "
1577 << setw(10) << particlePtr->m0() <<
" "
1578 << setw(10) << particlePtr->mWidth() <<
" "
1579 << setw(10) << particlePtr->mMin() <<
" "
1580 << setw(10) << particlePtr->mMax() <<
" "
1581 << scientific << setprecision(5)
1582 << setw(12) << particlePtr->tau0() <<
" " << setw(2)
1583 << particlePtr->isResonance() <<
" " << setw(2)
1584 << (particlePtr->mayDecay() && particlePtr->canDecay())
1585 <<
" " << setw(2) << particlePtr->doExternalDecay() <<
" "
1586 << setw(2) << particlePtr->isVisible() <<
" "
1587 << setw(2) << particlePtr->doForceWidth() <<
"\n";
1590 if (particlePtr->sizeChannels() > 0) {
1591 for (
int j = 0; j < int(particlePtr->sizeChannels()); ++j) {
1592 const DecayChannel& channel = particlePtr->channel(j);
1593 os <<
" " << setprecision(7)
1595 << setw(6) << channel.onMode()
1596 << fixed<< setw(12) << channel.bRatio()
1597 << setw(5) << channel.meMode() <<
" ";
1598 for (
int k = 0; k < channel.multiplicity(); ++k)
1599 os << setw(8) << channel.product(k) <<
" ";
1607 os <<
"\n -------- End PYTHIA Particle Data Table -----------------"
1608 <<
"--------------------------------------------------------------"
1609 <<
"----------\n" << endl;
1624 void ParticleData::checkTable(
int verbosity, ostream& os) {
1627 os <<
"\n -------- PYTHIA Check of Particle Data Table ------------"
1632 for (map<int, ParticleDataEntry>::iterator pdtEntry
1633 = pdt.begin(); pdtEntry != pdt.end(); ++pdtEntry) {
1634 particlePtr = &pdtEntry->second;
1637 int idNow = particlePtr->id();
1638 bool hasAntiNow = particlePtr->hasAnti();
1639 int spinTypeNow = particlePtr->spinType();
1640 int chargeTypeNow = particlePtr->chargeType();
1641 int baryonTypeNow = particlePtr->baryonNumberType();
1642 double m0Now = particlePtr->m0();
1643 double mMinNow = particlePtr->mMin();
1644 double mMaxNow = particlePtr->mMax();
1645 double mWidthNow = particlePtr->mWidth();
1646 double tau0Now = particlePtr->tau0();
1647 bool isResonanceNow = particlePtr->isResonance();
1648 bool hasPrinted =
false;
1649 bool studyCloser = verbosity > 10 || !isResonanceNow;
1652 string particleName = particlePtr->name(1);
1653 if (particleName.size() > 16) {
1654 os <<
" Warning: particle " << idNow <<
" has name " << particleName
1655 <<
" of length " << particleName.size() <<
"\n";
1661 for (
int i = 0; i < int(particleName.size()); ++i) {
1662 if (particleName[i] ==
'+') ++nPos;
1663 if (particleName[i] ==
'-') ++nNeg;
1665 if ( (nPos > 0 && nNeg > 0) || ( nPos + nNeg > 0
1666 && 3 * (nPos - nNeg) != chargeTypeNow )) {
1667 os <<
" Warning: particle " << idNow <<
" has name " << particleName
1668 <<
" inconsistent with charge type " << chargeTypeNow <<
"\n";
1675 particleName = particlePtr->name(-1);
1676 if (particleName.size() > 16) {
1677 os <<
" Warning: particle " << idNow <<
" has name " << particleName
1678 <<
" of length " << particleName.size() <<
"\n";
1684 for (
int i = 0; i < int(particleName.size()); ++i) {
1685 if (particleName[i] ==
'+') ++nPos;
1686 if (particleName[i] ==
'-') ++nNeg;
1688 if ( (nPos > 0 && nNeg > 0) || ( nPos + nNeg > 0
1689 && 3 * (nPos - nNeg) != -chargeTypeNow )) {
1690 os <<
" Warning: particle " << -idNow <<
" has name "
1691 << particleName <<
" inconsistent with charge type "
1692 << -chargeTypeNow <<
"\n";
1699 if (particlePtr->useBreitWigner()) {
1700 if (mMinNow > m0Now) {
1701 os <<
" Error: particle " << idNow <<
" has mMin "
1702 << fixed << setprecision(5) << mMinNow
1703 <<
" larger than m0 " << m0Now <<
"\n";
1707 if (mMaxNow > mMinNow && mMaxNow < m0Now) {
1708 os <<
" Error: particle " << idNow <<
" has mMax "
1709 << fixed << setprecision(5) << mMaxNow
1710 <<
" smaller than m0 " << m0Now <<
"\n";
1714 if (mMaxNow > mMinNow && mMaxNow - mMinNow < mWidthNow) {
1715 os <<
" Warning: particle " << idNow <<
" has mMax - mMin "
1716 << fixed << setprecision(5) << mMaxNow - mMinNow
1717 <<
" smaller than mWidth " << mWidthNow <<
"\n";
1724 if (mWidthNow > 0. && tau0Now > 0.) {
1725 os <<
" Warning: particle " << idNow <<
" has both nonvanishing width "
1726 << scientific << setprecision(5) << mWidthNow <<
" and lifetime "
1733 if (particlePtr->sizeChannels() > 0) {
1736 double bRatioSum = 0.;
1737 double bRatioPos = 0.;
1738 double bRatioNeg = 0.;
1739 bool hasPosBR =
false;
1740 bool hasNegBR =
false;
1741 double threshMass = 0.;
1742 bool openChannel =
false;
1743 for (
int i = 0; i < particlePtr->sizeChannels(); ++i) {
1746 int onMode = particlePtr->channel(i).onMode();
1747 double bRatio = particlePtr->channel(i).bRatio();
1748 int meMode = particlePtr->channel(i).meMode();
1749 int mult = particlePtr->channel(i).multiplicity();
1751 for (
int j = 0; j < 8; ++j)
1752 prod[j] = particlePtr->channel(i).product(j);
1755 if (onMode == 0 || onMode == 1) bRatioSum += bRatio;
1756 else if (onMode == 2) {bRatioPos += bRatio; hasPosBR =
true;}
1757 else if (onMode == 3) {bRatioNeg += bRatio; hasNegBR =
true;}
1760 for (
int j = 0; j < 8; ++j) {
1761 if ( prod[j] != 0 && !isParticle(prod[j]) ) {
1762 os <<
" Error: unknown decay product for " << idNow
1763 <<
" -> " << prod[j] <<
"\n";
1772 for (
int j = 0; j < 8; ++j)
1773 if (prod[j] != 0) nLast = j + 1;
1774 if (mult == 0 || mult != nLast) {
1775 os <<
" Error: corrupted decay product list for "
1776 << particlePtr->id() <<
" -> ";
1777 for (
int j = 0; j < 8; ++j) os << prod[j] <<
" ";
1785 int chargeTypeSum = -chargeTypeNow;
1786 int baryonTypeSum = -baryonTypeNow;
1787 double avgFinalMass = 0.;
1788 double minFinalMass = 0.;
1789 bool canHandle =
true;
1790 for (
int j = 0; j < mult; ++j) {
1791 chargeTypeSum += chargeType( prod[j] );
1792 baryonTypeSum += baryonNumberType( prod[j] );
1793 avgFinalMass += m0( prod[j] );
1794 minFinalMass += m0Min( prod[j] );
1795 if (prod[j] == 81 || prod[j] == 82 || prod[j] == 83)
1798 threshMass += bRatio * avgFinalMass;
1801 if (chargeTypeSum != 0 && canHandle) {
1802 os <<
" Error: 3*charge changed by " << chargeTypeSum
1803 <<
" in " << idNow <<
" -> ";
1804 for (
int j = 0; j < mult; ++j) os << prod[j] <<
" ";
1810 if ( baryonTypeSum != 0 && canHandle && particlePtr->isHadron() ) {
1811 os <<
" Error: 3*baryon number changed by " << baryonTypeSum
1812 <<
" in " << idNow <<
" -> ";
1813 for (
int j = 0; j < mult; ++j) os << prod[j] <<
" ";
1821 bool correctME =
true;
1824 if (meMode == 0 && !isResonanceNow) {
1825 bool hasPartons =
false;
1826 for (
int j = 0; j < mult; ++j) {
1827 int idAbs = abs(prod[j]);
1828 if ( idAbs < 10 || idAbs == 21 || idAbs == 81 || idAbs == 82
1829 || idAbs == 83 || (idAbs > 1000 && idAbs < 10000
1830 && (idAbs/10)%10 == 0) ) hasPartons =
true;
1832 if (hasPartons) correctME =
false;
1836 bool useME1 = ( mult == 3 && spinTypeNow == 3 && idNow > 100
1838 && particlePtr->channel(i).contains(211, -211, 111) );
1839 if ( meMode == 1 && !useME1 ) correctME =
false;
1840 if ( meMode != 1 && useME1 ) correctME =
false;
1843 bool useME2 = ( mult == 2 && spinTypeNow == 3 && idNow > 100
1844 && idNow < 1000 && spinType(prod[0]) == 1
1845 && spinType(prod[1]) == 1 );
1846 if ( meMode == 2 && !useME2 ) correctME =
false;
1847 if ( meMode != 2 && useME2 ) correctME =
false;
1852 bool useME11 = ( mult == 3 && !isResonanceNow
1853 && (prod[1] == 11 || prod[1] == 13 || prod[1] == 15)
1854 && prod[2] == -prod[1] );
1855 bool useME12 = ( mult > 3 && !isResonanceNow
1856 && (prod[mult - 2] == 11 || prod[mult - 2] == 13
1857 || prod[mult - 2] == 15) && prod[mult - 1] == -prod[mult - 2] );
1858 bool useME13 = ( mult == 4 && !isResonanceNow
1859 && (prod[0] == 11 || prod[0] == 13) && prod[1] == -prod[0]
1860 && (prod[2] == 11 || prod[2] == 13) && prod[3] == -prod[2] );
1861 if (useME13) useME12 =
false;
1862 if ( meMode == 11 && !useME11 ) correctME =
false;
1863 if ( meMode != 11 && useME11 ) correctME =
false;
1864 if ( meMode == 12 && !useME12 ) correctME =
false;
1865 if ( meMode != 12 && useME12 ) correctME =
false;
1866 if ( meMode == 13 && !useME13 ) correctME =
false;
1867 if ( meMode != 13 && useME13 ) correctME =
false;
1870 bool useME21 = (idNow == 15 && mult > 2 && prod[0] == 16
1871 && abs(prod[1]) > 100);
1872 if ( meMode == 21 && !useME21 ) correctME =
false;
1873 if ( meMode != 21 && useME21 ) correctME =
false;
1877 if ( isLepton(prod[0]) && isLepton(prod[1]) ) {
1878 bool useME22 =
false;
1882 if (particlePtr->isLepton()) {
1883 typeA = (idNow > 0) ? 1 + (idNow-1)%2 : -1 - (1-idNow)%2;
1884 }
else if (particlePtr->isHadron()) {
1885 int hQ = particlePtr->heaviestQuark();
1887 if (idNow == 541 && heaviestQuark(prod[2]) == -5) hQ = 4;
1888 typeA = (hQ > 0) ? 1 + (hQ-1)%2 : -1 - (1-hQ)%2;
1890 typeB = (prod[0] > 0) ? 1 + (prod[0]-1)%2 : -1 - (1-prod[0])%2;
1891 typeC = (prod[1] > 0) ? 1 + (prod[1]-1)%2 : -1 - (1-prod[1])%2;
1893 if ( (idNow == 130 || idNow == 310) && typeC * typeA < 0)
1895 if (mult == 3 && idNow == 2112 && prod[2] == 2212)
1897 if (mult == 3 && idNow == 3222 && prod[2] == 3122)
1899 if (mult > 2 && typeC == typeA && typeB * typeC < 0
1900 && (typeB + typeC)%2 != 0) useME22 =
true;
1901 if ( meMode == 22 && !useME22 ) correctME =
false;
1902 if ( meMode != 22 && useME22 ) correctME =
false;
1908 for (
int j = 0; j < mult; ++j)
if (prod[j] == 22) ++nGamma;
1909 if (nGamma != 1) correctME =
false;
1913 if ( !isResonanceNow && (meMode < 0 || (meMode > 2 && meMode <= 10)
1914 || (meMode > 13 && meMode <= 20) || (meMode > 23 && meMode <= 30)
1915 || (meMode > 31 && meMode <= 41) || meMode == 51 || meMode == 61
1916 || meMode == 71 || (meMode > 80 && meMode <= 90)
1917 || (!particlePtr->isOctetHadron() && meMode > 92) ) )
1922 os <<
" Warning: meMode " << meMode <<
" used for "
1924 for (
int j = 0; j < mult; ++j) os << prod[j] <<
" ";
1931 if ( studyCloser && verbosity > 0 && canHandle && onMode > 0
1932 && particlePtr->m0Min() - minFinalMass < 0. ) {
1933 if (particlePtr->m0Max() - minFinalMass < 0.)
1934 os <<
" Error: decay never possible for ";
1935 else os <<
" Warning: decay sometimes not possible for ";
1936 os << idNow <<
" -> ";
1937 for (
int j = 0; j < mult; ++j) os << prod[j] <<
" ";
1944 if (onMode > 0 && bRatio > 0.) openChannel =
true;
1948 if (verbosity%10 > 1 && particlePtr->useBreitWigner()) {
1949 threshMass /= bRatioSum;
1950 os <<
" Info: particle " << idNow << fixed << setprecision(5)
1951 <<
" has average mass threshold " << threshMass
1952 <<
" while mMin is " << mMinNow <<
"\n";
1957 if (studyCloser && !openChannel) {
1958 os <<
" Error: no acceptable decay channel found for particle "
1965 if (studyCloser && (!hasAntiNow || (!hasPosBR && !hasNegBR))
1966 && abs(bRatioSum + bRatioPos - 1.) > 1e-8) {
1967 os <<
" Warning: particle " << idNow << fixed << setprecision(8)
1968 <<
" has branching ratio sum " << bRatioSum <<
"\n";
1971 }
else if (studyCloser && hasAntiNow
1972 && (abs(bRatioSum + bRatioPos - 1.) > 1e-8
1973 || abs(bRatioSum + bRatioNeg - 1.) > 1e-8)) {
1974 os <<
" Warning: particle " << idNow << fixed << setprecision(8)
1975 <<
" has branching ratio sum " << bRatioSum + bRatioPos
1976 <<
" while its antiparticle has " << bRatioSum + bRatioNeg
1984 if (hasPrinted) os <<
"\n";
1988 os <<
" Total number of errors and warnings is " << nErr <<
"\n";
1989 os <<
"\n -------- End PYTHIA Check of Particle Data Table --------"
1990 <<
"------\n" << endl;
1998 int ParticleData::nextId(
int idIn) {
2001 if (idIn < 0 || (idIn > 0 && !isParticle(idIn)))
return 0;
2002 if (idIn == 0)
return pdt.begin()->first;
2005 map<int, ParticleDataEntry>::const_iterator pdtIn = pdt.find(idIn);
2006 if (pdtIn == pdt.end())
return 0;
2008 if (pdtIn == pdt.end())
return 0;
2009 return pdtIn->first;
2017 double ParticleData::resOpenFrac(
int id1In,
int id2In,
int id3In) {
2023 if (isParticle(id1In)) answer = pdt[abs(id1In)].resOpenFrac(id1In);
2026 if (isParticle(id2In)) answer *= pdt[abs(id2In)].resOpenFrac(id2In);
2029 if (isParticle(id3In)) answer *= pdt[abs(id2In)].resOpenFrac(id3In);
2040 string ParticleData::attributeValue(
string line,
string attribute) {
2042 if (line.find(attribute) == string::npos)
return "";
2043 int iBegAttri = line.find(attribute);
2044 int iBegQuote = line.find(
"\"", iBegAttri + 1);
2045 int iEndQuote = line.find(
"\"", iBegQuote + 1);
2046 return line.substr(iBegQuote + 1, iEndQuote - iBegQuote - 1);
2054 bool ParticleData::boolAttributeValue(
string line,
string attribute) {
2056 string valString = attributeValue(line, attribute);
2057 if (valString ==
"")
return false;
2058 return boolString(valString);
2066 int ParticleData::intAttributeValue(
string line,
string attribute) {
2067 string valString = attributeValue(line, attribute);
2068 if (valString ==
"")
return 0;
2069 istringstream valStream(valString);
2071 valStream >> intVal;
2080 double ParticleData::doubleAttributeValue(
string line,
string attribute) {
2081 string valString = attributeValue(line, attribute);
2082 if (valString ==
"")
return 0.;
2083 istringstream valStream(valString);
2085 valStream >> doubleVal;