In AliStack: TClonesArray* fParticles replaced by TClonesArray
[u/mrichter/AliRoot.git] / THijing / AliGenHijing.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 // Generator using HIJING as an external generator
19 // The main HIJING options are accessable for the user through this interface.
20 // Uses the THijing implementation of TGenerator.
21 // Author:
22 // Andreas Morsch    (andreas.morsch@cern.ch)
23 //
24
25 #include <TClonesArray.h>
26 #include <TGraph.h>
27 #include <THijing.h>
28 #include <TLorentzVector.h>
29 #include <TPDGCode.h>
30 #include <TParticle.h>
31
32 #include "AliGenHijing.h"
33 #include "AliGenHijingEventHeader.h"
34 #include "AliRun.h"
35 #include "AliHijingRndm.h"
36
37 ClassImp(AliGenHijing)
38
39 AliGenHijing::AliGenHijing()
40     :AliGenMC(),
41      fFrame("CMS"),
42      fMinImpactParam(0.),
43      fMaxImpactParam(5.),
44      fKeep(0),
45      fQuench(1),
46      fShadowing(1),
47      fDecaysOff(1),
48      fTrigger(0),     
49      fEvaluate(0),
50      fSelectAll(0),
51      fFlavor(0),
52      fEnergyCMS(5500.),
53      fKineBias(0.),
54      fTrials(0),
55      fXsection(0.),
56      fHijing(0),
57      fPtHardMin(0.),
58      fPtHardMax(1.e4),
59      fSpectators(1),
60      fDsigmaDb(0),
61      fDnDb(0),
62      fPtMinJet(-2.5),
63      fEtaMinJet(-20.),
64      fEtaMaxJet(+20.),
65      fPhiMinJet(0.),
66      fPhiMaxJet(2. * TMath::Pi()),
67      fRadiation(3),
68      fSimpleJet(kFALSE),
69      fNoGammas(kFALSE),
70      fProjectileSpecn(0),
71      fProjectileSpecp(0),
72      fTargetSpecn(0),
73      fTargetSpecp(0),
74      fLHC(kFALSE),
75      fRandomPz(kFALSE),
76      fNoHeavyQuarks(kFALSE)
77 {
78 // Constructor
79     AliHijingRndm::SetHijingRandom(GetRandom());
80 }
81
82 AliGenHijing::AliGenHijing(Int_t npart)
83     :AliGenMC(npart),
84      fFrame("CMS"),
85      fMinImpactParam(0.),
86      fMaxImpactParam(5.),
87      fKeep(0),
88      fQuench(1),
89      fShadowing(1),
90      fDecaysOff(1),
91      fTrigger(0),     
92      fEvaluate(0),
93      fSelectAll(0),
94      fFlavor(0),
95      fEnergyCMS(5500.),
96      fKineBias(0.),
97      fTrials(0),
98      fXsection(0.),
99      fHijing(0),
100      fPtHardMin(0.),
101      fPtHardMax(1.e4),
102      fSpectators(1),
103      fDsigmaDb(0),
104      fDnDb(0),
105      fPtMinJet(-2.5),
106      fEtaMinJet(-20.),
107      fEtaMaxJet(+20.),
108      fPhiMinJet(0.),
109      fPhiMaxJet(2. * TMath::Pi()),
110      fRadiation(3),
111      fSimpleJet(kFALSE),
112      fNoGammas(kFALSE),
113      fProjectileSpecn(0),
114      fProjectileSpecp(0),
115      fTargetSpecn(0),
116      fTargetSpecp(0),
117      fLHC(kFALSE),
118      fRandomPz(kFALSE),
119      fNoHeavyQuarks(kFALSE)
120 {
121 // Default PbPb collisions at 5. 5 TeV
122 //
123     fName = "Hijing";
124     fTitle= "Particle Generator using HIJING";
125 //
126 //
127 // Set random number generator   
128     AliHijingRndm::SetHijingRandom(GetRandom());
129 }
130
131 AliGenHijing::~AliGenHijing()
132 {
133 // Destructor
134     if ( fDsigmaDb) delete  fDsigmaDb;  
135     if ( fDnDb)     delete  fDnDb;  
136 }
137
138 void AliGenHijing::Init()
139 {
140 // Initialisation
141     fFrame.Resize(8);
142     fTarget.Resize(8);
143     fProjectile.Resize(8);
144     
145     SetMC(new THijing(fEnergyCMS, fFrame, fProjectile, fTarget, 
146                       fAProjectile, fZProjectile, fATarget, fZTarget, 
147                       fMinImpactParam, fMaxImpactParam));
148
149     fHijing=(THijing*) fMCEvGen;
150     fHijing->SetIHPR2(2,  fRadiation);
151     fHijing->SetIHPR2(3,  fTrigger);
152     fHijing->SetIHPR2(6,  fShadowing);
153     fHijing->SetIHPR2(12, fDecaysOff);    
154     fHijing->SetIHPR2(21, fKeep);
155     fHijing->SetHIPR1(10, fPtMinJet);   
156     fHijing->SetHIPR1(50, fSimpleJet);
157 //
158 //  Quenching
159 //
160 //
161 //  fQuench = 0:  no quenching
162 //  fQuench = 1:  hijing default
163 //  fQuench = 2:  new LHC  parameters for HIPR1(11) and HIPR1(14)
164 //  fQuench = 3:  new RHIC parameters for HIPR1(11) and HIPR1(14)
165 //  fQuench = 4:  new LHC  parameters with log(e) dependence
166 //  fQuench = 5:  new RHIC parameters with log(e) dependence
167     fHijing->SetIHPR2(50, 0);
168     if (fQuench > 0) 
169         fHijing->SetIHPR2(4,  1);
170     else
171         fHijing->SetIHPR2(4,  0);
172 // New LHC parameters from Xin-Nian Wang
173     if (fQuench == 2) {
174         fHijing->SetHIPR1(14, 1.1);
175         fHijing->SetHIPR1(11, 3.7);
176     } else if (fQuench == 3) {
177         fHijing->SetHIPR1(14, 0.20);
178         fHijing->SetHIPR1(11, 2.5);
179     } else if (fQuench == 4) {
180         fHijing->SetIHPR2(50, 1);
181         fHijing->SetHIPR1(14, 4.*0.34);
182         fHijing->SetHIPR1(11, 3.7);
183     } else if (fQuench == 5) {
184         fHijing->SetIHPR2(50, 1);
185         fHijing->SetHIPR1(14, 0.34);
186         fHijing->SetHIPR1(11, 2.5);
187     }
188     
189 //
190 // Heavy quarks
191 //    
192     if (fNoHeavyQuarks) {
193         fHijing->SetIHPR2(49, 1);
194     } else {
195         fHijing->SetIHPR2(49, 0);
196     }
197     
198     
199     AliGenMC::Init();
200     
201 //
202 //  Initialize Hijing  
203 //    
204     fHijing->Initialize();
205 //
206     if (fEvaluate) EvaluateCrossSections();
207 //
208 }
209
210 void AliGenHijing::Generate()
211 {
212 // Generate one event
213
214   Float_t polar[3]    =   {0,0,0};
215   Float_t origin[3]   =   {0,0,0};
216   Float_t origin0[3]  =   {0,0,0};
217   Float_t p[3];
218   Float_t tof;
219
220 //  converts from mm/c to s
221   const Float_t kconv = 0.001/2.99792458e8;
222 //
223   Int_t nt  = 0;
224   Int_t jev = 0;
225   Int_t j, kf, ks, ksp, imo;
226   kf = 0;
227     
228
229     
230   fTrials = 0;
231   
232   for (j = 0;j < 3; j++) origin0[j] = fOrigin[j];
233   if(fVertexSmear == kPerEvent) {
234       Vertex();
235       for (j=0; j < 3; j++) origin0[j] = fVertex[j];
236   } 
237
238
239   Float_t sign = (fRandomPz && (Rndm() < 0.5))? -1. : 1.;
240   while(1)
241   {
242 //    Generate one event
243 // --------------------------------------------------------------------------
244       fProjectileSpecn    = 0;  
245       fProjectileSpecp    = 0;
246       fTargetSpecn        = 0;  
247       fTargetSpecp        = 0;
248 // --------------------------------------------------------------------------
249       fHijing->GenerateEvent();
250       fTrials++;
251       fNprimaries = 0;
252       fHijing->ImportParticles(&fParticles,"All");
253       if (fTrigger != kNoTrigger) {
254           if (!CheckTrigger()) continue;
255       }
256       if (fLHC) Boost();
257       
258       
259       Int_t np = fParticles.GetEntriesFast();
260       printf("\n **************************************************%d\n",np);
261       Int_t nc = 0;
262       if (np == 0 ) continue;
263       Int_t i;
264       Int_t* newPos     = new Int_t[np];
265       Int_t* pSelected  = new Int_t[np];
266
267       for (i = 0; i < np; i++) {
268           newPos[i]    = i;
269           pSelected[i] = 0;
270       }
271       
272 //      Get event vertex
273 //
274       TParticle *  iparticle = (TParticle *) fParticles.At(0);
275       fVertex[0] = origin0[0];
276       fVertex[1] = origin0[1];  
277       fVertex[2] = origin0[2];
278       
279 //
280 //      First select parent particles
281 //
282
283       for (i = 0; i < np; i++) {
284           iparticle = (TParticle *) fParticles.At(i);
285
286 // Is this a parent particle ?
287           if (Stable(iparticle)) continue;
288 //
289           Bool_t  selected             =  kTRUE;
290           Bool_t  hasSelectedDaughters =  kFALSE;
291           
292           
293           kf        = iparticle->GetPdgCode();
294           ks        = iparticle->GetStatusCode();
295           if (kf == 92) continue;
296             
297           if (!fSelectAll) selected = KinematicSelection(iparticle, 0) && 
298                                SelectFlavor(kf);
299           hasSelectedDaughters = DaughtersSelection(iparticle);
300 //
301 // Put particle on the stack if it is either selected or 
302 // it is the mother of at least one seleted particle
303 //
304           if (selected || hasSelectedDaughters) {
305               nc++;
306               pSelected[i] = 1;
307           } // selected
308       } // particle loop parents
309 //
310 // Now select the final state particles
311 //
312
313       for (i = 0; i<np; i++) {
314           TParticle *  iparticle = (TParticle *) fParticles.At(i);
315 // Is this a final state particle ?
316           if (!Stable(iparticle)) continue;
317       
318           Bool_t  selected             =  kTRUE;
319           kf        = iparticle->GetPdgCode();
320           ks        = iparticle->GetStatusCode();
321           ksp       = iparticle->GetUniqueID();
322           
323 // --------------------------------------------------------------------------
324 // Count spectator neutrons and protons
325           if(ksp == 0 || ksp == 1){
326               if(kf == kNeutron) fProjectileSpecn += 1;
327               if(kf == kProton)  fProjectileSpecp += 1;
328           }
329           else if(ksp == 10 || ksp == 11){
330               if(kf == kNeutron) fTargetSpecn += 1;
331               if(kf == kProton)  fTargetSpecp += 1;
332           }
333 // --------------------------------------------------------------------------
334 //          
335           if (!fSelectAll) {
336               selected = KinematicSelection(iparticle,0)&&SelectFlavor(kf);
337               if (!fSpectators && selected) selected = (ksp != 0 && ksp != 1 && ksp != 10
338                                                         && ksp != 11);
339           }
340 //
341 // Put particle on the stack if selected
342 //
343           if (selected) {
344               nc++;
345               pSelected[i] = 1;
346           } // selected
347       } // particle loop final state
348
349 //
350 //    Time of the interactions
351       Float_t tInt = 0.;
352       if (fPileUpTimeWindow > 0.) tInt = fPileUpTimeWindow * (2. * gRandom->Rndm() - 1.);
353
354 //
355 // Write particles to stack
356
357       for (i = 0; i<np; i++) {
358           TParticle *  iparticle = (TParticle *) fParticles.At(i);
359           Bool_t  hasMother   = (iparticle->GetFirstMother()     >=0);
360           Bool_t  hasDaughter = (iparticle->GetFirstDaughter()   >=0);
361           if (pSelected[i]) {
362               kf   = iparticle->GetPdgCode();
363               ks   = iparticle->GetStatusCode();
364               p[0] = iparticle->Px();
365               p[1] = iparticle->Py();
366               p[2] = iparticle->Pz() * sign;
367               origin[0] = origin0[0]+iparticle->Vx()/10;
368               origin[1] = origin0[1]+iparticle->Vy()/10;
369               origin[2] = origin0[2]+iparticle->Vz()/10;
370               tof = kconv * iparticle->T() + sign * origin0[2] / 3.e10;
371               if (fPileUpTimeWindow > 0.) tof += tInt;
372               
373               imo = -1;
374               TParticle* mother = 0;
375               if (hasMother) {
376                   imo = iparticle->GetFirstMother();
377                   mother = (TParticle *) fParticles.At(imo);
378                   imo = (mother->GetPdgCode() != 92) ? newPos[imo] : -1;
379               } // if has mother   
380               Bool_t tFlag = (fTrackIt && !hasDaughter);
381               PushTrack(tFlag,imo,kf,p,origin,polar,tof,kPNoProcess,nt, 1., ks);
382               fNprimaries++;
383               KeepTrack(nt);
384               newPos[i] = nt;
385           } // if selected
386       } // particle loop
387       delete[] newPos;
388       delete[] pSelected;
389       
390       printf("\n I've put %i particles on the stack \n",nc);
391       if (nc > 0) {
392           jev += nc;
393           if (jev >= fNpart || fNpart == -1) {
394               fKineBias = Float_t(fNpart)/Float_t(fTrials);
395               printf("\n Trials: %i %i %i\n",fTrials, fNpart, jev);
396               break;
397           }
398       }
399   } // event loop
400   MakeHeader();
401   SetHighWaterMark(nt);
402 }
403
404 void AliGenHijing::KeepFullEvent()
405 {
406     fKeep=1;
407 }
408
409 void AliGenHijing::EvaluateCrossSections()
410 {
411 //     Glauber Calculation of geometrical x-section
412 //
413     Float_t xTot       = 0.;          // barn
414     Float_t xTotHard   = 0.;          // barn 
415     Float_t xPart      = 0.;          // barn
416     Float_t xPartHard  = 0.;          // barn 
417     Float_t sigmaHard  = 0.1;         // mbarn
418     Float_t bMin       = 0.;
419     Float_t bMax       = fHijing->GetHIPR1(34)+fHijing->GetHIPR1(35);
420     const Float_t kdib = 0.2;
421     Int_t   kMax       = Int_t((bMax-bMin)/kdib)+1;
422
423
424     printf("\n Projectile Radius (fm): %f \n",fHijing->GetHIPR1(34));
425     printf("\n Target     Radius (fm): %f \n",fHijing->GetHIPR1(35));    
426     Int_t i;
427     Float_t oldvalue= 0.;
428
429     Float_t* b   = new Float_t[kMax];
430     Float_t* si1 = new Float_t[kMax];    
431     Float_t* si2 = new Float_t[kMax];    
432     
433     for (i = 0; i < kMax; i++)
434     {
435         Float_t xb  = bMin+i*kdib;
436         Float_t ov;
437         ov=fHijing->Profile(xb);
438         Float_t gb  =  2.*0.01*fHijing->GetHIPR1(40)*kdib*xb*(1.-TMath::Exp(-fHijing->GetHINT1(12)*ov));
439         Float_t gbh =  2.*0.01*fHijing->GetHIPR1(40)*kdib*xb*sigmaHard*ov;
440         xTot+=gb;
441         xTotHard += gbh;
442         printf("profile %f %f %f\n", xb, ov, fHijing->GetHINT1(12));
443         
444         if (xb > fMinImpactParam && xb < fMaxImpactParam)
445         {
446             xPart += gb;
447             xPartHard += gbh;
448         }
449         
450         if(oldvalue) if ((xTot-oldvalue)/oldvalue<0.0001) break;
451         oldvalue = xTot;
452         printf("\n Total cross section (barn): %d %f %f \n",i, xb, xTot);
453         printf("\n Hard  cross section (barn): %d %f %f \n\n",i, xb, xTotHard);
454         if (i>0) {
455             si1[i] = gb/kdib;
456             si2[i] = gbh/gb;
457             b[i]  = xb;
458         }
459     }
460
461     printf("\n Total cross section (barn): %f \n",xTot);
462     printf("\n Hard  cross section (barn): %f \n \n",xTotHard);
463     printf("\n Partial       cross section (barn): %f %f \n",xPart, xPart/xTot*100.);
464     printf("\n Partial  hard cross section (barn): %f %f \n",xPartHard, xPartHard/xTotHard*100.);
465
466 //  Store result as a graph
467     b[0] = 0;
468     si1[0] = 0;
469     si2[0]=si2[1];
470     
471     fDsigmaDb  = new TGraph(i, b, si1);
472     fDnDb      = new TGraph(i, b, si2);
473 }
474
475 Bool_t AliGenHijing::DaughtersSelection(TParticle* iparticle)
476 {
477 //
478 // Looks recursively if one of the daughters has been selected
479 //
480 //    printf("\n Consider daughters %d:",iparticle->GetPdgCode());
481     Int_t imin = -1;
482     Int_t imax = -1;
483     Int_t i;
484     Bool_t hasDaughters = (iparticle->GetFirstDaughter() >=0);
485     Bool_t selected = kFALSE;
486     if (hasDaughters) {
487         imin = iparticle->GetFirstDaughter();
488         imax = iparticle->GetLastDaughter();       
489         for (i = imin; i <= imax; i++){
490             TParticle *  jparticle = (TParticle *) fParticles.At(i);    
491             Int_t ip = jparticle->GetPdgCode();
492             if (KinematicSelection(jparticle,0)&&SelectFlavor(ip)) {
493                 selected=kTRUE; break;
494             }
495             if (DaughtersSelection(jparticle)) {selected=kTRUE; break; }
496         }
497     } else {
498         return kFALSE;
499     }
500     return selected;
501 }
502
503
504 Bool_t AliGenHijing::SelectFlavor(Int_t pid)
505 {
506 // Select flavor of particle
507 // 0: all
508 // 4: charm and beauty
509 // 5: beauty
510     Bool_t res = 0;
511     
512     if (fFlavor == 0) {
513         res = kTRUE;
514     } else {
515         Int_t ifl = TMath::Abs(pid/100);
516         if (ifl > 10) ifl/=10;
517         res = (fFlavor == ifl);
518     }
519 //
520 //  This part if gamma writing is inhibited
521     if (fNoGammas) 
522         res = res && (pid != kGamma && pid != kPi0);
523 //
524     return res;
525 }
526
527 Bool_t AliGenHijing::Stable(TParticle*  particle) const
528 {
529 // Return true for a stable particle
530 //
531     
532     if (particle->GetFirstDaughter() < 0 )
533     {
534         return kTRUE;
535     } else {
536         return kFALSE;
537     }
538 }
539
540
541
542 void AliGenHijing::MakeHeader()
543 {
544 // Builds the event header, to be called after each event
545     AliGenEventHeader* header = new AliGenHijingEventHeader("Hijing");
546     ((AliGenHijingEventHeader*) header)->SetNProduced(fNprimaries);
547     ((AliGenHijingEventHeader*) header)->SetImpactParameter(fHijing->GetHINT1(19));
548     ((AliGenHijingEventHeader*) header)->SetTotalEnergy(fHijing->GetEATT());
549     ((AliGenHijingEventHeader*) header)->SetHardScatters(fHijing->GetJATT());
550     ((AliGenHijingEventHeader*) header)->SetParticipants(fHijing->GetNP(), fHijing->GetNT());
551     ((AliGenHijingEventHeader*) header)->SetCollisions(fHijing->GetN0(),
552                                                        fHijing->GetN01(),
553                                                        fHijing->GetN10(),
554                                                        fHijing->GetN11());
555     ((AliGenHijingEventHeader*) header)->SetSpectators(fProjectileSpecn, fProjectileSpecp,
556                                                        fTargetSpecn,fTargetSpecp);
557     ((AliGenHijingEventHeader*) header)->SetReactionPlaneAngle(fHijing->GetHINT1(20));
558     
559
560
561 // 4-momentum vectors of the triggered jets.
562 //
563 // Before final state gluon radiation.
564     TLorentzVector* jet1 = new TLorentzVector(fHijing->GetHINT1(21), 
565                                               fHijing->GetHINT1(22),
566                                               fHijing->GetHINT1(23),
567                                               fHijing->GetHINT1(24));
568
569     TLorentzVector* jet2 = new TLorentzVector(fHijing->GetHINT1(31), 
570                                               fHijing->GetHINT1(32),
571                                               fHijing->GetHINT1(33),
572                                               fHijing->GetHINT1(34));
573 // After final state gluon radiation.
574     TLorentzVector* jet3 = new TLorentzVector(fHijing->GetHINT1(26), 
575                                               fHijing->GetHINT1(27),
576                                               fHijing->GetHINT1(28),
577                                               fHijing->GetHINT1(29));
578
579     TLorentzVector* jet4 = new TLorentzVector(fHijing->GetHINT1(36), 
580                                               fHijing->GetHINT1(37),
581                                               fHijing->GetHINT1(38),
582                                               fHijing->GetHINT1(39));
583     ((AliGenHijingEventHeader*) header)->SetJets(jet1, jet2, jet3, jet4);
584 // Bookkeeping for kinematic bias
585     ((AliGenHijingEventHeader*) header)->SetTrials(fTrials);
586 // Event Vertex
587     header->SetPrimaryVertex(fVertex);
588     AddHeader(header);
589     fCollisionGeometry = (AliGenHijingEventHeader*)  header;
590 }
591
592
593 Bool_t AliGenHijing::CheckTrigger()
594 {
595 // Check the kinematic trigger condition
596 //
597     Bool_t   triggered = kFALSE;
598  
599     if (fTrigger == 1) {
600 //
601 //  jet-jet Trigger     
602         
603         TLorentzVector* jet1 = new TLorentzVector(fHijing->GetHINT1(26), 
604                                                   fHijing->GetHINT1(27),
605                                                   fHijing->GetHINT1(28),
606                                                   fHijing->GetHINT1(29));
607         
608         TLorentzVector* jet2 = new TLorentzVector(fHijing->GetHINT1(36), 
609                                                   fHijing->GetHINT1(37),
610                                                   fHijing->GetHINT1(38),
611                                                   fHijing->GetHINT1(39));
612         Double_t eta1      = jet1->Eta();
613         Double_t eta2      = jet2->Eta();
614         Double_t phi1      = jet1->Phi();
615         Double_t phi2      = jet2->Phi();
616 //    printf("\n Trigger: %f %f %f %f",
617 //         fEtaMinJet, fEtaMaxJet, fPhiMinJet, fPhiMaxJet);
618         if (
619             (eta1 < fEtaMaxJet && eta1 > fEtaMinJet &&  
620              phi1 < fPhiMaxJet && phi1 > fPhiMinJet) 
621             ||
622             (eta2 < fEtaMaxJet && eta2 > fEtaMinJet &&  
623              phi2 < fPhiMaxJet && phi2 > fPhiMinJet)
624             ) 
625             triggered = kTRUE;
626     } else if (fTrigger == 2) {
627 //  Gamma Jet
628 //
629         Int_t np = fParticles.GetEntriesFast();
630         for (Int_t i = 0; i < np; i++) {
631             TParticle* part = (TParticle*) fParticles.At(i);
632             Int_t kf = part->GetPdgCode();
633             Int_t ksp = part->GetUniqueID();
634             if (kf == 22 && ksp == 40) {
635                 Float_t phi = part->Phi();
636                 Float_t eta = part->Eta();
637                 if  (eta < fEtaMaxJet && 
638                      eta > fEtaMinJet &&
639                      phi < fPhiMaxJet && 
640                      phi > fPhiMinJet) {
641                     triggered = 1;
642                     break;
643                 } // check phi,eta within limits
644             } // direct gamma ? 
645         } // particle loop
646     } // fTrigger == 2
647     return triggered;
648 }