FairShip
Loading...
Searching...
No Matches
HNLPythia8Generator.cxx
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-3.0-or-later
2// SPDX-FileCopyrightText: Copyright CERN for the benefit of the SHiP
3// Collaboration
4
6
7#include <cmath>
8
9#include "BeamSmearingUtils.h"
10#include "FairPrimaryGenerator.h"
11#include "TDatabasePDG.h" // for TDatabasePDG
12#include "TMath.h"
13#include "TROOT.h"
14#include "TSystem.h"
15const Double_t cm = 10.; // pythia units are mm
16const Double_t mm = 1.; // pythia base unit
17const Double_t c_light = 2.99792458e+10; // speed of light in cm/sec (c_light
18 // = 2.99792458e+8 * m/s)
19const Bool_t debug = false;
20// using namespace Pythia8;
21
22// ----- Default constructor -------------------------------------------
24 fId = 2212; // proton
25 fMom = 400; // proton
26 fHNL = 9900015; // HNL pdg code
27 fLmin = 5000. * cm; // mm minimum decay position z ROOT units !
28 fLmax = 12000. * cm; // mm maximum decay position z
29 fFDs = 7.7 / 10.4; // correction for Pythia6 to match measured Ds production
30 fsmearBeam = 8 * mm; // default value for smearing beam (8 mm)
31 fPaintBeam = 5 * cm; // default value for painting beam (5 cm)
32 fInputFile = nullptr;
33 fnRetries = 0;
34 fShipEventNr = 0;
35 fPythia = new Pythia8::Pythia();
36}
37// -------------------------------------------------------------------------
38
39// ----- Default constructor -------------------------------------------
41 if (debug) {
42 List(9900015);
43 }
44 if (fUseRandom1) fRandomEngine = std::make_shared<PyTr1Rng>();
45 if (fUseRandom3) fRandomEngine = std::make_shared<PyTr3Rng>();
46 fPythia->setRndmEnginePtr(fRandomEngine);
47 fn = 0;
48 if (fextFile) {
49 fInputFile = TFile::Open(fextFile->c_str());
50 LOG(info) << "Open external file with charm or beauty hadrons: "
51 << *fextFile;
52 if (!fInputFile) {
53 LOG(fatal) << "Error opening input file.";
54 return kFALSE;
55 }
56
57 fTree = fInputFile->Get<TTree>("pythia6");
58 fNevents = fTree->GetEntries();
59 fn = firstEvent;
60 fTree->SetBranchAddress("id", &hid); // particle id
61 fTree->SetBranchAddress("px", &hpx); // momentum
62 fTree->SetBranchAddress("py", &hpy);
63 fTree->SetBranchAddress("pz", &hpz);
64 fTree->SetBranchAddress("E", &hE);
65 fTree->SetBranchAddress("M", &hM);
66 fTree->SetBranchAddress("mid", &mid); // mother
67 fTree->SetBranchAddress("mpx", &mpx); // momentum
68 fTree->SetBranchAddress("mpy", &mpy);
69 fTree->SetBranchAddress("mpz", &mpz);
70 fTree->SetBranchAddress("mE", &mE);
71 } else {
72 LOG(debug) << "Beam Momentum " << fMom;
73 fPythia->settings.mode("Beams:idA", fId);
74 fPythia->settings.mode("Beams:idB", 2212);
75 fPythia->settings.mode("Beams:frameType", 2);
76 fPythia->settings.parm("Beams:eA", fMom); // codespell:ignore parm
77 fPythia->settings.parm("Beams:eB", 0.); // codespell:ignore parm
78 }
79 TDatabasePDG* pdgBase = TDatabasePDG::Instance();
80 Double_t root_ctau = pdgBase->GetParticle(fHNL)->Lifetime();
81 fctau = fPythia->particleData.tau0(fHNL); //* 3.3333e-12
82 LOG(debug) << "tau root " << root_ctau
83 << "[s] ctau root = " << root_ctau * 3e10 << "[cm]";
84 LOG(debug) << "ctau pythia " << fctau << "[mm]";
85 if (debug) {
86 List(9900015);
87 }
88 fPythia->init();
89 return kTRUE;
90}
91// -------------------------------------------------------------------------
92
93// ----- Destructor ----------------------------------------------------
95// -------------------------------------------------------------------------
96
97// ----- Passing the event ---------------------------------------------
98Bool_t HNLPythia8Generator::ReadEvent(FairPrimaryGenerator* cpg) {
99 Double_t tp, tS, zp, xp, yp, zS, xS, yS, pz, px, py, e, w;
100 Double_t tm, zm, xm, ym, pmz, pmx, pmy, em;
101 Int_t im;
102 // take HNL decay of Pythia, move it to the SHiP decay region
103 // recalculate decay time
104 // weight event with exp(-t_ship/tau_HNL) / exp(-t_pythia/tau_HNL)
105
106 int iHNL = 0; // index of the chosen HNL (the 1st one), also ensures that at
107 // least 1 HNL is produced
108 std::vector<int>
109 dec_chain; // pythia indices of the particles to be stored on the stack
110 std::vector<int> hnls; // pythia indices of HNL particles
111 do {
112 if (fextFile) {
113 // take charm or beauty hadron from external file
114 // correct for too much Ds produced by pythia6
115 bool x = true;
116 while (x) {
117 if (fn == fNevents) {
118 LOG(warning) << "End of input file. Rewind.";
119 }
120 fTree->GetEntry(fn % fNevents);
121 fn++;
122 if (static_cast<int>(fabs(hid[0])) != 431) {
123 x = false;
124 } else {
125 Double_t rnr = gRandom->Uniform(0, 1);
126 if (rnr < fFDs) {
127 x = false;
128 };
129 // cout<<"what is x "<<x<<" id "<<int(fabs(hid[0]))<<" rnr " << rnr
130 // <<" "<< fFDs <<std::endl ;
131 }
132 }
133 fPythia->event.reset();
134 fPythia->event.append((Int_t)hid[0], 1, 0, 0, hpx[0], hpy[0], hpz[0],
135 hE[0], hM[0], 0., 9.);
136 }
137 fPythia->next();
138 for (int i = 0; i < fPythia->event.size(); i++) {
139 // find first HNL
140 if (abs(fPythia->event[i].id()) == fHNL) {
141 hnls.push_back(i);
142 }
143 }
144 iHNL = hnls.size();
145 if (iHNL == 0) {
146 // fLogger->Info(MESSAGE_ORIGIN,"Event without HNL. Retry.");
147 // fPythia->event.list();
148 fnRetries += 1; // can happen if phasespace does not allow charm hadron
149 // to decay to HNL
150 } else {
151 int r = static_cast<int>(gRandom->Uniform(0, iHNL));
152 // cout << " ----> debug 2 " << r << endl;
153 int i = hnls[r];
154 // production vertex
155 zp = fPythia->event[i].zProd();
156 xp = fPythia->event[i].xProd();
157 yp = fPythia->event[i].yProd();
158 tp = fPythia->event[i].tProd();
159 // momentum
160 pz = fPythia->event[i].pz();
161 px = fPythia->event[i].px();
162 py = fPythia->event[i].py();
163 e = fPythia->event[i].e();
164 // new decay vertex
165 Double_t LS = gRandom->Uniform(fLmin, fLmax); // mm, G4 and Pythia8 units
166 Double_t p = TMath::Sqrt(px * px + py * py + pz * pz);
167 Double_t lam = LS / p;
168 xS = xp + lam * px;
169 yS = yp + lam * py;
170 zS = zp + lam * pz;
171 Double_t gam = e / TMath::Sqrt(e * e - p * p);
172 Double_t beta = p / e;
173 tS = tp + LS / beta; // units ? [mm/c] + [mm/beta] (beta is dimensionless
174 // speed, and c=1 here) if one would use [s], then
175 // tS = tp/(cm*c_light) + (LS/cm)/(beta*c_light) =
176 // tS/(cm*c_light) i.e. units look consistent
177 w = TMath::Exp(-LS / (beta * gam * fctau)) *
178 ((fLmax - fLmin) / (beta * gam * fctau));
179 im = (Int_t)fPythia->event[i].mother1();
180 zm = fPythia->event[im].zProd();
181 xm = fPythia->event[im].xProd();
182 ym = fPythia->event[im].yProd();
183 pmz = fPythia->event[im].pz();
184 pmx = fPythia->event[im].px();
185 pmy = fPythia->event[im].py();
186 em = fPythia->event[im].e();
187 tm = fPythia->event[im].tProd();
188 // foresee finite beam size
189 auto [dx, dy] = CalculateBeamOffset(fsmearBeam, fPaintBeam);
190 if (fextFile) {
191 // take grand mother particle from input file, to know if primary or
192 // secondary production
193 cpg->AddTrack((Int_t)mid[0], mpx[0], mpy[0], mpz[0], xm / cm + dx / cm,
194 ym / cm + dy / cm, zm / cm, -1, false, mE[0], 0., 1.);
195 cpg->AddTrack(
196 (Int_t)fPythia->event[im].id(), pmx, pmy, pmz, xm / cm + dx / cm,
197 ym / cm + dy / cm, zm / cm, 0, false, em, tm / cm / c_light,
198 w); // convert pythia's (x,y,z[mm], t[mm/c]) to ([cm], [s])
199 cpg->AddTrack(fHNL, px, py, pz, xp / cm + dx / cm, yp / cm + dy / cm,
200 zp / cm, 1, false, e, tp / cm / c_light, w);
201 } else {
202 cpg->AddTrack(
203 (Int_t)fPythia->event[im].id(), pmx, pmy, pmz, xm / cm + dx / cm,
204 ym / cm + dy / cm, zm / cm, -1, false, em, tm / cm / c_light,
205 w); // convert pythia's (x,y,z[mm], t[mm/c]) to ([cm], [s])
206 cpg->AddTrack(fHNL, px, py, pz, xp / cm + dx / cm, yp / cm + dy / cm,
207 zp / cm, 0, false, e, tp / cm / c_light, w);
208 }
209 // bookkeep the indices of stored particles
210 dec_chain.push_back(im);
211 dec_chain.push_back(i);
212 // cout << endl << " insert mother pdg=" <<fPythia->event[im].id() << "
213 // pmz = " << pmz << " [GeV], zm = " << zm << " [mm] tm = " << tm << "
214 // [mm/c]" << endl; cout << " ----> insert HNL =" << fHNL << " pz = " <<
215 // pz << " [GeV] zp = " << zp << " [mm] tp = " << tp << " [mm/c]" << endl;
216 iHNL = i;
217 }
218 } while (iHNL ==
219 0); // ----------- avoid rare empty events w/o any HNL's produced
220
221 if (fShipEventNr % 100 == 0) {
222 LOGF(info, "ship event %i / pythia event-nr %i", fShipEventNr, fn);
223 }
224 fShipEventNr += 1;
225 // fill a container with pythia indices of the HNL decay chain
226 for (int k = 0; k < fPythia->event.size(); k++) {
227 // if daughter of HNL, copy
228 im = fPythia->event[k].mother1();
229 while (im > 0) {
230 if (im == iHNL) {
231 break;
232 } // pick the decay products of only 1 chosen HNL
233 // if ( abs(fPythia->event[im].id())==fHNL && im == iHNL ){break;}
234 else {
235 im = fPythia->event[im].mother1();
236 }
237 }
238 if (im < 1) {
239 continue;
240 }
241 dec_chain.push_back(k);
242 }
243
244 // go over daughters and store them on the stack, starting from 2 to account
245 // for HNL and its mother
246 for (std::vector<int>::iterator it = dec_chain.begin() + 2;
247 it != dec_chain.end(); ++it) {
248 // pythia index of the particle to store
249 int k = *it;
250 // find mother position on the output stack: impy -> im
251 int impy = fPythia->event[k].mother1();
252 std::vector<int>::iterator itm =
253 std::find(dec_chain.begin(), dec_chain.end(), impy);
254 im = -1; // safety
255 if (itm != dec_chain.end())
256 im = itm - dec_chain.begin(); // convert iterator into sequence number
257
258 Bool_t wanttracking = false;
259 if (fPythia->event[k].isFinal()) {
260 wanttracking = true;
261 }
262 pz = fPythia->event[k].pz();
263 px = fPythia->event[k].px();
264 py = fPythia->event[k].py();
265 e = fPythia->event[k].e();
266 if (fextFile) {
267 im += 1;
268 }
269 cpg->AddTrack((Int_t)fPythia->event[k].id(), px, py, pz, xS / cm, yS / cm,
270 zS / cm, im, wanttracking, e, tS / cm / c_light, w);
271 // std::cout <<k<< " insert pdg =" <<fPythia->event[k].id() << " pz = " <<
272 // pz << " [GeV] zS = " << zS << " [mm] tS = " << tS << "[mm/c]" << endl;
273 }
274 return kTRUE;
275}
276// -------------------------------------------------------------------------
278 // Set Parameters
279 fPythia->readString(par);
280 LOG(debug) << "fPythia->readString(\"" << par << "\")";
281}
282
283// -------------------------------------------------------------------------
std::pair< Double_t, Double_t > CalculateBeamOffset(Double_t smearBeam, Double_t paintBeam)
const Int_t debug
const Double_t c_light
const Double_t cm
const Double_t mm
const Double_t c_light
const Bool_t debug
Double_t cm
Double_t mm
TTree * fTree
pointer to a file
Bool_t ReadEvent(FairPrimaryGenerator *) override
Bool_t Init() override
std::shared_ptr< Pythia8::RndmEngine > fRandomEngine
Pythia8::Pythia * fPythia
std::optional< std::string > fextFile
Definition: Generator.h:47
Int_t firstEvent
Definition: Generator.h:48