BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
Loading...
Searching...
No Matches
BDSSDEnergyDeposition.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2023.
4
5This file is part of BDSIM.
6
7BDSIM is free software: you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published
9by the Free Software Foundation version 3 of the License.
10
11BDSIM is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with BDSIM. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include "BDSAuxiliaryNavigator.hh"
20#include "BDSHitEnergyDeposition.hh"
21#include "BDSSDEnergyDeposition.hh"
22#include "BDSDebug.hh"
23#include "BDSGlobalConstants.hh"
24#include "BDSPhysicalVolumeInfo.hh"
25#include "BDSPhysicalVolumeInfoRegistry.hh"
26#include "BDSStep.hh"
27#include "BDSUtilities.hh"
28
29#include "globals.hh" // geant4 types / globals
30#include "G4AffineTransform.hh"
31#include "G4Event.hh"
32#include "G4EventManager.hh"
33#include "G4LogicalVolume.hh"
34#include "G4ParticleDefinition.hh"
35#include "G4SDManager.hh"
36#include "G4Step.hh"
37#include "G4ThreeVector.hh"
38#include "G4Track.hh"
39#include "G4VPhysicalVolume.hh"
40#include "G4VTouchable.hh"
41#include "Randomize.hh"
42
43
44BDSSDEnergyDeposition::BDSSDEnergyDeposition(const G4String& name,
45 G4bool storeExtrasIn,
46 G4bool killedParticleMassAddedToElossIn):
47 BDSSensitiveDetector("energy_counter/"+name),
48 storeExtras(storeExtrasIn),
49 killedParticleMassAddedToEloss(killedParticleMassAddedToElossIn),
50 colName(name),
51 hits(nullptr),
52 HCIDe(-1),
53 auxNavigator(new BDSAuxiliaryNavigator())
54{
55 collectionName.insert(colName);
56}
57
58BDSSDEnergyDeposition::~BDSSDEnergyDeposition()
59{
60 delete auxNavigator;
61}
62
63void BDSSDEnergyDeposition::Initialize(G4HCofThisEvent* HCE)
64{
66 if (HCIDe < 0)
67 {HCIDe = G4SDManager::GetSDMpointer()->GetCollectionID(hits);}
68 HCE->AddHitsCollection(HCIDe,hits);
69
70#ifdef BDSDEBUG
71 G4cout << __METHOD_NAME__ << "Hits Collection ID: " << HCIDe << G4endl;
72#endif
73}
74
76 G4TouchableHistory* /*th*/)
77{
78 // Get the energy deposited along the step
79 G4double energy = aStep->GetTotalEnergyDeposit();
80
81 //if the energy is 0, don't do anything
82 if (!BDS::IsFinite(energy))
83 {return false;}
84
85 G4Track* track = aStep->GetTrack();
86 G4int parentID = track->GetParentID(); // needed later on too
87 G4int ptype = track->GetDefinition()->GetPDGEncoding();
88
89 // step points - used many times
90 G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
91 G4StepPoint* postStepPoint = aStep->GetPostStepPoint();
92
93 G4double preStepKineticEnergy = preStepPoint->GetKineticEnergy();
94
95 // attribute the energy deposition to a uniformly random position along the step - correct!
96 // random distance - store to use twice to ensure global and local represent the same point
97 G4double randDist = G4UniformRand();
98
99 // global coordinate positions of the step
100 const G4ThreeVector& posbefore = preStepPoint->GetPosition();
101 const G4ThreeVector& posafter = postStepPoint->GetPosition();
102 G4ThreeVector eDepPos = posbefore + randDist*(posafter - posbefore);
103
104 // calculate local coordinates
105 BDSStep stepLocal = auxNavigator->ConvertToLocal(aStep);
106 const G4ThreeVector& posbeforelocal = stepLocal.PreStepPoint();
107 const G4ThreeVector& posafterlocal = stepLocal.PostStepPoint();
108 G4ThreeVector eDepPosLocal = posbeforelocal + randDist*(posafterlocal - posbeforelocal);
109 G4double stepLength = (posafterlocal - posbeforelocal).mag();
110
111 // global
112 G4double X = eDepPos.x();
113 G4double Y = eDepPos.y();
114 G4double Z = eDepPos.z();
115 // local
116 G4double x = eDepPosLocal.x();
117 G4double y = eDepPosLocal.y();
118 G4double z = eDepPosLocal.z();
119
120 // Just as the energy deposition is attributed to a uniformly random
121 // point between the preStep and the postStep positions, attribute the
122 // deposition to random time between preStep and postStep times,
123 // using the same random number as for the position.
124 G4double preGlobalTime = preStepPoint->GetGlobalTime();
125 G4double postGlobalTime = postStepPoint->GetGlobalTime();
126 G4double globalTime = preGlobalTime + randDist * (postGlobalTime - preGlobalTime);
127
128 // get the s coordinate (central s + local z)
129 // volume is from curvilinear coordinate parallel geometry
130 BDSPhysicalVolumeInfo* theInfo = BDSPhysicalVolumeInfoRegistry::Instance()->GetInfo(stepLocal.VolumeForTransform());
131 G4int beamlineIndex = -1;
132
133 // declare lambda for updating parameters if info found (avoid duplication of code)
134 G4double sBefore = -1000;
135 G4double sAfter = -1000;
136 auto UpdateParams = [&](BDSPhysicalVolumeInfo* info)
137 {
138 G4double sCentre = info->GetSPos();
139 sAfter = sCentre + posafterlocal.z();
140 sBefore = sCentre + posbeforelocal.z();
141 beamlineIndex = info->GetBeamlineIndex();
142 };
143
144 if (theInfo)
145 {UpdateParams(theInfo);}
146 else
147 {
148 // Try again but with the pre step point only
149 G4ThreeVector unitDirection = (posafter - posbefore).unit();
150 BDSStep stepLocal2 = auxNavigator->ConvertToLocal(posbefore, unitDirection);
152 if (theInfo)
153 {UpdateParams(theInfo);}
154 else
155 {
156 // Try yet again with just a slight shift (100um is bigger than any padding space).
157 G4ThreeVector shiftedPos = posbefore + 0.1*CLHEP::mm*unitDirection;
158 stepLocal2 = auxNavigator->ConvertToLocal(shiftedPos, unitDirection);
160 if (theInfo)
161 {UpdateParams(theInfo);}
162 else
163 {
164#ifdef BDSDEBUG
165 G4cerr << "No volume info for ";
166 auto vol = stepLocal.VolumeForTransform();
167 if (vol)
168 {G4cerr << vol->GetName() << G4endl;}
169 else
170 {G4cerr << "Unknown" << G4endl;}
171#endif
172 // unphysical default value to allow easy identification in output
173 sAfter = -1000;
174 sBefore = -1000;
175 beamlineIndex = -2;
176 }
177 }
178 }
179
180 G4double sHit = sBefore + randDist*(sAfter - sBefore);
181
182 G4double weight = track->GetWeight();
183 G4int trackID = track->GetTrackID();
184 G4int turnsTaken = BDSGlobalConstants::Instance()->TurnsTaken();
185
186 G4int postStepProcessType = -1;
187 G4int postStepProcessSubType = -1;
188 if (storeExtras)
189 {// physics processes
190 const G4StepPoint* postPoint = aStep->GetPostStepPoint();
191 const G4VProcess* postProcess = postPoint->GetProcessDefinedStep();
192 if (postProcess)
193 {
194 postStepProcessType = postProcess->GetProcessType();
195 postStepProcessSubType = postProcess->GetProcessSubType();
196 }
197 }
198
199 //create hits and put in hits collection of the event
201 sHit,
202 weight,
204 preStepKineticEnergy,
205 X, Y, Z,
206 x, y, z,
207 globalTime,
208 ptype,
209 trackID,
210 parentID,
211 turnsTaken,
212 stepLength,
213 beamlineIndex,
214 postStepProcessType,
215 postStepProcessSubType);
216
217 // don't worry, won't add 0 energy tracks as filtered at top by if statement
218 hits->insert(hit);
219
220 return true;
221}
222
223G4bool BDSSDEnergyDeposition::ProcessHitsTrack(const G4Track* track,
224 G4TouchableHistory* /*th*/)
225{
226 G4int parentID = track->GetParentID(); // needed later on too
227 G4int ptype = track->GetDefinition()->GetPDGEncoding();
228
229 // depending on our option, include the rest mass - for backwards compatibility
230 G4double energy = killedParticleMassAddedToEloss ? track->GetTotalEnergy() : track->GetKineticEnergy();
231
232 G4double globalTime = track->GetGlobalTime();
233 G4double weight = track->GetWeight();
234 G4int trackID = track->GetTrackID();
235 G4double preStepKineticEnergy = track->GetKineticEnergy();
236
237 // if the energy is 0, don't do anything
238 if (!BDS::IsFinite(energy))
239 {return false;}
240
241 G4double stepLength = 0;
242 const G4ThreeVector& posGlobal = track->GetPosition();
243 G4double X = posGlobal.x();
244 G4double Y = posGlobal.y();
245 G4double Z = posGlobal.z();
246
247 // calculate local coordinates
248 const G4ThreeVector& momGlobalUnit = track->GetMomentumDirection();
249 BDSStep stepLocal = auxNavigator->ConvertToLocal(posGlobal, momGlobalUnit, 1*CLHEP::mm, true, 1*CLHEP::mm);
250 G4ThreeVector posLocal = stepLocal.PreStepPoint();
251 // local
252 G4double x = posLocal.x();
253 G4double y = posLocal.y();
254 G4double z = posLocal.z();
255
256 // get the s coordinate (central s + local z)
257 // volume is from curvilinear coordinate parallel geometry
259 G4int beamlineIndex = -1;
260
261 // declare lambda for updating parameters if info found (avoid duplication of code)
262 G4double sBefore = -1000;
263 G4double sAfter = -1000;
264 auto UpdateParams = [&](BDSPhysicalVolumeInfo* info)
265 {
266 G4double sCentre = info->GetSPos();
267 sAfter = sCentre + posLocal.z();
268 sBefore = sCentre + posLocal.z();
269 beamlineIndex = info->GetBeamlineIndex();
270 };
271
272 if (theInfo)
273 {UpdateParams(theInfo);}
274 else
275 {
276 // Try yet again with just a slight shift (100um is bigger than any padding space).
277 G4ThreeVector shiftedPos = posGlobal + 0.1*CLHEP::mm * momGlobalUnit;
278 BDSStep stepLocal2 = auxNavigator->ConvertToLocal(shiftedPos, momGlobalUnit);
280 if (theInfo)
281 {UpdateParams(theInfo);}
282 else
283 {
284#ifdef BDSDEBUG
285 G4cerr << "No volume info for ";
286 auto vol = stepLocal.VolumeForTransform();
287 if (vol)
288 {G4cerr << vol->GetName() << G4endl;}
289 else
290 {G4cerr << "Unknown" << G4endl;}
291#endif
292 // unphysical default value to allow easy identification in output
293 sAfter = -1000;
294 sBefore = -1000;
295 beamlineIndex = -2;
296 }
297 }
298 G4double sHit = sBefore; // duplicate
299
300 G4int turnsTaken = BDSGlobalConstants::Instance()->TurnsTaken();
301
302 G4int postStepProcessType = -1;
303 G4int postStepProcessSubType = -1;
304 if (storeExtras)
305 {// physics processes
306 const G4Step* aStep = track->GetStep();
307 if (aStep)
308 {
309 const G4StepPoint* postPoint = aStep->GetPostStepPoint();
310 const G4VProcess* postProcess = postPoint->GetProcessDefinedStep();
311 if (postProcess)
312 {
313 postStepProcessType = postProcess->GetProcessType();
314 postStepProcessSubType = postProcess->GetProcessSubType();
315 }
316 }
317 }
318
319 //create hits and put in hits collection of the event
321 sHit,
322 weight,
324 preStepKineticEnergy,
325 X, Y, Z,
326 x, y, z,
327 globalTime,
328 ptype,
329 trackID,
330 parentID,
331 turnsTaken,
332 stepLength,
333 beamlineIndex,
334 postStepProcessType,
335 postStepProcessSubType);
336
337 // don't worry, won't add 0 energy tracks as filtered at top by if statement
338 hits->insert(hit);
339
340 return true;
341}
342
344{
345 BDSHitEnergyDeposition* lastHit = hits->GetVector()->back();
346 return dynamic_cast<G4VHit*>(lastHit);
347}
Extra G4Navigator to get coordinate transforms.
BDSStep ConvertToLocal(G4Step const *const step, G4bool useCurvilinear=true) const
static BDSGlobalConstants * Instance()
Access method.
Information recorded for a single piece of energy deposition.
BDSPhysicalVolumeInfo * GetInfo(G4VPhysicalVolume *logicalVolume, G4bool isTunnel=false)
static BDSPhysicalVolumeInfoRegistry * Instance()
Singleton accessor.
A class holding any information pertaining to a particular physical volume in a BDSIM geant4 model.
G4double GetSPos() const
Get the s position coordinate of the logical volume.
G4bool killedParticleMassAddedToEloss
In the case of a G4Track being deposited.
G4String colName
Collection name.
G4bool storeExtras
Whether to store extra information.
virtual G4bool ProcessHits(G4Step *aStep, G4TouchableHistory *th)
BDSAuxiliaryNavigator * auxNavigator
Navigator for checking points in read out geometry.
virtual G4VHit * last() const
Provide access to last hit.
virtual G4bool ProcessHitsTrack(const G4Track *track, G4TouchableHistory *th)
Virtual class to define interface for ordered multi-sensitive detector.
A simple class to represent the positions of a step.
Definition: BDSStep.hh:33
G4VPhysicalVolume * VolumeForTransform() const
Accessor.
Definition: BDSStep.hh:44
G4ThreeVector PreStepPoint() const
Accessor.
Definition: BDSStep.hh:42
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())
const char * GetName(int)
Name of element.
Definition: python.cc:38