Heavy ion Analysis Libriares
Loading...
Searching...
No Matches
Decay.cxx
1/*
2 * Decay.cxx
3 *
4 * Created on: 21 gru 2023
5 * Author: Daniel Wielanek
6 * E-mail: daniel.wielanek@gmail.com
7 * Warsaw University of Technology, Faculty of Physics
8 */
9
10#include "Decay.h"
11
12#include "Cout.h"
13#include "McEvent.h"
14#include "McTrack.h"
15
16#include <Rtypes.h>
17#include <RtypesCore.h>
18#include <TDatabasePDG.h>
19#include <TLorentzVector.h>
20#include <TMath.h>
21#include <TParticlePDG.h>
22#include <TRandom.h>
23#include <TString.h>
24
25namespace Hal {
26
27 DecayChannel::DecayChannel(Int_t dau1, Int_t dau2, Double_t ratio) : fDaughters(2), fBranchRatio(ratio) {
28 fPdgCodes.resize(2);
29 fMass.resize(2);
30 fPdgCodes[0] = dau1;
31 fPdgCodes[1] = dau2;
32 auto pids = TDatabasePDG::Instance();
33 for (int i = 0; i < 2; i++) {
34 auto pidpart = pids->GetParticle(fPdgCodes[i]);
35 if (pidpart) {
36 fMass[i] = pidpart->Mass();
37 } else {
38 fMass[i] = 0.0;
39 Hal::Cout::Text(Form("DecayChannel: Cannot find Particle with PID %i", fPdgCodes[i]), "L", kOrange);
40 }
41 }
42 }
43
44 DecayChannel::DecayChannel(Int_t dau1, Int_t dau2, Int_t dau3, Double_t ratio) : fDaughters(3), fBranchRatio(ratio) {
45 fPdgCodes.resize(3);
46 fMass.resize(3);
47 fPdgCodes[0] = dau1;
48 fPdgCodes[1] = dau2;
49 fPdgCodes[2] = dau3;
50 auto pids = TDatabasePDG::Instance();
51 for (int i = 0; i < 3; i++) {
52 auto pidpart = pids->GetParticle(fPdgCodes[i]);
53 if (pidpart) {
54 fMass[i] = pidpart->Mass();
55 } else {
56 fMass[i] = 0.0;
57 Hal::Cout::Text(Form("DecayChannel: Cannot find Particle with PID %i", fPdgCodes[i]), "L", kOrange);
58 }
59 }
60 }
61
62 Bool_t DecayChannel::Init() {
63 for (auto m : fMass) {
64 fMassThres += m;
65 }
66 return kTRUE;
67 }
68
69 Decay::Decay(Int_t motherPdg) {
70 fMotherPdg = motherPdg;
71 auto pids = TDatabasePDG::Instance();
72 auto pidpart = pids->GetParticle(fMotherPdg);
73 if (pidpart) { fMotherMass = pidpart->Mass(); }
74 }
75
76 Double_t Decay::GetDecayTime(McTrack& mother, Double_t mass) const {
77 auto mP = mother.GetMomentum();
78 if (fGamma == 0) { return 1E+10; }
79 double tTau0 = mP.E() / (mass * fGamma);
80 // When it decays
81 return -tTau0 * TMath::Log(gRandom->Rndm());
82 }
83
84 void Decay::Decay2Body(McTrack& mother, std::vector<McTrack*>& daughters, const DecayChannel& channel) const {
85 Double_t M = fMotherMass;
86 if (fBreightWigher) { M = GetDecayTime(mother, fMotherMass); }
87 if (M < channel.GetMassThreshold()) { M = channel.GetMassThreshold(); }
88 Double_t tTime = GetDecayTime(mother, M);
89
90 const TLorentzVector& mP = mother.GetMomentum();
91 const TLorentzVector& mX = mother.GetFreezoutPosition();
92 Int_t pdg1 = channel.GetDaughterPdg(0);
93 Int_t pdg2 = channel.GetDaughterPdg(1);
94 Double_t m1 = channel.GetDaughterMass(0);
95 Double_t m2 = channel.GetDaughterMass(1);
96 // Decay posistion
97 TVector3 boost = mP.BoostVector();
98 Double_t X = mX.X() + boost.X() * tTime;
99 Double_t Y = mX.Y() + boost.Y() * tTime;
100 Double_t Z = mX.Z() + boost.Z() * tTime;
101 Double_t T = mX.T() + tTime;
102
103 Double_t tMC1 = (M * M - (m1 + m2) * (m1 + m2));
104 Double_t tMC2 = (M * M - (m1 - m2) * (m1 - m2));
105 Double_t tMom = TMath::Sqrt(tMC1 * tMC2) / (2 * M);
106
107 Double_t px1, py1, pz1;
108 Double_t px2, py2, pz2;
109 gRandom->Sphere(px1, py1, pz1, tMom);
110 px2 = -px1;
111 py2 = -py1;
112 pz2 = -pz1;
113 TLorentzVector dau1, dau2;
114 dau1.SetPxPyPzE(px1, py1, pz1, TMath::Sqrt(tMom * tMom + m1 * m1));
115 dau2.SetPxPyPzE(px2, py2, pz2, TMath::Sqrt(tMom * tMom + m2 * m2));
116 dau1.Boost(boost);
117 dau2.Boost(boost);
118 auto& daughter1 = daughters[0];
119 auto& daughter2 = daughters[1];
120 daughter1->SetMotherIndex(mother.GetThisID());
121 daughter2->SetMotherIndex(mother.GetThisID());
122 daughter1->SetPdg(pdg1);
123 daughter2->SetPdg(pdg2);
124 daughter1->SetMomentum(dau1.X(), dau1.Y(), dau1.Z(), dau1.T());
125 daughter2->SetMomentum(dau2.X(), dau2.Y(), dau2.Z(), dau2.T());
126 daughter1->SetFreezoutPosition(X, Y, Z, T);
127 daughter2->SetFreezoutPosition(X, Y, Z, T);
128 }
129
130 void Decay::Decay3Body(McTrack& mother, std::vector<McTrack*>& daughters, const DecayChannel& channel) const {
131 Double_t tE = mother.GetMomentum().E();
132 Double_t tM1 = channel.GetDaughterMass(0);
133 Double_t tM2 = channel.GetDaughterMass(1);
134 Double_t tM3 = channel.GetDaughterMass(2);
135 Double_t M = fMotherMass;
136 if (fBreightWigher) { M = GetDecayTime(mother, fMotherMass); }
137 if (M < channel.GetMassThreshold()) { M = channel.GetMassThreshold(); }
138 Double_t tTime = GetDecayTime(mother, M);
139 // Father mass via BreitWigner
140 Double_t tES1, tES2, tP1, tP2, tCos12, tZ;
141 do {
142 // Generate E1 and E2 with the Monte-Carlo method
143 do {
144 tES1 = gRandom->Rndm() * (M - tM2 - tM3 - tM1) + tM1;
145 tES2 = gRandom->Rndm() * (M - tM1 - tM3 - tM2) + tM2;
146 } while (tES1 + tES2 > M); // The sum of both energies must be smaller than the resonance mass
147 tP1 = TMath::Sqrt(tES1 * tES1 - tM1 * tM1);
148 tP2 = TMath::Sqrt(tES2 * tES2 - tM2 * tM2);
149 tZ = M - tES1 - tES2;
150 tZ *= tZ;
151 tCos12 = (tZ - tP1 * tP1 - tP2 * tP2 - tM3 * tM3) / (2 * tP1 * tP2);
152 } while ((tCos12 < -1.0) || (tCos12 > 1.0)); // Cos Theta must exist (be within -1.0 to 1.0 )
153
154
155 auto& momP = mother.GetMomentum();
156 auto& momX = mother.GetFreezoutPosition();
157 // Decay coordinates
158 Double_t X = momX.X() + (momP.Px() / tE) * tTime;
159 Double_t Y = momX.Y() + (momP.Py() / tE) * tTime;
160 Double_t Z = momX.Z() + (momP.Pz() / tE) * tTime;
161 Double_t T = momX.T() + tTime;
162
163 Double_t tPxr2 = tP2 * TMath::Sqrt(1 - tCos12 * tCos12);
164 Double_t tPzr2 = tP2 * tCos12;
165 Double_t tPxr3 = -tPxr2;
166 Double_t tPzr3 = -(tP1 + tPzr2);
167 Double_t tP3 = TMath::Hypot(tPxr3, tPzr3);
168 Double_t tES3 = TMath::Hypot(tM3, tP3);
169
170 // Generating Euler angles
171 Double_t tPhi = gRandom->Rndm() * 2 * TMath::Pi();
172 Double_t tKsi = gRandom->Rndm() * 2 * TMath::Pi();
173 Double_t tCosTh = gRandom->Rndm() * 2.0 - 1.0;
174
175 Double_t sp = TMath::Sin(tPhi);
176 Double_t cp = TMath::Cos(tPhi);
177 Double_t sk = TMath::Sin(tKsi);
178 Double_t ck = TMath::Cos(tKsi);
179 Double_t st = TMath::Sqrt(1.0 - tCosTh * tCosTh);
180 Double_t ct = tCosTh;
181
182 // Rotating the whole system
183 Double_t tPxp1 = -st * ck * tP1;
184 Double_t tPyp1 = st * sk * tP1;
185 Double_t tPzp1 = ct * tP1;
186
187 Double_t tPxp2 = (cp * ct * ck - sp * sk) * tPxr2 + (-st * ck) * tPzr2;
188 Double_t tPyp2 = (-cp * ct * sk - sp * ck) * tPxr2 + (st * sk) * tPzr2;
189 Double_t tPzp2 = cp * st * tPxr2 + ct * tPzr2;
190
191 Double_t tPxp3 = (cp * ct * ck - sp * sk) * tPxr3 + (-st * ck) * tPzr3;
192 Double_t tPyp3 = (-cp * ct * sk - sp * ck) * tPxr3 + (st * sk) * tPzr3;
193 Double_t tPzp3 = cp * st * tPxr3 + ct * tPzr3;
194 TVector3 boost = momP.BoostVector();
195
196 tES1 = TMath::Sqrt(tM1 * tM1 + tPxp1 * tPxp1 + tPyp1 * tPyp1 + tPzp1 * tPzp1);
197 tES2 = TMath::Sqrt(tM2 * tM2 + tPxp2 * tPxp2 + tPyp2 * tPyp2 + tPzp2 * tPzp2);
198 tES3 = TMath::Sqrt(tM3 * tM3 + tPxp3 * tPxp3 + tPyp3 * tPyp3 + tPzp3 * tPzp3);
199
200 TLorentzVector p1, p2, p3;
201 p1.SetPxPyPzE(tPxp1, tPyp1, tPzp1, tES1);
202 p2.SetPxPyPzE(tPxp2, tPyp2, tPzp2, tES2);
203 p3.SetPxPyPzE(tPxp3, tPyp3, tPzp3, tES3);
204 p1.Boost(boost);
205 p2.Boost(boost);
206 p3.Boost(boost);
207
208 auto& daughter1 = daughters[0];
209 auto& daughter2 = daughters[1];
210 auto& daughter3 = daughters[2];
211 daughter1->SetMotherIndex(mother.GetThisID());
212 daughter2->SetMotherIndex(mother.GetThisID());
213 daughter3->SetMotherIndex(mother.GetThisID());
214 daughter1->SetPdg(channel.GetDaughterPdg(0));
215 daughter2->SetPdg(channel.GetDaughterPdg(1));
216 daughter3->SetPdg(channel.GetDaughterPdg(2));
217 daughter1->SetMomentum(p1.X(), p1.Y(), p1.Z(), p1.T());
218 daughter2->SetMomentum(p2.X(), p2.Y(), p2.Z(), p2.T());
219 daughter3->SetMomentum(p3.X(), p3.Y(), p3.Z(), p3.T());
220 daughter1->SetFreezoutPosition(X, Y, Z, T);
221 daughter2->SetFreezoutPosition(X, Y, Z, T);
222 daughter3->SetFreezoutPosition(X, Y, Z, T);
223 }
224
225 Int_t Decay::DecayParticle(McTrack& mother, std::vector<McTrack*>& daughters, Bool_t addToEvent) const {
229 Double_t val = gRandom->Uniform();
230 Int_t chan = 0;
231 while (val > fDecayChannels[chan].GetBranchingRatio()) {
232 chan++;
233 }
234 auto decay = fDecayChannels[chan];
235 Int_t daughtersNo = decay.GetDaughtersNo();
236 if (daughtersNo <= 0) {
237 Hal::Cout::PrintInfo("Decay::DecayParitcle this number of channels not supported", EInfo::kError);
238 return -1;
239 }
240 if (daughtersNo == 2) {
241 Decay2Body(mother, daughters, decay);
242 } else if (daughtersNo == 3) {
243 Decay3Body(mother, daughters, decay);
244 }
245 if (addToEvent) {
246 McEvent* event = (McEvent*) mother.GetEvent();
247 for (int i = 0; i < daughtersNo; i++) {
248 int tracks = event->GetTotalTrackNo();
249 McTrack* to = (McTrack*) event->AddTrack();
250 McTrack* from = daughters[i];
251 from->SetThisID(tracks);
252 from->SetEvent(event);
253 to->CopyAllData(from);
254 }
255 }
256
257 return daughtersNo;
258 }
259
260 Bool_t Decay::Init() {
261 if (fDecayChannels.size() == 0) return kFALSE;
262 Double_t branchSum = 0;
263 for (auto& d : fDecayChannels) {
264 if (!d.Init()) return kFALSE;
265 }
266 for (auto d : fDecayChannels) {
267 branchSum += d.GetBranchingRatio();
268 }
269 for (auto& d : fDecayChannels) {
270 d.SetBranchRatio(d.GetBranchingRatio() / branchSum);
271 }
272 branchSum = 0;
273 for (auto& d : fDecayChannels) {
274 branchSum += d.GetBranchingRatio();
275 d.SetBranchRatio(branchSum);
276 }
277 fDecayChannels[fDecayChannels.size() - 1].SetBranchRatio(1.1); // additional crosscheck
278 auto pids = TDatabasePDG::Instance();
279 auto pidpart = pids->GetParticle(fMotherPdg);
280 if (!pidpart) return kFALSE;
281 fMotherMass = pidpart->Mass();
282 return kTRUE;
283 }
284} // namespace Hal
static void Text(TString text, TString option="L", Color_t color=-1)
Definition Cout.cxx:92
static void PrintInfo(TString text, Hal::EInfo status)
Definition Cout.cxx:370
DecayChannel(Int_t dau1=0, Int_t dau2=0, Double_t ratio=0.0)
Definition Decay.cxx:27
virtual Int_t DecayParticle(McTrack &mother, std::vector< McTrack * > &daughters, Bool_t addToEvent=kFALSE) const
Definition Decay.cxx:225
Decay(Int_t motherPdg=-1)
Definition Decay.cxx:69
virtual Bool_t Init()
Definition Decay.cxx:260
void SetThisID(Int_t id)
Definition Track.h:78
Event * GetEvent() const
Definition Track.h:315
const TLorentzVector & GetMomentum() const
Definition Track.h:118
void SetEvent(Event *event)
Definition Track.h:337
virtual void CopyAllData(Track *other)
Definition Track.cxx:60