7 #include "Pythia8/SLHAinterface.h"
19 void SLHAinterface::init( Settings& settings, Rndm* rndmPtr,
20 Couplings* couplingsPtrIn, ParticleData* particleDataPtr,
21 bool& useSLHAcouplings) {
24 couplingsPtr = couplingsPtrIn;
25 useSLHAcouplings =
false;
28 if( !initSLHA(settings, particleDataPtr))
29 infoPtr->errorMsg(
"Error in SLHAinterface::init: "
30 "Could not read SLHA file");
33 if (couplingsPtr->isSUSY) {
35 coupSUSY.init( settings, rndmPtr);
36 coupSUSY.initSUSY(&slha, infoPtr, particleDataPtr, &settings);
39 couplingsPtr = (Couplings *) &coupSUSY;
40 useSLHAcouplings =
true;
49 bool SLHAinterface::initSLHA(Settings& settings,
50 ParticleData* particleDataPtr) {
53 string errPref =
"Error in SLHAinterface::initSLHA: ";
54 string warnPref =
"Warning in SLHAinterface::initSLHA: ";
55 string infoPref =
"Info from SLHAinterface::initSLHA: ";
60 int readFrom = settings.mode(
"SLHA:readFrom");
61 string lhefFile = settings.word(
"Beams:LHEF");
62 string lhefHeader = settings.word(
"Beams:LHEFheader");
63 string slhaFile = settings.word(
"SLHA:file");
64 int verboseSLHA = settings.mode(
"SLHA:verbose");
65 bool slhaUseDec = settings.flag(
"SLHA:useDecayTable");
68 meMode = settings.mode(
"SLHA:meMode");
71 couplingsPtr->isSUSY =
false;
74 if (readFrom == 0)
return true;
78 if (lhefHeader !=
"void")
79 ifailLHE = slha.readFile(lhefHeader, verboseSLHA, slhaUseDec );
80 else if (lhefFile !=
"void")
81 ifailLHE = slha.readFile(lhefFile, verboseSLHA, slhaUseDec );
87 couplingsPtr->isSUSY =
true;
91 if ( settings.word(
"SLHA:file") ==
"none"
92 || settings.word(
"SLHA:file") ==
"void"
93 || settings.word(
"SLHA:file") ==
""
94 || settings.word(
"SLHA:file") ==
" ")
return true;
95 ifailSpc = slha.readFile(slhaFile,verboseSLHA, slhaUseDec);
100 infoPtr->errorMsg(errPref +
"problem reading SLHA file", slhaFile);
103 couplingsPtr->isSUSY =
true;
107 ifailSpc = slha.checkSpectrum();
112 couplingsPtr->isSUSY =
false;
113 infoPtr->errorMsg(infoPref +
114 "No MODSEL found, keeping internal SUSY switched off");
115 }
else if (ifailSpc >= 2) {
117 infoPtr->errorMsg(warnPref +
"Problem with SLHA MASS or QNUMBERS.");
118 couplingsPtr->isSUSY =
false;
121 else if (ifailSpc == 0) {
123 slha.printSpectrum(0);
125 else if (ifailSpc < 0) {
126 infoPtr->errorMsg(warnPref +
"Problem with SLHA spectrum.",
127 "\n Only using masses and switching off SUSY.");
128 settings.flag(
"SUSY:all",
false);
129 couplingsPtr->isSUSY =
false;
130 slha.printSpectrum(ifailSpc);
134 if ( (ifailSpc == 1 || ifailSpc == 0) && slha.modsel(3) >= 1 ) {
136 particleDataPtr->name(25,
"H_1");
137 particleDataPtr->name(35,
"H_2");
138 particleDataPtr->name(45,
"H_3");
139 particleDataPtr->name(36,
"A_1");
140 particleDataPtr->name(46,
"A_2");
141 particleDataPtr->name(1000045,
"~chi_50");
145 if ( (ifailSpc == 1 || ifailSpc == 0) && slha.modsel(6) >= 1 ) {
147 if ( (slha.modsel(6) == 1 || slha.modsel(6) >= 3)
148 && slha.usqmix.exists() && slha.dsqmix.exists() ) {
150 particleDataPtr->names(1000001,
"~d1",
"~d1bar");
151 particleDataPtr->names(1000002,
"~u1",
"~u1bar");
152 particleDataPtr->names(1000003,
"~d2",
"~d2bar");
153 particleDataPtr->names(1000004,
"~u2",
"~u2bar");
154 particleDataPtr->names(1000005,
"~d3",
"~d3bar");
155 particleDataPtr->names(1000006,
"~u3",
"~u3bar");
156 particleDataPtr->names(2000001,
"~d4",
"~d4bar");
157 particleDataPtr->names(2000002,
"~u4",
"~u4bar");
158 particleDataPtr->names(2000003,
"~d5",
"~d5bar");
159 particleDataPtr->names(2000004,
"~u5",
"~u5bar");
160 particleDataPtr->names(2000005,
"~d6",
"~d6bar");
161 particleDataPtr->names(2000006,
"~u6",
"~u6bar");
164 if ( (slha.modsel(6) == 2 || slha.modsel(6) >= 3)
165 && slha.selmix.exists()) {
167 particleDataPtr->names(1000011,
"~e1-",
"~e1+");
168 particleDataPtr->names(1000013,
"~e2-",
"~e2+");
169 particleDataPtr->names(1000015,
"~e3-",
"~e3+");
170 particleDataPtr->names(2000011,
"~e4-",
"~e4+");
171 particleDataPtr->names(2000013,
"~e5-",
"~e5+");
172 particleDataPtr->names(2000015,
"~e6-",
"~e6+");
175 if ( (slha.modsel(6) == 2 || slha.modsel(6) >= 3)
176 && slha.snumix.exists()) {
178 particleDataPtr->names(1000012,
"~nu_1",
"~nu_1bar");
179 particleDataPtr->names(1000014,
"~nu_2",
"~nu_2bar");
180 particleDataPtr->names(1000016,
"~nu_3",
"~nu_3bar");
183 if ( slha.snsmix.exists() && slha.snamix.exists() ) {
185 particleDataPtr->names(1000012,
"~nu_S1",
"~nu_S1bar");
186 particleDataPtr->names(1000014,
"~nu_S2",
"~nu_S2bar");
187 particleDataPtr->names(1000016,
"~nu_S3",
"~nu_S3bar");
189 particleDataPtr->addParticle(1000017,
"~nu_A1",
"~nu_A1bar",1, 0., 0);
190 particleDataPtr->addParticle(1000018,
"~nu_A2",
"~nu_A2bar",1, 0., 0);
191 particleDataPtr->addParticle(1000019,
"~nu_A3",
"~nu_A3bar",1, 0., 0);
196 if ( (ifailSpc == 1 || ifailSpc == 0) && slha.modsel(4) >= 1 ) {
197 if ( slha.rvnmix.exists() ) {
199 particleDataPtr->names(12,
"nu_1",
"nu_1bar");
200 particleDataPtr->names(14,
"nu_2",
"nu_2bar");
201 particleDataPtr->names(16,
"nu_3",
"nu_3bar");
202 particleDataPtr->names(1000022,
"nu_4",
"nu_4bar");
203 particleDataPtr->names(1000023,
"nu_5",
"nu_5bar");
204 particleDataPtr->names(1000025,
"nu_6",
"nu_6bar");
205 particleDataPtr->names(1000035,
"nu_7",
"nu_7bar");
207 if ( slha.rvumix.exists() && slha.rvvmix.exists() ) {
209 particleDataPtr->names(11,
"e_1-",
"e_1+");
210 particleDataPtr->names(13,
"e_2-",
"e_2+");
211 particleDataPtr->names(15,
"e_3-",
"e_3+");
212 particleDataPtr->names(1000024,
"e_4+",
"e_4-");
213 particleDataPtr->names(1000037,
"e_5+",
"e_5-");
215 if ( slha.rvhmix.exists() ) {
217 particleDataPtr->name(25,
"H_1");
218 particleDataPtr->name(35,
"H_2");
219 particleDataPtr->name(1000012,
"H_3");
220 particleDataPtr->name(1000014,
"H_4");
221 particleDataPtr->name(1000016,
"H_5");
223 if ( slha.rvamix.exists() ) {
225 particleDataPtr->name(36,
"A_1");
226 particleDataPtr->name(1000017,
"A_2");
227 particleDataPtr->name(1000018,
"A_3");
228 particleDataPtr->name(1000019,
"A_4");
230 if ( slha.rvlmix.exists() ) {
232 particleDataPtr->names(37,
"H_1+",
"H_1-");
233 particleDataPtr->names(1000011,
"H_2-",
"H_2+");
234 particleDataPtr->names(1000013,
"H_3-",
"H_3+");
235 particleDataPtr->names(1000015,
"H_4-",
"H_4+");
236 particleDataPtr->names(2000011,
"H_5-",
"H_5+");
237 particleDataPtr->names(2000013,
"H_6-",
"H_6+");
238 particleDataPtr->names(2000015,
"H_7-",
"H_7+");
243 if ( (ifailSpc == 1 || ifailSpc == 0) && slha.modsel(5) >= 1 ) {
245 particleDataPtr->name(25,
"H_1");
246 particleDataPtr->name(35,
"H_2");
247 particleDataPtr->name(36,
"H_3");
251 if ( (ifailSpc == 1 || ifailSpc == 0) && slha.qnumbers.size() > 0) {
252 for (
int iQnum=0; iQnum < int(slha.qnumbers.size()); iQnum++) {
254 int id = abs(slha.qnumbers[iQnum](0));
255 ostringstream idCode;
257 if (particleDataPtr->isParticle(
id)) {
258 infoPtr->errorMsg(warnPref +
"ignoring QNUMBERS",
"for id = "
259 + idCode.str() +
" (already exists)",
true);
261 int qEM3 = slha.qnumbers[iQnum](1);
262 int nSpins = slha.qnumbers[iQnum](2);
263 int colRep = slha.qnumbers[iQnum](3);
264 int hasAnti = slha.qnumbers[iQnum](4);
267 if (colRep == 3) colType = 1;
268 else if (colRep == -3) colType = -1;
269 else if (colRep == 8) colType = 2;
270 else if (colRep == 6) colType = 3;
271 else if (colRep == -6) colType = -3;
273 string name, antiName;
274 ostringstream idStream;
276 name = idStream.str();
278 if (iQnum <
int(slha.qnumbersName.size())) {
279 name = slha.qnumbersName[iQnum];
280 antiName = slha.qnumbersAntiName[iQnum];
281 if (antiName ==
"") {
282 if (name.find(
"+") != string::npos) {
284 antiName.replace(antiName.find(
"+"),1,
"-");
285 }
else if (name.find(
"-") != string::npos) {
287 antiName.replace(antiName.find(
"-"),1,
"+");
289 antiName = name+
"bar";
295 particleDataPtr->addParticle(
id, name, nSpins, qEM3, colType);
297 particleDataPtr->addParticle(
id, name, antiName, nSpins, qEM3,
305 bool keepSM = settings.flag(
"SLHA:keepSM");
306 double minMassSM = settings.parm(
"SLHA:minMassSM");
307 bool allowUserOverride = settings.flag(
"SLHA:allowUserOverride");
308 vector<int> idModified;
309 if (ifailSpc == 1 || ifailSpc == 0) {
312 int id = slha.mass.first();
314 for (
int i = 1; i <= slha.mass.size() ; i++) {
316 if (i>1)
id = slha.mass.next();
317 ostringstream idCode;
319 double mass = abs(slha.mass(
id));
323 if (keepSM && (
id < 25 || (
id > 80 &&
id < 1000000))) ;
324 else if (id < 1000000 && particleDataPtr->m0(
id) < minMassSM) {
325 cout<<
" id = "<<
id<<
" m0 = "<<particleDataPtr->m0(
id)<<
" minMassSM = "
327 infoPtr->errorMsg(warnPref +
"ignoring MASS entry",
"for id = "
328 + idCode.str() +
" (m0 < SLHA:minMassSM)",
true);
333 else if (allowUserOverride && particleDataPtr->hasChanged(
id)) {
334 ostringstream mValue;
335 mValue << particleDataPtr->m0(
id);
336 infoPtr->errorMsg(warnPref +
"keeping user mass",
337 "for id = " + idCode.str() +
", m0 = " + mValue.str(),
true);
338 idModified.push_back(
id);
341 particleDataPtr->m0(
id,mass);
342 idModified.push_back(
id);
349 for (
int iTable=0; iTable < int(slha.decays.size()); iTable++) {
352 LHdecayTable* slhaTable=&(slha.decays[iTable]);
355 int idRes = slhaTable->getId();
356 ostringstream idCode;
358 ParticleDataEntry* particlePtr
359 = particleDataPtr->particleDataEntryPtr(idRes);
363 if (keepSM && (idRes < 25 || (idRes > 80 && idRes < 1000000)))
continue;
364 else if (idRes < 1000000 && particleDataPtr->m0(idRes) < minMassSM
365 && !particleDataPtr->hasChanged(idRes) ) {
366 infoPtr->errorMsg(warnPref +
"ignoring DECAY table",
"for id = "
367 + idCode.str() +
" (m0 < SLHA:minMassSM)",
true);
372 if (verboseSLHA <= 1)
373 infoPtr->errorMsg(infoPref +
"importing SLHA decay table(s)",
"");
375 infoPtr->errorMsg(infoPref +
"importing SLHA decay table",
"for id = "
379 double widRes = abs(slhaTable->getWidth());
380 double pythiaMinWidth = settings.parm(
"ResonanceWidths:minWidth");
381 if (widRes > 0. && widRes < pythiaMinWidth) {
382 infoPtr->errorMsg(warnPref +
"forcing width = 0 ",
"for id = "
383 + idCode.str() +
" (width < ResonanceWidths:minWidth)" ,
true);
386 particlePtr->setMWidth(widRes);
391 double decayLength = 1.97e-13/widRes;
392 particlePtr->setTau0(decayLength);
395 if (slhaTable->size() > 0) {
396 particlePtr->clearChannels();
397 particleDataPtr->mayDecay(idRes,
true);
398 particleDataPtr->isResonance(idRes,
true);
400 infoPtr->errorMsg(warnPref +
"empty DECAY table ",
"for id = "
401 + idCode.str() +
" (total width provided but no branching"
402 +
" fractions)",
true);
407 particlePtr->clearChannels();
408 particleDataPtr->mayDecay(idRes,
false);
409 particleDataPtr->isResonance(idRes,
false);
414 double massWTsum = 0.;
419 for (
int iChannel=0 ; iChannel<slhaTable->size(); iChannel++) {
420 LHdecayChannel slhaChannel = slhaTable->getChannel(iChannel);
421 double brat = slhaChannel.getBrat();
422 vector<int> idDa = slhaChannel.getIdDa();
423 if (idDa.size() >= 9) {
424 infoPtr->errorMsg(errPref +
"max number of DECAY products is 8");
425 }
else if (idDa.size() <= 1) {
426 infoPtr->errorMsg(errPref +
"min number of DECAY products is 2");
430 if (brat < 0.0) onMode = 0;
431 int meModeNow = meMode;
435 double widSqSum = pow2(widRes);
436 int nDa = idDa.size();
437 for (
int jDa=0; jDa<nDa; ++jDa) {
438 massSum += particleDataPtr->m0( idDa[jDa] );
439 widSqSum += pow2(particleDataPtr->mWidth( idDa[jDa] ));
441 double deltaM = particleDataPtr->m0(idRes) - massSum;
443 if (onMode == 1 && brat > 0.0 && deltaM < 0.) {
445 ostringstream errCode;
446 errCode << idRes <<
" ->";
447 for (
int jDa=0; jDa<nDa; ++jDa) errCode<<
" "<<idDa[jDa];
449 if (abs(deltaM) > 100. * sqrt(widSqSum)) {
450 infoPtr->errorMsg(warnPref +
"switched off DECAY mode",
451 ": " + errCode.str()+
" (too far off shell)",
true);
457 if (meModeNow != 100) {
458 infoPtr->errorMsg(warnPref +
"adding off shell DECAY mode",
459 ": "+errCode.str()+
" (forced meMode = 100)",
true);
462 infoPtr->errorMsg(warnPref +
"adding off shell DECAY mode",
463 errCode.str(),
true);
468 brWTsum += abs(brat);
469 massWTsum += abs(brat) * massSum;
474 int id2 = (idDa.size() >= 3) ? idDa[2] : 0;
475 int id3 = (idDa.size() >= 4) ? idDa[3] : 0;
476 int id4 = (idDa.size() >= 5) ? idDa[4] : 0;
477 int id5 = (idDa.size() >= 6) ? idDa[5] : 0;
478 int id6 = (idDa.size() >= 7) ? idDa[6] : 0;
479 int id7 = (idDa.size() >= 8) ? idDa[7] : 0;
480 particlePtr->addChannel(onMode,abs(brat),meModeNow,
481 id0,id1,id2,id3,id4,id5,id6,id7);
487 if (slhaTable->size() > 0) {
488 double massAvg = massWTsum / brWTsum;
489 double massMin = min( massAvg, particlePtr->m0()) ;
490 particlePtr->setMMin(massMin);
494 idModified.push_back(idRes);
499 for (
int iMod = 0; iMod < int(idModified.size()); ++iMod) {
500 int id = idModified[iMod];
501 ostringstream idCode;
503 ParticleDataEntry* particlePtr
504 = particleDataPtr->particleDataEntryPtr(
id);
505 double m0 = particlePtr->m0();
506 double wid = particlePtr->mWidth();
508 if (m0 <= 0.0 && (wid > 0.0 || particlePtr->mayDecay())) {
509 infoPtr->errorMsg(warnPref +
"massless particle forced stable",
" id = "
510 + idCode.str(),
true);
511 particlePtr->clearChannels();
512 particlePtr->setMWidth(0.0);
513 particlePtr->setMayDecay(
false);
514 particleDataPtr->isResonance(
id,
false);
518 if (wid == 0.0 && particlePtr->mayDecay()) {
519 particlePtr->setMayDecay(
false);
523 double mSumMin = 10. * m0;
524 int nChannels = particlePtr->sizeChannels();
525 if (nChannels >= 1) {
526 for (
int iChannel=0; iChannel<nChannels; ++iChannel) {
527 DecayChannel channel = particlePtr->channel(iChannel);
528 if (channel.onMode() <= 0)
continue;
529 int nProd = channel.multiplicity();
531 for (
int iDa = 0; iDa < nProd; ++iDa) {
532 int idDa = channel.product(iDa);
533 mSum += particleDataPtr->m0(idDa);
535 mSumMin = min(mSumMin, mSum);
539 infoPtr->errorMsg(warnPref +
"particle forced stable",
" id = "
540 + idCode.str() +
" (no on-shell decay channels)",
true);
541 particlePtr->setMWidth(0.0);
542 particlePtr->setMayDecay(
false);
549 double mMin = min(particlePtr->mMin(), max(0.0,m0 - 5.*wid));
550 mMin = max(mSumMin,mMin);
551 particlePtr->setMMin(mMin);
565 void SLHAinterface::pythia2slha(ParticleData* particleDataPtr) {
568 string blockName =
"sminputs";
569 double mZ = particleDataPtr->m0(23);
570 slha.set(blockName,1,1.0/couplingsPtr->alphaEM(pow2(mZ)));
571 slha.set(blockName,2,couplingsPtr->GF());
572 slha.set(blockName,3,couplingsPtr->alphaS(pow2(mZ)));
573 slha.set(blockName,4,mZ);
575 slha.set(blockName,5,particleDataPtr->m0(5));
576 slha.set(blockName,6,particleDataPtr->m0(6));
577 slha.set(blockName,7,particleDataPtr->m0(15));
578 slha.set(blockName,8,particleDataPtr->m0(16));
579 slha.set(blockName,11,particleDataPtr->m0(11));
580 slha.set(blockName,12,particleDataPtr->m0(12));
581 slha.set(blockName,13,particleDataPtr->m0(13));
582 slha.set(blockName,14,particleDataPtr->m0(14));
584 slha.set(blockName,21,
double(0.0));
585 slha.set(blockName,22,
double(0.0));
586 slha.set(blockName,23,
double(0.0));
588 slha.set(blockName,24,particleDataPtr->m0(4));
594 while (particleDataPtr->nextId(
id) > id) {
595 slha.set(blockName,
id,particleDataPtr->m0(
id));
596 id = particleDataPtr->nextId(
id);
599 infoPtr->errorMsg(
"Error in SLHAinterface::pythia2slha(): "
600 "encountered infinite loop when saving mass block");