BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSSDSampler.cc
1/*
2Beam Delivery Simulation (BDSIM) Copyright (C) Royal Holloway,
3University of London 2001 - 2022.
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 "BDSGlobalConstants.hh"
20#include "BDSDebug.hh"
21#include "BDSHitSampler.hh"
22#include "BDSParticleCoordsFull.hh"
23#include "BDSPhysicalConstants.hh"
24#include "BDSSamplerRegistry.hh"
25#include "BDSSDSampler.hh"
26#include "BDSUtilities.hh"
27
28#include "globals.hh" // geant4 types / globals
29#include "G4AffineTransform.hh"
30#include "G4DynamicParticle.hh"
31#include "G4ParticleDefinition.hh"
32#include "G4SDManager.hh"
33#include "G4Step.hh"
34#include "G4StepPoint.hh"
35#include "G4ThreeVector.hh"
36#include "G4TouchableHistory.hh"
37#include "G4Track.hh"
38#include "G4VPhysicalVolume.hh"
39#include "G4VTouchable.hh"
40
41#include <vector>
42
43BDSSDSampler::BDSSDSampler(const G4String& name):
44 BDSSensitiveDetector("sampler/" + name),
45 SamplerCollection(nullptr),
46 itsCollectionName(name),
47 itsHCID(-1),
48 registry(nullptr),
49 globals(nullptr)
50{
51 collectionName.insert(name);
52}
53
54BDSSDSampler::~BDSSDSampler()
55{;}
56
57void BDSSDSampler::Initialize(G4HCofThisEvent* HCE)
58{
59 // Create Sampler hits collection
61
62 // Record id for use in EventAction to save time - slow string lookup by collection name
63 if (itsHCID < 0)
64 {itsHCID = G4SDManager::GetSDMpointer()->GetCollectionID(SamplerCollection);}
65 HCE->AddHitsCollection(itsHCID,SamplerCollection);
66
67 registry = BDSSamplerRegistry::Instance(); // cache pointer to registry
68 globals = BDSGlobalConstants::Instance(); // cache pointer to globals
69}
70
71G4bool BDSSDSampler::ProcessHits(G4Step* aStep, G4TouchableHistory* /*readOutTH*/)
72{
73 // Do not store hit if the particle pre step point is not on the boundary
74 G4StepPoint* postStepPoint = aStep->GetPostStepPoint();
75 if(postStepPoint->GetStepStatus() != fGeomBoundary)
76 {
77#ifdef BDSDEBUG
78 G4cout << __METHOD_NAME__ << "not storing as not on geometry boundary" << G4endl;
79#endif
80 return false; // this step was not stored
81 }
82
83 G4Track* track = aStep->GetTrack();
84 const G4DynamicParticle* dp = track->GetDynamicParticle();
85 G4int TrackID = track->GetTrackID(); // unique ID of track
86 G4int ParentID = track->GetParentID(); // unique ID of track's mother
87 G4double T = track->GetGlobalTime(); // time since beginning of event
88 G4double energy = track->GetTotalEnergy(); // total track energy
89 G4double charge = dp->GetCharge(); // dynamic effective charge
90 G4int turnstaken = globals->TurnsTaken(); // turn Number
91 const G4ThreeVector& pos = track->GetPosition(); // current particle position (global)
92 const G4ThreeVector& mom = track->GetMomentumDirection(); // current particle direction (global) (unit)
93 G4double weight = track->GetWeight(); // weighting
94 G4int nElectrons = dp->GetTotalOccupancy();
95 G4double mass = dp->GetMass();
96 G4double rigidity = 0;
97 if (BDS::IsFinite(charge))
98 {rigidity = BDS::Rigidity(track->GetMomentum().mag(), charge);}
99 G4double p = dp->GetTotalMomentum();
100
101 // The copy number of physical volume is the sampler ID in BDSIM scheme.
102 // track->GetVolume gives the volume in the mass world. pre/postStepPoint->->GetVolume()
103 // give the ones in the parallel sampler world this SD is attached to. If the post step
104 // point is on a boundary, it belongs to the next volume - ie not the one of interest
105 // so always use the pre step point for volume identification.
106 G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
107 G4int samplerID = preStepPoint->GetTouchable()->GetVolume()->GetCopyNo();
108
109 //Initialize variables for the local position and direction
110 G4ThreeVector localPosition;
111 G4ThreeVector localDirection;
112
113 // Get coordinate transform and prepare local coordinates
114 G4Transform3D globalToLocal = registry->GetTransformInverse(samplerID);
115 if (globalToLocal == G4Transform3D::Identity) // no transform was provided - look it up
116 {
117#ifdef BDSDEBUG
118 G4cout << __METHOD_NAME__ << "Getting transform dynamically from geometry." << G4endl;
119#endif
120 // Transform not provided so look up geometry and get the transform. OK in mass world
121 // but error-prone in parallel worlds for very thin volumes.
122 // NOTE: we're looking up mass world here!
123 G4AffineTransform tf = preStepPoint->GetTouchableHandle()->GetHistory()->GetTopTransform();
124 localPosition = tf.TransformPoint(pos);
125 localDirection = tf.TransformAxis(mom);
126 }
127 else
128 {
129 // The global to local transform is defined in the registry.
130 // Cast 3 vector to 'point' to transform position (required to be explicit for * operator)
131 localPosition = globalToLocal * (HepGeom::Point3D<G4double>)pos;
132 // Now, if the sampler is infinitely thin, the local z should be 0, but it's finite.
133 // Account for this by purposively setting local z to be 0.
134 localPosition.setZ(0.0);
135 // Cast 3 vector to 3 vector to transform vector (required to be explicit for * operator)
136 localDirection = globalToLocal * (HepGeom::Vector3D<G4double>)mom;
137 }
138
139 const BDSSamplerPlacementRecord& info = registry->GetInfo(samplerID);
140 G4double s = info.SPosition();
141 G4int beamlineIndex = info.BeamlineIndex();
142 G4int PDGtype = track->GetDefinition()->GetPDGEncoding();
143 G4String pName = track->GetDefinition()->GetParticleName();
144
145 BDSParticleCoordsFull coords(localPosition.x(),
146 localPosition.y(),
147 localPosition.z(),
148 localDirection.x(),
149 localDirection.y(),
150 localDirection.z(),
151 T,
152 s,
153 energy,
154 weight);
155
156 BDSHitSampler* smpHit = new BDSHitSampler(samplerID,
157 coords,
158 p,
159 mass,
160 charge,
161 rigidity,
162 PDGtype,
163 ParentID,
164 TrackID,
165 turnstaken,
166 beamlineIndex,
167 nElectrons);
168
169 SamplerCollection->insert(smpHit);
170 return true; // the hit was stored
171}
172
173G4VHit* BDSSDSampler::last() const
174{
175 BDSHitSampler* lastHit = SamplerCollection->GetVector()->back();
176 return dynamic_cast<G4VHit*>(lastHit);
177}
static BDSGlobalConstants * Instance()
Access method.
The information recorded from a particle impacting a sampler.
A set of particle coordinates including energy and weight.
BDSGlobalConstants * globals
Cached pointer to global constants as accessed many times.
Definition: BDSSDSampler.hh:77
virtual void Initialize(G4HCofThisEvent *HCE)
Definition: BDSSDSampler.cc:57
virtual G4bool ProcessHits(G4Step *aStep, G4TouchableHistory *readOutTH)
Definition: BDSSDSampler.cc:71
BDSSDSampler(const G4String &name)
Construct a sampler with name and type (plane/cylinder).
Definition: BDSSDSampler.cc:43
virtual G4VHit * last() const
Provide access to last hit.
BDSHitsCollectionSampler * SamplerCollection
The hits collection for this sensitive detector class that's owned by each instance.
Definition: BDSSDSampler.hh:63
BDSSamplerRegistry * registry
Cached pointer to registry as accessed many times.
Definition: BDSSDSampler.hh:74
G4String itsCollectionName
The name of the hits collection that's created and registered.
Definition: BDSSDSampler.hh:66
Information about a registered sampler.
G4int BeamlineIndex() const
Accessor.
G4double SPosition() const
Accessor.
static BDSSamplerRegistry * Instance()
Accessor for registry.
const BDSSamplerPlacementRecord & GetInfo(G4int index) const
Accessor.
G4Transform3D GetTransformInverse(G4int index) const
Accessor.
Virtual class to define interface for ordered multi-sensitive detector.
G4double Rigidity(G4double momentumMagnitude, G4double charge)
Calculate the rigidity for a total momentum and charge.
G4bool IsFinite(G4double value, G4double tolerance=std::numeric_limits< double >::epsilon())