7 #include <FairLogger.h>
8 #include <FairParticle.h>
9 #include <FairPrimaryGenerator.h>
10 #include <FairRunSim.h>
12 #include <TDatabasePDG.h>
14 #include <TParticle.h>
15 #include <TParticlePDG.h>
25 constexpr
auto cRED =
"\033[1;31m";
28 constexpr
auto cGREEN =
"\033[1;32m";
29 constexpr
auto cBLUE =
"\033[1;34m";
31 Int_t AtTPC2Body::fgNIon = 0;
41 Int_t mult, std::vector<Double_t> *px, std::vector<Double_t> *py, std::vector<Double_t> *pz,
42 std::vector<Double_t> *mass, std::vector<Double_t> *Ex, Double_t ResEner, Double_t MinCMSAng,
44 : fMult(mult), fPx(0.), fPy(0.), fPz(0.), fVx(0.), fVy(0.), fVz(0.), fIon(0), fPType(0.), fQ(0),
45 fThetaCmsMin(MinCMSAng), fThetaCmsMax(MaxCMSAng), fBeamEnergy_buff(ResEner), fNoSolution(kFALSE),
46 fIsFixedTargetPos(kFALSE), fIsFixedMomentum(kFALSE)
52 auto *kProton =
new TParticle();
53 kProton->SetPdgCode(2212);
54 auto *kNeutron =
new TParticle();
55 kNeutron->SetPdgCode(2112);
57 for (Int_t i = 0; i < fMult; i++) {
59 fPx.push_back(Double_t(a->at(i)) * px->at(i));
60 fPy.push_back(Double_t(a->at(i)) * py->at(i));
61 fPz.push_back(Double_t(a->at(i)) * pz->at(i));
62 Masses.push_back(mass->at(i) * 1000.0);
63 fExEnergy.push_back(Ex->at(i));
64 fWm.push_back(mass->at(i) * 1000.0 * 0.93149401 + Ex->at(i));
66 FairParticle *ParticleBuff;
67 sprintf(buffer,
"Product_Ion%d", i);
71 IonBuff =
new FairIon(buffer, z->at(i), a->at(i), q->at(i), 0.0, mass->at(i));
72 ParticleBuff =
new FairParticle(
"dummyPart", 1, 1, 1.0, 0, 0.0, 0.0);
73 fPType.emplace_back(
"Ion");
74 std::cout <<
" Adding : " << buffer << std::endl;
76 }
else if (a->at(i) == 1 && z->at(i) == 1) {
78 IonBuff =
new FairIon(
"dummyIon", 50, 50, 0, 0.0, 100);
79 ParticleBuff =
new FairParticle(2212, kProton);
80 fPType.emplace_back(
"Proton");
82 }
else if (a->at(i) == 1 && z->at(i) == 0) {
84 IonBuff =
new FairIon(
"dummyIon", 50, 50, 0, 0.0, 100);
85 ParticleBuff =
new FairParticle(2112, kNeutron);
86 fPType.emplace_back(
"Neutron");
89 std::cout <<
" Z " << z->at(i) <<
" A " << a->at(i) << std::endl;
91 fIon.push_back(IonBuff);
92 fParticle.push_back(ParticleBuff);
95 FairRunSim *run = FairRunSim::Instance();
97 std::cout <<
"-E- FairIonGenerator: No FairRun instantised!" << std::endl;
98 Fatal(
"FairIonGenerator",
"No FairRun instantised!");
101 for (Int_t i = 0; i < fMult; i++) {
103 if (fPType.at(i) ==
"Ion") {
105 std::cout <<
" In position " << i <<
" adding an : " << fPType.at(i) << std::endl;
106 run->AddNewIon(fIon.at(i));
107 std::cout <<
" fIon name :" << fIon.at(i)->GetName() << std::endl;
108 std::cout <<
" fParticle name :" << fParticle.at(i)->GetName() << std::endl;
110 }
else if (fPType.at(i) ==
"Proton") {
112 std::cout <<
" In position " << i <<
" adding an : " << fPType.at(i) << std::endl;
114 std::cout <<
" fIon name :" << fIon.at(i)->GetName() << std::endl;
115 std::cout <<
" fParticle name :" << fParticle.at(i)->GetName() << std::endl;
116 std::cout << fParticle.at(i)->GetName() << std::endl;
118 }
else if (fPType.at(i) ==
"Neutron") {
120 std::cout <<
" In position " << i <<
" adding an : " << fPType.at(i) << std::endl;
122 std::cout <<
" fIon name :" << fIon.at(i)->GetName() << std::endl;
123 std::cout <<
" fParticle name :" << fParticle.at(i)->GetName() << std::endl;
124 std::cout << fParticle.at(i)->GetName() << std::endl;
131 std::cout <<
" -I- AtTPC2Body : Fixed target position at " << vx <<
" " << vy <<
" " << vz << std::endl;
132 fIsFixedTargetPos = kTRUE;
140 std::cout <<
" -I- AtTPC2Body : Fixed beam momentum " << px <<
" " << py <<
" " << pz << std::endl;
141 fIsFixedMomentum = kTRUE;
151 std::vector<Double_t> Ang;
152 std::vector<Double_t> Ene;
163 Double_t costhetamin = TMath::Cos(fThetaCmsMin * TMath::DegToRad());
164 Double_t costhetamax = TMath::Cos(fThetaCmsMax * TMath::DegToRad());
167 Double_t thetacmsInput =
168 TMath::ACos((costhetamax - costhetamin) * gRandom->Uniform() + costhetamin) * TMath::RadToDeg();
170 std::cout <<
cBLUE <<
" -I- AtTPC2Body : Random CMS Theta angle in degrees : " << thetacmsInput <<
cNORMAL
172 const Double_t rad2deg = 0.0174532925;
174 if (fIsFixedTargetPos) {
175 fBeamEnergy = fBeamEnergy_buff;
177 std::cout <<
cBLUE <<
" -I- AtTPC2Body Beam energy (Fixed Target mode) : " << fBeamEnergy <<
cNORMAL << std::endl;
182 std::cout <<
cBLUE <<
" -I- AtTPC2Body Residual energy (Active Target mode) : "
186 if (fBeamEnergy > 0 &&
188 fIsFixedTargetPos)) {
190 if (fIsFixedTargetPos) {
191 fPxBeam = fPxBeam_buff;
192 fPyBeam = fPyBeam_buff;
193 fPzBeam = fPzBeam_buff;
202 Double_t eb = fBeamEnergy + fWm.at(0);
203 Double_t pb2 = fBeamEnergy * fBeamEnergy + 2.0 * fBeamEnergy * fWm.at(0);
204 Double_t pb = TMath::Sqrt(pb2);
205 Double_t beta = pb / (eb + fWm.at(1));
206 Double_t gamma = 1.0 / sqrt(1.0 - beta * beta);
208 Double_t thetacms = thetacmsInput * rad2deg;
210 Double_t thetacmr = TMath::Pi() - thetacms;
211 Double_t e = fBeamEnergy + fWm.at(0) + fWm.at(1);
212 Double_t e_cm2 = e * e - pb2;
213 Double_t e_cm = TMath::Sqrt(e_cm2);
214 Double_t t_cm = e_cm - fWm.at(2) - fWm.at(3);
217 std::cout <<
"-I- AtTPC2Body : No solution!" << std::endl;
225 Double_t t_cm2 = t_cm * t_cm;
226 Double_t t3_cm = (t_cm2 + 2. * fWm.at(3) * t_cm) / (t_cm + fWm.at(2) + fWm.at(3)) / 2.0;
227 Double_t t4_cm = (t_cm2 + 2. * fWm.at(2) * t_cm) / (t_cm + fWm.at(2) + fWm.at(3)) / 2.0;
228 Double_t p3_cm2 = t3_cm * t3_cm + 2.0 * t3_cm * fWm.at(2);
229 Double_t p3_cm = TMath::Sqrt(p3_cm2);
230 Double_t tg_thetalabs =
231 p3_cm * TMath::Sin(thetacms) /
232 (gamma * (p3_cm * TMath::Cos(thetacms) + beta * TMath::Sqrt(p3_cm * p3_cm + fWm.at(2) * fWm.at(2))));
234 if (tg_thetalabs >= 1.0e6) {
235 Ang.push_back(TMath::Pi() / 2.0);
237 Ang.push_back(TMath::ATan(tg_thetalabs));
241 Ang.at(0) = TMath::Pi() + Ang.at(0);
243 Double_t p4_cm2 = t4_cm * t4_cm + 2. * t4_cm * fWm.at(3);
244 Double_t p4_cm = TMath::Sqrt(p4_cm2);
245 Double_t tg_thetalabr =
246 p4_cm * TMath::Sin(thetacmr) /
247 (gamma * (p4_cm * TMath::Cos(thetacmr) + beta * TMath::Sqrt(p4_cm * p4_cm + fWm.at(3) * fWm.at(3))));
250 if (tg_thetalabr > 1.0e6) {
251 Ang.push_back(TMath::Pi() / 2.0);
253 Ang.push_back(TMath::ATan(tg_thetalabr));
257 Ang.at(1) = TMath::Pi() + Ang.at(1);
261 Double_t p3_cmx = p3_cm * sin(thetacms);
262 Double_t p3_cmz = p3_cm * cos(thetacms);
263 Double_t p3_labx = p3_cmx;
264 Double_t p3_labz = gamma * (p3_cmz + beta * (t3_cm + fWm.at(2)));
265 Double_t p3_lab = TMath::Sqrt(p3_labx * p3_labx + p3_labz * p3_labz);
266 Ene.push_back(TMath::Sqrt(p3_lab * p3_lab + fWm.at(2) * fWm.at(2)) - fWm.at(2));
268 Double_t p4_cmx = p4_cm * sin(thetacmr);
269 Double_t p4_cmz = p4_cm * cos(thetacmr);
270 Double_t p4_labx = p4_cmx;
271 Double_t p4_labz = gamma * (p4_cmz + beta * (t4_cm + fWm.at(3)));
272 Double_t p4_lab = TMath::Sqrt(p4_labx * p4_labx + p4_labz * p4_labz);
273 Ene.push_back(TMath::Sqrt(p4_lab * p4_lab + fWm.at(3) * fWm.at(3)) - fWm.at(3));
276 std::cout <<
" -I- ===== AtTPC2Body - Kinematics ====== " << std::endl;
277 std::cout <<
" -I- ===== No Valid Solution on Beam Event for these kinematics (probably due to threshold "
280 std::cout <<
" -I- ===== Setting Values to 0 ====== " << std::endl;
288 std::cout <<
cBLUE <<
" -I- ===== AtTPC2Body - Kinematics ====== " << std::endl;
289 std::cout <<
" Decay of scattered particle enabled : " << kIsDecay <<
"\n";
290 std::cout <<
" Scattered energy:" << Ene.at(0) <<
" MeV" << std::endl;
291 std::cout <<
" Scattered angle:" << Ang.at(0) * 180 / TMath::Pi() <<
" deg" << std::endl;
292 std::cout <<
" Recoil energy:" << Ene.at(1) <<
" MeV" << std::endl;
293 std::cout <<
" Recoiled angle:" << Ang.at(1) * 180.0 / TMath::Pi() <<
" deg" <<
cNORMAL << std::endl;
311 fPx.at(2) = p3_labx / 1000.0;
313 fPz.at(2) = p3_labz / 1000.0;
315 fPx.at(3) = p4_labx / 1000.0;
317 fPz.at(3) = p4_labz / 1000.0;
319 Double_t phiBeam1 = 0., phiBeam2 = 0.;
321 phiBeam1 = 2 * TMath::Pi() * gRandom->Uniform();
322 phiBeam2 = phiBeam1 + TMath::Pi();
337 TVector3 BeamPos(fPxBeam * 1000, fPyBeam * 1000, fPzBeam * 1000);
339 LOG(DEBUG) <<
" Beam Theta (Mom) : " << BeamPos.Theta() * 180.0 / TMath::Pi();
340 LOG(DEBUG) <<
" Beam Phi (Mom) : " << BeamPos.Phi() * 180.0 / TMath::Pi();
342 Double_t thetaLab1, phiLab1, thetaLab2, phiLab2;
343 auto EulerTransformer = std::make_unique<AtEulerTransformation>();
344 EulerTransformer->SetBeamDirectionAtVertexTheta(BeamPos.Theta());
345 EulerTransformer->SetBeamDirectionAtVertexPhi(BeamPos.Phi());
347 EulerTransformer->SetThetaInBeamSystem(Ang.at(0));
348 EulerTransformer->SetPhiInBeamSystem(phiBeam1);
349 EulerTransformer->DoTheEulerTransformationBeam2Lab();
352 thetaLab1 = EulerTransformer->GetThetaInLabSystem();
353 phiLab1 = EulerTransformer->GetPhiInLabSystem();
354 LOG(DEBUG) <<
" Scattered angle Phi :" << phiBeam1 * 180.0 / TMath::Pi() <<
" deg";
355 LOG(DEBUG) <<
" Scattered angle Theta (Euler) :" << thetaLab1 * 180.0 / TMath::Pi() <<
" deg";
356 LOG(DEBUG) <<
" Scattered angle Phi (Euler) :" << phiLab1 * 180.0 / TMath::Pi() <<
" deg";
362 TVector3 direction1 = TVector3(sin(thetaLab1) * cos(phiLab1), sin(thetaLab1) * sin(phiLab1), cos(thetaLab1));
364 EulerTransformer->SetThetaInBeamSystem(Ang.at(1));
365 EulerTransformer->SetPhiInBeamSystem(phiBeam2);
366 EulerTransformer->DoTheEulerTransformationBeam2Lab();
369 thetaLab2 = EulerTransformer->GetThetaInLabSystem();
370 phiLab2 = EulerTransformer->GetPhiInLabSystem();
372 TVector3 direction2 = TVector3(sin(thetaLab2) * cos(phiLab2), sin(thetaLab2) * sin(phiLab2), cos(thetaLab2));
374 LOG(DEBUG) <<
" Recoiled angle Phi :" << phiBeam2 * 180.0 / TMath::Pi() <<
" deg";
375 LOG(DEBUG) <<
" Recoiled angle Theta (Euler) :" << thetaLab2 * 180.0 / TMath::Pi() <<
" deg";
376 LOG(DEBUG) <<
" Recoiled angle Phi (Euler) :" << phiLab2 * 180.0 / TMath::Pi() <<
" deg";
378 LOG(DEBUG) <<
" Phi Diference :" << (phiBeam1 * 180.0 / TMath::Pi()) - (phiBeam2 * 180.0 / TMath::Pi())
380 LOG(DEBUG) <<
" Phi Diference (Euler) :" << (phiLab1 * 180.0 / TMath::Pi()) - (phiLab2 * 180.0 / TMath::Pi())
383 LOG(DEBUG) <<
" Direction 1 Theta : " << direction1.Theta() * 180.0 / TMath::Pi();
384 LOG(DEBUG) <<
" Direction 1 Phi : " << direction1.Phi() * 180.0 / TMath::Pi();
385 LOG(DEBUG) <<
" Direction 2 Theta : " << direction2.Theta() * 180.0 / TMath::Pi();
386 LOG(DEBUG) <<
" Direction 2 Phi : " << direction2.Phi() * 180.0 / TMath::Pi();
388 fPx.at(2) = p3_lab * direction1.X() / 1000.0;
389 fPy.at(2) = p3_lab * direction1.Y() / 1000.0;
390 fPz.at(2) = p3_lab * direction1.Z() / 1000.0;
392 fPx.at(3) = p4_lab * direction2.X() / 1000.0;
393 fPy.at(3) = p4_lab * direction2.Y() / 1000.0;
394 fPz.at(3) = p4_lab * direction2.Z() / 1000.0;
444 for (Int_t i = 0; i < fMult; i++) {
446 TParticlePDG *thisPart =
nullptr;
448 if (fPType.at(i) ==
"Ion")
449 thisPart = TDatabasePDG::Instance()->GetParticle(fIon.at(i)->GetName());
450 else if (fPType.at(i) ==
"Proton")
451 thisPart = TDatabasePDG::Instance()->GetParticle(fParticle.at(i)->GetName());
452 else if (fPType.at(i) ==
"Neutron")
453 thisPart = TDatabasePDG::Instance()->GetParticle(fParticle.at(i)->GetName());
457 if (fPType.at(i) ==
"Ion")
458 std::cout <<
"-W- FairIonGenerator: Ion " << fIon.at(i)->GetName() <<
" not found in database!"
460 else if (fPType.at(i) ==
"Proton")
461 std::cout <<
"-W- FairIonGenerator: Particle " << fParticle.at(i)->GetName() <<
" not found in database!"
463 else if (fPType.at(i) ==
"Neutron")
464 std::cout <<
"-W- FairIonGenerator: Particle " << fParticle.at(i)->GetName() <<
" not found in database!"
470 int pdgType = thisPart->PdgCode();
473 if (fIsFixedTargetPos) {
486 TVector3 ScatP(fPx.at(2), fPy.at(2), fPz.at(2));
490 Int_t trackIdCut = 0;
498 pdgType != 1000500500 && fPType.at(i) ==
"Ion") {
500 std::cout <<
cBLUE <<
"-I- FairIonGenerator: Generating ions of type " << fIon.at(i)->GetName()
501 <<
" (PDG code " << pdgType <<
")" << std::endl;
502 std::cout <<
" Momentum (" << fPx.at(i) <<
", " << fPy.at(i) <<
", " << fPz.at(i)
503 <<
") Gev from vertex (" << fVx <<
", " << fVy <<
", " << fVz <<
") cm" << std::endl;
504 primGen->AddTrack(pdgType, fPx.at(i), fPy.at(i), fPz.at(i), fVx, fVy, fVz);
507 pdgType == 2212 && fPType.at(i) ==
"Proton") {
509 std::cout <<
"-I- FairIonGenerator: Generating ions of type " << fParticle.at(i)->GetName() <<
" (PDG code "
510 << pdgType <<
")" << std::endl;
511 std::cout <<
" Momentum (" << fPx.at(i) <<
", " << fPy.at(i) <<
", " << fPz.at(i)
512 <<
") Gev from vertex (" << fVx <<
", " << fVy <<
", " << fVz <<
") cm" << std::endl;
513 primGen->AddTrack(pdgType, fPx.at(i), fPy.at(i), fPz.at(i), fVx, fVy, fVz);
516 pdgType == 2112 && fPType.at(i) ==
"Neutron") {
518 std::cout <<
"-I- FairIonGenerator: Generating ions of type " << fParticle.at(i)->GetName() <<
" (PDG code "
519 << pdgType <<
")" << std::endl;
520 std::cout <<
" Momentum (" << fPx.at(i) <<
", " << fPy.at(i) <<
", " << fPz.at(i)
521 <<
") Gev from vertex (" << fVx <<
", " << fVy <<
", " << fVz <<
") cm" <<
cNORMAL << std::endl;
522 primGen->AddTrack(pdgType, fPx.at(i), fPy.at(i), fPz.at(i), fVx, fVy, fVz);
528 if (kIsDecay == kFALSE)