er  dev
ERElasticScattering.cxx
1 /********************************************************************************
2  * Copyright (C) Joint Institute for Nuclear Research *
3  * *
4  * This software is distributed under the terms of the *
5  * GNU Lesser General Public Licence version 3 (LGPL) version 3, *
6  * copied verbatim in the file "LICENSE" *
7  ********************************************************************************/
8 
9 #include "ERElasticScattering.h"
10 
11 #include <iostream>
12 
13 #include <TF1.h>
14 #include <TMath.h>
15 #include <TLorentzRotation.h>
16 #include <TVectorD.h>
17 #include <TGraph.h>
18 #include <TVirtualMC.h>
19 
20 #include "G4IonTable.hh"
21 
22 #include <FairRunSim.h>
23 #include <FairLogger.h>
24 
25 using TMath::DegToRad;
26 using TMath::RadToDeg;
27 
28 TGraph* thetaCDFGr = NULL;
29 TGraph* thetaInvCDFGr = NULL;
30 
31 //-------------------------Globals----------------------------------
32 Double_t ThetaCDF(Double_t *x, Double_t *par) {
33  return thetaCDFGr->Eval(x[0]);
34 }
35 
36 Double_t ThetaInvCDF(Double_t *x, Double_t *par) {
37  return thetaInvCDFGr->Eval(x[0]);
38 }
39 //------------------------------------------------------------------
40 
42  ERDecay(name)
43 {
44 }
45 
47  if(fThetaInvCDF)
48  delete fThetaInvCDF;
49  if (thetaInvCDFGr)
50  delete thetaInvCDFGr;
51 }
52 
53 void ERElasticScattering::SetTargetIon(Int_t A, Int_t Z, Int_t Q) {
54  FairRunSim* run = FairRunSim::Instance();
55  fTargetIonName = fName + TString("_TargetIon");
56  FairIon* ion = new FairIon(fTargetIonName,A,Z,Q);
57  run->AddNewIon(ion);
58 }
59 
60 void ERElasticScattering::SetThetaRange(Double_t th1, Double_t th2, ERInteractionParticipant DetIonType) {
61  fThetaMinCM = th1; fThetaMaxCM = th2;
62  fDetectionIonType = DetIonType;
63 }
64 
65 void ERElasticScattering::SetLabThetaRange(Double_t thetaCenter, Double_t dTheta, ERInteractionParticipant DetIonType, Bool_t relMod, Double_t BeamAvE) {
66  fThetaRangeCenter = thetaCenter; fThetaRangedTheta = dTheta;
67  fDetectionIonType = DetIonType;
68  fRelativisticMode = relMod;
69  fBeamAverageEnergy = BeamAvE;
70  if (fRelativisticMode == kTRUE && fBeamAverageEnergy == 0.) {
71  LOG(FATAL) << "ERElasticScattering::SetLabThetaRange: In the relativistic case (4-th param = kTRUE) "
72  << "the average energy of the beam (5-th param) can't be zero."
73  << "For the relativistic case this energy must be set correct." << FairLogger::endl;
74  }
75  if (relMod == kFALSE && fBeamAverageEnergy != 0.) {
76  LOG(WARNING) << "ERElasticScattering::SetLabThetaRange: The average energy of the beam (5-th param) is not zero, "
77  << "but in non relativistic case (4-th param = kFALSE) "
78  << "the average energy of the beam is not used! This energy should be set to zero!" << FairLogger::endl;
79  }
80 }
81 
83  if (fInteractNumInTarget == 0)
84  return 0.;
86 }
87 
88 Bool_t ERElasticScattering::Init() {
89  if (!ERDecay::Init()) {
90  return kFALSE;
91  }
92 
93  fTargetIonPDG = TDatabasePDG::Instance()->GetParticle(fTargetIonName);
94  if ( ! fTargetIonPDG ) {
95  LOG(FATAL) << "ERElasticScattering::Init: Target ion was not found in pdg database!" << FairLogger::endl;
96  }
97 
98  DefineOfIonsMasses();
99  LOG(DEBUG) << "ERElasticScattering::Init()" << FairLogger::endl;
100  LOG(DEBUG) << "Traget Ions Mass is " << GetTargetIonMass()
101  << ", Prigectile Ions Mass is " << GetProjectileIonMass() << FairLogger::endl;
102 
103  if (fRelativisticMode)
105  else
107 
108  if (!ThetaCDFRead()) {
109  LOG(FATAL) << "The input file which contains the CDF function can't be read!" << FairLogger::endl;
110  return kFALSE;
111  }
112  return kTRUE;
113 }
114 
115 Bool_t ERElasticScattering::Stepping() {
116  if (!fDecayFinish && gMC->TrackPid() == fInputIonPDG->PdgCode() && TString(gMC->CurrentVolName()).Contains(fVolumeName)) {
117  gMC->SetMaxStep(fStep);
118  TLorentzVector curPos;
119  gMC->TrackPosition(curPos);
120  if (curPos.Z() >= fDecayPosZ) {
121  TLorentzVector fProjectileIonV;
122  gMC->TrackMomentum(fProjectileIonV);
123  Double_t pM = GetProjectileIonMass();
124  Double_t tM = GetTargetIonMass();
125  Double_t pM2 = pow(pM, 2);
126  Double_t tM2 = pow(tM, 2);
127 
128  Double_t projectileIonIonT = sqrt(pow(fProjectileIonV.P(), 2)+pM2) - pM;
129 
130  LOG(DEBUG) << "ElasticScattering: " << fName << FairLogger::endl;
131  LOG(DEBUG) << " ProjectileIon ion with Ekin = " << projectileIonIonT
132  << ", mass = " << pM
133  << " mom = (" << fProjectileIonV.Px() << "," << fProjectileIonV.Py() << "," << fProjectileIonV.Pz() << ")" << FairLogger::endl;
134 
135  Double_t invariant = pow((pM+tM), 2) + 2*tM*projectileIonIonT;
136  Double_t shorty = pow(invariant-pM2-tM2, 2);
137  Double_t Pcm = sqrt( (shorty-4*pM2*tM2) / (4*invariant) );
138 
139  LOG(DEBUG) << " CM momentum: " << Pcm << FairLogger::endl;
140  LOG(DEBUG) << " CM Ekin: " << sqrt(pow(Pcm,2)+pM2) - pM << FairLogger::endl;
141 
142  // Generate random angles theta and phi
143  Double_t theta = ThetaGen();
144  Double_t phi = fRnd->Uniform(fPhiMin*DegToRad(), fPhiMax*DegToRad());
145 
146  // In case of target ion registration
147  if (fDetectionIonType == kTARGET) {
148  phi = phi + 180.*DegToRad();
149  fThetaCMSum += theta*RadToDeg();
150  }
151  else
152  fThetaCMSum += theta*RadToDeg();
153 
154  if (fThetaFileName != "") {
155  LOG(DEBUG) << " CM [CDFmin,CDFmax] = [" << fCDFmin << "," << fCDFmax << "]" << FairLogger::endl;
156  }
157  TLorentzVector out1V (Pcm*sin(theta)*cos(phi), Pcm*sin(theta)*sin(phi), Pcm*cos(theta), sqrt(pow(Pcm,2) + pM2));
158  TLorentzVector out2V (-out1V.Px(), -out1V.Py(), -out1V.Pz(), sqrt(pow(Pcm,2) + tM2));
159  LOG(DEBUG) << "BEFORE BOOST=======================================================" << FairLogger::endl;
160  LOG(DEBUG) << " CM Theta = " << theta*RadToDeg() << ", phi = " << phi*RadToDeg() << FairLogger::endl;
161  LOG(DEBUG) << " CM out1 state(px,py,pz,E) = "<<out1V.Px()<<", "<<out1V.Py()<<", "<<out1V.Pz()
162  << ", " << out1V.E() << FairLogger::endl;
163  LOG(DEBUG) << " CM out2 state(px,py,pz,E) = "<<out2V.Px()<<", "<<out2V.Py()<<", "<<out2V.Pz()
164  << ", " << out2V.E() << FairLogger::endl;
165  LOG(DEBUG) << " CM out1 Ekin = "<< sqrt(pow(out1V.P(),2)+pM2) - pM << FairLogger::endl;
166  LOG(DEBUG) << " CM out2 Ekin = "<< sqrt(pow(out2V.P(),2)+tM2) - tM << FairLogger::endl;
167 
168  TLorentzVector targetV(0,0,0,tM);
169  TLorentzVector cmV = targetV + fProjectileIonV;
170  TVector3 cmVBoost = cmV.BoostVector();
171  LOG(DEBUG) << " tM in targetV(0, 0, 0, tM): " << tM << FairLogger::endl;
172  LOG(DEBUG) << " cmV components: (" << cmV.Px() << ", " << cmV.Py() << ", " << cmV.Pz() << ", " << cmV.E() << ")" << FairLogger::endl;
173  LOG(DEBUG) << " Boosting with beta = " << cmV.Beta()
174  << ", gamma = " << cmV.Gamma() << FairLogger::endl;
175  LOG(DEBUG) << " Module of cmV.BoostVector: " << sqrt(cmVBoost.Px()*cmVBoost.Px() + cmVBoost.Py()*cmVBoost.Py() + cmVBoost.Pz()*cmVBoost.Pz()) << FairLogger::endl;
176  LOG(DEBUG) << " cmV.BoostVector components: (" << cmVBoost.Px() << ", " << cmVBoost.Py() << ", " << cmVBoost.Pz() << ")" << FairLogger::endl;
177 
178  theta = cmV.Theta();
179  phi = cmV.Phi();
180  LOG(DEBUG) << " Rotation angles: theta = " << theta*RadToDeg() << ", Phi = " << phi*RadToDeg() << FairLogger::endl;
181 
182  out1V.RotateZ(-phi);
183  out1V.RotateY(theta);
184  out1V.RotateZ(phi);
185  out1V.Boost(cmV.BoostVector());
186 
187  out2V.RotateZ(-phi);
188  out2V.RotateY(theta);
189  out2V.RotateZ(phi);
190  out2V.Boost(cmV.BoostVector());
191 
192  LOG(DEBUG) << "AFTER BOOST=======================================================" << FairLogger::endl;
193  LOG(DEBUG) << " Lab theta projectile ion = " << out1V.Theta()*RadToDeg() << " phi = " << out1V.Phi()*RadToDeg() << FairLogger::endl;
194  LOG(DEBUG) << " Lab out1 T = "<< sqrt(pow(out1V.P(),2)+pM2) - pM << FairLogger::endl;
195  LOG(DEBUG) << " Lab out2 T = "<< sqrt(pow(out2V.P(),2)+tM2) - tM << FairLogger::endl;
196  LOG(DEBUG) << " Lab theta target ion = " << out2V.Theta()*RadToDeg() << " phi = " << out2V.Phi()*RadToDeg() << FairLogger::endl;
197  LOG(DEBUG) << " Lab out1 state(px,py,pz,E) = " << out1V.Px() << "," << out1V.Py() << "," << out1V.Pz()
198  << "," << out1V.E() << FairLogger::endl;
199  LOG(DEBUG) << " Lab out2 state(px,py,pz,E) = "<<out2V.Px()<<","<<out2V.Py()<<","<<out2V.Pz()
200  << "," << out2V.E() << FairLogger::endl;
201 
202  AddParticleToStack(fInputIonPDG->PdgCode(), curPos,out1V);
203  AddParticleToStack(fTargetIonPDG->PdgCode(), curPos,out2V);
204 
205  fDecayFinish = kTRUE;
206  gMC->StopTrack();
207  gMC->SetMaxStep(10000.);
208 
209  // Interactions numbers counter
211  }
212  }
213  return kTRUE;
214 }
215 
217  Double_t pM = GetProjectileIonMass();
218  Double_t tM = GetTargetIonMass();
219  LOG(DEBUG) << "ERElasticScattering::ThetaRangesLab2CM(pM = " << pM << ", tM = " << tM << ")" << FairLogger::endl;
220  Double_t rAng = fThetaRangeCenter*DegToRad();
221  Double_t ratio = pM/tM;
222  Double_t ratio2 = ratio*ratio;
223  Double_t rdThetaLab = fThetaRangedTheta*DegToRad(); // Detectors rdThetaLab
224  if (fDetectionIonType == kPROJECTILE) {
225  // Projectile Ion
226  if (pM != tM) {
227  fThetaMinCM = RadToDeg()*acos( -ratio*sin(rAng-rdThetaLab)*sin(rAng-rdThetaLab)
228  + cos(rAng-rdThetaLab)*sqrt(1.-ratio2*sin(rAng-rdThetaLab)*sin(rAng-rdThetaLab)) );
229  fThetaMaxCM = RadToDeg()*acos( -ratio*sin(rAng+rdThetaLab)*sin(rAng+rdThetaLab)
230  + cos(rAng+rdThetaLab)*sqrt(1.-ratio2*sin(rAng+rdThetaLab)*sin(rAng+rdThetaLab)) );
231  }
232  else {
233  fThetaMinCM = RadToDeg()*(2.*rAng - rdThetaLab);
234  fThetaMaxCM = RadToDeg()*(2.*rAng + rdThetaLab);
235  }
236 
237  LOG(DEBUG) << " Projectile CMTheta1: " << fThetaMinCM << ", Projectile CMTheta2: " << fThetaMaxCM
238  << ", average value: " << 0.5*(fThetaMaxCM-fThetaMinCM) + fThetaMinCM << FairLogger::endl;
239  }
240  else if (fDetectionIonType == kTARGET) {
241  // Target Ion
242  fThetaMinCM = 180. - 2.*RadToDeg()*rAng - RadToDeg()*rdThetaLab;
243  fThetaMaxCM = 180. - 2.*RadToDeg()*rAng + RadToDeg()*rdThetaLab;
244  LOG(DEBUG) << " B11: CMTheta1: " << fThetaMinCM << ", CMTheta2: " << fThetaMaxCM
245  << ", average value: " << 0.5*(fThetaMaxCM-fThetaMinCM) + fThetaMinCM << FairLogger::endl;
246  }
247  else {
248  LOG(FATAL) << "Unknown fDetectionIonType!" << FairLogger::endl;
249  }
250 }
251 
276  Double_t pM = GetProjectileIonMass();
277  Double_t tM = GetTargetIonMass();
279  if (fDetectionIonType == kTARGET)
280  pM = tM;
281 
282  Double_t pMom = sqrt(fBeamAverageEnergy*fBeamAverageEnergy - pM*pM);
283  Double_t VelocityOfCMRelOfLab = pMom / (fBeamAverageEnergy + tM);
284  if (VelocityOfCMRelOfLab > 1.) {
285  LOG(FATAL) << "In ERElasticScattering::ThetaRangesLab2CMRelativistic() the velocity of CM can't be > 1." << FairLogger::endl;
286  }
289  Double_t MomInCM = VelocityOfCMRelOfLab*tM / sqrt(1. - VelocityOfCMRelOfLab*VelocityOfCMRelOfLab);
290  Double_t yMin = tan(fThetaRangeCenter*DegToRad()-fThetaRangedTheta*DegToRad());
291  Double_t yMax = tan(fThetaRangeCenter*DegToRad()+fThetaRangedTheta*DegToRad());
292  Double_t z = VelocityOfCMRelOfLab*sqrt(pM*pM + MomInCM*MomInCM);
293  Double_t t = 1.-VelocityOfCMRelOfLab*VelocityOfCMRelOfLab;
294  Double_t B1Min = t*((MomInCM*MomInCM-z*z)*yMin*yMin + MomInCM*MomInCM*t);
295  Double_t B1Max = t*((MomInCM*MomInCM-z*z)*yMax*yMax + MomInCM*MomInCM*t);
296  if (B1Min < 0. || B1Max < 0.) {
297  LOG(FATAL) << "In ERElasticScattering::ThetaRangesLab2CMRelativistic() B1 can't be < 0." << FairLogger::endl;
298  }
299  B1Min = sqrt(B1Min);
300  B1Max = sqrt(B1Max);
301  Double_t B2Min = yMin*yMin*z;
302  Double_t B2Max = yMax*yMax*z;
303  Double_t B3Min = MomInCM*(yMin*yMin + t);
304  Double_t B3Max = MomInCM*(yMax*yMax + t);
305  Double_t CosThetaCMMin;
306  Double_t CosThetaCMMax;
307 
308  if (fDetectionIonType == kPROJECTILE) {
309  CosThetaCMMin = (-B2Min+B1Min) / B3Min;
310  CosThetaCMMax = (-B2Max+B1Max) / B3Max;
311  }
312  else if (fDetectionIonType == kTARGET) {
313  CosThetaCMMin = (B2Min-B1Min) / B3Min;
314  CosThetaCMMax = (B2Max-B1Max) / B3Max;
315  }
316  else {
317  LOG(FATAL) << "In ERElasticScattering::ThetaRangesLab2CMRelativistic() unknown fDetectionIonType!" << FairLogger::endl;
318  }
319 
320  fThetaMinCM = acos(CosThetaCMMin)*RadToDeg();
321  fThetaMaxCM = acos(CosThetaCMMax)*RadToDeg();
322 }
323 
325  if (fThetaFileName != "") {
326  LOG(INFO) << "ElasticScattering " << fName << " initialized from theta distribution file" << FairLogger::endl;
327 
328  TString path = TString(gSystem->Getenv("VMCWORKDIR")) + "/input/" + fThetaFileName;
329  std::ifstream f;
330  f.open(path.Data());
331  if (!f.is_open()) {
332  LOG(FATAL) << "Can't open file " << path << FairLogger::endl;
333  return kFALSE;
334  }
335 
336  Int_t nPoints = std::count(std::istreambuf_iterator<char>(f),
337  std::istreambuf_iterator<char>(), '\n');
338  f.seekg(0, std::ios::beg);
339  TVectorD tet(nPoints);
340  TVectorD sigma(nPoints);
341 
342  LOG(DEBUG2) << "nPoints = " << nPoints << FairLogger::endl;
343 
344  Int_t i = 0;
345  while (!f.eof()) {
346  // Костыль
347  if (i == nPoints) break;
348  f >> tet(i) >> sigma(i);
349  LOG(DEBUG2) << i << ": " << tet(i) << "\t" << sigma(i) << FairLogger::endl;
350  i++;
351  }
352 
353  thetaCDFGr = new TGraph(tet, sigma);
354  thetaInvCDFGr = new TGraph(sigma, tet);
355 
356  fThetaCDF = new TF1("thetaCDF", ThetaCDF, 0., 180., 0);
357  fThetaInvCDF = new TF1("thetaInvCDF", ThetaInvCDF, 0., 1., 0);
358 
359  fCDFmin = fThetaCDF->Eval(fThetaMinCM);
360  fCDFmax = fThetaCDF->Eval(fThetaMaxCM);
361 
362  delete thetaCDFGr;
363  delete fThetaCDF;
364  }
365  return kTRUE;
366 }
367 
369  Double_t theta;
370  if (fThetaFileName == "") {
371  theta = acos(fRnd->Uniform(cos(fThetaMinCM*DegToRad()), cos(fThetaMaxCM*DegToRad())));
372  }
373  else {
374  theta = fThetaInvCDF->Eval(fRnd->Uniform(fCDFmin, fCDFmax))*DegToRad();
375  }
376  return theta;
377 }
378 
379 Bool_t ERElasticScattering::DefineOfIonsMasses() {
380  G4ParticleTable* table = G4ParticleTable::GetParticleTable();
381  if (! table ) {
382  LOG(FATAL) << "G4 Particle Table is not found!" << FairLogger::endl;
383  return kFALSE;
384  }
385 
386  SetProjectileIonMass(1e-3*((G4ParticleDefinition*)table->FindParticle((G4int)fInputIonPDG->PdgCode()))->GetPDGMass());
387  SetTargetIonMass(1e-3*((G4ParticleDefinition*)table->FindParticle((G4int)fTargetIonPDG->PdgCode()))->GetPDGMass());
388 
389  if (! GetProjectileIonMass() ) {
390  LOG(FATAL) << "Can't difine Mass for projectile ion!" << FairLogger::endl;
391  return kFALSE;
392  }
393 
394  if (! GetTargetIonMass() ) {
395  LOG(FATAL) << "Can't difine Mass for target ion!" << FairLogger::endl;
396  return kFALSE;
397  }
398 
399  return kTRUE;
400 }
401 
402 ClassImp(ERElasticScattering)
Double_t fThetaMinCM
Theta minimum for primary ion in CM [Deg].
Double_t GetThetaCMMean() const
Returns mean of thetaCM by all events in run [Deg].
Double_t fCDFmin
ThetaCDF(fThetaMinCM) minimum.
Bool_t fRelativisticMode
kTRUE of a relativistic case is simulated and kFALSE if It isn&#39;t. kTRUE by default ...
void SetTargetIon(Int_t A, Int_t Z, Int_t Q)
Defines target ion parameters.
Double_t fPhiMax
Phi maximum for primary ion in CM [Deg].
void ThetaRangesLab2CMRelativistic()
The private method is to convert Lab theta range to CM for relativistic case.
void SetTargetIonMass(Double_t mass)
Defines target ion mass.
TF1 * fThetaCDF
Pointer to theta CDF function.
TF1 * fThetaInvCDF
Pointer to inversety theta CDF function.
ERInteractionParticipant fDetectionIonType
Ion status TODO.
ERElasticScattering(TString name)
Constructor with reaction name.
Double_t fCDFmax
ThetaCDF(fThetaMaxCM) maximum.
TString fTargetIonName
Target ion name.
void SetProjectileIonMass(Double_t mass)
Defines primary ion mass.
Double_t fPhiMin
Phi minimum for primary ion in CM [Deg].
Double_t GetProjectileIonMass() const
Returns projectile ion mass.
Double_t ThetaGen()
The private method is to generate theta value.
TParticlePDG * fTargetIonPDG
Target ion PDG.
void SetLabThetaRange(Double_t thetaCenter, Double_t dTheta, ERInteractionParticipant DetIonType=kPROJECTILE, Bool_t relMod=kTRUE, Double_t BeamAvE=0.)
Defines theta position for detector slot center in Lab.
Double_t fThetaRangedTheta
The half-width of the range of theta.
Double_t fThetaRangeCenter
Theta range&#39;s center.
Bool_t ThetaCDFRead()
The private method is to read ThetaCDF cumulative function file.
TString fThetaFileName
File name that contains theta CDF values.
Double_t fThetaCMSum
Sum of thetaCM by all events in run.
Double_t GetTargetIonMass() const
Returns target ion mass.
Double_t fBeamAverageEnergy
Avarage Energy of the beam.
void SetThetaRange(Double_t th1, Double_t th2, ERInteractionParticipant DetIonType=kPROJECTILE)
Defines range of theta value.
Double_t fThetaMaxCM
Theta maximum for primary ion in CM [Deg].
Int_t fInteractNumInTarget
Interactions counter in target (by all events in run)
void ThetaRangesLab2CM()
The private method is to convert Lab theta range to CM.
Class for the elastic scattering simulate.
virtual ~ERElasticScattering()
Destructor.