FairShip
Loading...
Searching...
No Matches
MuDISGenerator.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
5#include "MuDISGenerator.h"
6
7#include <cmath>
8
9#include "FairLogger.h"
10#include "FairPrimaryGenerator.h"
11#include "MeanMaterialBudget.h"
12#include "TFile.h"
13#include "TGeoCompositeShape.h"
14#include "TGeoEltu.h"
15#include "TGeoManager.h"
16#include "TGeoNode.h"
17#include "TGeoVolume.h"
18#include "TMath.h"
19#include "TROOT.h"
20#include "TRandom.h"
21#include "TSystem.h"
22#include "TVectorD.h"
23
24// MuDIS momentum GeV
25// Vertex in SI units, assume this means m
26
27const Double_t c_light = 29.9792458; // speed of light in cm/ns
28const Double_t muon_mass = 0.10565999895334244; // muon mass in GeV
29
30// ----- Default constructor -------------------------------------------
32// -------------------------------------------------------------------------
33// ----- Default constructor -------------------------------------------
34Bool_t MuDISGenerator::Init(const char* fileName) { return Init(fileName, 0); }
35Bool_t MuDISGenerator::Init(const char* fileName, const int startEvent) {
36 LOGF(info, "Opening input file %s", fileName);
37
38 iMuon = 0;
39 dPart = 0;
40 dPartSoft = 0;
41 fInputFile = TFile::Open(fileName);
42 if (!fInputFile) {
43 LOG(fatal) << "Error opening input file";
44 return kFALSE;
45 }
46 fTree = fInputFile->Get<TTree>("DIS");
47 fNevents = fTree->GetEntries();
48 fn = startEvent;
49
50 fTree->SetBranchAddress("InMuon", &iMuon); // incoming muon
51 fTree->SetBranchAddress("DISParticles", &dPart);
52 fTree->SetBranchAddress("SoftParticles",
53 &dPartSoft); // Soft interaction particles
54 LOG(info) << "MuDISGenerator: Initialization successful.";
55 return kTRUE;
56}
57
58// ----- Destructor ----------------------------------------------------
60 fInputFile->Close();
61 fInputFile->Delete();
62 delete fInputFile;
63}
64// ----- Passing the event ---------------------------------------------
65Bool_t MuDISGenerator::ReadEvent(FairPrimaryGenerator* cpg) {
66 if (fn == fNevents) {
67 LOG(warning) << "End of input file. Rewind.";
68 }
69 fTree->GetEntry(fn % fNevents);
70 fn++;
71 if (fn % 10 == 0) {
72 LOG(info) << "Info MuDISGenerator: MuDIS event-nr " << fn;
73 }
74
75 int nf = dPart->GetEntries();
76 LOG(debug) << "*********************************************************";
77 LOG(debug) << "muon DIS Generator debug " << iMuon->GetEntries() << " "
78 << iMuon->AddrAt(0) << " nf " << nf << " fn=" << fn;
79
80 // some start/end positions in z (f.i. emulsion to Tracker 1)
81 Double_t start[3] = {0., 0., startZ};
82 Double_t end[3] = {0., 0., endZ};
83
84 // incoming muon array('d',[pid,px,py,pz,E,x,y,z,w,t])
85 TVectorD* mu = dynamic_cast<TVectorD*>(iMuon->AddrAt(0));
86 LOG(debug) << "muon DIS Generator in muon " << int((*mu)[0]);
87 Double_t x = (*mu)[5] * 100.; // come in m -> cm
88 Double_t y = (*mu)[6] * 100.; // come in m -> cm
89 Double_t z = (*mu)[7] * 100.; // come in m -> cm
90 Double_t w =
91 (*mu)[8]; // weight of the original muon ( normalised to a spill)
92 Double_t cross_sec = (*mu)[10]; // in mbarns
93 Double_t t_muon = (*mu)[11]; // in ns
94 Double_t DIS_multiplicity = 1 / (*mu)[12]; // 1/nDIS
95
96 // calculate start/end positions along this muon, and amount of material in
97 // between
98
99 Double_t txmu = (*mu)[1] / (*mu)[3];
100 Double_t tymu = (*mu)[2] / (*mu)[3];
101 start[0] = x - (z - start[2]) * txmu;
102 start[1] = y - (z - start[2]) * tymu;
103 end[0] = x - (z - end[2]) * txmu;
104 end[1] = y - (z - end[2]) * tymu;
105 LOG(debug) << "MuDIS: mu xyz position " << x << ", " << y << ", " << z;
106 LOG(debug) << "MuDIS: mu pxyz position " << (*mu)[1] << ", " << (*mu)[2]
107 << ", " << (*mu)[3];
108 LOG(debug) << "MuDIS: mu weight*DISmultiplicity " << w;
109 LOG(debug) << "MuDIS: mu DIS cross section " << cross_sec;
110 LOG(debug) << "MuDIS: start position " << start[0] << ", " << start[1] << ", "
111 << start[2];
112 LOG(debug) << "MuDIS: end position " << end[0] << ", " << end[1] << ", "
113 << end[2];
114
115 Double_t bparam;
116 Double_t mparam[10];
117 bparam = shipgen::MeanMaterialBudget(start, end, mparam);
118 // loop over trajectory between start and end to pick an interaction point
119 Double_t prob2int = 0.;
120 Double_t xmu = 0.;
121 Double_t ymu = 0.;
122 Double_t zmu = 0.;
123 Int_t count = 0;
124 LOG(debug) << "Info MuDISGenerator Start prob2int while loop, bparam= "
125 << bparam << ", " << bparam * 1.e8;
126 LOG(debug) << "Info MuDISGenerator What was maximum density, mparam[7]= "
127 << mparam[7] << ", " << mparam[7] * 1.e8;
128
129 while (prob2int < gRandom->Uniform(0., 1.)) {
130 zmu = gRandom->Uniform(start[2], end[2]);
131 xmu = x - (z - zmu) * txmu;
132 ymu = y - (z - zmu) * tymu;
133 // get local material at this point
134 TGeoNode* node = gGeoManager->FindNode(xmu, ymu, zmu);
135 TGeoMaterial* mat = nullptr;
136 if (node && !gGeoManager->IsOutside())
137 mat = node->GetVolume()->GetMaterial();
138 LOG(debug) << "Info MuDISGenerator: mat " << count << ", " << mat->GetName()
139 << ", " << mat->GetDensity();
140 // density relative to Prob largest density along this trajectory, i.e. use
141 // rho(Pt)
142 prob2int = mat->GetDensity() / mparam[7];
143 if (prob2int > 1.) {
144 LOG(warning) << "MuDISGenerator: prob2int > Maximum density????";
145 LOG(warning) << "prob2int: " << prob2int;
146 LOG(warning) << "maxrho: " << mparam[7];
147 LOG(warning) << "material: " << mat->GetName();
148 }
149 count += 1;
150 }
151
152 LOG(debug) << "Info MuDISGenerator: prob2int " << prob2int << ", " << count;
153 LOG(debug) << "MuDIS: put position " << xmu << ", " << ymu << ", " << zmu;
154
155 Double_t total_mom =
156 TMath::Sqrt(TMath::Power((*mu)[1], 2) + TMath::Power((*mu)[2], 2) +
157 TMath::Power((*mu)[3], 2)); // in GeV
158
159 Double_t distance =
160 TMath::Sqrt(TMath::Power(x - xmu, 2) + TMath::Power(y - ymu, 2) +
161 TMath::Power(z - zmu, 2)); // in cm
162
163 Double_t v =
164 c_light * total_mom /
165 TMath::Sqrt(TMath::Power(total_mom, 2) + TMath::Power(muon_mass, 2));
166 Double_t t_rmu = distance / v;
167
168 // Adjust time based on the relative positions
169 if (zmu < z) {
170 t_rmu = -t_rmu;
171 }
172
173 Double_t t_DIS =
174 (t_muon + t_rmu) / 1e9; // time taken in seconds to reach [xmu,ymu,zmu]
175
176 cpg->AddTrack(static_cast<int>((*mu)[0]), // incoming muon track ()
177 (*mu)[1], (*mu)[2], (*mu)[3], xmu, ymu, zmu, -1,
178 false, // tracking disabled
179 (*mu)[4],
180 t_DIS, // shift time of the incoming muon track wrt t_muon from
181 // the input file.
182 w * DIS_multiplicity); // muon weight associated with a spill*
183 // DISmultiplicity
184
185 // outgoing DIS particles, [did,dpx,dpy,dpz,E], put density along trajectory
186 // as weight, g/cm^2
187
188 w = mparam[0] * mparam[4]; // modify weight, by multiplying with average
189 // density * track length
190 int index = 0;
191 for (auto&& particle : *dPart) {
192 TVectorD* Part = dynamic_cast<TVectorD*>(particle);
193 LOG(debug) << "muon DIS Generator out part " << int((*Part)[0]);
194 LOG(debug) << "muon DIS Generator out part mom " << (*Part)[1] << " "
195 << (*Part)[2] << " " << (*Part)[3] << " " << (*Part)[4];
196 LOG(debug) << "muon DIS Generator out part pos " << xmu << " " << ymu << ""
197 << zmu;
198 LOG(debug) << "muon DIS Generator out part w " << w;
199
200 if (index == 0) {
201 cpg->AddTrack(static_cast<int>((*Part)[0]), (*Part)[1], (*Part)[2],
202 (*Part)[3], xmu, ymu, zmu, 0, true, (*Part)[4], t_DIS,
203 cross_sec); // save DIS cross section in MCTrack[1]
204 } else {
205 cpg->AddTrack(static_cast<int>((*Part)[0]), (*Part)[1], (*Part)[2],
206 (*Part)[3], xmu, ymu, zmu, 0, true, (*Part)[4], t_DIS, w);
207 }
208 index += 1;
209 }
210
211 // Soft interaction tracks
212 for (auto&& softParticle : *dPartSoft) {
213 TVectorD* SoftPart = dynamic_cast<TVectorD*>(softParticle);
214 if ((*SoftPart)[7] > zmu) {
215 continue;
216 } // Soft interactions after the DIS point are not saved
217 Double_t t_soft = (*SoftPart)[8] / 1e9; // Time in seconds
218 cpg->AddTrack(static_cast<int>((*SoftPart)[0]), (*SoftPart)[1],
219 (*SoftPart)[2], (*SoftPart)[3], (*SoftPart)[5],
220 (*SoftPart)[6], (*SoftPart)[7], 0, true, (*SoftPart)[4],
221 t_soft, w);
222 }
223
224 return kTRUE;
225}
226// -------------------------------------------------------------------------
const Int_t debug
const Double_t c_light
const Double_t muon_mass
const Double_t c_light
~MuDISGenerator() override
Bool_t Init(const char *, int) override
Bool_t ReadEvent(FairPrimaryGenerator *) override
TClonesArray * dPartSoft
TFile * fInputFile
don't make it persistent, magic ROOT command
TClonesArray * iMuon
TClonesArray * dPart
double MeanMaterialBudget(std::span< const double, 3 > start, std::span< const double, 3 > end, std::span< double, 10 > mparam)