]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EVGEN/AliGenHijing.cxx
Count the number of spectator neutrons and protons and add information
[u/mrichter/AliRoot.git] / EVGEN / 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 /*
17 $Log$
18 Revision 1.23  2001/07/13 17:30:22  morsch
19 Derive from AliGenMC.
20
21 Revision 1.22  2001/06/11 13:09:23  morsch
22 - Store cross-Section and number of binary collisions as a function of impact parameter
23 - Pass AliGenHijingEventHeader to gAlice.
24
25 Revision 1.21  2001/02/28 17:35:24  morsch
26 Consider elastic interactions (ks = 1 and ks = 11) as spectator (Chiara Oppedisano)
27
28 Revision 1.20  2001/02/14 15:50:40  hristov
29 The last particle in event marked using SetHighWaterMark
30
31 Revision 1.19  2000/12/21 16:24:06  morsch
32 Coding convention clean-up
33
34 Revision 1.18  2000/12/06 17:46:30  morsch
35 Avoid random numbers 1 and 0.
36
37 Revision 1.17  2000/12/04 11:22:03  morsch
38 Init of sRandom as in 1.15
39
40 Revision 1.16  2000/12/02 11:41:39  morsch
41 Use SetRandom() to initialize random number generator in constructor.
42
43 Revision 1.15  2000/11/30 20:29:02  morsch
44 Initialise static variable sRandom in constructor: sRandom = fRandom;
45
46 Revision 1.14  2000/11/30 07:12:50  alibrary
47 Introducing new Rndm and QA classes
48
49 Revision 1.13  2000/11/09 17:40:27  morsch
50 Possibility to select/unselect spectator protons and neutrons.
51 Method SetSpectators(Int_t spect) added. (FCA, Ch. Oppedisano)
52
53 Revision 1.12  2000/10/20 13:38:38  morsch
54 Debug printouts commented.
55
56 Revision 1.11  2000/10/20 13:22:26  morsch
57 - skip particle type 92 (string)
58 - Charmed and beauty baryions (5122, 4122) are considered as stable consistent with
59   mesons.
60
61 Revision 1.10  2000/10/17 15:10:20  morsch
62 Write first all the parent particles to the stack and then the final state particles.
63
64 Revision 1.9  2000/10/17 13:38:59  morsch
65 Protection against division by zero in EvaluateCrossSection() and KinematicSelection(..)     (FCA)
66
67 Revision 1.8  2000/10/17 12:46:31  morsch
68 Protect EvaluateCrossSections() against division by zero.
69
70 Revision 1.7  2000/10/02 21:28:06  fca
71 Removal of useless dependecies via forward declarations
72
73 Revision 1.6  2000/09/11 13:23:37  morsch
74 Write last seed to file (fortran lun 50) and reed back from same lun using calls to
75 luget_hijing and luset_hijing.
76
77 Revision 1.5  2000/09/07 16:55:40  morsch
78 fHijing->Initialize(); after change of parameters. (Dmitri Yurevitch Peressounko)
79
80 Revision 1.4  2000/07/11 18:24:56  fca
81 Coding convention corrections + few minor bug fixes
82
83 Revision 1.3  2000/06/30 12:08:36  morsch
84 In member data: char* replaced by TString, Init takes care of resizing the strings to
85 8 characters required by Hijing.
86
87 Revision 1.2  2000/06/15 14:15:05  morsch
88 Add possibility for heavy flavor selection: charm and beauty.
89
90 Revision 1.1  2000/06/09 20:47:27  morsch
91 AliGenerator interface class to HIJING using THijing (test version)
92
93 */
94
95
96
97 // Generator using HIJING as an external generator
98 // The main HIJING options are accessable for the user through this interface.
99 // Uses the THijing implementation of TGenerator.
100 //
101 // andreas.morsch@cern.ch
102
103 #include "AliGenHijing.h"
104 #include "AliGenHijingEventHeader.h"
105 #include "AliRun.h"
106 #include "AliPDG.h"
107
108 #include <TArrayI.h>
109 #include <TParticle.h>
110 #include <THijing.h>
111 #include <TGraph.h>
112
113
114  ClassImp(AliGenHijing)
115
116 AliGenHijing::AliGenHijing()
117                  :AliGenMC()
118 {
119 // Constructor
120 }
121
122 AliGenHijing::AliGenHijing(Int_t npart)
123     :AliGenMC(npart)
124 {
125 // Default PbPb collisions at 5. 5 TeV
126 //
127     SetEnergyCMS();
128     SetImpactParameterRange();
129     SetTarget();
130     SetProjectile();
131     fKeep       = 0;
132     fQuench     = 1;
133     fShadowing  = 1;
134     fTrigger    = 0;
135     fDecaysOff  = 1;
136     fEvaluate   = 0;
137     fSelectAll  = 0;
138     fFlavor     = 0;
139     fSpectators = 1;
140     fDsigmaDb   = 0;  
141     fDnDb       = 0; 
142 //
143 // Set random number generator   
144     sRandom = fRandom;
145 }
146
147 AliGenHijing::AliGenHijing(const AliGenHijing & Hijing)
148 {
149 // copy constructor
150 }
151
152
153 AliGenHijing::~AliGenHijing()
154 {
155 // Destructor
156     if ( fDsigmaDb) delete  fDsigmaDb;  
157     if ( fDnDb)     delete  fDnDb;  
158 }
159
160 void AliGenHijing::Init()
161 {
162 // Initialisation
163     fFrame.Resize(8);
164     fTarget.Resize(8);
165     fProjectile.Resize(8);
166     
167     SetMC(new THijing(fEnergyCMS, fFrame, fProjectile, fTarget, 
168                       fAProjectile, fZProjectile, fATarget, fZTarget, 
169                       fMinImpactParam, fMaxImpactParam));
170
171     fHijing=(THijing*) fgMCEvGen;
172
173     fHijing->SetIHPR2(3,  fTrigger);
174     fHijing->SetIHPR2(4,  fQuench);
175     fHijing->SetIHPR2(6,  fShadowing);
176     fHijing->SetIHPR2(12, fDecaysOff);    
177     fHijing->SetIHPR2(21, fKeep);
178     fHijing->Initialize();
179
180     
181 //
182     if (fEvaluate) EvaluateCrossSections();
183 //
184 //
185 //  Initialize random generator
186 }
187
188 void AliGenHijing::Generate()
189 {
190 // Generate one event
191
192   Float_t polar[3]    =   {0,0,0};
193   Float_t origin[3]   =   {0,0,0};
194   Float_t origin0[3]  =   {0,0,0};
195   Float_t p[3], random[6];
196   Float_t tof;
197
198   static TClonesArray *particles;
199 //  converts from mm/c to s
200   const Float_t kconv = 0.001/2.999792458e8;
201 //
202   Int_t nt  = 0;
203   Int_t jev = 0;
204   Int_t j, kf, ks, imo;
205   kf = 0;
206     
207   if(!particles) particles = new TClonesArray("TParticle",10000);
208     
209   fTrials = 0;
210   for (j = 0;j < 3; j++) origin0[j] = fOrigin[j];
211   if(fVertexSmear == kPerEvent) {
212         Rndm(random,6);
213         for (j=0; j < 3; j++) {
214             origin0[j] += fOsigma[j]*TMath::Cos(2*random[2*j]*TMath::Pi())*
215                 TMath::Sqrt(-2*TMath::Log(random[2*j+1]));
216         }
217   } else if (fVertexSmear == kPerTrack) {
218 //          fHijing->SetMSTP(151,0);
219       for (j = 0; j < 3; j++) {
220 //            fHijing->SetPARP(151+j, fOsigma[j]*10.);
221       }
222   }
223   while(1)
224   {
225 //    Generate one event
226 // --------------------------------------------------------------------------
227       fSpecn    = 0;  
228       fSpecp    = 0;
229 // --------------------------------------------------------------------------
230       fHijing->GenerateEvent();
231       fTrials++;
232       fHijing->ImportParticles(particles,"All");
233       Int_t np = particles->GetEntriesFast();
234       printf("\n **************************************************%d\n",np);
235       Int_t nc = 0;
236       if (np == 0 ) continue;
237       Int_t i;
238       Int_t * newPos = new Int_t[np];
239
240       for (i = 0; i < np; i++) *(newPos+i) = i;
241 //
242 //      First write parent particles
243 //
244
245       for (i = 0; i < np; i++) {
246           TParticle *  iparticle       = (TParticle *) particles->At(i);
247 // Is this a parent particle ?
248         if (Stable(iparticle)) continue;
249 //
250         Bool_t  hasMother            =  (iparticle->GetFirstMother()   >=0);
251         Bool_t  selected             =  kTRUE;
252         Bool_t  hasSelectedDaughters =  kFALSE;
253             
254             
255         kf        = iparticle->GetPdgCode();
256         ks        = iparticle->GetStatusCode();
257         if (kf == 92) continue;
258             
259         if (!fSelectAll) selected = KinematicSelection(iparticle, 0)&&SelectFlavor(kf);
260         hasSelectedDaughters = DaughtersSelection(iparticle, particles);
261 //
262 // Put particle on the stack if it is either selected or it is the mother of at least one seleted particle
263 //
264         if (selected || hasSelectedDaughters) {
265             nc++;
266             p[0] = iparticle->Px();
267             p[1] = iparticle->Py();
268             p[2] = iparticle->Pz();
269             origin[0] = origin0[0]+iparticle->Vx()/10;
270             origin[1] = origin0[1]+iparticle->Vy()/10;
271             origin[2] = origin0[2]+iparticle->Vz()/10;
272             tof = kconv*iparticle->T();
273             imo = -1;
274             if (hasMother) {
275                 imo = iparticle->GetFirstMother();
276                 TParticle* mother = (TParticle *) particles->At(imo);
277                 imo = (mother->GetPdgCode() != 92) ? imo =* (newPos+imo) : -1;
278             }
279 // Put particle on the stack ... 
280 //              printf("\n set track mother: %d %d %d %d %d %d ",i,imo, kf, nt+1, selected, hasSelectedDaughters);
281             
282             gAlice->SetTrack(0,imo,kf,p,origin,polar,
283                              tof,kPPrimary,nt);
284 // ... and keep it there
285             gAlice->KeepTrack(nt);
286 //
287             *(newPos+i)=nt;
288         } // selected
289       } // particle loop parents
290 //
291 // Now write the final state particles
292 //
293
294       for (i = 0; i<np; i++) {
295         TParticle *  iparticle       = (TParticle *) particles->At(i);
296 // Is this a final state particle ?
297         if (!Stable(iparticle)) continue;
298
299         Bool_t  hasMother            =  (iparticle->GetFirstMother()   >=0);
300         Bool_t  selected             =  kTRUE;
301         kf        = iparticle->GetPdgCode();
302         ks        = iparticle->GetStatusCode();
303 // --------------------------------------------------------------------------
304 // Count spectator neutrons and protons
305         if(ks == 0 || ks == 1 || ks == 10 || ks == 11){
306           if(kf == kNeutron) fSpecn += 1;
307           if(kf == kProton)  fSpecp += 1;
308         }
309 // --------------------------------------------------------------------------
310 //          
311         if (!fSelectAll) {
312             selected = KinematicSelection(iparticle,0)&&SelectFlavor(kf);
313             if (!fSpectators && selected) selected = (ks != 0 && ks != 1 && ks != 10
314                                                       && ks != 11);
315         }
316 //
317 // Put particle on the stack if selected
318 //
319         if (selected) {
320             nc++;
321             p[0] = iparticle->Px();
322             p[1] = iparticle->Py();
323             p[2] = iparticle->Pz();
324             origin[0] = origin0[0]+iparticle->Vx()/10;
325             origin[1] = origin0[1]+iparticle->Vy()/10;
326             origin[2] = origin0[2]+iparticle->Vz()/10;
327             tof = kconv*iparticle->T();
328             imo = -1;
329             
330             if (hasMother) {
331                 imo = iparticle->GetFirstMother();
332                 TParticle* mother = (TParticle *) particles->At(imo);
333                 imo = (mother->GetPdgCode() != 92) ? imo=*(newPos+imo) : -1;
334             }   
335 // Put particle on the stack
336             gAlice->SetTrack(fTrackIt,imo,kf,p,origin,polar,
337                              tof,kPNoProcess,nt);
338             gAlice->KeepTrack(nt);
339             *(newPos+i)=nt;
340         } // selected
341       } // particle loop final state
342  
343       delete newPos;
344
345       printf("\n I've put %i particles on the stack \n",nc);
346       if (nc > 0) {
347           jev += nc;
348           if (jev >= fNpart || fNpart == -1) {
349               fKineBias = Float_t(fNpart)/Float_t(fTrials);
350               printf("\n Trials: %i %i %i\n",fTrials, fNpart, jev);
351               break;
352           }
353       }
354   } // event loop
355   MakeHeader();
356   
357   gAlice->SetHighWaterMark(nt);
358 }
359
360 void AliGenHijing::KeepFullEvent()
361 {
362     fKeep=1;
363 }
364
365 void AliGenHijing::EvaluateCrossSections()
366 {
367 //     Glauber Calculation of geometrical x-section
368 //
369     Float_t xTot       = 0.;          // barn
370     Float_t xTotHard   = 0.;          // barn 
371     Float_t xPart      = 0.;          // barn
372     Float_t xPartHard  = 0.;          // barn 
373     Float_t sigmaHard  = 0.1;         // mbarn
374     Float_t bMin       = 0.;
375     Float_t bMax       = fHijing->GetHIPR1(34)+fHijing->GetHIPR1(35);
376     const Float_t kdib = 0.2;
377     Int_t   kMax       = Int_t((bMax-bMin)/kdib)+1;
378
379
380     printf("\n Projectile Radius (fm): %f \n",fHijing->GetHIPR1(34));
381     printf("\n Target     Radius (fm): %f \n",fHijing->GetHIPR1(35));    
382     Int_t i;
383     Float_t oldvalue= 0.;
384
385     Float_t* b   = new Float_t[kMax];
386     Float_t* si1 = new Float_t[kMax];    
387     Float_t* si2 = new Float_t[kMax];    
388     
389     for (i = 0; i < kMax; i++)
390     {
391         Float_t xb  = bMin+i*kdib;
392         Float_t ov;
393         ov=fHijing->Profile(xb);
394         Float_t gb  =  2.*0.01*fHijing->GetHIPR1(40)*kdib*xb*(1.-TMath::Exp(-fHijing->GetHINT1(12)*ov));
395         Float_t gbh =  2.*0.01*fHijing->GetHIPR1(40)*kdib*xb*sigmaHard*ov;
396         xTot+=gb;
397         xTotHard += gbh;
398         if (xb > fMinImpactParam && xb < fMaxImpactParam)
399         {
400             xPart += gb;
401             xPartHard += gbh;
402         }
403         
404         if(oldvalue) if ((xTot-oldvalue)/oldvalue<0.0001) break;
405         oldvalue = xTot;
406         printf("\n Total cross section (barn): %d %f %f \n",i, xb, xTot);
407         printf("\n Hard  cross section (barn): %d %f %f \n\n",i, xb, xTotHard);
408         if (i>0) {
409             si1[i] = gb/kdib;
410             si2[i] = gbh/gb;
411             b[i]  = xb;
412         }
413     }
414
415     printf("\n Total cross section (barn): %f \n",xTot);
416     printf("\n Hard  cross section (barn): %f \n \n",xTotHard);
417     printf("\n Partial       cross section (barn): %f %f \n",xPart, xPart/xTot*100.);
418     printf("\n Partial  hard cross section (barn): %f %f \n",xPartHard, xPartHard/xTotHard*100.);
419
420 //  Store result as a graph
421     b[0] = 0;
422     si1[0] = 0;
423     si2[0]=si2[1];
424     
425     fDsigmaDb  = new TGraph(i, b, si1);
426     fDnDb      = new TGraph(i, b, si2);
427 }
428
429 Bool_t AliGenHijing::DaughtersSelection(TParticle* iparticle, TClonesArray* particles)
430 {
431 //
432 // Looks recursively if one of the daughters has been selected
433 //
434 //    printf("\n Consider daughters %d:",iparticle->GetPdgCode());
435     Int_t imin = -1;
436     Int_t imax = -1;
437     Int_t i;
438     Bool_t hasDaughters = (iparticle->GetFirstDaughter() >=0);
439     Bool_t selected = kFALSE;
440     if (hasDaughters) {
441         imin = iparticle->GetFirstDaughter();
442         imax = iparticle->GetLastDaughter();       
443         for (i = imin; i <= imax; i++){
444             TParticle *  jparticle = (TParticle *) particles->At(i);    
445             Int_t ip = jparticle->GetPdgCode();
446             if (KinematicSelection(jparticle,0)&&SelectFlavor(ip)) {
447                 selected=kTRUE; break;
448             }
449             if (DaughtersSelection(jparticle, particles)) {selected=kTRUE; break; }
450         }
451     } else {
452         return kFALSE;
453     }
454     return selected;
455 }
456
457
458 Bool_t AliGenHijing::SelectFlavor(Int_t pid)
459 {
460 // Select flavor of particle
461 // 0: all
462 // 4: charm and beauty
463 // 5: beauty
464     if (fFlavor == 0) return kTRUE;
465     
466     Int_t ifl = TMath::Abs(pid/100);
467     if (ifl > 10) ifl/=10;
468     return (fFlavor == ifl);
469 }
470
471 Bool_t AliGenHijing::Stable(TParticle*  particle)
472 {
473 // Return true for a stable particle
474 //
475     Int_t kf = TMath::Abs(particle->GetPdgCode());
476     
477     if ( (particle->GetFirstDaughter() < 0 ) || (kf == 1000*fFlavor+122))
478     {
479         return kTRUE;
480     } else {
481         return kFALSE;
482     }
483 }
484
485 void AliGenHijing::MakeHeader()
486 {
487 // Builds the event header, to be called after each event
488     AliGenEventHeader* header = new AliGenHijingEventHeader("Hijing");
489    ((AliGenHijingEventHeader*) header)->SetNProduced(fHijing->GetNATT());
490    ((AliGenHijingEventHeader*) header)->SetImpactParameter(fHijing->GetHINT1(19));
491    ((AliGenHijingEventHeader*) header)->SetTotalEnergy(fHijing->GetEATT());
492    ((AliGenHijingEventHeader*) header)->SetHardScatters(fHijing->GetJATT());
493    ((AliGenHijingEventHeader*) header)->SetParticipants(fHijing->GetNP(), fHijing->GetNT());
494    ((AliGenHijingEventHeader*) header)->SetCollisions(fHijing->GetN0(),
495                           fHijing->GetN01(),
496                           fHijing->GetN10(),
497                           fHijing->GetN11());
498    ((AliGenHijingEventHeader*) header)->SetSpectators(fSpecn, fSpecp);
499    gAlice->SetGenEventHeader(header);
500    
501 }
502
503 AliGenHijing& AliGenHijing::operator=(const  AliGenHijing& rhs)
504 {
505 // Assignment operator
506     return *this;
507 }
508
509 #ifndef WIN32
510 # define rluget_hijing rluget_hijing_
511 # define rluset_hijing rluset_hijing_
512 # define rlu_hijing    rlu_hijing_
513 # define type_of_call
514 #else
515 # define rluget_hijing RLUGET_HIJING
516 # define rluset_hijing RLUSET_HIJING
517 # define rlu_hijing    RLU_HIJING
518 # define type_of_call _stdcall
519 #endif
520
521
522 extern "C" {
523   void type_of_call rluget_hijing(Int_t & /*lfn*/, Int_t & /*move*/)
524   {printf("Dummy version of rluget_hijing reached\n");}
525
526   void type_of_call rluset_hijing(Int_t & /*lfn*/, Int_t & /*move*/)
527   {printf("Dummy version of rluset_hijing reached\n");}
528
529   Double_t type_of_call rlu_hijing(Int_t & /*idum*/) 
530   {
531       Float_t r;
532       do r=sRandom->Rndm(); while(0 >= r || r >= 1);
533       return r;
534   }
535 }