CbmRoot
Loading...
Searching...
No Matches
CbmEventGenerator.cxx
Go to the documentation of this file.
1/* Copyright (C) 2019-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Volker Friese [committer] */
4
9
10#include "CbmEventGenerator.h"
11
12#include "CbmBeam.h"
13
14#include <FairGenericStack.h>
15#include <FairMCEventHeader.h>
16#include <Logger.h>
17
18#include <TDatabasePDG.h>
19#include <TMath.h>
20#include <TRandom.h>
21#include <TVector3.h>
22
23#include <cassert>
24
25using std::cerr;
26using std::cout;
27using std::endl;
28
29
30// ----- Constructor ---------------------------------------------------
32 : FairPrimaryGenerator()
33 , fBeamProfile()
34 , fTarget()
36 , fForceVertexAtZ(kFALSE)
37 , fVertexZ(0.)
38{
39 // Mother class members
40 fName = "EventGenerator";
41 fBeamAngle = kTRUE;
42}
43// -------------------------------------------------------------------------
44
45
46// ----- Destructor ----------------------------------------------------
48// -------------------------------------------------------------------------
49
50
51// ----- Add a track to the stack --------------------------------------
52// Code copied from fairroot/base/sim/FairPrimary Generator.cxx,
53// with the implementation of the beam angle rotation being modified.
54void CbmEventGenerator::AddTrack(Int_t pdgid, Double_t px_raw, Double_t py_raw, Double_t pz_raw, Double_t vx,
55 Double_t vy, Double_t vz, Int_t parent, Bool_t wanttracking, Double_t e, Double_t tof,
56 Double_t weight, TMCProcess proc)
57{
58 // ---> Add event vertex to track vertex
59 vx += fVertex.X();
60 vy += fVertex.Y();
61 vz += fVertex.Z();
62
63 TVector3 mom(px_raw, py_raw, pz_raw);
64
65 // ---> Rotate the track momentum in the transverse (x-y) plane by the event plane angle.
66 if (fEventPlane) mom.RotateZ(fPhi);
67
68 // ---> Rotate the track momentum to account for the beam direction, which may not be
69 // in the z axis. This implementation deviates from that in fairroot, where TVector3::RotateUz() is used.
70 // We found this to behave wrongly and use here TVector3::Rotate() instead.
71 if (fBeamAngle) {
72 TVector3 axis(-fBeamDirection.Unit().Y(), fBeamDirection.Unit().X(), 0);
73 auto angle = TMath::ACos(fBeamDirection.Unit().Z());
74 mom.Rotate(angle, axis);
75 }
76
77 // ---> Convert K0 and AntiK0 into K0s and K0L (random decision with equal probability)
78 if (pdgid == 311 || pdgid == -311) {
79 Double_t test = gRandom->Uniform(0., 1.);
80 if (test >= 0.5) {
81 pdgid = 310;
82 } // K0S
83 else {
84 pdgid = 130;
85 } // K0L
86 }
87
88 // ---> Check whether particle type is in PDG Database
89 TDatabasePDG* pdgBase = TDatabasePDG::Instance();
90 if (!pdgBase) {
91 Fatal("CbmEventGenerator", "No TDatabasePDG instantiated");
92 }
93 else {
94 TParticlePDG* pdgPart = pdgBase->GetParticle(pdgid);
95 if (!pdgPart) {
96 if (e < 0) {
97 cerr << "\033[5m\033[31m -E CbmEventGenerator: PDG code " << pdgid << " not found in database.\033[0m " << endl;
98 cerr << "\033[5m\033[31m -E CbmEventGenerator: Discarding particle "
99 "\033[0m "
100 << endl;
101 cerr << "\033[5m\033[31m -E CbmEventGenerator: now MC Index is "
102 "corrupted \033[0m "
103 << endl;
104 return;
105 }
106 else {
107 cout << "\033[5m\033[31m -W CbmEventGenerator: PDG code " << pdgid
108 << " not found in database. This warning can be savely "
109 "ignored.\033[0m "
110 << endl;
111 }
112 }
113 }
114 // ---> Get mass and calculate energy of particle
115 if (e < 0) {
116 Double_t mass = pdgBase->GetParticle(pdgid)->Mass();
117 e = TMath::Sqrt(mom.Mag2() + mass * mass);
118 } // else, use the value of e given to the function
119
120 // ---> Set all other parameters required by PushTrack
121 Int_t doTracking = 0; // Go to tracking
122 if (fdoTracking && wanttracking) {
123 doTracking = 1;
124 }
125 Int_t dummyparent = -1; // Primary particle (now the value is -1 by default)
126 Double_t polx = 0.; // Polarisation
127 Double_t poly = 0.;
128 Double_t polz = 0.;
129 Int_t ntr = 0; // Track number; to be filled by the stack
130 Int_t status = 0; // Generation status
131
132 if (parent != -1) {
133 parent += fMCIndexOffset;
134 } // correct for tracks which are in list before generator is called
135 // Add track to stack
136 fStack->PushTrack(doTracking, dummyparent, pdgid, mom.X(), mom.Y(), mom.Z(), e, vx, vy, vz, tof, polx, poly, polz,
137 proc, ntr, weight, status, parent);
138 fNTracks++;
139}
140// -------------------------------------------------------------------------
141
142
143// ----- Force vertex at a given z position ----------------------------
145{
146 fForceVertexAtZ = kTRUE;
147 fForceVertexInTarget = kFALSE;
148 fVertexZ = zVertex;
149}
150// -------------------------------------------------------------------------
151
152
153// ----- Generate the input event --------------------------------------
155{
156
157 std::cout << std::endl;
158 LOG(info) << GetName() << ": Generate event " << ++fEventNr;
159
160 // An MCEventHeader must be present
161 assert(fEvent);
162
163 // Set the stack
164 assert(stack);
165 fStack = stack;
166
167 // Reset MCEventHeader and track counter
168 fEvent->Reset();
169 fNTracks = 0;
170
171 // Generate the event vertex and the beam angle
172 MakeVertex();
173
174 // Generate the event plane angle
175 if (fEventPlane) {
176 MakeEventPlane();
177 LOG(info) << GetName() << ": Rotate event by " << fPhi << " rad";
178 }
179
180 // Call the registered generator classes
181 fListIter->Reset();
182 TObject* item = nullptr;
183 while ((item = fListIter->Next())) {
184 FairGenerator* generator = dynamic_cast<FairGenerator*>(item);
185 assert(generator);
186 fMCIndexOffset = fNTracks; // Number of tracks before call of generator
187 if (!generator->ReadEvent(this)) {
188 LOG(info) << GetName() << ": ReadEvent failed for generator " << generator->GetName();
189 return kFALSE;
190 }
191 }
192
193 // Update event header
194 if (!fEvent->IsSet()) fEvent->SetEventID(fEventNr);
195 fEvent->SetNPrim(fNTracks);
196 fEvent->SetVertex(fVertex);
197 fEvent->SetRotX(fBeamAngleX);
198 fEvent->SetRotY(fBeamAngleY);
199 Double_t phiGen = fEvent->GetRotZ(); // from concrete generators
200 fEvent->SetRotZ(phiGen + fPhi); // total event plane angle
201 // Event info to screen
202 LOG(info) << GetName() << ": Event ID " << fEvent->GetEventID() << ", tracks " << fNTracks << ", vertex ("
203 << fVertex.X() << ", " << fVertex.Y() << ", " << fVertex.Z() << ") cm";
204 LOG(info) << GetName() << ": Beam angle (" << fBeamAngleX << ", " << fBeamAngleY << ") rad, event plane angle "
205 << fPhi << " rad (total " << fEvent->GetRotZ() << " rad) change";
206
207 // Update global track counter (who knows what it's good for ...)
208 fTotPrim += fNTracks;
209
210 return kTRUE;
211}
212// -------------------------------------------------------------------------
213
214
215// ----- Generate event vertex -----------------------------------------
217{
218 if (fForceVertexAtZ) {
220 }
221 else if (fForceVertexInTarget && fTarget) {
223 }
224 else {
226 }
227}
228// -------------------------------------------------------------------------
229
230
231// ----- Generate event vertex in the beam focal plane -----------------
233{
234
235 std::unique_ptr<CbmBeam> beam;
236 beam = fBeamProfile.GenerateBeam();
237 TVector3 point(0., 0., fVertexZ);
238 TVector3 norm(0, 0., 1.);
239 fVertex = beam->ExtrapolateToPlane(point, norm);
240 fBeamAngleX = beam->GetThetaX();
241 fBeamAngleY = beam->GetThetaY();
242 fBeamDirection = beam->GetDirection();
243}
244// -------------------------------------------------------------------------
245
246
247// ----- Generate event vertex in the beam focal plane -----------------
249{
250
251 std::unique_ptr<CbmBeam> beam;
252 beam = fBeamProfile.GenerateBeam();
253 fVertex = beam->GetPosition();
254 fBeamAngleX = beam->GetThetaX();
255 fBeamAngleY = beam->GetThetaY();
256 fBeamDirection = beam->GetDirection();
257}
258// -------------------------------------------------------------------------
259
260
261// ----- Generate event vertex -----------------------------------------
263{
264
265 assert(fTarget);
266
267 // Target surface centres and normal vector
268 TVector3 surf1 = fTarget->GetSurfaceCentreUp();
269 TVector3 surf2 = fTarget->GetSurfaceCentreDown();
270 TVector3 norm = fTarget->GetNormal();
271
272 // Declare some vectors
273 TVector3 point1; // Intersection of beam with first target surface
274 TVector3 point2; // Intersection of beam with second target surface
275
276 // It is possible that a generated beam trajectory misses the target.
277 // In that case, the beam will be re-sampled until it hits the target.
278 Bool_t isInTarget = kFALSE;
279 Int_t nSamples = 0;
280 std::unique_ptr<CbmBeam> beam;
281 while (!isInTarget) {
282
283 // Abort if too many beam samples
284 if (nSamples > 1000.)
285 LOG(fatal) << GetName() << ": Aborting after " << nSamples << " beam samplings. Adjust beam and target.";
286
287 // Sample a beam trajectory
288 beam = fBeamProfile.GenerateBeam();
289 nSamples++;
290
291 // Intersections of beam trajectory with target surfaces
292 point1 = beam->ExtrapolateToPlane(surf1, norm);
293 point2 = beam->ExtrapolateToPlane(surf2, norm);
294
295 // Check whether both intersections are inside the target
296 // (i.e., the beam crosses both target surfaces)
297 Bool_t check1 = ((point1 - surf1).Mag() < 0.5 * fTarget->GetDiameter());
298 Bool_t check2 = ((point2 - surf2).Mag() < 0.5 * fTarget->GetDiameter());
299 isInTarget = check1 && check2;
300
301 } //? Beam not in target
302
303 LOG(debug) << beam->ToString() << ", generated after " << nSamples << (nSamples > 1 ? " samplings: " : " sampling");
304
305 // Sample a point between entry and exit of beam in target
306 Double_t scale = 0.5;
307 if (fSmearVertexZ) scale = gRandom->Uniform();
308 fVertex = point1 + scale * (point2 - point1);
309
310 // Set the beam angles (member variables of base class)
311 fBeamAngleX = beam->GetThetaX();
312 fBeamAngleY = beam->GetThetaY();
313 fBeamDirection = beam->GetDirection();
314}
315// -------------------------------------------------------------------------
316
317
318// ----- Info ----------------------------------------------------------
319void CbmEventGenerator::Print(Option_t*) const
320{
321 LOG(info) << fBeamProfile.ToString();
322 if (fTarget) LOG(info) << fTarget->ToString();
323 LOG(info) << "Vertex smearing along beam " << (fSmearVertexZ ? "ON" : "OFF");
324 if (fEventPlane) {
325 LOG(info) << "Random event plane angle between " << fPhiMin << " and " << fPhiMax << " rad";
326 }
327 else {
328 LOG(info) << "Fixed event plane angle = 0";
329 }
330 LOG(info) << "Number of generators " << fGenList->GetEntries();
331 for (Int_t iGen = 0; iGen < fGenList->GetEntries(); iGen++) {
332 fGenList->At(iGen)->Print();
333 }
334}
335// -------------------------------------------------------------------------
336
337
338// ----- Set beam angle ------------------------------------------------
339void CbmEventGenerator::SetBeamAngle(Double_t meanThetaX, Double_t meanThetaY, Double_t sigmaThetaX,
340 Double_t sigmaThetaY)
341{
342 fBeamProfile.SetAngle(meanThetaX, meanThetaY, sigmaThetaX, sigmaThetaY);
343}
344// -------------------------------------------------------------------------
345
346
347// ----- Set beam position ---------------------------------------------
348void CbmEventGenerator::SetBeamPosition(Double_t meanX, Double_t meanY, Double_t sigmaX, Double_t sigmaY, Double_t zF)
349{
350 fBeamProfile.SetPosition(meanX, meanY, sigmaX, sigmaY, zF);
351}
352// -------------------------------------------------------------------------
353
354
ClassImp(CbmConverterManager)
int Int_t
bool Bool_t
CbmEventGenerator.
virtual void Print(Option_t *opt="") const
Log output.
virtual Bool_t GenerateEvent(FairGenericStack *stack)
Generate the input event.
Double_t fVertexZ
forced z coordinate of event vertex
void SetBeamAngle(Double_t meanThetaX, Double_t meanThetaY, Double_t sigmaThetaX=-1., Double_t sigmaThetaY=-1.)
Set the beam angle in the focal plane.
CbmEventGenerator()
Default constructor.
void MakeVertexAtZ()
Generate event vertex position at a given z.
Bool_t fForceVertexInTarget
Target properties.
virtual ~CbmEventGenerator()
Destructor.
Bool_t fForceVertexAtZ
If set, vertex must be at given z.
void ForceVertexAtZ(Double_t zVertex)
Force event vertex to be at a given z.
virtual void MakeVertexInFocalPlane()
Generate event vertex position in the beam focal plane.
virtual void AddTrack(Int_t pdgid, Double_t px, Double_t py, Double_t pz, Double_t vx, Double_t vy, Double_t vz, Int_t parent=-1, Bool_t wanttracking=true, Double_t e=-9e9, Double_t tof=0., Double_t weight=0., TMCProcess proc=kPPrimary)
Add a track to the stack to be transported.
virtual void MakeVertex()
Generate event vertex position.
CbmBeamProfile fBeamProfile
Beam properties.
void SetBeamPosition(Double_t meanX, Double_t meanY, Double_t sigmaX=-1., Double_t sigmaY=-1., Double_t zF=0.)
Set the beam position in the focal plane.
std::shared_ptr< const CbmTarget > fTarget
virtual void MakeVertexInTarget()
Generate event vertex position in the target.