BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSOutputROOTEventCollimator.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) BDSIM Collaboration, 2001 - 2026.
3
4This file is part of BDSIM.
5
6BDSIM is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published
8by the Free Software Foundation version 3 of the License.
9
10BDSIM is distributed in the hope that it will be useful, but
11WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
17*/
18#include "BDSOutputROOTEventCollimator.hh"
19#include "BDSOutputROOTParticleData.hh"
20
21#ifndef __ROOTBUILD__
22#include "BDSHitCollimator.hh"
23#include "BDSHitEnergyDeposition.hh"
24#include "BDSUtilities.hh"
25
26#include "globals.hh"
27#include "G4TwoVector.hh"
28
29#include "CLHEP/Units/SystemOfUnits.h"
30
31#include <utility>
32#endif
33
34#include <set>
35#include <vector>
36
38
40
41BDSOutputROOTParticleData* BDSOutputROOTEventCollimator::particleTable = nullptr;
42
44 primaryInteracted(false),
45 primaryStopped(false),
46 n(0),
47 totalEnergyDeposited(0)
48{;}
49
50BDSOutputROOTEventCollimator::~BDSOutputROOTEventCollimator()
51{;}
52
54{
55 primaryInteracted = false;
56 primaryStopped = false;
57 n = 0;
58 energy.clear();
59 energyDeposited.clear();
60 xIn.clear();
61 yIn.clear();
62 zIn.clear();
63 xpIn.clear();
64 ypIn.clear();
65 zpIn.clear();
66 T.clear();
67 weight.clear();
68 partID.clear();
69 parentID.clear();
70 turn.clear();
72 impactParameterX.clear();
73 impactParameterY.clear();
74 isIon.clear();
75 ionZ.clear();
76 ionA.clear();
77 turnSet.clear();
78 charge.clear();
79 kineticEnergy.clear();
80 mass.clear();
81 rigidity.clear();
83}
84
85#ifndef __ROOTBUILD__
86void BDSOutputROOTEventCollimator::Fill(const BDSHitCollimator* hit,
88 const std::pair<G4double, G4double>& differences,
89 G4bool storeHits)
90{
91 if (storeHits)
92 {
93 n++;
94 energy.push_back((float) (hit->totalEnergy / CLHEP::GeV));
95 const G4ThreeVector& pos = hit->preStepPosition;
96 const G4ThreeVector& mom = hit->preStepMomentum;
97 xIn.push_back((float) (pos.x() / CLHEP::m));
98 yIn.push_back((float) (pos.y() / CLHEP::m));
99 zIn.push_back((float) (pos.z() / CLHEP::m));
100 xpIn.push_back((float) (mom.x() / CLHEP::rad));
101 ypIn.push_back((float) (mom.y() / CLHEP::rad));
102 zpIn.push_back((float) (mom.z() / CLHEP::rad));
103
104 // calculate impact parameters - note done in output units (as is info object)
105 G4double impactX = std::abs(xIn.back() - info.offsetX);
106 G4double impactY = std::abs(yIn.back() - info.offsetY);
107 G4double impactZ = zIn.back();
108
109 // interpolate aperture to that point
110 G4double zFromStart = -0.5 * info.length - impactZ;
111 if (zFromStart < 0)
112 {zFromStart = 0;} // sometimes rounding problems
113 G4double fraction = zFromStart / info.length;
114 G4double xAperAtZ = info.xSizeIn + differences.first * fraction;
115 G4double yAperAtZ = info.ySizeIn + differences.second * fraction;
116
117 // impact parameter is absolute
118 impactX = impactX - xAperAtZ;
119 impactY = impactY - yAperAtZ;
120
121 if (BDS::IsFinite(info.tilt))
122 {
123 G4TwoVector impactPos(impactX, impactY);
124 impactPos.rotate(info.tilt);
125 impactX = impactPos.x();
126 impactY = impactPos.y();
127 }
128 impactParameterX.push_back((float) impactX);
129 impactParameterY.push_back((float) impactY);
130 }
131
133 if (eHit)
134 {
135 totalEnergyDeposited += eHit->GetEnergyWeighted() / CLHEP::GeV;
136 primaryInteracted = primaryInteracted || eHit->GetParentID() == 0;
137 }
138
139 if (!storeHits)
140 {return;} // skip the rest of this function to avoid storing extra bits
141
142 // Every stored hit must fill every vector so that they all have length n. Use the
143 // energy deposition hit for the step if there is one, else the track information
144 // stored in the collimator hit (there is no energy deposited then).
145 if (eHit)
146 {
147 energyDeposited.push_back((float)(eHit->GetEnergy() / CLHEP::GeV));
148 T.push_back((float)(eHit->GetGlobalTime() / CLHEP::ns));
149 weight.push_back((float)eHit->GetWeight());
150 partID.push_back(eHit->GetPartID());
151 parentID.push_back(eHit->GetParentID());
152 turn.push_back(eHit->GetTurnsTaken());
153 }
154 else
155 {
156 energyDeposited.push_back(0);
157 T.push_back((float)(hit->globalTime / CLHEP::ns));
158 weight.push_back((float)hit->weight);
159 partID.push_back(hit->partID);
160 parentID.push_back(hit->parentID);
161 turn.push_back(hit->turnsTaken);
162 }
163 G4int tn = turn.back();
164 // Mark if this is the first primary impact of this turn as there may
165 // be multiple 'hits' inside the collimator for a primary passing through
166 // but we're really interested in the first one. Judge by whether we have
167 // an hits for this turn already. We assume (safely) that the first entry
168 // for a given turn will be the primary.
169 if (parentID.back() == 0)
170 {firstPrimaryHitThisTurn.push_back(turnSet.find(tn) == turnSet.end());}
171 else
172 {firstPrimaryHitThisTurn.push_back(false);} // can't be true
173 turnSet.insert(tn);
174}
175
176void BDSOutputROOTEventCollimator::FillExtras(G4bool fillIonInfo,
177 G4bool fillLinks)
178{
179 if (!particleTable)
180 {return;}
181
182 if (!(fillIonInfo || fillLinks))
183 {return;}
184
185 for (int i = 0; i < n; ++i)
186 {// loop over all existing entries in the branch vectors
187 auto& pid = partID[i];
188 if (particleTable->IsIon(pid))
189 {
190 auto& ionInfo = particleTable->GetIonInfo(pid);
191 if (fillIonInfo)
192 {
193 isIon.push_back(true);
194 ionA.push_back(ionInfo.a);
195 ionZ.push_back(ionInfo.z);
196 }
197 if (fillLinks)
198 {
199 charge.push_back(ionInfo.charge);
200 mass.push_back((float)ionInfo.mass);
201 rigidity.push_back((float)ionInfo.rigidity(energy[i], ionInfo.charge));
202 kineticEnergy.push_back((float)particleTable->KineticEnergy(pid, energy[i]));
203 }
204 }
205 else
206 {// particle
207 auto& pInfo = particleTable->GetParticleInfo(pid);
208 if (fillIonInfo)
209 {
210 isIon.push_back(false);
211 ionA.push_back(0);
212 ionZ.push_back(0);
213 }
214 if (fillLinks)
215 {
216 charge.push_back(pInfo.charge);
217 mass.push_back((float)pInfo.mass);
218 rigidity.push_back((float)pInfo.rigidity(energy[i], pInfo.charge));
219 kineticEnergy.push_back((float)particleTable->KineticEnergy(pid, energy[i]));
220 }
221 }
222 }
223}
224
225#endif
226
227void BDSOutputROOTEventCollimator::Fill(const BDSOutputROOTEventCollimator* other)
228{
229 if (!other)
230 {return;}
231 primaryInteracted = other->primaryInteracted;
232 primaryStopped = other->primaryStopped;
233 n = other->n;
234 energy = other->energy;
235 energyDeposited = other->energyDeposited;
236
237 xIn = other->xIn;
238 yIn = other->yIn;
239 zIn = other->zIn;
240 xpIn = other->xpIn;
241 ypIn = other->ypIn;
242 zpIn = other->zpIn;
243 T = other->T;
244
245 weight = other->weight;
246 partID = other->partID;
247 parentID = other->parentID;
248 turn = other->turn;
249
251 impactParameterX = other->impactParameterX;
252 impactParameterY = other->impactParameterY;
253
254 isIon = other->isIon;
255 ionA = other->ionA;
256 ionZ = other->ionZ;
257 turnSet = other->turnSet;
258 charge = other->charge;
259
261 mass = other->mass;
262 rigidity = other->rigidity;
263}
Snapshot of information for particle passing through a collimator.
G4double totalEnergy
Total energy of particle.
G4int parentID
Track ID of the parent of the particle.
G4ThreeVector preStepMomentum
Local pre step point momentum.
G4int turnsTaken
Turn number of the hit.
G4double globalTime
Pre step point global time.
G4double weight
Statistical weight of the track.
G4int partID
PDG ID of the particle.
BDSHitEnergyDeposition * energyDepositionHit
G4ThreeVector preStepPosition
Local pre step point (z from centre of object).
Information recorded for a single piece of energy deposition.
G4int GetTurnsTaken() const
Accessor for extra piece of information.
G4int GetPartID() const
Accessor for extra piece of information.
G4int GetParentID() const
Accessor for extra piece of information.
G4double GetGlobalTime() const
Accessor for extra piece of information.
Data stored for each collimator in the model.
Data stored for each collimator per event.
std::vector< float > energy
Total energy of particle for each hit.
std::set< int > turnSet
Different length set of turn number.
std::vector< int > charge
These are not filled by default.
std::vector< float > mass
These are not filled by default.
virtual void Flush()
Flush this instance.
std::vector< float > kineticEnergy
These are not filled by default.
BDSOutputROOTEventCollimator()
Default constructor for ROOT.
double totalEnergyDeposited
Sum of energy deposits including weights.
std::vector< float > rigidity
These are not filled by default.
Geant4 particle data for particles used in simulation.
bool IsIon(const int &pdgID) const
This doesn't count a proton (even with electrons) as an ion.
double KineticEnergy(const int &pdgID, const double &totalEnergy) const
Calculate kinetic energy of particle given PDG ID and total energy in GeV.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())