14 #include "Pythia8/RHadrons.h"
21 #include "G4ParticleDefinition.hh"
22 #include "G4ParticleTable.hh"
23 #include "G4ThreeVector.hh"
24 #include "TLorentzVector.h"
26 static inline unsigned short int nth_digit(
const int&
val,
const unsigned short&
n) {
return (std::abs(
val)/(
int(
std::pow(10,
n-1))))%10;}
39 m_pythia = std::make_unique<Pythia8::Pythia>(docstring);
40 m_pythia->readString(
"SLHA:file = SLHA_INPUT.DAT");
41 m_pythia->readString(
"ProcessLevel:all = off");
42 m_pythia->readString(
"Init:showChangedSettings = off");
43 m_pythia->readString(
"RHadrons:allow = on");
44 m_pythia->readString(
"RHadrons:allowDecay = on");
45 m_pythia->readString(
"RHadrons:probGluinoball = 0.1");
46 m_pythia->readString(
"PartonLevel:FSR = off");
47 m_pythia->readString(
"Init:showAllParticleData = on");
51 std::ifstream command_stream (
"PYTHIA8_COMMANDS.TXT");
52 while(getline(command_stream,
line)){
56 command_stream.close();
64 G4ParticleTable* particleTable = G4ParticleTable::GetParticleTable();
65 G4ParticleDefinition* particleDefinition(
nullptr);
66 if (pdgEncoding != 0) particleDefinition = particleTable->FindParticle(pdgEncoding);
67 return particleDefinition;
75 int idRSb =
m_pythia->settings.mode(
"RHadrons:idSbottom");
76 int idRSt =
m_pythia->settings.mode(
"RHadrons:idStop");
77 int idLight = (abs(idRHad) - 1000000) / 10;
78 int idSq = (idLight < 100) ? idLight/10 : idLight/100;
79 int id1 = (idSq == 6) ? idRSt : idRSb;
80 if (idRHad < 0) id1 = -id1;
83 int id2 = (idLight < 100) ? idLight%10 : idLight%100;
84 if (
id2 > 10)
id2 = 100 *
id2 + abs(idRHad)%10;
85 if ((id2 < 10 && idRHad > 0) || (
id2 > 10 && idRHad < 0))
id2 = -
id2;
88 return std::make_pair( id1,
id2);
96 int idLight = (abs(idRHad) - 1000000) / 10;
97 int id1,
id2, idTmp, idA, idB, idC;
98 double diquarkSpin1RH = 0.5;
102 id1 = (rndmPtr->flat() < 0.5) ? 1 : 2;
106 }
else if (idLight < 1000) {
107 id1 = (idLight / 10) % 10;
108 id2 = -(idLight % 10);
119 idA = (idLight / 100) % 10;
120 idB = (idLight / 10) % 10;
122 double rndmQ = 3. * rndmPtr->flat();
123 if (idA > 3) rndmQ = 0.5;
126 id2 = 1000 * idB + 100 * idC + 3;
127 if (idB != idC && rndmPtr->flat() > diquarkSpin1RH)
id2 -= 2;
128 }
else if (rndmQ < 2.) {
130 id2 = 1000 * idA + 100 * idC + 3;
131 if (idA != idC && rndmPtr->flat() > diquarkSpin1RH)
id2 -= 2;
134 id2 = 1000 * idA + 100 * idB +3;
135 if (idA != idB && rndmPtr->flat() > diquarkSpin1RH)
id2 -= 2;
146 return std::make_pair( id1,
id2);
158 double mm = aTrack.GetDynamicParticle()->GetMass();
161 event.append( aTrack.GetDefinition()->GetPDGEncoding(), 1, 0, 0, aTrack.GetMomentum().x()/
CLHEP::GeV, aTrack.GetMomentum().y()/
CLHEP::GeV,
168 const unsigned short digitValue_q1 = nth_digit(pdgId,4);
169 const unsigned short digitValue_l = nth_digit(pdgId,5);
172 if (digitValue_l == 9 || (digitValue_l==0 && digitValue_q1 == 9) ){
178 if (pdgId==1000993)
return true;
190 Pythia8::ParticleData& pdt =
m_pythia->particleData;
197 int idRHad =
event[iRNow].id();
198 double mRHad =
event[iRNow].m();
206 int id1 = idPair.first;
207 int id2 = idPair.second;
211 int idRSb =
m_pythia->settings.mode(
"RHadrons:idSbottom");
212 int idRSt =
m_pythia->settings.mode(
"RHadrons:idStop");
213 int idRGo =
m_pythia->settings.mode(
"RHadrons:idGluino");
214 int idLight = (abs(idRHad) - 1000000) / 10;
215 int idSq = (idLight < 100) ? idLight/10 : idLight/100;
216 int idRSq = (idSq == 6) ? idRSt : idRSb;
219 idRSq = idRSq * std::copysign(1, idRHad);
221 int idRBef = isTriplet ? idRSq : idRGo;
224 double mRBef = pdt.mSel(idRBef);
227 double fracR = mRBef / mRHad;
231 G4cout <<
"Needed more than 10 attempts with constituent " << idRBef <<
" mass (" << mRBef <<
" above R-Hadron " << idRHad <<
" mass " << mRHad << G4endl;
233 G4cout <<
"Pythia8ForDecays::Py1ent ERROR Failed >100 times. Constituent " << idRBef <<
" mass (" << mRBef <<
" above R-Hadron " << idRHad <<
" mass " << mRHad << G4endl;
236 mRBef = pdt.mSel(idRBef);
237 fracR = mRBef / mRHad;
243 const int col = (pdt.colType(idRBef) != 0) ?
event.nextColTag() : 0;
244 int tmpSparticleColor = id1>0 ?
col : 0;
245 int tmpSparticleAnticolor = id1>0 ? 0 :
col;
251 iR0 =
event.append( id1, 106, iRNow, 0, 0, 0, tmpSparticleColor, tmpSparticleAnticolor, fracR *
event[iRNow].
p(), fracR * mRHad, 0.);
253 iR2 =
event.append(
id2, 106, iRNow, 0, 0, 0, tmpSparticleAnticolor, tmpSparticleColor, (1. - fracR) *
event[iRNow].p(), (1. - fracR) * mRHad, 0.);
257 double mOffsetCloudRH = 0.2;
258 double m1Eff = pdt.constituentMass(id1) + mOffsetCloudRH;
259 double m2Eff = pdt.constituentMass(
id2) + mOffsetCloudRH;
260 double frac1 = (1. - fracR) * m1Eff / ( m1Eff + m2Eff);
261 double frac2 = (1. - fracR) * m2Eff / ( m1Eff + m2Eff);
264 int col1 =
event.nextColTag();
265 int col2 =
event.nextColTag();
268 iR0 =
event.append( idRBef, 106, iRNow, 0, 0, 0, col2, col1, fracR *
event[iRNow].
p(), fracR * mRHad, 0.);
269 event.append( id1, 106, iRNow, 0, 0, 0, col1, 0, frac1 *
event[iRNow].
p(), frac1 * mRHad, 0.);
270 iR2 =
event.append(
id2, 106, iRNow, 0, 0, 0, 0, col2, frac2 *
event[iRNow].
p(), frac2 * mRHad, 0.);
274 event[iRNow].statusNeg();
275 event[iRNow].daughters( iR0, iR2);
288 if (
m_pythia->event[
i].status()<0 )
continue;
293 if (!particleDefinition){
294 G4cout <<
"I don't know a definition for pdgid "<<
m_pythia->event[
i].id()<<
"! Skipping it..." << G4endl;
298 G4DynamicParticle* dynamicParticle =
new G4DynamicParticle(particleDefinition,
momentum);