BDSIM
BDSIM is a Geant4 extension toolkit for simulation of particle transport in accelerator beamlines.
BDSSDSamplerSphere.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 "BDSHitSamplerSphere.hh"
22#include "BDSParticleCoordsSpherical.hh"
23#include "BDSPhysicalConstants.hh"
24#include "BDSSamplerRegistry.hh"
25#include "BDSSDSamplerSphere.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
44 BDSSensitiveDetector("samplersphere/" + name),
45 samplerHitsCollection(nullptr),
46 itsCollectionName(name),
47 itsHCID(-1),
48 registry(nullptr),
49 globals(nullptr)
50{
51 collectionName.insert(name);
52}
53
54BDSSDSamplerSphere::~BDSSDSamplerSphere()
55{;}
56
57void BDSSDSamplerSphere::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(samplerHitsCollection);}
65 HCE->AddHitsCollection(itsHCID,samplerHitsCollection);
66
67 registry = BDSSamplerRegistry::Instance(); // cache pointer to registry
68 globals = BDSGlobalConstants::Instance(); // cache pointer to globals
69}
70
71G4bool BDSSDSamplerSphere::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 {return false;} // this step was not stored
77
78 G4Track* track = aStep->GetTrack();
79 const G4DynamicParticle* dp = track->GetDynamicParticle();
80 G4int trackID = track->GetTrackID();
81 G4int parentID = track->GetParentID();
82 G4double T = track->GetGlobalTime();
83 G4double energy = track->GetTotalEnergy();
84 G4double charge = dp->GetCharge(); // dynamic effective charge
85 G4int turnsTaken = globals->TurnsTaken();
86 const G4ThreeVector& pos = track->GetPosition(); // current particle position (global)
87 const G4ThreeVector& mom = track->GetMomentumDirection(); // current particle direction (global) (unit)
88 G4double weight = track->GetWeight(); // weighting
89 G4int nElectrons = dp->GetTotalOccupancy();
90 G4double mass = dp->GetMass();
91 G4double rigidity = 0;
92 if (BDS::IsFinite(charge))
93 {rigidity = BDS::Rigidity(track->GetMomentum().mag(), charge);}
94 G4double p = dp->GetTotalMomentum();
95
96 // The copy number of physical volume is the sampler ID in BDSIM scheme.
97 // track->GetVolume gives the volume in the mass world. pre/postStepPoint->->GetVolume()
98 // give the ones in the parallel sampler world this SD is attached to. If the post step
99 // point is on a boundary, it belongs to the next volume - ie not the one of interest
100 // so always use the pre step point for volume identification.
101 G4StepPoint* preStepPoint = aStep->GetPreStepPoint();
102 G4int samplerID = preStepPoint->GetTouchable()->GetVolume()->GetCopyNo();
103
104 //Initialize variables for the local position and direction
105 G4ThreeVector localPosition;
106 G4ThreeVector localDirection;
107
108 // Get coordinate transform and prepare local coordinates
109 G4Transform3D globalToLocal = registry->GetTransformInverse(samplerID);
110 if (globalToLocal == G4Transform3D::Identity) // no transform was provided - look it up
111 {
112 // Transform not provided so look up geometry and get the transform. OK in mass world
113 // but error-prone in parallel worlds for very thin volumes.
114 // NOTE: we're looking up mass world here!
115 G4AffineTransform tf = preStepPoint->GetTouchableHandle()->GetHistory()->GetTopTransform();
116 localPosition = tf.TransformPoint(pos);
117 localDirection = tf.TransformAxis(mom);
118 }
119 else
120 {
121 // The global to local transform is defined in the registry.
122 // Cast 3 vector to 'point' to transform position (required to be explicit for * operator)
123 localPosition = globalToLocal * (HepGeom::Point3D<G4double>)pos;
124 // Cast 3 vector to 3 vector to transform vector (required to be explicit for * operator)
125 localDirection = globalToLocal * (HepGeom::Vector3D<G4double>)mom;
126 }
127
128 const BDSSamplerPlacementRecord& info = registry->GetInfo(samplerID);
129 G4double s = info.SPosition();
130 G4int beamlineIndex = info.BeamlineIndex();
131 G4int PDGtype = track->GetDefinition()->GetPDGEncoding();
132 G4String pName = track->GetDefinition()->GetParticleName();
133
134 // spherical coords
135 G4double r = localPosition.mag();
136 G4ThreeVector unitR = localPosition.unit();
137 G4ThreeVector lds = localDirection - unitR; // localDirectionSpherical
138
139 G4double rp = localDirection.dot(unitR);
140 G4double thetap = localDirection.theta(unitR);
141 G4double phip = localDirection.deltaPhi(unitR);
142
143 BDSParticleCoordsSpherical coords(r, localPosition.theta(), localPosition.phi(),
144 rp, thetap, phip, T);
145
146 BDSHitSamplerSphere* smpHit = new BDSHitSamplerSphere(samplerID,
147 coords,
148 energy,
149 weight,
150 s,
151 p,
152 mass,
153 charge,
154 rigidity,
155 PDGtype,
156 parentID,
157 trackID,
158 turnsTaken,
159 beamlineIndex,
160 nElectrons);
161
162 samplerHitsCollection->insert(smpHit);
163 return true; // the hit was stored
164}
165
167{
168 BDSHitSamplerSphere* lastHit = samplerHitsCollection->GetVector()->back();
169 return dynamic_cast<G4VHit*>(lastHit);
170}
static BDSGlobalConstants * Instance()
Access method.
The information recorded from a particle impacting a sampler.
A set of spherical particle coordinates.
virtual void Initialize(G4HCofThisEvent *HCE)
BDSGlobalConstants * globals
Cached pointer to global constants as accessed many times.
BDSSDSamplerSphere(const G4String &name)
Construct a sampler with name and type (plane/cylinder).
BDSHitsCollectionSamplerSphere * samplerHitsCollection
The hits collection for this sensitive detector class that's owned by each instance.
virtual G4bool ProcessHits(G4Step *aStep, G4TouchableHistory *readOutTH)
G4String itsCollectionName
The name of the hits collection that's created and registered.
virtual G4VHit * last() const
Provide access to last hit.
BDSSamplerRegistry * registry
Cached pointer to registry as accessed many times.
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())