StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
TGeVSim.cxx
1 //
3 // GeVSim is a simple Monte-Carlo event generator for testing detector and
4 // algorythm performance especialy concerning flow and event-by-event studies
5 //
6 // In this event generator particles are generated from thermal distributions
7 // without dynamics and microscopic simulations. Distribution parameters like
8 // multiplicity, particle type yields, inverse slope parameters, flow
9 // coeficients and expansion velocities are expleicite defined by the user.
10 //
11 // GeVSim contains five thermal distributions. Four of them
12 // are the same as in MevSim event generator developed
13 // for STAR experiment. In GeVSim also Levy distribution is implemented
14 // for beter decription of high transverse momentum tracks.
15 //
16 // In addition custom distributions can be used be the mean
17 // either two dimensional formula (TF2), a two dimensional histogram or
18 // two one dimensional histograms.
19 //
20 // Azimuthal distribution is deconvoluted from (Pt,Y) distribution
21 // and is described by two Fourier coefficients representing
22 // Directed and Elliptic flow.
23 //
24 // Details on implemented Pt-Y distributions:
25 //
26 // User can use either standard distribution or use custom one.
27 // Distributions are indentified by enumeration type GeVSim::Model_t
28 //
29 // Standard distributions can be divided into two classes.
30 // First class containng kBoltzman and kLevy. Those distributions have
31 // Pt deconvoluted from rapidity distribution. Rapidity is aproximated
32 // bu Gaussian.
33 //
34 // Second class contains; kPratt, kBertsch and kExpansion. In those
35 // distributions Pt-Y is decribed by 2 dimensional formula.
36 // Note that generation from this class is slower.
37 //
38 // Pt-Y distribution as well as its parameters are defined for each particle
39 // type. Technically one perticle type corresponds to one object TGeVSimParticle.
40 // Refer for the documentation of this class for details.
41 //
42 // Event by Event:
43 //
44 // GeVSim have extended capabilities on Event-by-Event fluctuations.
45 // Those are defined by named formula. Refer to method FindScaler for details.
46 //
47 // MACROS:
48 // GeVSim event generator is accompanied be a set of macros.
49 //
50 // testGeVSim.C : a place to start
51 // testGeVSimCut.C : acceptance cuts
52 // testGeVSimPtEta.C : test implemented Pt and pseud-rapidity distributions
53 // testGeVSimdNdY.C : total multiplcity and multiplicity density
54 // testGeVSimEbyE.C : multiplicity fluctuations
55 // testGeVSimScan.C : multiplicity scan
56 // testGeVSimForm.C : custom momentum distribution
57 //
58 //
59 // Sylwester Radomski, mail: S.Radomski@gsi.de
60 // GSI, Dec 12, 2002
61 //
63 
64 #include "TROOT.h"
65 #include "TRandom.h"
66 #include "TCanvas.h"
67 #include "TDatabasePDG.h"
68 #include "TParticle.h"
69 #include "TObjArray.h"
70 #include "TF1.h"
71 #include "TF2.h"
72 #include "TH1.h"
73 #include "TH2.h"
74 
75 #include "TCanvas.h"
76 
77 #include "TGeVSim.h"
78 #include "TGeVSimParticle.h"
79 #include "TGeVSimEvent.h"
80 #include "TGeVSimParams.h"
81 
82 #include <iostream>
83 #include <sys/times.h>
84 
85 ClassImp(TGeVSim);
86 
88 
89 TGeVSim::TGeVSim() : TGenAcceptance()
90 {
91  //
92  // Default constructor
93  // To be used by ROOT framework only
94  // Please use other constructors.
95  //
96 
97  fPsi = 0;
98  fIsMultTotal = kTRUE;
99  fEventNumber = 0;
100 
101  //PH InitFormula();
102  for (Int_t i=0; i<4; i++)
103  fPtYFormula[i] = 0;
104 }
105 
107 
108 TGeVSim::TGeVSim(const char *name)
109  :TGenAcceptance(name, "GeVSim Event Generator")
110 {
111  //
112  // Standard Constructor
113  // Creates generator with a name
114  //
115  // Reaction plane angle is assumed = 0
116  // Multiplicity mode: TOTAL
117  //
118 
119  fPsi = 0;
120  fIsMultTotal = kTRUE;
121  fEventNumber = 0;
122 
123  // initalization
124 
125  fPartTypes = new TObjArray();
126  fPartBuffer = new TClonesArray("TParticle", 5000, kTRUE);
127  fEvent = new TGeVSimEvent(10);
128 
129  InitFormula();
130 }
131 
133 
134 TGeVSim::TGeVSim(const char *name, Float_t psi, Bool_t isMultTotal)
135  : TGenAcceptance(name,"GeVSim Event Generator")
136 {
137  //
138  // Standard Constructor.
139  // Creates generator with a name, reaction plane angle
140  // and multiplicity mode.
141  //
142  // psi - event plane in degrees [0-360]
143  //
144  // isMultTotal - multiplicity mode
145  // kTRUE - total multiplicity (default)
146  // kFALSE - multiplicity density dN/dY at midrapidity
147  //
148  // Note that event plane can be modified on the event by event basis
149  //
150 
151  // checking consistancy
152 
153  if (psi < 0 || psi > 360 )
154  Error ("TGeVSim", "Event plane angle ( %d )out of range [0..360]", psi);
155 
156  fPsi = psi * TMath::Pi() / 180. ;
157  fIsMultTotal = isMultTotal;
158 
159  fEventNumber = 0;
160 
161  fPartTypes = new TObjArray();
162  fPartBuffer = new TClonesArray("TParticle", 1000);
163  fEvent = new TGeVSimEvent(10);
164 
165  InitFormula();
166 }
167 
169 
170 TGeVSim::~TGeVSim()
171 {
172  //
173  // Default Destructor
174  //
175  // Removes TObjArray keeping list of registered particle types
176  //
177 
178  if (fPartTypes) delete fPartTypes;
179  if (fPartBuffer) delete fPartBuffer;
180 }
181 
183 
184 TGeVSim* TGeVSim::GetDefault()
185 {
186  //
187  // Static function
188  //
189  // Returns CONFIGURED gevsim event generator with
190  // standard particle multiplcities and themperatures.
191  //
192  // Currently standard configuration is
193  // 1000 Pi+ and 1000 Pi- following Levy distr. with temp = 0.18
194  // 200 K+ and 200 K- following Levy distr. with temp = 0.25
195  //
196  // sigmaTemp parameters of Levy are set to 10
197  // rapdity width = 1
198  //
199 
200  TGeVSim *g = new TGeVSim("default", 0);
201 
202  TGeVSimParticle *p;
203 
204  p = new TGeVSimParticle(211, kLevy, 1000, 0.18, 1, 10);
205  p->SetEllipticSimple(0.05);
206  g->AddParticleType(p);
207 
208  p = new TGeVSimParticle(-211, kLevy, 1000, 0.18, 1, 10);
209  p->SetEllipticSimple(0.05);
210  g->AddParticleType(p);
211 
212  g->AddParticleType(new TGeVSimParticle(321, kLevy, 200, 0.25, 1, 10));
213  g->AddParticleType(new TGeVSimParticle(-321, kLevy, 200, 0.25, 1, 10));
214 
215  g->SetEtaRange(-3, 3);
216  //g->SetPtCut(0, 3);
217 
218  return g;
219 }
220 
222 
223 void TGeVSim::Print(Option_t* option) const
224 {
225  //
226  // Prints Information about configuration of the generator
227  // and all registered particle types.
228  //
229 
230  const char *multType;
231  if (fIsMultTotal) multType = "TOTAL";
232  else multType = "DENSITY dN/dY";
233 
234  printf("\n*******************************************************\n**\n");
235  printf("** WELCOME to GeVSim\n");
236  printf("** NAME: %s TITLE: %s\n**\n", GetName(), GetTitle());
237  printf("** Multiplicity type = %s\n", multType);
238  printf("** Event Plane %3.2f [deg]\n**\n", fPsi*180/3.14);
239  printf("** Registered Particle Types:\n**\n");
240 
241  if (fPartTypes) {
242  for (Int_t i=0; i<fPartTypes->GetEntries(); i++)
243  ((TGeVSimParticle*)fPartTypes->At(i))->Print();
244  }
245 
246  printf("**\n*******************************************************\n\n");
247 
248 }
249 
251 
252 void TGeVSim::InitFormula()
253 {
254  //
255  // private function
256  //
257  // Initalizes formulas used in GeVSim.
258  // Manages strings and creates TFormula objects from strings
259  //
260 
261  // Deconvoluted Pt Y formula
262 
263  // ptForm: pt -> x , mass -> [0] , temperature -> [1]
264  // levy pt -> x , mass -> [2] , temperature -> [1] sigmaTemp -> [2]
265 
266 
267  const char* ptNames[2] = {"gevsimPt1", "gevsimPt2"};
268 
269  const char* ptForm[2] = {
270  " x * exp( -sqrt([0]*[0] + x*x) / [1] )",
271  " x * ( 1+ (sqrt([0]*[0]+x*x)*[2])/[1] )^(-1./[2]) "
272  };
273 
274  for(Int_t i=0; i<2; i++) {
275  fPtFormula[i] = new TF1(ptNames[i], ptForm[i], 0, 4);
276  fPtFormula[i]->SetNpx(100);
277  }
278 
279  fPtFormula[0]->SetParNames("mass", "temperature");
280  fPtFormula[0]->SetParameters(1., 1.);
281 
282  fPtFormula[1]->SetParNames("mass", "temperature", "sigmaTemp");
283  fPtFormula[1]->SetParameters(1., 1., 1.);
284 
285 
286  // 2D Models
287 
288  // pt -> x , Y -> y
289  // mass -> [0] , temperature -> [1] , expansion velocity -> [2]
290 
291 
292  const char *formE = " ( sqrt([0]*[0] + x*x) * cosh(y) ) ";
293  const char *formG = " ( 1 / sqrt( 1 - [2]*[2] ) ) ";
294  const char *formYp = "( [2]*sqrt(([0]*[0]+x*x)*cosh(y)*cosh(y)-[0]*[0])/([1]*sqrt(1-[2]*[2]))) ";
295 
296  const char* formula[3] = {
297  " x * %s * exp( -%s / [1]) ",
298  " (x * %s) / ( exp( %s / [1]) - 1 ) ",
299  " x*%s*exp(-%s*%s/[1])*((sinh(%s)/%s)+([1]/(%s*%s))*(sinh(%s)/%s-cosh(%s)))"
300  };
301 
302  const char* paramNames[3] = {"mass", "temperature", "expVel"};
303 
304  char buffer[1024];
305 
306  sprintf(buffer, formula[0], formE, formE);
307  fPtYFormula[0] = new TF2("gevsimPtY_2", buffer, 0, 3, -2, 2);
308 
309  sprintf(buffer, formula[1], formE, formE);
310  fPtYFormula[1] = new TF2("gevsimPtY_3", buffer, 0, 3, -2, 2);
311 
312  sprintf(buffer, formula[2], formE, formG, formE, formYp, formYp, formG, formE, formYp, formYp, formYp);
313  fPtYFormula[2] = new TF2("gevsimPtY_4", buffer, 0, 3, -2, 2);
314 
315  fPtYFormula[3] = 0;
316 
317 
318  // setting names & initialisation
319 
320  Int_t i, j;
321  for (i=0; i<3; i++) {
322 
323  fPtYFormula[i]->SetNpx(100); // step 30 MeV
324  fPtYFormula[i]->SetNpy(100); //
325 
326  for (j=0; j<3; j++) {
327 
328  if ( i != 2 && j == 2 ) continue; // ExpVel
329  fPtYFormula[i]->SetParName(j, paramNames[j]);
330  fPtYFormula[i]->SetParameter(j, 0.5);
331  }
332  }
333 
334  // Phi Flow Formula
335 
336  // phi -> x
337  // Psi -> [0] , Direct Flow -> [1] , Ellipticla Flow -> [2]
338 
339  const char* phiForm = " 1 + 2*[1]*cos(x-[0]) + 2*[2]*cos(2*(x-[0])) ";
340  fPhiFormula = new TF1("gevsimPhi", phiForm, 0, 2*TMath::Pi());
341 
342  fPhiFormula->SetParNames("psi", "directed", "elliptic");
343  fPhiFormula->SetParameters(0., 0., 0.);
344 
345  fPhiFormula->SetNpx(180);
346 
347 }
348 
350 
351 void TGeVSim::AddParticleType(TGeVSimParticle *part)
352 {
353  //
354  // Adds new type of particles.
355  //
356  // Parameters are defeined in TGeVSimParticle object
357  // This method has to be called for every particle type
358  //
359 
360  if (!fPartTypes) fPartTypes = new TObjArray();
361  fPartTypes->Add(part);
362 }
363 
365 
366 void TGeVSim::SetMultTotal(Bool_t isTotal)
367 {
368  //
369  // Set multiplicity mode
370  // isTotal = kTRUE: Total multiplicity
371  // kFALSE: Multiplicity density dN/dy
372  //
373  // Particle type can modify this value
374  //
375 
376  fIsMultTotal = isTotal;
377 }
378 
380 
381 Float_t TGeVSim::FindScaler(Int_t paramId, Int_t pdg)
382 {
383  //
384  // private function
385  // Finds Scallar for a given parameter.
386  // Function used in event-by-event mode.
387  //
388  // There are two types of scallars: deterministic and random
389  // and they can work on either global or particle type level.
390  // For every variable there are four scallars defined.
391  //
392  // Scallars are named as folowa
393  // deterministic global level : "gevsimParam" (eg. "gevsimTemp")
394  // deterinistig type level : "gevsimPdgParam" (eg. "gevsim211Mult")
395  // random global level : "gevsimParamRndm" (eg. "gevsimMultRndm")
396  // random type level : "gevsimPdgParamRndm" (eg. "gevsim-211V2Rndm");
397  //
398  // Pdg - code of a particle type in PDG standard (see: http://pdg.lbl.gov)
399  // Param - parameter name. Allowed parameters:
400  //
401  // "Temp" - inverse slope parameter
402  // "SigmaY" - rapidity width - for model (1) only
403  // "ExpVel" - expansion velocity - for model (4) only
404  // "SigmaTemp" - parameter of the Levy distribution
405  // "V1" - directed flow
406  // "V2" - elliptic flow
407  // "Mult" - multiplicity
408  //
409 
410  static const char* params[] = {"Temp", "SigmaY", "ExpVel", "SigmaTemp", "V1", "V2", "Mult"};
411  static const char* ending[] = {"", "Rndm"};
412 
413  static const char* patt1 = "gevsim%s%s";
414  static const char* patt2 = "gevsim%d%s%s";
415 
416  char buffer[80];
417  TF1 *form;
418 
419  Float_t scaler = 1.;
420 
421  // Scaler evoluation: i - global/local, j - determ/random
422 
423  Int_t i, j;
424 
425  for (i=0; i<2; i++) {
426  for (j=0; j<2; j++) {
427 
428  form = 0;
429 
430  if (i == 0) sprintf(buffer, patt1, params[paramId], ending[j]);
431  else sprintf(buffer, patt2, pdg, params[paramId], ending[j]);
432 
433  form = (TF1 *)gROOT->GetFunction(buffer);
434 
435  if (form != 0) {
436  if (j == 0) scaler *= form->Eval(fEventNumber);
437  if (j == 1) {
438  form->SetParameter(0, fEventNumber);
439  scaler *= form->GetRandom();
440  }
441  }
442  }
443  }
444 
445  return scaler;
446 }
447 
449 
450 void TGeVSim::DetermineReactionPlane()
451 {
452  //
453  // private function used by Generate()
454  //
455  // Retermines Reaction Plane angle and set this value
456  // as a parameter [0] in fPhiFormula
457  //
458  // Event Plane can be set on the event-by-event basis using
459  // TF1 object named "gevsimPsi" or "gevsimPsiRndm"
460  //
461  // Note: if "gevsimPsiRndm" function is found it overrides both
462  // "gevsimPhi" function and initial fPsi value
463  //
464  //
465 
466  TF1 *form;
467 
468  form = 0;
469  form = (TF1 *)gROOT->GetFunction("gevsimPsi");
470  if (form) fPsi = form->Eval(fEventNumber) * TMath::Pi() / 180;
471 
472  form = 0;
473  form = (TF1 *)gROOT->GetFunction("gevsimPsiRndm");
474  if (form) fPsi = form->GetRandom() * TMath::Pi() / 180;
475 
476  //cout << "Psi = " << fPsi << "\t" << (Int_t)(fPsi*180./TMath::Pi()) << endl;
477 
478  fPhiFormula->SetParameter(0, fPsi);
479 }
480 
482 
483 Float_t TGeVSim::GetdNdYToTotal()
484 {
485  //
486  // Private, helper function used by Generate()
487  // Returns total multiplicity to dN/dY ration using current model.
488  //
489  // Not testes carefully
490  //
491 
492  Float_t integ, mag;
493  const Double_t maxPt = 3.0, maxY = 2.;
494 
495  switch (fModel) {
496 
497  case kBoltzman:
498  case kLevy:
499 
500  return TMath::Sqrt(2*TMath::Pi()) * fSigmaY;
501 
502  case kPratt:
503  case kBertsch:
504  case kExpansion:
505  case kFormula2D:
506 
507  integ = fCurrentForm2D->Integral(0,maxPt, -maxY, maxY);
508  mag = fCurrentForm2D->Integral(0, maxPt, -0.1, 0.1) / 0.2;
509  return integ/mag;
510 
511  case kHist1D:
512 
513  integ = fHist[1]->Integral();
514  mag = fHist[1]->GetBinContent(fHist[0]->FindBin(0.));
515  mag /= fHist[1]->GetBinWidth(fHist[0]->FindBin(0.));
516  return integ/mag;
517 
518  case kHist2D:
519 
520  Int_t yBins = fPtYHist->GetNbinsY();
521  Int_t ptBins = fPtYHist->GetNbinsX();
522 
523  integ = fPtYHist->Integral(0, ptBins, 0, yBins);
524  mag = fPtYHist->Integral(0, ptBins, (yBins/2)-1, (yBins/2)+1 ) / 2;
525  return integ/mag;
526  }
527 
528  return 1;
529 }
530 
532 
533 void TGeVSim::SetFormula(Int_t pdg)
534 {
535  //
536  // Private function used by Generate()
537  //
538  // Configure a formula for a given particle type and model Id (in fModel).
539  // If custom formula or histogram was selected the function tries
540  // to find it.
541  //
542  // The function implements naming conventions for custom distributions names
543  //
544 
545  char buff[40];
546  const char* msg[4] = {
547  "Custom Formula for Pt Y distribution not found [pdg = %d]",
548  "Histogram for Pt distribution not found [pdg = %d]",
549  "Histogram for Y distribution not found [pdg = %d]",
550  "HIstogram for Pt Y dostribution not found [pdg = %d]"
551  };
552 
553  const char* pattern[8] = {
554  "gevsimDistPtY", "gevsimDist%dPtY",
555  "gevsimHistPt", "gevsimHist%dPt",
556  "gevsimHistY", "gevsimHist%dY",
557  "gevsimHistPtY", "gevsimHist%dPtY"
558  };
559 
560  const char *where = "SetFormula";
561 
562  fCurrentForm1D = fCurrentForm2D = 0;
563 
564 
565  switch (fModel) {
566 
567  case kBoltzman:
568  case kLevy:
569 
570  fCurrentForm1D = fPtFormula[fModel-1];
571  return;
572 
573  case kPratt:
574  case kBertsch:
575  case kExpansion:
576 
577  fCurrentForm2D = fPtYFormula[fModel-3];
578  return;
579 
580  case kFormula2D:
581 
582  sprintf(buff, pattern[1], pdg);
583  fCurrentForm2D = (TF2*)gROOT->GetFunction(buff);
584 
585  if (!fCurrentForm2D)
586  fCurrentForm2D = (TF2*)gROOT->GetFunction(pattern[0]);
587 
588  if (!fCurrentForm2D) Error(where, msg[0], pdg);
589  return;
590 
591  case kHist1D:
592 
593  for (Int_t i=0; i<2; i++) {
594 
595  fHist[i] = 0;
596  sprintf(buff, pattern[3+2*i], pdg);
597  fHist[i] = (TH1D*)gROOT->FindObject(buff);
598 
599  if (!fHist[i])
600  fHist[i] = (TH1D*)gROOT->FindObject(pattern[2+2*i]);
601 
602  if (!fHist[i]) Error(where, msg[1+i], pdg);
603  }
604  return;
605 
606  case kHist2D:
607 
608  fPtYHist = 0;
609  sprintf(buff, pattern[7], pdg);
610  fPtYHist = (TH2D*)gROOT->FindObject(buff);
611 
612  if (!fPtYHist)
613  fPtYHist = (TH2D*)gROOT->FindObject(pattern[6]);
614 
615  if (!fPtYHist) Error(where, msg[4], pdg);
616  return;
617  }
618 }
619 
621 
622 void TGeVSim:: AdjustFormula()
623 {
624  //
625  // Private Function
626  // Adjust fomula bounds according to acceptance cuts.
627  //
628  // To improve performance function scan the formulas
629  // and cuts to "resonable" limits.
630  //
631  // WARNING !
632  // If custom formula was provided original cuts are preserved
633  //
634 
635  const Double_t kCutMaxPt = 5.0;
636  const Double_t kCutMaxY = 6.0;
637  Double_t minPt, maxPt, minY, maxY;
638 
639 
640  const Int_t NPART = 20;
641  const Float_t dX = 1./NPART;
642  const Int_t NBINS = 30;
643 
644  if (fModel > kExpansion) return;
645 
646  // max Pt
647  if (TestBit(kPtRange) && fPtCutMax < kCutMaxPt ) maxPt = fPtCutMax;
648  else maxPt = kCutMaxPt;
649 
650  // min Pt
651  if (TestBit(kPtRange)) minPt = fPtCutMin;
652  else minPt = 0;
653 
654  // CutMax Pt < CutMax P
655  if (TestBit(kPRange) && maxPt > fPCutMax) maxPt = fPCutMax;
656 
657  // max and min rapidity
658  if (TestBit(kYRange)) {
659  minY = fYCutMin;
660  maxY = fYCutMax;
661  } else {
662  minY = -kCutMaxY;
663  maxY = kCutMaxY;
664  }
665 
666  // adjust formula
667  // factored models
668 
669  if (fModel < kPratt) {
670 
671  Float_t maxValue = 0, value;
672 
673  fCurrentForm1D->SetRange(minPt, maxPt);
674 
675  // find aprox max value
676  maxValue = 0;
677  for(Int_t part=NPART; part>1; part--) {
678  Float_t x = dX * (maxPt-minPt) * part + minPt;
679  value = fCurrentForm1D->Eval(x);
680  maxValue = (value>maxValue)? value : maxValue;
681  }
682 
683  // find cut-off position
684  for(Int_t part=NPART; part>1; part--) {
685  Float_t x = dX * (maxPt-minPt) * part + minPt;
686  value = fCurrentForm1D->Eval(x);
687  if (value> 0.001*maxValue) {
688  maxPt = x;
689  break;
690  }
691  }
692 
693  fCurrentForm1D->SetRange(minPt, maxPt);
694  fCurrentForm1D->SetNpx((int)((maxPt-minPt)*NBINS));
695  }
696 
697  // two dimensional models
698 
699  if (fModel > kLevy) {
700 
701  fCurrentForm2D->SetRange(minPt, minY, maxPt, maxY);
702 
703  Float_t maxValue = 0, midPt = 0.1, value;
704 
705  // find aproximately max value on rapidity = 0 line
706  for(Int_t part=NPART; part>1; part--) {
707  Float_t x = dX * (maxPt-minPt) * part + minPt;
708  value = fCurrentForm2D->Eval(x, 0);
709  if (value>maxValue) {
710  maxValue = value;
711  midPt = x;
712  }
713  }
714 
715  for(Int_t part=NPART; part>1; part--) {
716  Float_t x = dX * maxPt * part;
717  value = fCurrentForm2D->Eval(x, 0);
718  if (value > 0.01 * maxValue) {
719  maxPt = x;
720  break;
721  }
722  }
723 
724  // trim negative and positive rapidity
725 
726  for (Int_t part=NPART; part>1; part--) {
727  Float_t y = -dX * minY * part;
728  value = fCurrentForm2D->Eval(midPt, y);
729  if (value > 0.005 * maxValue) {
730  minY = -y;
731  break;
732  }
733  }
734 
735  for (Int_t part=NPART; part>1; part--) {
736  Float_t y = dX * maxY * part;
737  value = fCurrentForm2D->Eval(midPt, y);
738  if (value > 0.005 * maxValue) {
739  maxY = y;
740  break;
741  }
742  }
743 
744  fCurrentForm2D->SetRange(minPt, minY, maxPt, maxY);
745  fCurrentForm2D->SetNpx((int)((maxPt-minPt)*NBINS));
746  fCurrentForm2D->SetNpy((int)((maxY-minY)*NBINS));
747  }
748 
749  // azimuthal cut
750 
751  if (TestBit(kPhiRange)) {
752  fPhiFormula->SetRange(fPhiCutMin, fPhiCutMax);
753  fPhiFormula->SetNpx((int)((fPhiCutMax-fPhiCutMin)*2*NBINS));
754  }
755 }
756 
758 
759 void TGeVSim::GetRandomPtY(Double_t &pt, Double_t &y)
760 {
761  //
762  // Private function used by Generate()
763  //
764  // Returns random values of Pt and Y corresponding to selected
765  // distribution.
766  //
767 
768  switch(fModel) {
769 
770  case kBoltzman:
771  case kLevy:
772 
773  pt = fCurrentForm1D->GetRandom();
774  y = gRandom->Gaus(0, fSigmaY);
775  return;
776 
777  case kPratt:
778  case kBertsch:
779  case kExpansion:
780  case kFormula2D:
781 
782  fCurrentForm2D->GetRandom2(pt, y);
783  return;
784 
785  case kHist1D:
786 
787  pt = fHist[0]->GetRandom();
788  y = fHist[1]->GetRandom();
789  return;
790 
791  case kHist2D:
792 
793  fPtYHist->GetRandom2(pt, y);
794  return;
795 
796  //case kFormula1D:
797  //case kFunction:
798  //return;
799  }
800 }
801 
803 
804 void TGeVSim::GenerateEvent()
805 {
806  //
807  // One (and preferred) function to generate an event
808  //
809  // Generated particles are stored in internal TClonesArray
810  // the array can be accesed by GetListOfParticles()
811  // refer to macro testGeVSim.C for usage
812  //
813 
814  fEventNumber++;
815  fPartBuffer->Clear();
816  Generate(kTRUE);
817 }
818 
820 
821 Int_t TGeVSim::ImportParticles(TClonesArray *particles, Option_t *option)
822 {
823  //
824  // Function to generate en event
825  //
826  // Particles are stored in provided TClonesArray
827  //
828 
829  fEventNumber++;
830 
831  fPartBuffer = particles;
832  fPartBuffer->Clear();
833  Generate(kTRUE);
834 
835  return 0;
836 }
837 
839 
840 TObjArray* TGeVSim::ImportParticles(Option_t *option)
841 {
842  //
843  // Function to generate an event
844  //
845  // Particles are stored in internal TObjArray and can
846  // be accesd one by one using GetParticle(i) or
847  // the array can be taken be GetPrimaries()
848  //
849 
850  fEventNumber++;
851 
852  if (fPartBuffer) fPartBuffer = 0;
853 
854  fParticles->Clear();
855  Generate(kFALSE);
856 
857  return fParticles;
858 }
859 
861 
862 void TGeVSim::Generate(Bool_t clones)
863 {
864  //
865  // Private function used by ImportParticle() and GenerateEvent()
866  // functions. This function do actual job and puts particles on the stack.
867  //
868  //
869 
870  long points[20];
871  int npoint = 0;
872 
873 
874  Int_t pdg; // particle type
875  Float_t mass; // particle mass
876  Float_t energy; // total energy
877 
878  Float_t multiplicity = 0;
879  Bool_t isMultTotal = kTRUE;
880 
881  Int_t nPartTotal = 0;
882 
883  Float_t paramScaler;
884  Float_t directedScaller = 1., ellipticScaller = 1.;
885 
886  TLorentzVector *v = new TLorentzVector(0,0,0,0);
887  TLorentzVector *orgin = new TLorentzVector(0,0,0,fEventNumber);
888 
889  // Particle params database
890 
891  TDatabasePDG *db = TDatabasePDG::Instance();
892  TParticlePDG *type;
893  TGeVSimParticle *partType;
894  // TGeVSimParams *evpars; // MSD
895 
896  Int_t nType, nParticle, nParam;
897 
898  // reaction plane determination and model
899  DetermineReactionPlane();
900 
901  // *** MSD ***
902  if (!fEvent) {
903  //cout << endl << "*** ERROR: NO EVENT INITIALIZED! ***" << endl;
904  Warning("Generate","No event initialized");
905  return;
906  }
907  //if (!fEvent) fEvent = new TGeVSimEvent(10); // Initialize if necessary
908  fEvent->NextEvent(); // Reset for next event
909  fEvent->SetEventNumber(fEventNumber); // Set event number
910  fEvent->SetPsi(fPsi); // Set reaction plane angle
911  TGeVSimParams *evpars = new TGeVSimParams();
912 // evpars->Print(); // DEBUG
913  // **********
914 
915 
916  if (fIsVerbose) Info("Generate", "Generating Event = %d \t Event Plane = %3.2f deg", fEventNumber, fPsi*180/3.14);
917 
918  // loop over particle types
919 
920  for (nType = 0; nType < fPartTypes->GetEntries(); nType++) {
921 
922  points[npoint++] = times(0);
923 
924  partType = (TGeVSimParticle *)fPartTypes->At(nType);
925 
926  pdg = partType->GetPdgCode();
927  type = db->GetParticle(pdg);
928  mass = type->Mass();
929 
930  fModel = partType->GetModel();
931  SetFormula(pdg);
932 
933  // ******* MSD ******
934  //if (evpars) delete evpars;
935  //TGeVSimParams *evpars = new TGeVSimParams();
936  evpars->PDG = pdg;
937  evpars->Model = fModel;
938  // ******************
939 
940  if (fCurrentForm1D) fCurrentForm1D->SetParameter("mass", mass);
941  if (fCurrentForm2D) fCurrentForm2D->SetParameter("mass", mass);
942 
943  // Evaluation of parameters - loop over parameters
944 
945  for (nParam = kTemp; nParam <= kMult; nParam++) {
946 
947  Float_t tmp;
948 
949  paramScaler = FindScaler(nParam, pdg);
950 
951  switch (nParam) {
952 
953  case kTemp:
954  tmp = paramScaler * partType->GetTemperature();
955  if (fCurrentForm1D) fCurrentForm1D->SetParameter("temperature", tmp);
956  if (fCurrentForm2D) fCurrentForm2D->SetParameter("temperature", tmp);
957  evpars->Temp = tmp; // MSD
958  break;
959 
960  case kSigmaY:
961  fSigmaY = paramScaler * partType->GetSigmaY();
962  evpars->SigmaY = fSigmaY; // MSD
963  break;
964 
965  case kExpVel:
966  if (fModel == kExpansion) {
967  tmp = paramScaler * partType->GetExpansionVelocity();
968  if (tmp == 0.0) tmp = 0.0001;
969  if (tmp == 1.0) tmp = 0.9999; // Used to be 9.9999
970  fCurrentForm2D->SetParameter("expVel", tmp);
971  evpars->ExpVel = tmp; // MSD
972  }
973  break;
974 
975  case kSigmaTemp:
976  if (fModel == kLevy) {
977  tmp =paramScaler*partType->GetSigmaTemp();
978  fCurrentForm1D->SetParameter("sigmaTemp", tmp);
979  evpars->SigmaTemp = tmp; // MSD
980  }
981  break;
982 
983  case kV1:
984  directedScaller = paramScaler;
985  evpars->V1Scalar = paramScaler; // MSD
986  break;
987 
988  case kV2:
989  ellipticScaller = paramScaler;
990  evpars->V2Scalar = paramScaler; // MSD
991  break;
992 
993  case kMult:
994  multiplicity = paramScaler * partType->GetMultiplicity();
995  break;
996  } // switch
997  }
998 
999  // Flow defined on the particle type level (not parameterised)
1000  if (partType->IsFlowSimple()) {
1001  fPhiFormula->SetParameter(1, partType->GetDirectedFlow(0,0) * directedScaller);
1002  fPhiFormula->SetParameter(2, partType->GetEllipticFlow(0,0) * ellipticScaller);
1003  }
1004 
1005  AdjustFormula();
1006 
1007  if (partType->IsMultForced()) isMultTotal = partType->IsMultTotal();
1008  else isMultTotal = fIsMultTotal;
1009 
1010  multiplicity *= (isMultTotal)? 1 : GetdNdYToTotal();
1011  evpars->Mult = (Int_t)multiplicity+1; // MSD
1012 
1013  if (fIsVerbose) {
1014  //Info("Generate","PDG = %d \t Mult = %d", pdg, (Int_t)multiplicity);
1015  printf("Generating PDG = %5d Mult = %d\n", pdg, (Int_t)multiplicity+1 );
1016  }
1017 
1018  // Store the particle parameters for this event // MSD
1019  // NOTE : I have come across a wierd error when adding this object to the array
1020  // when I use the command:
1021  // fEvent->evParams->Add(evpars);
1022  // it overwrites every other element too. I cannot understand why this happens.
1023  // As a workaround, I can clone the object and add the clone; this works fine.
1024  TGeVSimParams *foo = (TGeVSimParams*)evpars->Clone("foo"); // This should NOT be necessary
1025  fEvent->evParams->Add(foo);
1026  //fEvent->evParams->Add(evpars);
1027  evpars->Clear(); // Reset for next particle type
1028 
1029  // loop over particles
1030  points[npoint++] = times(0);
1031 
1032  nParticle = 0;
1033  while (nParticle < multiplicity) {
1034 
1035  Double_t pt, y, phi; // momentum in [pt,y,phi]
1036  Float_t p[3] = {0,0,0}; // particle momentum
1037 
1038  GetRandomPtY(pt, y);
1039 
1040  // phi distribution configuration when differential flow defined
1041  // to be optimised in future release
1042 
1043  if (!partType->IsFlowSimple()) {
1044  fPhiFormula->SetParameter(1, partType->GetDirectedFlow(pt,y) * directedScaller);
1045  fPhiFormula->SetParameter(2, partType->GetEllipticFlow(pt,y) * ellipticScaller);
1046  }
1047 
1048  phi = fPhiFormula->GetRandom();
1049 
1050  if (!isMultTotal) nParticle++;
1051  if (!CheckPtYPhi(pt,y,phi)) continue;
1052 
1053  // coordinate transformation
1054  p[0] = pt * TMath::Cos(phi);
1055  p[1] = pt * TMath::Sin(phi);
1056  p[2] = TMath::Sqrt(mass*mass + pt*pt) * TMath::SinH(y);
1057 
1058  // momentum range test
1059  if ( !CheckPXYZ(p) ) continue;
1060 
1061  // putting particle on the stack
1062  energy = TMath::Sqrt(mass*mass + p[0]*p[0] + p[1]*p[1] + p[2]*p[2]);
1063  v->SetPxPyPzE(p[0], p[1], p[2], energy);
1064 
1065  if (clones) {
1066  new ((*fEvent->evParts)[nPartTotal]) TParticle(pdg, 0, -1, -1, -1, -1, *v, *orgin);
1067  new ((*fPartBuffer)[nPartTotal++]) TParticle(pdg, 0, -1, -1, -1, -1, *v, *orgin);
1068  }
1069  else
1070  fParticles->Add(new TParticle(pdg, 0, -1, -1, -1, -1, *v, *orgin));
1071 
1072  if (isMultTotal) nParticle++;
1073  } // loop over particles
1074 
1075  points[npoint++] = times(0);
1076  } // loop over particle types
1077 
1078  // *** MSD ***
1079  // if (clones)
1080  //fEvent->evParts = (TClonesArray*)fPartBuffer->Clone("evParts"); // Copy particles to event
1081  // ***********
1082 
1083  delete v;
1084  delete orgin;
1085 
1086 
1087  //for(Int_t i=1; i<npoint; i++) {
1089  // cout << (points[i] - points[i-1]) << endl;
1090  //}
1091 }
1092 
Definition: FJcore.h:367