CbmRoot
Loading...
Searching...
No Matches
CbmUnigenGenerator.cxx
Go to the documentation of this file.
1/* Copyright (C) 2006-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Dmytro Kresan [committer], Volker Friese */
4
13#include "CbmUnigenGenerator.h"
14
15#include "FairMCEventHeader.h"
16#include "FairPrimaryGenerator.h"
17#include "FairRunSim.h"
18#include <Logger.h>
19
20#include "TFile.h"
21#include "TRandom.h"
22#include "TTree.h"
23#include "TVector3.h"
24
25#include <cassert>
26#include <sstream>
27
28#include "UEvent.h"
29#include "UParticle.h"
30#include "URun.h"
31
32
33// ----- Constructor ----------------------------------------------------
35 : FairGenerator("UnigenGenerator", "CBM generator")
36 , fFileName(fileName)
37 , fMode(mode)
38{
39 LOG(debug) << GetName() << ": Constructor";
40 if (mode == kRotateFixed)
41 LOG(fatal) << GetName() << ": When choosing "
42 << "mode kRotateFixed, a rotation angle must be specified!";
43 if (fileName[0] == '\0') return;
44 if (!Init()) LOG(fatal) << GetName() << ": Error in intialisation! Aborting...";
45}
46// --------------------------------------------------------------------------
47
48
49// ----- Constructor ----------------------------------------------------
50CbmUnigenGenerator::CbmUnigenGenerator(const char* fileName, EMode mode, Double_t phi)
51 : FairGenerator("UnigenGenerator", "CBM generator")
52 , fFileName(fileName)
53 , fMode(mode)
54 , fPhi(phi)
55{
56 LOG(debug) << GetName() << ": Constructor";
57 if (fileName[0] == '\0') return;
58 if (!Init()) LOG(fatal) << GetName() << ": Error in intialisation! Aborting...";
59}
60// --------------------------------------------------------------------------
61
62
63// ----- Destructor -----------------------------------------------------
65{
66 LOG(debug) << GetName() << ": Destructor";
67 CloseInput();
68 if (fEvent) delete fEvent;
69}
70// --------------------------------------------------------------------------
71
72
73// ----- Add a primary to the event generator ---------------------------
74void CbmUnigenGenerator::AddPrimary(FairPrimaryGenerator* primGen, Int_t pdgCode, const TVector3& momentum)
75{
76 primGen->AddTrack(pdgCode, momentum.Px(), momentum.Py(), momentum.Pz(), 0., 0., 0.);
78}
79// --------------------------------------------------------------------------
80
81
82// ----- Close the input file -------------------------------------------
84{
85 if (!fFile) return;
86 LOG(info) << GetName() << ": Closing input file " << fFileName;
87 fFile->Close();
88 fFile = nullptr;
89}
90// --------------------------------------------------------------------------
91
92
93// ----- Read next entry from tree --------------------------------------
95{
96
97 if (++fCurrentEntry >= fTree->GetEntries()) {
98 if (fMode == kReuseEvents) {
99 LOG(info) << GetName() << ": End of input tree - restarting with first entry";
100 fCurrentEntry = 0;
101 } //? Re-use entries
102 else {
103 LOG(info) << GetName() << ": End of input tree reached";
104 return kFALSE;
105 } //? Do not re-use entries
106 } //? End of input tree
107
108 // Read entry
109 Int_t result = fTree->GetEntry(fCurrentEntry);
110 if (result <= 0) {
111 LOG(error) << GetName() << ": Error reading entry " << fCurrentEntry << " (returns " << result << ")!";
112 return kFALSE;
113 }
114
115 return kTRUE;
116}
117// --------------------------------------------------------------------------
118
119
120// ----- Open the input file --------------------------------------------
122{
123
124 // --- Check for file being already initialised
125 if (fIsInit) {
126 LOG(warning) << GetName() << ": Already initialised!";
127 return kTRUE;
128 }
129
130 LOG(info) << GetName() << ": Initialising...";
131 std::stringstream ss;
132 switch (fMode) {
133 case kStandard: ss << " standard; rotate event plane to zero"; break;
134 case kRotateFixed: ss << " rotate event plane by fixed angle " << fPhi; break;
135 case kNoRotation: ss << " no event plane rotation"; break;
136 case kReuseEvents: ss << " re-use events if necessary; random event plane angle"; break;
137 default: ss << "unkown"; break;
138 }
139 LOG(info) << GetName() << ": Mode " << ss.str();
140
142 TFile* oldFile = gFile;
143 TDirectory* oldDir = gDirectory;
144
145 // --- Try to open file
146 fFile = new TFile(fFileName, "READ");
147
149 gFile = oldFile;
150 gDirectory = oldDir;
151
152 if (!fFile->IsOpen()) {
153 LOG(error) << GetName() << ": Could not open input file " << fFileName;
154 return kFALSE;
155 }
156 LOG(info) << GetName() << ": Open input file " << fFileName;
157
158 // --- Get and print run description
159 URun* run = fFile->Get<URun>("run");
160 if (run == nullptr) {
161 LOG(error) << GetName() << ": No run description in input file!";
162 fFile->Close();
163 return kFALSE;
164 }
165 LOG(info) << GetName() << ": Run description";
166 run->Print();
167
168 // --- Lorentz transformation to the lab (target) system
169 Double_t mProt = 0.938272;
170 Double_t pTarg = run->GetPTarg(); // target momentum per nucleon
171 Double_t pProj = run->GetPProj(); // projectile momentum per nucleon
172 Double_t eTarg = TMath::Sqrt(pProj * pProj + mProt * mProt);
173 Double_t eProj = TMath::Sqrt(pTarg * pTarg + mProt * mProt);
174 fBetaCM = pTarg / eTarg;
175 fGammaCM = 1. / TMath::Sqrt(1. - fBetaCM * fBetaCM);
176 Double_t pBeam = fGammaCM * (pProj - fBetaCM * eProj);
177 LOG(info) << GetName() << ": sqrt(s_NN) = " << run->GetNNSqrtS() << " GeV, p_beam = " << pBeam << " GeV/u";
178 LOG(info) << GetName() << ": Lorentz transformation to lab system: "
179 << " beta " << fBetaCM << ", gamma " << fGammaCM;
180
181 // --- Get input tree and connect event object to its branch
182 fTree = fFile->Get<TTree>("events");
183 if (fTree == nullptr) {
184 LOG(error) << GetName() << ": No event tree in input file!";
185 fFile->Close();
186 return kFALSE;
187 }
188 fTree->SetBranchAddress("event", &fEvent);
189 fAvailableEvents = fTree->GetEntriesFast();
190 LOG(info) << GetName() << ": " << fAvailableEvents << " events in input tree";
191
192 // --- Register ions found in the input file
193 Int_t nIons = RegisterIons();
194 LOG(info) << GetName() << ": " << nIons << " ions registered.";
195
196 fIsInit = kTRUE;
197 return kTRUE;
198}
199// --------------------------------------------------------------------------
200
201
202// ----- Process a composite particle -----------------------------------
203void CbmUnigenGenerator::ProcessIon(FairPrimaryGenerator* primGen, Int_t pdgCode, const TVector3& momentum)
204{
205
206 assert(pdgCode >= 1e9); // Should be an ion PDG
207
208 // Since hyper-nuclei are not (yet) supported by FairRoot, their PDG
209 // is replaced by that of the non-strange analogue.
210 Int_t ionPdg = pdgCode;
211 if (GetIonLambdas(pdgCode)) {
212 ionPdg = pdgCode - GetIonLambdas(pdgCode) * kPdgLambda;
213 LOG(warn) << GetName() << ": Replacing hypernucleus (PDG " << pdgCode << ") by PDG " << ionPdg;
214 } //? Lambdas in ion
215
216 // Charged ions can be registered
217 if (GetIonCharge(ionPdg)) AddPrimary(primGen, ionPdg, momentum);
218
219 // Neutral ions are not supported by GEANT4.
220 // They are thus decomposed into neutrons (as an approximation)
221 else {
222 Int_t mass = GetIonMass(ionPdg);
223 TVector3 neutronMom = momentum * (1. / Double_t(mass));
224 for (Int_t iNeutron = 0; iNeutron < mass; iNeutron++)
225 AddPrimary(primGen, 2112, neutronMom);
226 LOG(warn) << GetName() << ": Neutral fragment with PDG " << ionPdg << " is split into " << mass << " neutrons";
227 } //? Neutral ion
228}
229// --------------------------------------------------------------------------
230
231
232// ----- Read input event -----------------------------------------------
233Bool_t CbmUnigenGenerator::ReadEvent(FairPrimaryGenerator* primGen)
234{
235
236 // Init must have been called before
237 assert(fIsInit);
238
239 // Get next entry from tree
240 fNofEvents++;
241 if (!GetNextEntry()) return kFALSE;
242
243 // Event properties
244 Int_t eventId = fEvent->GetEventNr(); // Generator event ID
245 Int_t nPart = fEvent->GetNpa(); // Number of particles in event
246 Double_t impact = fEvent->GetB(); // Impact parameter
247 Double_t phi1 = fEvent->GetPhi(); // Event plane angle (generator) [rad]
248 fNofPrimaries = 0; // Number of registered primaries
249
250 // Event rotation angle to be applied on the input momentum vectors
251 Double_t phi2 = 0.;
252 switch (fMode) {
253 case kStandard: phi2 = -1. * phi1; break;
254 case kRotateFixed: phi2 = fPhi; break;
255 case kNoRotation: phi2 = 0.; break;
256 case kReuseEvents: phi2 = gRandom->Uniform(0., 2 * TMath::Pi()); break;
257 default: phi2 = 0.; break;
258 } //? mode
259
260 // Loop over particles in current event
261 for (Int_t iPart = 0; iPart < fEvent->GetNpa(); iPart++) {
262 UParticle* particle = fEvent->GetParticle(iPart);
263
264 // Lorentz transformation into lab (target) frame
265 Double_t pz = fGammaCM * (particle->Pz() - fBetaCM * particle->E());
266
267 TVector3 momentum(particle->Px(), particle->Py(), pz);
268 // Apply event rotation if needed
269 if (phi2 != 0.) momentum.RotateZ(phi2);
270
271 // Normal particle
272 if (particle->GetPdg() < 1e9) // elementary particle
273 AddPrimary(primGen, particle->GetPdg(), momentum);
274 else
275 ProcessIon(primGen, particle->GetPdg(), momentum);
276
277 } //# Particles
278
279 // Set event information in the MC event header
280 FairMCEventHeader* eventHeader = primGen->GetEvent();
281 assert(eventHeader);
282 if (eventHeader->IsSet()) {
283 LOG(warning) << GetName() << ": Event header is already set; "
284 << " event info will not be stored";
285 }
286 else {
287 eventHeader->SetEventID(eventId); // Generator event ID
288 eventHeader->SetB(fEvent->GetB()); // Impact parameter
289 eventHeader->SetRotZ(phi1 + phi2); // Event plane angle
290 eventHeader->MarkSet(kTRUE);
291 }
292
293 // Info to screen
294 LOG(info) << GetName() << ": Event ID " << eventId << ", particles " << nPart << ", primaries " << fNofPrimaries
295 << ", b = " << impact << " fm, phi (source) = " << phi1 << " rad , phi (generated) = " << phi2 << " rad";
296
297 return kTRUE;
298}
299// --------------------------------------------------------------------------
300
301
302// ----- Register ions to the run ---------------------------------------
304{
305
306 LOG(debug) << GetName() << ": Registering ions";
307 UParticle* particle {nullptr};
308 Int_t nIons {0};
309 fIonMap.clear();
310
311 // --- Event loop
312 for (Int_t iEvent = 0; iEvent < fTree->GetEntries(); ++iEvent) {
313 fTree->GetEntry(iEvent);
314
315 // --- Particle loop
316 for (Int_t iParticle = 0; iParticle < fEvent->GetNpa(); ++iParticle) {
317 particle = fEvent->GetParticle(iParticle);
318
319 Int_t pdgCode = particle->GetPdg();
320 if (pdgCode > 1e9) { // ion
321
322 // For ions the PDG code is +-10LZZZAAAI,
323 // where A = n_Lambda + n_proton + n_neutron, Z = n_proton, L = n_Lambda
324 // and I = 0 - ground state, I>0 - excitations
325 const Int_t nLambda = GetIonLambdas(pdgCode);
326 const Int_t charge = GetIonCharge(pdgCode);
327 const Int_t mass = GetIonMass(pdgCode);
328
329 // Neutral ions are skipped (not present in G4IonTable)
330 if (charge == 0) continue;
331
332 // Add ion to ion map
333 TString ionName = Form("Ion_%d_%d_%d", mass, charge, nLambda);
334 if (fIonMap.find(ionName) == fIonMap.end()) { // new ion
335 fIonMap[ionName] = new FairIon(ionName, charge, mass, charge);
336 nIons++;
337 LOG(debug) << GetName() << ": Adding new ion " << ionName << ", PDG " << pdgCode << " (mass " << mass
338 << ", charge " << charge << ", nLambda " << nLambda << ") from event " << iEvent << " at index "
339 << iParticle;
340 } //? new ion
341
342 } //? ion
343 } //# particles
344 } //# events
345
346 FairRunSim* run = FairRunSim::Instance();
347 for (const auto& entry : fIonMap)
348 run->AddNewIon(entry.second);
349
350 return fIonMap.size();
351}
352// ------------------------------------------------------------------------
353
ClassImp(CbmUnigenGenerator)
Generates input to transport simulation from files in Unigen format.
Double_t fPhi
Event plane rotation angle.
Int_t fNofEvents
Number of processed events.
void ProcessIon(FairPrimaryGenerator *primGen, Int_t pdgCode, const TVector3 &momentum)
Treat a composite particle (ion)
TString fFileName
Input file name.
CbmUnigenGenerator(const char *fileName="", EMode mode=kStandard)
Default constructor.
UEvent * fEvent
Current input event.
void AddPrimary(FairPrimaryGenerator *primGen, Int_t pdgCode, const TVector3 &momentum)
Add a primary particle to the event generator.
TFile * fFile
Input ROOT file.
EMode fMode
Rotation mode.
std::map< TString, FairIon * > fIonMap
Map from ion name to FairIon.
Int_t GetIonCharge(Int_t pdgCode) const
Charge number of an ion.
Double_t fGammaCM
Gamma factor of CM in lab frame.
Bool_t GetNextEntry()
Get next entry from input tree.
Int_t GetIonLambdas(Int_t pdgCode) const
Number of Lambdas in an ion.
TTree * fTree
Input ROOT tree.
Double_t fBetaCM
CM velocity in the lab frame.
virtual ~CbmUnigenGenerator()
Destructor.
Int_t fCurrentEntry
Current entry number.
void CloseInput()
Close the input file.
Int_t RegisterIons()
Register ions to the simulation.
EMode
Mode enumerator.
@ kNoRotation
No event rotation.
@ kStandard
Rotate events to zero event plane (default)
@ kRotateFixed
Rotate events around z by a fixed angle.
@ kReuseEvents
Reuse events if more are requested than present.
Bool_t Init()
Initialisation.
Bool_t fIsInit
Flag whether generator is initialised.
static const Int_t kPdgLambda
Decomposition of ion PDG code.
Int_t fAvailableEvents
Maximum number of events in the input file.
Int_t GetIonMass(Int_t pdgCode) const
Mass number of an ion.
Int_t fNofPrimaries
Number of primaries registered in current event.
virtual Bool_t ReadEvent(FairPrimaryGenerator *primGen)
Read one event from the input file.
Int_t GetEventNr() const
Definition UEvent.h:36
Int_t GetNpa() const
Definition UEvent.h:42
Double_t GetPhi() const
Definition UEvent.h:38
UParticle * GetParticle(Int_t index) const
Definition UEvent.cxx:101
Double_t GetB() const
Definition UEvent.h:37
Int_t GetPdg() const
Definition UParticle.h:50
Double_t Py() const
Definition UParticle.h:59
Double_t E() const
Definition UParticle.h:61
Double_t Pz() const
Definition UParticle.h:60
Double_t Px() const
Definition UParticle.h:58
Definition URun.h:12
Double_t GetNNSqrtS()
Definition URun.cxx:152
Double_t GetPTarg() const
Definition URun.h:49
void Print(Option_t *="") const
Definition URun.cxx:81
Double_t GetPProj() const
Definition URun.h:46