1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////////
20 // AliGenAfterBurnerFlow is a After Burner event generator applying flow.
21 // The generator changes Phi coordinate of the particle momentum.
22 // Flow (directed and elliptical) can be defined on particle type level
24 // For examples, parameters and testing macros refer to:
25 // http:/home.cern.ch/radomski
28 // Sylwester Radomski,
33 //////////////////////////////////////////////////////////////////////////////
35 #include <Riostream.h>
36 #include "TParticle.h"
37 #include "TLorentzVector.h"
39 #include "AliGenAfterBurnerFlow.h"
40 #include "AliGenCocktailAfterBurner.h"
42 // emanuele ---------------------------------------------------------------(
44 #include "AliCollisionGeometry.h"
45 #include "AliGenCocktailEntry.h"
47 // emanuele ---------------------------------------------------------------)
49 ClassImp(AliGenAfterBurnerFlow)
51 ////////////////////////////////////////////////////////////////////////////////////////////////////
53 AliGenAfterBurnerFlow::AliGenAfterBurnerFlow() {
55 // Deafult Construction
62 ////////////////////////////////////////////////////////////////////////////////////////////////////
64 AliGenAfterBurnerFlow::AliGenAfterBurnerFlow(Float_t reactionPlane) {
66 // Standard Construction
68 // reactionPlane - Reaction Plane Angle given in Deg [0-360]
69 // but stored and applied in radiants (standard for TParticle & AliCollisionGeometry)
71 // emanuele ---------------------------------------------------------------(
73 if(reactionPlane == 0) { Info("AliGenAfterBurnerFlow", "Using a random R.P. Angle event by event ( ! not the same used by Hijing ! ) ") ; }
74 else if(reactionPlane < 0) { Info("AliGenAfterBurnerFlow", "Using the Hijing R.P. Angle event by event ") ; }
75 else if(reactionPlane > 0) { Info("AliGenAfterBurnerFlow", "Using a fixed R.P. Angle ( psi = %d deg.) for every event ", reactionPlane) ; }
77 // it was // if(reactionPlane < 0 || reactionPlane > 360) Error("AliGenAfterBurnerFlow", "Reaction Plane Angle - %d - out of bounds [0-360]", reactionPlane); //
79 // emanuele ---------------------------------------------------------------(
81 fReactionPlane = 2 * TMath::Pi() * (reactionPlane/360) ; // r.p. given in degrees (Radomski's way) but stored and applied in radiants (TParticle's way)
85 ////////////////////////////////////////////////////////////////////////////////////////////////////
87 AliGenAfterBurnerFlow::~AliGenAfterBurnerFlow() {
88 // Standard Destructor
92 ////////////////////////////////////////////////////////////////////////////////////////////////////
94 void AliGenAfterBurnerFlow::SetDirectedSimple(Int_t pdg, Float_t v1) {
97 // The same directed flow is applied to all specified particles
98 // independently on transverse momentum or rapidity
100 // PDG - particle type to apply directed flow
101 // if (PDG == 0) use as default
104 SetFlowParameters(pdg, 1, 0, v1, 0, 0, 0);
107 ////////////////////////////////////////////////////////////////////////////////////////////////////
109 void AliGenAfterBurnerFlow::SetDirectedParam
110 (Int_t pdg, Float_t v11, Float_t v12, Float_t v13, Float_t v14) {
113 // Directed flow is parameterised as follows
115 // V1(Pt,Y) = (V11 + V12*Pt) * sign(Y) * (V13 + V14 * Y^3)
117 // where sign = 1 for Y > 0 and -1 for Y < 0
123 // PDG - particle type to apply directed flow
124 // if (PDG == 0) use as default
127 SetFlowParameters(pdg, 1, 1, v11, v12, v13, v14);
130 ////////////////////////////////////////////////////////////////////////////////////////////////////
132 void AliGenAfterBurnerFlow::SetEllipticSimple(Int_t pdg, Float_t v2) {
135 // The same Elliptic flow is applied to all specified particles
136 // independently on transverse momentum or rapidity
138 // PDG - particle type to apply directed flow
139 // if (PDG == 0) use as default
141 // V2 - flow coefficient
143 // NOTE: for starting playing with FLOW
144 // start with this function and values 0.05 - 0.1
147 SetFlowParameters(pdg, 2, 0, v2, 0, 0, 0);
150 ////////////////////////////////////////////////////////////////////////////////////////////////////
152 void AliGenAfterBurnerFlow::SetEllipticParamPion
153 (Int_t pdg, Float_t v21, Float_t pTmax, Float_t v22) {
157 // Elliptic flow is parametrised to reproduce
158 // V2 of Pions at RHIC energies and is given by:
160 // V2 = v21 * (pT/pTMax ) * exp (-v22 * y^2) where pT <= pTmax
161 // v21 * exp (-v22 * y^2) where pT > pTmax
163 // v21 - value at saturation
164 // pTmax - saturation transverse momentum
165 // v22 - rapidity decrising
168 SetFlowParameters(pdg, 2, 1, v21, pTmax, v22, 0);
171 ////////////////////////////////////////////////////////////////////////////////////////////////////
173 void AliGenAfterBurnerFlow::SetEllipticParamOld
174 (Int_t pdg, Float_t v21, Float_t v22, Float_t v23) {
178 // Elliptic flow is parameterised using
179 // old MevSim parameterisation
181 // V2 = (V21 + V22 pT^2) * exp (-v22 * y^2)
184 SetFlowParameters(pdg, 2, 2, v21, v22, v23, 0);
187 ////////////////////////////////////////////////////////////////////////////////////////////////////
189 void AliGenAfterBurnerFlow::SetFlowParameters
190 (Int_t pdg, Int_t order, Int_t type, Float_t v1, Float_t v2,Float_t v3,Float_t v4) {
196 Bool_t newEntry = kTRUE;
201 index = fgkN - order;
205 // try to find existing entry
206 for (Int_t i=0; i<fCounter; i++) {
207 if (pdg == (Int_t)fParams[i][0] &&
208 order == (Int_t)fParams[i][1]) {
217 if (newEntry && (fCounter > fgkN-3)) {
218 Error("AliAfterBurnerFlow","Overflow");
227 // Set new particle type
229 fParams[index][0] = pdg;
230 fParams[index][1] = order;
231 fParams[index][2] = type;
232 fParams[index][3] = v1;
233 fParams[index][4] = v2;
234 fParams[index][5] = v3;
235 fParams[index][6] = v4;
238 ////////////////////////////////////////////////////////////////////////////////////////////////////
240 void AliGenAfterBurnerFlow::Init() {
242 // Standard AliGenerator Initializer
247 ////////////////////////////////////////////////////////////////////////////////////////////////////
249 Float_t AliGenAfterBurnerFlow::GetCoefficient
250 (Int_t pdg, Int_t n, Float_t Pt, Float_t Y) {
253 // Return Flow Coefficient for a given particle type flow order
254 // and particle momentum (Pt, Y)
257 Int_t index = fgkN - n; // default index
260 // try to find specific parametrs
262 for (Int_t i=0; i<fCounter; i++) {
264 if ((Int_t)fParams[i][0] == pdg &&
265 (Int_t)fParams[i][1] == n) {
274 Int_t type = (Int_t)fParams[index][2];
276 if ((Int_t)fParams[index][1] == 1) { // Directed
279 v = fParams[index][3];
281 v = (fParams[index][3] + fParams[index][4] * Pt) * TMath::Sign((Float_t)1.,Y) *
282 (fParams[index][5] + fParams[index][6] * TMath::Abs(Y*Y*Y) );
286 if (type == 0) v = fParams[index][3];
288 // Pion parameterisation
291 if (Pt < fParams[index][4])
292 v = fParams[index][3] * (Pt / fParams[index][4]) ;
294 v = fParams[index][3];
296 v *= TMath::Exp( - fParams[index][5] * Y * Y);
299 // Old parameterisation
302 v = (fParams[index][3] + fParams[index][4] * Pt * Pt) *
303 TMath::Exp( - fParams[index][5] * Y * Y);
309 ////////////////////////////////////////////////////////////////////////////////////////////////////
311 void AliGenAfterBurnerFlow::Generate() {
313 // AliGenerator generate function doing actual job.
316 // 1. loop over particles on the stack
317 // 2. find direct and elliptical flow coefficients for
318 // a particle type ore use defaults
319 // 3. calculate delta phi
320 // 4. change phi in orginal particle
322 // Algorythm based on:
323 // A.M. Poskanzer, S.A. Voloshin
324 // "Methods of analysisng anisotropic flow in relativistic nuclear collisions"
325 // PRC 58, 1671 (September 1998)
328 AliGenCocktailAfterBurner *gen;
331 TLorentzVector momentum;
337 // Get Stack of the first Generator
338 gen = (AliGenCocktailAfterBurner *)gAlice->Generator();
340 // emanuele ---------------------------------------------------------------(
342 AliGenerator* genHijing = 0 ;
343 AliCollisionGeometry* geom = 0 ;
344 AliGenCocktailEntry* entry = 0 ;
345 TList* fEntries = 0 ;
347 TRandom* rand = new TRandom(0) ;
348 Float_t fHow = fReactionPlane ; // this is a temp. solution not to add a new data member in the .h
350 for(Int_t ns=0;ns<gen->GetNumberOfEvents();ns++)
352 gen->SetActiveEventNumber(ns) ;
353 stack = gen->GetStack(ns); // it was 0.
354 fEntries = gen->Entries() ;
356 TIter next(fEntries) ;
357 while((entry = (AliGenCocktailEntry*)next()))
359 if(fHow == 0) // hijing R.P.
361 Info("Generate (e)","Using R.P. from HIJING ... ");
362 genHijing = entry->Generator() ; // cout <<" * GENERATOR IS "<< genHijing << " : " << genHijing->GetName() << endl;
363 if(genHijing->ProvidesCollisionGeometry())
365 geom = gen->GetCollisionGeometry(ns) ; // cout << " * GEOMETRY YES * " << endl ;
366 fReactionPlane = geom->ReactionPlaneAngle() ;
370 Error("Generate (e)", "NO CollisionGeometry !!! - using fixed R.P. angle = 0. ") ;
371 fReactionPlane = 0. ;
374 else if(fHow < 0) // random R.P.
376 Info("Generate (e)","Using random R.P.s ... ");
377 fReactionPlane = 2 * TMath::Pi() * rand->Rndm() ;
379 else // if constant R.P. -> do nothing (fReactionPlane already setted)
381 Info("Generate (e)","Using a fixed R.P. psi = %d rad.",fReactionPlane);
383 cout << " * Reaction Plane Angle (event " << ns << ") = " << fReactionPlane << " rad. ( = " << (360*fReactionPlane/(2*TMath::Pi())) << " deg.) * " << endl ;
386 // emanuele ---------------------------------------------------------------)
388 // Loop over particles
390 for (Int_t i=0; i<stack->GetNtrack(); i++)
392 particle = stack->Particle(i);
394 particle->Momentum(momentum);
395 pdg = particle->GetPdgCode();
396 phi = particle->Phi();
401 //y = momentum.Rapidity() ;
403 // emanuele ---------------------------------------------------------------(
405 if(TMath::Abs(momentum.Z()) != TMath::Abs(momentum.T())) { y = momentum.Rapidity() ; }
407 // cout << " * Lorentz Vector (momentum) = " << momentum.X() << " , " << momentum.Y() << " , " << momentum.Z() << " , " << momentum.T() << " . * " << endl ;
408 // cout << " * pt = " << momentum.Pt() << " . * " << endl ;
409 // cout << " * Y = " << y << " . * " << endl ;
411 // emanuele ---------------------------------------------------------------)
413 // Calculate Delta Phi for Directed and Elliptic Flow
415 dPhi = -2 * GetCoefficient(pdg, 1, pt, y) * TMath::Sin( phi - fReactionPlane );
416 dPhi -= GetCoefficient(pdg, 2, pt, y) * TMath::Sin( 2 * (phi - fReactionPlane));
421 momentum.SetPhi(phi);
422 particle->SetMomentum(momentum);
425 // emanuele ---------------------------------------------------------------(
427 // emanuele ---------------------------------------------------------------)
429 Info("Generate","Flow After Burner: DONE");
432 ////////////////////////////////////////////////////////////////////////////////////////////////////