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