KaliVeda
Toolkit for HIC analysis
KVFlowTensor.cpp
1 //Created by KVClassFactory on Tue Jun 30 12:41:37 2015
2 //Author: John Frankland,,,
3 
4 #include "KVFlowTensor.h"
5 #include "TMatrixDUtils.h"
6 #include "TMatrixDSymEigen.h"
7 
9 
10 
11 
12 
15 KVFlowTensor::KVFlowTensor(void): KVVarGlob(), fTensor(3), fEVal(3)
16 {
17  // Default constructor
18  init_KVFlowTensor();
19  SetName("KVFlowTensor");
20  SetTitle("Kinetic energy flow tensor of Gyulassy et al.");
21 }
22 
23 
24 
27 
28 KVFlowTensor::KVFlowTensor(const Char_t* nom): KVVarGlob(nom), fTensor(3), fEVal(3)
29 {
30  // Constructor with a name for the global variable
31  init_KVFlowTensor();
32 }
33 
34 
35 
38 
39 KVFlowTensor::KVFlowTensor(const KVFlowTensor& a): KVVarGlob(), fTensor(3), fEVal(3)
40 {
41  // Copy constructor
42  a.Copy(*this);
43 }
44 
45 
46 
49 
51 {
52  // Destructor
53 }
54 
55 
56 
59 
61 {
62  // Copy properties of 'this' object into the KVVarGlob object referenced by 'a'
63 
64  KVFlowTensor& aglob = (KVFlowTensor&)a;
65  KVVarGlob::Copy(a);// copy attributes of KVVarGlob base object
66  aglob.Init();
67  aglob.fTensor = fTensor;
68  aglob.fNParts = fNParts;
69  if (fCalculated) aglob.Calculate();
70 }
71 
72 
73 
76 
78 {
79  // Operateur =
80 
81  if (&a != this) a.Copy(*this);
82  return *this;
83 }
84 
85 
86 
89 
91 {
92  // Initialisation of internal variables, called once before beginning treatment
93 
94  Reset();
95  TString wgt = GetOptionString("weight");
96  if (wgt == "RKE") weight = kRKE;
97  else if (wgt == "ONE" || wgt == "" || wgt == "1") weight = kONE;
98  else weight = kNRKE;
99 }
100 
101 
102 
105 
107 {
108  // Reset internal variables, called before treatment of each event
109  fTensor.Zero();
110  fNParts = 0;
111  fCalculated = false;
112 }
113 
114 
115 
132 
133 Double_t KVFlowTensor::getvalue_int(Int_t index) const
134 {
135  // \param index one of the following values:
136  //
137  // Name | Index | Definition
138  // ---------------|-----------------------------|---------------------------------------------
139  // "FlowAngle" |KVFlowTensor::kFlowAngle |polar angle of \f$\vec{e_1}\f$
140  // "Sphericity" |KVFlowTensor::kSphericity |\f$\frac{3}{2}(1-\lambda_1)\f$
141  // "Coplanarity" |KVFlowTensor::kCoplanarity |\f$\frac{\sqrt{3}}{2}(\lambda_2-\lambda_3)\f$
142  // "KinFlowRatio13"|KVFlowTensor::kKinFlowRatio13|\f$\sqrt{\frac{\lambda_1}{\lambda_3}}\f$
143  // "KinFlowRatio23"|KVFlowTensor::kKinFlowRatio23|\f$\sqrt{\frac{\lambda_2}{\lambda_3}}\f$
144  // "PhiReacPlane" |KVFlowTensor::kPhiReacPlane |\f$\phi\f$ angle of \f$\vec{e_1}\f$
145  // "SqueezeAngle" |KVFlowTensor::kSqueezeAngle |see Gyulassy et al
146  // "SqueezeRatio" |KVFlowTensor::kSqueezeRatio |see Gyulassy et al
147  // "NumberParts" |KVFlowTensor::kNumberParts |number of particles used in tensor
148  //
149  // \return value associated with given index
150  switch (index) {
151  case kFlowAngle:
152  return TMath::RadToDeg() * e(1).Theta();
153  break;
154 
155  case kSphericity:
156  return fSphericity;
157  break;
158 
159  case kCoplanarity:
160  return fCoplanarity;
161  break;
162 
163  case kKinFlowRatio13: {
164  if (f(3) <= 0.) return -1.;
165  if (f(1) <= 0.) return -1.;
166  return TMath::Min(1e+03, pow(f(1) / f(3), 0.5));
167  }
168  break;
169 
170  case kKinFlowRatio23: {
171  if (f(3) <= 0.) return -1.;
172  if (f(2) <= 0.) return -1.;
173  return TMath::Min(1e+03, pow(f(2) / f(3), 0.5));
174  }
175  break;
176 
177  case kPhiReacPlane: {
178  Double_t phi = TMath::RadToDeg() * e(1).Phi();
179  return (phi < 0 ? 360 + phi : phi);
180  }
181  break;
182 
183  case kSqueezeAngle:
184  return fSqueezeAngle;
185  break;
186 
187  case kSqueezeRatio:
188  return fSqOutRatio;
189  break;
190 
191  case kNumberParts:
192  return fNParts;
193  break;
194 
195  default:
196  break;
197  }
198 
199  return 0;
200 }
201 
202 
203 
206 
208 {
209  // Calculate eigenvalues & eigenvectors of tensor
210 
211  TMatrixDSymEigen diagonalize(fTensor);
212  TMatrixD evectors = diagonalize.GetEigenVectors();
213  fEVal = diagonalize.GetEigenValues();
214 
215  for (int i = 0; i < 3; i++) {
216  TMatrixDColumn col(evectors, i);
217  fEVec[i].SetXYZ(col[0], col[1], col[2]);
218  }
219 
220  // check orientation of flow axis
221  // by symmetry/convention, we allow FlowAngle between 0 & 90° i.e. flow vector always
222  // points in the forward beam direction.
223  if (fEVec[0].Theta() > TMath::PiOver2()) {
224  fEVec[0] = -fEVec[0];
225  }
226 
227  // check we have an orthonormal basis
228  // we choose evec[0]=>'z' evec[1]=>'y' evec[2]=>'x'
229  // therefore we should have evec[2].Cross(evec[1])=evec[0]
230  // if not we change the sign of evec[2]
231  if (fEVec[2].Cross(fEVec[1]) != fEVec[0]) fEVec[2] = -fEVec[2];
232 
233  // set up azimuthal rotation of CM axes around beam axis in order to put new 'X'-axis in reaction plane
234  // we use the phi of the major axis (largest eigenvector)
235  fAziReacPlane.SetToIdentity();
236  fAziReacPlane.RotateZ(e(1).Phi());
237 
238  fFlowReacPlane.SetToIdentity();
239  fFlowReacPlane.RotateY(e(1).Theta());
240  fFlowReacPlane.RotateZ(e(1).Phi());
241 
242  // calculate Gutbrod squeeze angle (PRC42(1990)640
243  // defined as the angle by which the middle eigenvector e2
244  // needs to be rotated around the e1 flow axis
245  // in order to be brought in to the reaction plane
246  TVector3 normReac = e(1).Cross(TVector3(0, 0, 1)); //normal to reaction plane: e1 x z
247  Double_t angle = TMath::RadToDeg() * e(2).Angle(normReac);
248  // on the contrary to Gutbrod et al, we define this angle between 0 and 90 degrees.
249  // see Fig. 3 of paper: only 0-90 angles can be defined
250  fSqueezeAngle = (angle < 90 ? 90 - angle : angle - 90);
251 
252  // now calculate the in-plane and out-of-plane flow according to Fig. 5 of Gutbrod et al
253  Double_t a = pow(f(2), 0.5); //semi-axes of ellipsoid given by square roots of eigenvalues
254  Double_t b = pow(f(3), 0.5);
255  Double_t tan_t = -a / b * TMath::Tan(fSqueezeAngle * TMath::DegToRad());
256  Double_t t0 = TMath::ATan(tan_t);
257  Double_t inPlane = a * cos(t0) * cos(fSqueezeAngle * TMath::DegToRad()) - b * sin(t0) * sin(fSqueezeAngle * TMath::DegToRad());
258  tan_t = a / (b * tan(fSqueezeAngle * TMath::DegToRad()));
259  t0 = atan(tan_t);
260  Double_t outOfPlane = a * cos(t0) * sin(fSqueezeAngle * TMath::DegToRad()) + b * sin(t0) * cos(fSqueezeAngle * TMath::DegToRad());
261  if (inPlane <= 0.) fSqOutRatio = -1.;
262  else fSqOutRatio = TMath::Min(1.e+03, outOfPlane / inPlane);
263 
264  // calculate sphericity & coplanarity
265  sum_val_prop = f(1) + f(2) + f(3);
266  if (sum_val_prop > .1) {
267  fSphericity = 1.5 * (1. - f(1) / sum_val_prop);
268  fCoplanarity = sqrt(3.) * (f(2) - f(3)) / sum_val_prop / 2.;
269  }
270  else {
271  fSphericity = fCoplanarity = -1;
272  }
273  fCalculated = kTRUE;
274 }
275 
276 
277 
278 
294 
295 void KVFlowTensor::init_KVFlowTensor()
296 {
297  //Common initialisation for all constructors
298  //
299  // Default frame is set to "CM".
300  //
301  // Default weight is set to NRKE if none was given
302  // by calling method SetOption("weight","[your choice]")
303  // with one of the following choices:
304  // Option | Name | Weight
305  // ------------|--------------------------------------|---------------------------------------------------
306  // "NRKE" | non-relativistic KE tensor (default) | \f$w_{\nu}=(2m_{\nu})^{-1}\f$
307  // "RKE" | relativistic KE tensor | \f$w_{\nu}={1 \over {m_{\nu}(\gamma_{\nu}+1)}}\f$
308  // "ONE","1",""| sphericity tensor | \f$w=1\f$
309  //
310  // Default maximum number of branches for TTree is 3: FlowAngle, Sphericity, and Coplanarity
311 
312  fType = KVVarGlob::kOneBody; // this is a 1-body variable
313 
314  SetFrame("CM");
315  SetOption("weight", "NRKE");
316 
317  fTensor.Zero();
318 
319  SetNameIndex("FlowAngle", kFlowAngle);
320  SetNameIndex("Sphericity", kSphericity);
321  SetNameIndex("Coplanarity", kCoplanarity);
322  SetNameIndex("KinFlowRatio13", kKinFlowRatio13);
323  SetNameIndex("KinFlowRatio23", kKinFlowRatio23);
324  SetNameIndex("PhiReacPlane", kPhiReacPlane);
325  SetNameIndex("SqueezeAngle", kSqueezeAngle);
326  SetNameIndex("SqueezeRatio", kSqueezeRatio);
327  SetNameIndex("NumberParts", kNumberParts);
328 
330 
331  fNParts = 0;
332 }
333 
334 
335 
341 
343 {
344  // Fill tensor components with nucleus' momentum components using the required weight
345  //
346  // If option "DOUBLE" is set, the chosen weight will be doubled
347  // (this is for the case where e.g. only forward hemisphere particles are included)
348 
349  Double_t W;
350  switch (weight) {
351  case kONE:
352  W = 1;
353  break;
354  case kRKE:
355  W = 1. / (n->GetMass() * (1 + n->Gamma()));
356  break;
357  default:
358  case kNRKE:
359  W = 1. / (2.*n->GetMass());
360  break;
361  }
362  if (IsOptionGiven("DOUBLE")) W *= 2.;
363  for (int i = 0; i < 3; i++) {
364  for (int j = i; j < 3; j++) {
365  Double_t xx = W * n->GetMomentum()[i] * n->GetMomentum()[j];
366  fTensor(i, j) += xx;
367  if (i != j) fTensor(j, i) += xx;
368  }
369  }
370  ++fNParts;
371 }
372 
373 
374 
385 
387 {
388  // Returns the azimuthal rotation around the beam axis required
389  // to put the \f$x\f$-axis in the reaction plane defined by the beam axis
390  // and the major axis (largest eigenvalue) of the ellipsoid.
391  //
392  // The azimuthal angle of the rotation is that of the major axis
393  // in the forward direction.
394  //
395  // Note that this rotation applies to whatever frame was used to calculate
396  // the tensor (default: "CM")
397 
398  return fAziReacPlane;
399 }
400 
401 
402 
413 
415 {
416  // Returns composition of two rotations:
417  // - around \f$z\f$-axis to put \f$x\f$-axis in reaction plane (see GetAziReacPlaneRotation())
418  // - around \f$y\f$-axis to align \f$z\f$-axis with flow (major) axis
419  //
420  // In this rotated frame, \f$\theta\f$ is polar angle with respect to flow axis
421  // and \f$\phi\f$ is azimuthal angle around flow axis (\f$\phi\f$=0,180 => in-plane)
422  //
423  // Note that this rotation applies to whatever frame was used to calculate
424  // the tensor (default: "CM")
425 
426  return fFlowReacPlane;
427 }
428 
429 
430 
433 
435 {
436  // if opt="tensor", just print contents of tensor
437 
438  if (strcmp(opt, "tensor")) KVVarGlob::Print();
439  std::cout << "Number of particles = " << fNParts << std::endl;
440  fTensor.Print();
441 }
442 
443 
444 
int Int_t
char Char_t
double Double_t
constexpr Bool_t kTRUE
const char Option_t
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t b
Option_t Option_t TPoint TPoint angle
Kinetic energy flow tensor of Gyulassy et al and associated shape variables.
Definition: KVFlowTensor.h:78
void Init() override
Initialisation of internal variables, called once before beginning treatment.
void Calculate() override
Calculate eigenvalues & eigenvectors of tensor.
void fill(const KVNucleus *n) override
virtual ~KVFlowTensor(void)
Destructor.
KVFlowTensor & operator=(const KVFlowTensor &a)
Operateur =.
const TRotation & GetFlowReacPlaneRotation() const
void Copy(TObject &obj) const override
Copy properties of 'this' object into the KVVarGlob object referenced by 'a'.
KVFlowTensor()
Default constructor.
void Reset() override
Reset internal variables, called before treatment of each event.
void Print(Option_t *="") const override
if opt="tensor", just print contents of tensor
const TRotation & GetAziReacPlaneRotation() const
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:123
Base class for all global variable implementations.
Definition: KVVarGlob.h:233
void SetOption(const Char_t *option, const Char_t *value)
Definition: KVVarGlob.h:521
void Print(Option_t *="") const override
Definition: KVVarGlob.cpp:277
void SetMaxNumBranches(Int_t n)
Definition: KVVarGlob.h:683
TString GetOptionString(const Char_t *opt) const
Definition: KVVarGlob.h:536
Bool_t IsOptionGiven(const Char_t *opt)
Definition: KVVarGlob.h:529
void Copy(TObject &obj) const override
Definition: KVVarGlob.h:346
void SetFrame(const Char_t *ref)
Definition: KVVarGlob.h:505
void Copy(TObject &arc) const override
const TVectorD & GetEigenValues() const
const TMatrixD & GetEigenVectors() const
virtual TMatrixTBase< Element > & Zero()
void Print(Option_t *name="") const override
TRotation & SetToIdentity()
TRotation & RotateY(Double_t)
TRotation & RotateZ(Double_t)
void SetXYZ(Double_t x, Double_t y, Double_t z)
Double_t Phi() const
Double_t Angle(const TVector3 &) const
Double_t Theta() const
TVector3 Cross(const TVector3 &) const
Expr< UnaryOp< Sqrt< T >, SMatrix< T, D, D2, R >, T >, T, D, D2, R > sqrt(const SMatrix< T, D, D2, R > &rhs)
SVector< T, 3 > Cross(const SVector< T, 3 > &lhs, const SVector< T, 3 > &rhs)
RVec< PromoteType< T > > tan(const RVec< T > &v)
RVec< PromoteType< T > > cos(const RVec< T > &v)
RVec< PromoteTypes< T0, T1 > > pow(const T0 &x, const RVec< T1 > &v)
RVec< PromoteType< T > > atan(const RVec< T > &v)
RVec< PromoteType< T > > sin(const RVec< T > &v)
gr SetName("gr")
const Int_t n
Double_t Min(Double_t a, Double_t b)
Double_t ATan(Double_t)
constexpr Double_t PiOver2()
constexpr Double_t DegToRad()
Double_t Tan(Double_t)
constexpr Double_t RadToDeg()
TArc a
ClassImp(TPyArg)