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