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