SND@LHC Software
Loading...
Searching...
No Matches
Pythia8Generator.cxx
Go to the documentation of this file.
1#include <math.h>
2#include "TSystem.h"
3#include "TROOT.h"
4#include "FairPrimaryGenerator.h"
5#include "TGeoNode.h"
6#include "TGeoVolume.h"
7#include <TGeoManager.h>
8#include "TGeoBBox.h"
9#include "TMath.h"
10#include "Pythia8Generator.h"
11#include "HNLPythia8Generator.h"
12const Double_t cm = 10.; // pythia units are mm
13const Double_t c_light = 2.99792458e+10; // speed of light in cm/sec (c_light = 2.99792458e+8 * m/s)
14Int_t counter = 0;
15const Double_t mbarn = 1E-3*1E-24*TMath::Na(); // cm^2 * Avogadro
16
17// ----- Default constructor -------------------------------------------
19{
20 fUseRandom1 = kFALSE;
21 fUseRandom3 = kTRUE;
22 fId = 2212; // proton
23 fMom = 400; // proton
24 fFDs = 7.7/10.4; // correction for Pythia6 to match measured Ds production
25 fextFile = "";
26 fInputFile = NULL;
27 targetName = "";
28 xOff=0; yOff=0;
29 fPythia = new Pythia8::Pythia();
30}
31// -------------------------------------------------------------------------
32
33// ----- Default constructor -------------------------------------------
35{
38 if (fextFile && *fextFile) {
39 if (0 == strncmp("/eos",fextFile,4) ) {
40 TString tmp = gSystem->Getenv("EOSSHIP");
41 tmp+=fextFile;
42 fInputFile = TFile::Open(tmp);
43 LOGF(info, "Open external file with charm or beauty hadrons on eos: %s", tmp.Data());
44 if (!fInputFile) {
45 LOG(FATAL) << "Error opening input file. You may have forgotten to provide a krb5 token. Try kinit username@lxplus.cern.ch";
46 return kFALSE; }
47 }else{
48 LOGF(info, "Open external file with charm or beauty hadrons: %s", fextFile);
49 fInputFile = new TFile(fextFile);
50 if (!fInputFile) {
51 LOG(FATAL) << "Error opening input file";
52 return kFALSE; }
53 }
54 if (fInputFile->IsZombie()) {
55 LOG(FATAL) << "File is corrupted";
56 return kFALSE; }
57 fTree = (TTree *)fInputFile->Get("pythia6");
58 fNevents = fTree->GetEntries();
59 fn = firstEvent;
60 fTree->SetBranchAddress("id",&hid); // particle id
61 fTree->SetBranchAddress("px",&hpx); // momentum
62 fTree->SetBranchAddress("py",&hpy);
63 fTree->SetBranchAddress("pz",&hpz);
64 fTree->SetBranchAddress("E",&hE);
65 fTree->SetBranchAddress("M",&hM);
66 fTree->SetBranchAddress("mid",&mid); // mother
67 fTree->SetBranchAddress("mpx",&mpx); // momentum
68 fTree->SetBranchAddress("mpy",&mpy);
69 fTree->SetBranchAddress("mpz",&mpz);
70 fTree->SetBranchAddress("mE",&mE);
71 if (fTree->GetBranch("k")){
72 fTree->SetBranchAddress("k",&ck);
73 if (fTree->GetBranch("a0")){
74 for(Int_t i=0; i<16; i++){
75 TString na = "a";na+=i;
76 fTree->SetBranchAddress(na,&(ancestors[i]));
77 TString ns = "s";ns+=i;
78 fTree->SetBranchAddress(ns,&(subprocCodes[i]));
79 }
80 }
81 }else{
82 ck[0]=1;subprocCodes[0]=88;ancestors[0]=2212;
83 }
84 fPythia->readString("ProcessLevel:all = off");
85// find all long lived particles in pythia
86 Int_t n = 1;
87 while(n!=0){
88 n = fPythia->particleData.nextId(n);
89#ifndef PYTHIA8_V
90 Pythia8::ParticleDataEntry* p = fPythia->particleData.particleDataEntryPtr(n);
91#else
92#if PYTHIA8_V<8309
93 Pythia8::ParticleDataEntry* p = fPythia->particleData.particleDataEntryPtr(n);
94#else
95 Pythia8::ParticleDataEntryPtr p = fPythia->particleData.particleDataEntryPtr(n);
96#endif
97#endif
98 if (p->tau0()>1){
99 std::string particle = std::to_string(n)+":mayDecay = false";
100 fPythia->readString(particle);
101 LOGF(info, "Made %s stable for Pythia, should decay in Geant4", p->name().c_str());
102 }
103 }
104 } else {
105 fPythia->setRndmEnginePtr(fRandomEngine);
106 fPythia->settings.mode("Beams:idA", fId);
107 fPythia->settings.mode("Beams:idB", 2212);
108 fPythia->settings.mode("Beams:frameType", 2);
109 fPythia->settings.parm("Beams:eA",fMom);
110 fPythia->settings.parm("Beams:eB",0.);
111 }
112 fPythia->init();
113 if (targetName!=""){
115 TGeoVolume* top = gGeoManager->GetTopVolume();
116 TGeoNode* target = top->FindNode(targetName);
117 if (!target){
118 LOGF(error, "target not found, %s, program will crash", targetName.Data());
119 }
120 Double_t z_middle = target->GetMatrix()->GetTranslation()[2];
121 TGeoBBox* sha = (TGeoBBox*)target->GetVolume()->GetShape();
122 startZ = z_middle - sha->GetDZ();
123 endZ = z_middle + sha->GetDZ();
124 start[0]=xOff;
125 start[1]=yOff;
126 start[2]=startZ;
127 end[0]=xOff;
128 end[1]=yOff;
129 end[2]=endZ;
130//find maximum interaction length
133 }
134 return kTRUE;
135}
136// -------------------------------------------------------------------------
137
138
139// ----- Destructor ----------------------------------------------------
143// -------------------------------------------------------------------------
144
145// ----- Passing the event ---------------------------------------------
146Bool_t Pythia8Generator::ReadEvent(FairPrimaryGenerator* cpg)
147{
148 Double_t x,y,z,px,py,pz,dl,e,tof;
149 Int_t im,id,key;
150 fnRetries =0;
151// take charm hadrons from external file
152// correct eventually for too much primary Ds produced by pythia6
153 key=0;
154 bool l = true;
155 while(l){
156 if (fn==fNevents) {LOG(WARNING) << "End of input file. Rewind.";}
157 fTree->GetEntry((fn+1)%fNevents);
158// check that this and next entry is charm, otherwise continue reading
159 l = false;
160 if (int(mE[0])== 0){ l = true; }
161 bool isDs = false;
162 if ( int(fabs(hid[0]) ) == 431){ isDs = true; }
163 fTree->GetEntry(fn%fNevents);
164 if (int(mE[0])== 0){ l = true; }
165 fn++;
166 if ( int(fabs(hid[0]) ) == 431 || isDs ){
167 Double_t rnr = gRandom->Uniform(0,1);
168 if( rnr>fFDs ) {
169 l = true;
170 fn++;
171 }
172 }
173 }
174 Double_t zinter=0;
175 if (targetName!=""){
176// calculate primary proton interaction point:
177// loop over trajectory between start and end to pick an interaction point, copied from GenieGenerator and adapted to hadrons
178 Double_t prob2int = -1.;
179 Double_t rndm = 0.;
180 Double_t sigma;
181 Int_t count=0;
182 Double_t zinterStart = start[2];
183// simulate more downstream interaction points for interactions down in the cascade
184 Int_t nInter = ck[0]; if (nInter>16){nInter=16;}
185 for( Int_t nI=0; nI<nInter; nI++){
186 // if (!subprocCodes[nI]<90){continue;} //if process is not inelastic, go to next. Changed by taking now collision length
187 prob2int = -1.;
188 Int_t intLengthFactor = 1; // for nucleons
189 if (TMath::Abs(ancestors[nI]) < 1000){intLengthFactor = 1.16;} // for mesons
190 // Fe: nuclear /\ 16.77 cm pion 20.42 cm f=1.22
191 // W: nuclear /\ 9.946 cm pion 11.33 cm f=1.14
192 // Mo: nuclear /\ 15.25 cm pion 17.98 cm f=1.18
193 while (prob2int<rndm) {
194 //place x,y,z uniform along path
195 zinter = gRandom->Uniform(zinterStart,end[2]);
196 Double_t point[3]={xOff,yOff,zinter};
198 Double_t interLength = mparam[8] * intLengthFactor * 1.7; // 1.7 = interaction length / collision length from PDG Tables
199 TGeoNode *node = gGeoManager->FindNode(point[0],point[1],point[2]);
200 TGeoMaterial *mat = 0;
201 if (node && !gGeoManager->IsOutside()) {
202 mat = node->GetVolume()->GetMaterial();
203 Double_t n = mat->GetDensity()/mat->GetA();
204 sigma = 1./(n*mat->GetIntLen())/mbarn; // no need to multiply with intLengthFactor, will cancel in next equation.
205 prob2int = TMath::Exp(-interLength)*sigma/maxCrossSection;
206 }else{
207 prob2int=0.;
208 }
209 rndm = gRandom->Uniform(0.,1.);
210 count+=1;
211 }
212 zinterStart = zinter;
213 }
214 zinter = zinter*cm;
215 }
216 for(Int_t c=0; c<2; c++){
217 if(c>0){
218 fTree->GetEntry(fn%fNevents);
219 fn++;
220 }
221 fPythia->event.reset();
222 id = (Int_t)hid[0];
223 fPythia->event.append( id, 1, 0, 0, hpx[0], hpy[0], hpz[0], hE[0], hM[0], 0., 9. );
224//simulate displaced vertex, Pythia8 will not do it
225 Double_t tau0 = fPythia->particleData.tau0(id); // ctau in mm
226 dl = gRandom->Exp(tau0) / hM[0]; // mm/GeV
227 fPythia->next();
228 Int_t addedParticles = 0;
229 if(c==0){
230// original particle responsible for interaction, "mother of charm" from external file
231 px=mpx[0];
232 py=mpy[0];
233 pz=mpz[0];
234 x=0.;
235 y=0.;
236 z=zinter;
237 id=mid[0];
238 cpg->AddTrack(id,px,py,pz,x/cm,y/cm,z/cm,-1,false);
239 addedParticles +=1;
240 }
241 for(Int_t ii=1; ii<fPythia->event.size(); ii++){
242 id = fPythia->event[ii].id();
243 Bool_t wanttracking=false;
244 if(fPythia->event[ii].isFinal()){ wanttracking=true; }
245 if (ii>1){
246 z = fPythia->event[ii].zProd()+dl*fPythia->event[1].pz()+zinter;
247 x = fPythia->event[ii].xProd()+dl*fPythia->event[1].px();
248 y = fPythia->event[ii].yProd()+dl*fPythia->event[1].py();
249 tof = fPythia->event[ii].tProd()/ (10*c_light) + dl*fPythia->event[1].e()/cm/c_light;
250 }else{
251 z = fPythia->event[ii].zProd()+zinter;
252 x = fPythia->event[ii].xProd();
253 y = fPythia->event[ii].yProd();
254 tof = fPythia->event[ii].tProd() / (10*c_light) ; // to go from mm to s
255 }
256 pz = fPythia->event[ii].pz();
257 px = fPythia->event[ii].px();
258 py = fPythia->event[ii].py();
259 e = fPythia->event[ii].e();
260 im = fPythia->event[ii].mother1()+key;
261
262 if (ii==1){im = 0;}
263 cpg->AddTrack(id,px,py,pz,x/cm,y/cm,z/cm,im,wanttracking,e,tof,1.);
264 addedParticles+=1;
265 }
266 key+=addedParticles-1; // pythia counts from 1
267 }
268 counter+=1;
269// now the underyling event
270 bool lx = true;
271 while(lx){
272 fTree->GetEntry(fn%fNevents);
273 lx = false;
274 if (mE[0] == 0){
275 lx = true;
276 fn++;
277 cpg->AddTrack((Int_t)hid[0],hpx[0],hpy[0],hpz[0],(mpx[0]+fPythia->event[0].xProd())/cm,
278 (mpy[0]+fPythia->event[0].yProd())/cm,
279 (mpz[0]+fPythia->event[0].zProd())/cm+zinter/cm,-1,true);
280 // mpx,mpy,mpz are the vertex coordinates with respect to charm hadron, first particle in Pythia is (system)
281 }
282 }
283
284 return kTRUE;
285}
286// -------------------------------------------------------------------------
287
const Double_t c_light
const Double_t mbarn
Int_t counter
const Double_t cm
const Double_t c_light
const Double_t mbarn
Double_t cm
Double_t MeanMaterialBudget(const Double_t *start, const Double_t *end, Double_t *mparam)
virtual Bool_t Init()
Double_t mparam[10]
Bool_t ReadEvent(FairPrimaryGenerator *)
Pythia8::RndmEngine * fRandomEngine
Float_t subprocCodes[16]
const char * fextFile
Float_t ancestors[16]
Pythia8::Pythia * fPythia
GenieGenerator * fMaterialInvestigator
TTree * fTree
don't make it persistent, magic ROOT command
ClassImp(ecalContFact) ecalContFact