]> git.uio.no Git - u/mrichter/AliRoot.git/blame - EVGEN/AliGenGeVSim.cxx
Updating info for SDigitalizer after Artur modifications
[u/mrichter/AliRoot.git] / EVGEN / AliGenGeVSim.cxx
CommitLineData
0af12c00 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$ */
4966b266 17//
7e4131fc 18// AliGenGeVSim is a class implementing GeVSim event generator.
19//
20// GeVSim is a simple Monte-Carlo event generator for testing detector and
21// algorythm performance especialy concerning flow and event-by-event studies
4966b266 22//
23// In this event generator particles are generated from thermal distributions
24// without any dynamics and addicional constrains. Distribution parameters like
25// multiplicity, particle type yields, inverse slope parameters, flow coeficients
26// and expansion velocities are expleicite defined by the user.
27//
28// GeVSim contains four thermal distributions the same as
29// MevSim event generator developed for STAR experiment.
30//
7e4131fc 31// In addition custom distributions can be used be the mean
32// either two dimensional formula (TF2), a two dimensional histogram or
33// two one dimensional histograms.
4966b266 34//
35// Azimuthal distribution is deconvoluted from (Pt,Y) distribution
36// and is described by two Fourier coefficients representing
7e4131fc 37// Directed and Elliptic flow.
4966b266 38//
7e4131fc 39////////////////////////////////////////////////////////////////////////////////
40//
4966b266 41// To apply flow to event ganerated by an arbitraly event generator
42// refer to AliGenAfterBurnerFlow class.
43//
7e4131fc 44////////////////////////////////////////////////////////////////////////////////
45//
4966b266 46// For examples, parameters and testing macros refer to:
47// http:/home.cern.ch/radomski
7e4131fc 48//
49// for more detailed description refer to ALICE NOTE
50// "GeVSim Monte-Carlo Event Generator"
51// S.Radosmki, P. Foka.
4966b266 52//
53// Author:
54// Sylwester Radomski,
55// GSI, March 2002
56//
57// S.Radomski@gsi.de
58//
59////////////////////////////////////////////////////////////////////////////////
7e4131fc 60//
61// Updated and revised: September 2002, S. Radomski, GSI
62//
63////////////////////////////////////////////////////////////////////////////////
64
7816887f 65
116cbefd 66#include <Riostream.h>
67#include <TCanvas.h>
68#include <TF1.h>
69#include <TF2.h>
70#include <TH1.h>
71#include <TH2.h>
72#include <TObjArray.h>
73#include <TPDGCode.h>
74#include <TParticle.h>
75#include <TROOT.h>
7816887f 76
4966b266 77
4966b266 78#include "AliGeVSimParticle.h"
116cbefd 79#include "AliGenGeVSim.h"
daa61231 80#include "AliGenGeVSimEventHeader.h"
116cbefd 81#include "AliGenerator.h"
82#include "AliRun.h"
4966b266 83
7816887f 84
85ClassImp(AliGenGeVSim);
86
87//////////////////////////////////////////////////////////////////////////////////
88
89AliGenGeVSim::AliGenGeVSim() : AliGenerator(-1) {
4966b266 90 //
91 // Default constructor
92 //
7816887f 93
7816887f 94 fPsi = 0;
7e4131fc 95 fIsMultTotal = kTRUE;
7816887f 96
97 //PH InitFormula();
7e4131fc 98 for (Int_t i=0; i<4; i++)
7816887f 99 fPtYFormula[i] = 0;
0a78fc4d 100 fPartTypes = 0;
7816887f 101}
102
103//////////////////////////////////////////////////////////////////////////////////
104
7e4131fc 105AliGenGeVSim::AliGenGeVSim(Float_t psi, Bool_t isMultTotal) : AliGenerator(-1) {
4966b266 106 //
107 // Standard Constructor.
108 //
7e4131fc 109 // models - thermal model to be used:
4966b266 110 // 1 - deconvoluted pt and Y source
111 // 2,3 - thermalized sphericaly symetric sources
112 // 4 - thermalized source with expansion
113 // 5 - custom model defined in TF2 object named "gevsimPtY"
7e4131fc 114 // 6 - custom model defined by two 1D histograms
115 // 7 - custom model defined by 2D histogram
4966b266 116 //
7e4131fc 117 // psi - reaction plane in degrees
118 // isMultTotal - multiplicity mode
119 // kTRUE - total multiplicity (default)
120 // kFALSE - dN/dY at midrapidity
121 //
7816887f 122
123 // checking consistancy
7e4131fc 124
4966b266 125 if (psi < 0 || psi > 360 )
126 Error ("AliGenGeVSim", "Reaction plane angle ( %d )out of range [0..360]", psi);
7816887f 127
daa61231 128 fPsi = psi * TMath::Pi() / 180. ;
7e4131fc 129 fIsMultTotal = isMultTotal;
7816887f 130
131 // initialization
132
133 fPartTypes = new TObjArray();
134 InitFormula();
7816887f 135}
136
137//////////////////////////////////////////////////////////////////////////////////
138
139AliGenGeVSim::~AliGenGeVSim() {
4966b266 140 //
141 // Default Destructor
142 //
143 // Removes TObjArray keeping list of registered particle types
144 //
7816887f 145
146 if (fPartTypes != NULL) delete fPartTypes;
147}
148
149
150//////////////////////////////////////////////////////////////////////////////////
151
0af12c00 152Bool_t AliGenGeVSim::CheckPtYPhi(Float_t pt, Float_t y, Float_t phi) const {
4966b266 153 //
154 // private function used by Generate()
155 //
156 // Check bounds of Pt, Rapidity and Azimuthal Angle of a track
7e4131fc 157 // Used only when generating particles from a histogram
4966b266 158 //
7816887f 159
160 if ( TestBit(kPtRange) && ( pt < fPtMin || pt > fPtMax )) return kFALSE;
161 if ( TestBit(kPhiRange) && ( phi < fPhiMin || phi > fPhiMax )) return kFALSE;
162 if ( TestBit(kYRange) && ( y < fYMin || y > fYMax )) return kFALSE;
163
7816887f 164 return kTRUE;
165}
166
167//////////////////////////////////////////////////////////////////////////////////
168
7e4131fc 169Bool_t AliGenGeVSim::CheckAcceptance(Float_t p[3]) {
4966b266 170 //
171 // private function used by Generate()
172 //
7e4131fc 173 // Check bounds of a total momentum and theta of a track
4966b266 174 //
7816887f 175
7e4131fc 176 if ( TestBit(kThetaRange) ) {
177
178 Double_t theta = TMath::ATan2( TMath::Sqrt(p[0]*p[0]+p[1]*p[1]), p[2]);
179 if ( theta < fThetaMin || theta > fThetaMax ) return kFALSE;
180 }
181
7816887f 182
7e4131fc 183 if ( TestBit(kMomentumRange) ) {
184
185 Double_t momentum = TMath::Sqrt(p[0]*p[0] + p[1]*p[1] + p[2]*p[2]);
186 if ( momentum < fPMin || momentum > fPMax) return kFALSE;
187 }
7816887f 188
189 return kTRUE;
190}
191
192//////////////////////////////////////////////////////////////////////////////////
193
194void AliGenGeVSim::InitFormula() {
4966b266 195 //
196 // private function
197 //
198 // Initalizes formulas used in GeVSim.
199 // Manages strings and creates TFormula objects from strings
200 //
7816887f 201
202 // Deconvoluted Pt Y formula
203
204 // ptForm: pt -> x , mass -> [0] , temperature -> [1]
205 // y Form: y -> x , sigmaY -> [0]
206
49039a84 207 const char* kPtForm = " x * exp( -sqrt([0]*[0] + x*x) / [1] )";
208 const char* kYForm = " exp ( - x*x / (2 * [0]*[0] ) )";
7816887f 209
49039a84 210 fPtFormula = new TF1("gevsimPt", kPtForm, 0, 3);
211 fYFormula = new TF1("gevsimRapidity", kYForm, -3, 3);
7816887f 212
7e4131fc 213 fPtFormula->SetParNames("mass", "temperature");
7816887f 214 fPtFormula->SetParameters(1., 1.);
215
7e4131fc 216 fYFormula->SetParName(0, "sigmaY");
7816887f 217 fYFormula->SetParameter(0, 1.);
218
219 // Grid for Pt and Y
220 fPtFormula->SetNpx(100);
221 fYFormula->SetNpx(100);
222
223
224 // Models 1-3
225
226 // pt -> x , Y -> y
227 // mass -> [0] , temperature -> [1] , expansion velocity -> [2]
228
229
49039a84 230 const char *kFormE = " ( sqrt([0]*[0] + x*x) * cosh(y) ) ";
231 const char *kFormG = " ( 1 / sqrt( 1 - [2]*[2] ) ) ";
232 const char *kFormYp = "( [2]*sqrt(([0]*[0]+x*x)*cosh(y)*cosh(y)-[0]*[0])/([1]*sqrt(1-[2]*[2]))) ";
7816887f 233
49039a84 234 const char* kFormula[3] = {
7816887f 235 " x * %s * exp( -%s / [1]) ",
236 " (x * %s) / ( exp( %s / [1]) - 1 ) ",
4966b266 237 " x*%s*exp(-%s*%s/[1])*((sinh(%s)/%s)+([1]/(%s*%s))*(sinh(%s)/%s-cosh(%s)))"
7816887f 238 };
239
49039a84 240 const char* kParamNames[3] = {"mass", "temperature", "expVel"};
7816887f 241
242 char buffer[1024];
243
49039a84 244 sprintf(buffer, kFormula[0], kFormE, kFormE);
7e4131fc 245 fPtYFormula[0] = new TF2("gevsimPtY_2", buffer, 0, 3, -2, 2);
7816887f 246
49039a84 247 sprintf(buffer, kFormula[1], kFormE, kFormE);
7e4131fc 248 fPtYFormula[1] = new TF2("gevsimPtY_3", buffer, 0, 3, -2, 2);
7816887f 249
49039a84 250 sprintf(buffer, kFormula[2], kFormE, kFormG, kFormE, kFormYp, kFormYp, kFormG, kFormE, kFormYp, kFormYp, kFormYp);
7e4131fc 251 fPtYFormula[2] = new TF2("gevsimPtY_4", buffer, 0, 3, -2, 2);
7816887f 252
253 fPtYFormula[3] = 0;
254
255
256 // setting names & initialisation
257
258 Int_t i, j;
259 for (i=0; i<3; i++) {
260
7e4131fc 261 fPtYFormula[i]->SetNpx(100); // step 30 MeV
262 fPtYFormula[i]->SetNpy(100); //
7816887f 263
264 for (j=0; j<3; j++) {
265
266 if ( i != 2 && j == 2 ) continue; // ExpVel
49039a84 267 fPtYFormula[i]->SetParName(j, kParamNames[j]);
7816887f 268 fPtYFormula[i]->SetParameter(j, 0.5);
269 }
270 }
271
272 // Phi Flow Formula
273
274 // phi -> x
275 // Psi -> [0] , Direct Flow -> [1] , Ellipticla Flow -> [2]
276
49039a84 277 const char* kPhiForm = " 1 + 2*[1]*cos(x-[0]) + 2*[2]*cos(2*(x-[0])) ";
278 fPhiFormula = new TF1("gevsimPhi", kPhiForm, 0, 2*TMath::Pi());
7816887f 279
7e4131fc 280 fPhiFormula->SetParNames("psi", "directed", "elliptic");
281 fPhiFormula->SetParameters(0., 0., 0.);
7816887f 282
7e4131fc 283 fPhiFormula->SetNpx(180);
7816887f 284
285}
286
287//////////////////////////////////////////////////////////////////////////////////
288
289void AliGenGeVSim::AddParticleType(AliGeVSimParticle *part) {
4966b266 290 //
291 // Adds new type of particles.
292 //
293 // Parameters are defeined in AliGeVSimParticle object
294 // This method has to be called for every particle type
295 //
7816887f 296
297 if (fPartTypes == NULL)
298 fPartTypes = new TObjArray();
299
300 fPartTypes->Add(part);
7e4131fc 301}
302
303//////////////////////////////////////////////////////////////////////////////////
7816887f 304
7e4131fc 305void AliGenGeVSim::SetMultTotal(Bool_t isTotal) {
306 //
307 //
308 //
309
310 fIsMultTotal = isTotal;
7816887f 311}
312
313//////////////////////////////////////////////////////////////////////////////////
314
315Float_t AliGenGeVSim::FindScaler(Int_t paramId, Int_t pdg) {
4966b266 316 //
317 // private function
318 // Finds Scallar for a given parameter.
319 // Function used in event-by-event mode.
320 //
321 // There are two types of scallars: deterministic and random
322 // and they can work on either global or particle type level.
323 // For every variable there are four scallars defined.
324 //
325 // Scallars are named as folowa
326 // deterministic global level : "gevsimParam" (eg. "gevsimTemp")
327 // deterinistig type level : "gevsimPdgParam" (eg. "gevsim211Mult")
328 // random global level : "gevsimParamRndm" (eg. "gevsimMultRndm")
329 // random type level : "gevsimPdgParamRndm" (eg. "gevsim-211V2Rndm");
330 //
331 // Pdg - code of a particle type in PDG standard (see: http://pdg.lbl.gov)
332 // Param - parameter name. Allowed parameters:
333 //
334 // "Temp" - inverse slope parameter
335 // "SigmaY" - rapidity width - for model (1) only
336 // "ExpVel" - expansion velocity - for model (4) only
337 // "V1" - directed flow
338 // "V2" - elliptic flow
339 // "Mult" - multiplicity
340 //
341
342
7816887f 343 static const char* params[] = {"Temp", "SigmaY", "ExpVel", "V1", "V2", "Mult"};
344 static const char* ending[] = {"", "Rndm"};
345
346 static const char* patt1 = "gevsim%s%s";
347 static const char* patt2 = "gevsim%d%s%s";
348
349 char buffer[80];
350 TF1 *form;
351
352 Float_t scaler = 1.;
353
354 // Scaler evoluation: i - global/local, j - determ/random
355
356 Int_t i, j;
357
358 for (i=0; i<2; i++) {
359 for (j=0; j<2; j++) {
360
361 form = 0;
362
363 if (i == 0) sprintf(buffer, patt1, params[paramId], ending[j]);
364 else sprintf(buffer, patt2, pdg, params[paramId], ending[j]);
365
366 form = (TF1 *)gROOT->GetFunction(buffer);
367
368 if (form != 0) {
369 if (j == 0) scaler *= form->Eval(gAlice->GetEvNumber());
370 if (j == 1) {
371 form->SetParameter(0, gAlice->GetEvNumber());
372 scaler *= form->GetRandom();
373 }
374 }
375 }
376 }
377
378 return scaler;
379}
380
381//////////////////////////////////////////////////////////////////////////////////
382
4966b266 383void AliGenGeVSim::DetermineReactionPlane() {
384 //
385 // private function used by Generate()
386 //
387 // Retermines Reaction Plane angle and set this value
388 // as a parameter [0] in fPhiFormula
389 //
390 // Note: if "gevsimPsiRndm" function is found it override both
391 // "gevsimPhi" function and initial fPsi value
392 //
393
394 TF1 *form;
395
396 form = 0;
397 form = (TF1 *)gROOT->GetFunction("gevsimPsi");
daa61231 398 if (form) fPsi = form->Eval(gAlice->GetEvNumber()) * TMath::Pi() / 180;
4966b266 399
7e4131fc 400 form = 0;
4966b266 401 form = (TF1 *)gROOT->GetFunction("gevsimPsiRndm");
daa61231 402 if (form) fPsi = form->GetRandom() * TMath::Pi() / 180;
403
404
405 cout << "Psi = " << fPsi << "\t" << (Int_t)(fPsi*180./TMath::Pi()) << endl;
4966b266 406
407 fPhiFormula->SetParameter(0, fPsi);
408}
409
410//////////////////////////////////////////////////////////////////////////////////
411
7e4131fc 412Float_t AliGenGeVSim::GetdNdYToTotal() {
4966b266 413 //
7e4131fc 414 // Private, helper function used by Generate()
4966b266 415 //
7e4131fc 416 // Returns total multiplicity to dN/dY ration using current distribution.
417 // The function have to be called after setting distribution and its
418 // parameters (like temperature).
419 //
420
421 Float_t integ, mag;
49039a84 422 const Double_t kMaxPt = 3.0, kMaxY = 2.;
7e4131fc 423
424 if (fModel == 1) {
425
49039a84 426 integ = fYFormula->Integral(-kMaxY, kMaxY);
7e4131fc 427 mag = fYFormula->Eval(0);
428 return integ/mag;
429 }
430
431 // 2D formula standard or custom
432
433 if (fModel > 1 && fModel < 6) {
434
49039a84 435 integ = ((TF2*)fCurrentForm)->Integral(0,kMaxPt, -kMaxY, kMaxY);
436 mag = ((TF2*)fCurrentForm)->Integral(0, kMaxPt, -0.1, 0.1) / 0.2;
7e4131fc 437 return integ/mag;
438 }
439
440 // 2 1D histograms
441
442 if (fModel == 6) {
443
444 integ = fHist[1]->Integral();
445 mag = fHist[0]->GetBinContent(fHist[0]->FindBin(0.));
446 mag /= fHist[0]->GetBinWidth(fHist[0]->FindBin(0.));
447 return integ/mag;
448 }
449
450 // 2D histogram
4966b266 451
7e4131fc 452 if (fModel == 7) {
453
454 // Not tested ...
455 Int_t yBins = fPtYHist->GetNbinsY();
456 Int_t ptBins = fPtYHist->GetNbinsX();
457
458 integ = fPtYHist->Integral(0, ptBins, 0, yBins);
459 mag = fPtYHist->Integral(0, ptBins, (yBins/2)-1, (yBins/2)+1 ) / 2;
460 return integ/mag;
461 }
462
463 return 1;
4966b266 464}
465
466//////////////////////////////////////////////////////////////////////////////////
467
7e4131fc 468void AliGenGeVSim::SetFormula(Int_t pdg) {
4966b266 469 //
7e4131fc 470 // Private function used by Generate()
4966b266 471 //
7e4131fc 472 // Configure a formula for a given particle type and model Id (in fModel).
473 // If custom formula or histogram was selected the function tries
474 // to find it.
475 //
476 // The function implements naming conventions for custom distributions names
477 //
7816887f 478
7e4131fc 479 char buff[40];
480 const char* msg[4] = {
481 "Custom Formula for Pt Y distribution not found [pdg = %d]",
482 "Histogram for Pt distribution not found [pdg = %d]",
483 "Histogram for Y distribution not found [pdg = %d]",
484 "HIstogram for Pt Y dostribution not found [pdg = %d]"
485 };
486
487 const char* pattern[8] = {
488 "gevsimDistPtY", "gevsimDist%dPtY",
489 "gevsimHistPt", "gevsimHist%dPt",
490 "gevsimHistY", "gevsimHist%dY",
491 "gevsimHistPtY", "gevsimHist%dPtY"
492 };
493
494 const char *where = "SetFormula";
7816887f 495
7816887f 496
7e4131fc 497 if (fModel < 1 || fModel > 7)
498 Error("SetFormula", "Model Id (%d) out of range [1-7]", fModel);
499
500
501 // standard models
502
503 if (fModel == 1) fCurrentForm = fPtFormula;
504 if (fModel > 1 && fModel < 5) fCurrentForm = fPtYFormula[fModel-2];
505
506
507 // custom model defined by a formula
508
7816887f 509 if (fModel == 5) {
510
7e4131fc 511 fCurrentForm = 0;
512 fCurrentForm = (TF2*)gROOT->GetFunction(pattern[0]);
513
514 if (!fCurrentForm) {
515
516 sprintf(buff, pattern[1], pdg);
517 fCurrentForm = (TF2*)gROOT->GetFunction(buff);
518
519 if (!fCurrentForm) Error(where, msg[0], pdg);
520 }
521 }
522
523 // 2 1D histograms
524
525 if (fModel == 6) {
7816887f 526
7e4131fc 527 for (Int_t i=0; i<2; i++) {
7816887f 528
7e4131fc 529 fHist[i] = 0;
530 fHist[i] = (TH1D*)gROOT->FindObject(pattern[2+2*i]);
531
532 if (!fHist[i]) {
533
534 sprintf(buff, pattern[3+2*i], pdg);
535 fHist[i] = (TH1D*)gROOT->FindObject(buff);
536
537 if (!fHist[i]) Error(where, msg[1+i], pdg);
538 }
539 }
7816887f 540 }
7e4131fc 541
542 // 2d histogram
543
544 if (fModel == 7) {
545
546 fPtYHist = 0;
547 fPtYHist = (TH2D*)gROOT->FindObject(pattern[6]);
548
549 if (!fPtYHist) {
550
551 sprintf(buff, pattern[7], pdg);
552 fPtYHist = (TH2D*)gROOT->FindObject(buff);
553 }
554
a3d75961 555 if (!fPtYHist) Error(where, msg[3], pdg);
7e4131fc 556 }
557
558}
559
560//////////////////////////////////////////////////////////////////////////////////
561
562void AliGenGeVSim:: AdjustFormula() {
563 //
564 // Private Function
565 // Adjust fomula bounds according to acceptance cuts.
566 //
567 // Since GeVSim is producing "thermal" particles Pt
568 // is cut at 3 GeV even when acceptance extends to grater momenta.
569 //
570 // WARNING !
571 // If custom formula was provided function preserves
572 // original cuts.
573 //
574
575 const Double_t kMaxPt = 3.0;
576 const Double_t kMaxY = 2.0;
577 Double_t minPt, maxPt, minY, maxY;
578
579
580 if (fModel > 4) return;
581
582 // max Pt
583 if (TestBit(kPtRange) && fPtMax < kMaxPt ) maxPt = fPtMax;
584 else maxPt = kMaxPt;
585
586 // min Pt
587 if (TestBit(kPtRange)) minPt = fPtMin;
588 else minPt = 0;
589
590 if (TestBit(kPtRange) && fPtMin > kMaxPt )
591 Warning("Acceptance", "Minimum Pt (%3.2f GeV) greater that 3.0 GeV ", fPtMin);
592
593 // Max Pt < Max P
594 if (TestBit(kMomentumRange) && fPtMax < maxPt) maxPt = fPtMax;
595
596 // max and min rapidity
597 if (TestBit(kYRange)) {
598 minY = fYMin;
599 maxY = fYMax;
600 } else {
601 minY = -kMaxY;
602 maxY = kMaxY;
603 }
604
605 // adjust formula
606
607 if (fModel == 1) {
608 fPtFormula->SetRange(fPtMin, maxPt);
609 fYFormula->SetRange(fYMin, fYMax);
610 }
611
612 if (fModel > 1)
613 ((TF2*)fCurrentForm)->SetRange(minPt, minY, maxPt, maxY);
614
615 // azimuthal cut
616
617 if (TestBit(kPhiRange))
618 fPhiFormula->SetRange(fPhiMin, fPhiMax);
619
620}
621
622//////////////////////////////////////////////////////////////////////////////////
623
624void AliGenGeVSim::GetRandomPtY(Double_t &pt, Double_t &y) {
625 //
626 // Private function used by Generate()
627 //
628 // Returns random values of Pt and Y corresponding to selected
629 // distribution.
630 //
631
632 if (fModel == 1) {
633 pt = fPtFormula->GetRandom();
634 y = fYFormula->GetRandom();
635 return;
636 }
637
638 if (fModel > 1 && fModel < 6) {
639 ((TF2*)fCurrentForm)->GetRandom2(pt, y);
640 return;
641 }
642
643 if (fModel == 6) {
644 pt = fHist[0]->GetRandom();
645 y = fHist[1]->GetRandom();
646 }
647
648 if (fModel == 7) {
649 fPtYHist->GetRandom2(pt, y);
650 return;
651 }
652}
653
654//////////////////////////////////////////////////////////////////////////////////
655
656void AliGenGeVSim::Init() {
657 //
658 // Standard AliGenerator initializer.
659 // does nothing
660 //
7816887f 661}
662
663//////////////////////////////////////////////////////////////////////////////////
664
665void AliGenGeVSim::Generate() {
4966b266 666 //
667 // Standard AliGenerator function
668 // This function do actual job and puts particles on stack.
669 //
7816887f 670
7816887f 671 PDG_t pdg; // particle type
672 Float_t mass; // particle mass
673 Float_t orgin[3] = {0,0,0}; // particle orgin [cm]
674 Float_t polar[3] = {0,0,0}; // polarisation
7816887f 675 Float_t time = 0; // time of creation
7816887f 676
7e4131fc 677 Float_t multiplicity = 0;
678 Bool_t isMultTotal = kTRUE;
679
7816887f 680 Float_t paramScaler;
7e4131fc 681 Float_t directedScaller = 1., ellipticScaller = 1.;
682
683 TLorentzVector *v = new TLorentzVector(0,0,0,0);
7816887f 684
4966b266 685 const Int_t kParent = -1;
7816887f 686 Int_t id;
687
7816887f 688 // vertexing
7816887f 689 VertexInternal();
7816887f 690 orgin[0] = fVertex[0];
691 orgin[1] = fVertex[1];
692 orgin[2] = fVertex[2];
693
7816887f 694
695 // Particle params database
696
697 TDatabasePDG *db = TDatabasePDG::Instance();
698 TParticlePDG *type;
699 AliGeVSimParticle *partType;
700
701 Int_t nType, nParticle, nParam;
49039a84 702 const Int_t kNParams = 6;
7816887f 703
4966b266 704 // reaction plane determination and model
4966b266 705 DetermineReactionPlane();
7e4131fc 706
7816887f 707 // loop over particle types
708
709 for (nType = 0; nType < fPartTypes->GetEntries(); nType++) {
710
711 partType = (AliGeVSimParticle *)fPartTypes->At(nType);
712
713 pdg = (PDG_t)partType->GetPdgCode();
714 type = db->GetParticle(pdg);
715 mass = type->Mass();
716
7e4131fc 717 fModel = partType->GetModel();
718 SetFormula(pdg);
719 fCurrentForm->SetParameter("mass", mass);
7816887f 720
7816887f 721
722 // Evaluation of parameters - loop over parameters
723
49039a84 724 for (nParam = 0; nParam < kNParams; nParam++) {
7816887f 725
726 paramScaler = FindScaler(nParam, pdg);
727
7e4131fc 728 if (nParam == 0)
729 fCurrentForm->SetParameter("temperature", paramScaler * partType->GetTemperature());
7816887f 730
731 if (nParam == 1 && fModel == 1)
7e4131fc 732 fYFormula->SetParameter("sigmaY", paramScaler * partType->GetSigmaY());
7816887f 733
734 if (nParam == 2 && fModel == 4) {
735
7e4131fc 736 Double_t totalExpVal = paramScaler * partType->GetExpansionVelocity();
7816887f 737
738 if (totalExpVal == 0.0) totalExpVal = 0.0001;
739 if (totalExpVal == 1.0) totalExpVal = 9.9999;
740
7e4131fc 741 fCurrentForm->SetParameter("expVel", totalExpVal);
7816887f 742 }
743
744 // flow
7e4131fc 745
746 if (nParam == 3) directedScaller = paramScaler;
747 if (nParam == 4) ellipticScaller = paramScaler;
7816887f 748
749 // multiplicity
7e4131fc 750
751 if (nParam == 5) {
752
753 if (partType->IsMultForced()) isMultTotal = partType->IsMultTotal();
754 else isMultTotal = fIsMultTotal;
7816887f 755
7e4131fc 756 multiplicity = paramScaler * partType->GetMultiplicity();
757 multiplicity *= (isMultTotal)? 1 : GetdNdYToTotal();
758 }
7816887f 759 }
760
7e4131fc 761 // Flow defined on the particle type level (not parameterised)
762 if (partType->IsFlowSimple()) {
763 fPhiFormula->SetParameter(1, partType->GetDirectedFlow(0,0) * directedScaller);
764 fPhiFormula->SetParameter(2, partType->GetEllipticFlow(0,0) * ellipticScaller);
765 }
766
767 AdjustFormula();
768
769
770 Info("Generate","PDG = %d \t Mult = %d", pdg, (Int_t)multiplicity);
7816887f 771
772 // loop over particles
773
774 nParticle = 0;
7816887f 775 while (nParticle < multiplicity) {
776
7e4131fc 777 Double_t pt, y, phi; // momentum in [pt,y,phi]
778 Float_t p[3] = {0,0,0}; // particle momentum
7816887f 779
7e4131fc 780 GetRandomPtY(pt, y);
7816887f 781
7e4131fc 782 // phi distribution configuration when differential flow defined
783 // to be optimised in future release
7816887f 784
7e4131fc 785 if (!partType->IsFlowSimple()) {
786 fPhiFormula->SetParameter(1, partType->GetDirectedFlow(pt,y) * directedScaller);
787 fPhiFormula->SetParameter(2, partType->GetEllipticFlow(pt,y) * ellipticScaller);
788 }
7816887f 789
7e4131fc 790 phi = fPhiFormula->GetRandom();
7816887f 791
7e4131fc 792 if (!isMultTotal) nParticle++;
793 if (fModel > 4 && !CheckPtYPhi(pt,y,phi) ) continue;
794
7816887f 795 // coordinate transformation
7816887f 796 v->SetPtEtaPhiM(pt, y, phi, mass);
797
798 p[0] = v->Px();
799 p[1] = v->Py();
800 p[2] = v->Pz();
801
802 // momentum range test
7e4131fc 803 if ( !CheckAcceptance(p) ) continue;
7816887f 804
805 // putting particle on the stack
806
642f15cf 807 PushTrack(fTrackIt, kParent, pdg, p, orgin, polar, time, kPPrimary, id, fTrackIt);
7e4131fc 808 if (isMultTotal) nParticle++;
7816887f 809 }
810 }
7e4131fc 811
daa61231 812 // prepare and store header
813
814 AliGenGeVSimEventHeader *header = new AliGenGeVSimEventHeader("GeVSim header");
815 TArrayF eventVertex(3,orgin);
816
817 header->SetPrimaryVertex(eventVertex);
818 header->SetEventPlane(fPsi);
819 header->SetEllipticFlow(fPhiFormula->GetParameter(2));
820
821 gAlice->SetGenEventHeader(header);
822
7e4131fc 823 delete v;
7816887f 824}
825
826//////////////////////////////////////////////////////////////////////////////////