58 #ifndef DDG4_GEANT4HEPEMTRACKINGPHYSICS_H
59 #define DDG4_GEANT4HEPEMTRACKINGPHYSICS_H 1
65 #include <G4Electron.hh>
66 #include <G4EventManager.hh>
68 #include <G4Positron.hh>
69 #include <G4RegionStore.hh>
70 #include <G4TrackStatus.hh>
71 #include <G4VUserPhysicsList.hh>
74 #include <G4HepEmConfig.hh>
75 #include <G4HepEmTrackingManager.hh>
80 #include <unordered_set>
93 class Geant4RegionSelectiveHepEmTrackingManager :
public G4VTrackingManager {
95 Geant4RegionSelectiveHepEmTrackingManager(
bool trackInAllRegions,
96 std::unordered_set<G4int> hepEmRegionIDs,
102 virtual ~Geant4RegionSelectiveHepEmTrackingManager() =
default;
106 void BuildPhysicsTable(
const G4ParticleDefinition& part)
override {
110 void PreparePhysicsTable(
const G4ParticleDefinition& part)
override {
114 void FlushEvent()
override {
118 void HandOverOneTrack(G4Track* aTrack)
override {
119 if (useHepEm(aTrack)) {
123 trackWithGeant4(aTrack);
127 bool useHepEm(
const G4Track* aTrack)
const {
131 const G4VPhysicalVolume* volume = aTrack->GetVolume();
132 if (volume ==
nullptr && aTrack->GetTouchableHandle()) {
133 volume = aTrack->GetTouchableHandle()->GetVolume();
135 if (volume ==
nullptr) {
138 const G4LogicalVolume* logical = volume->GetLogicalVolume();
139 if (logical ==
nullptr) {
142 const G4Region* region = logical->GetRegion();
143 if (region ==
nullptr) {
149 void trackWithGeant4(G4Track* track) {
155 auto* eventManager = G4EventManager::GetEventManager();
156 auto* trackManager = eventManager->GetTrackingManager();
157 auto* stackManager = eventManager->GetStackManager();
159 trackManager->ProcessOneTrack(track);
161 G4TrackStatus track_status = track->GetTrackStatus();
162 G4VTrajectory* trajectory =
163 trackManager->GetStoreTrajectory() == 0 ? nullptr : trackManager->GimmeTrajectory();
164 G4TrackVector* secondaries = trackManager->GimmeSecondaries();
166 switch (track_status) {
169 case fSuspendAndWait:
170 stackManager->PushOneTrack(track, trajectory);
171 trajectory =
nullptr;
172 eventManager->StackTracks(secondaries);
174 case fPostponeToNextEvent:
175 stackManager->PushOneTrack(track);
176 eventManager->StackTracks(secondaries);
180 eventManager->StackTracks(secondaries);
184 case fKillTrackAndSecondaries:
185 if (secondaries !=
nullptr) {
186 for (
auto& secondary : *secondaries) {
189 secondaries->clear();
195 G4cerr <<
"+++ Geant4RegionSelectiveHepEmTrackingManager: unexpected track status from "
196 "G4TrackingManager, killing track."
198 eventManager->StackTracks(secondaries);
266 std::unordered_set<G4int> hepEmRegionIDs;
267 if (trackInAllRegions) {
268 info(
"+++ HepEm region selection: all regions");
271 G4Region* region = G4RegionStore::GetInstance()->GetRegion(regionName,
false);
272 if (region ==
nullptr) {
273 warning(
"+++ HepEm region not found in G4RegionStore: %s", regionName.c_str());
276 hepEmRegionIDs.insert(region->GetInstanceID());
277 info(
"+++ HepEm enabled in G4Region: %s", regionName.c_str());
279 if (hepEmRegionIDs.empty()) {
280 warning(
"+++ No valid HepEmRegions were resolved; HepEm tracking will be disabled.");
283 const std::unordered_set<G4int> resolvedHepEmRegionIDs = hepEmRegionIDs;
286 new Geant4RegionSelectiveHepEmTrackingManager(trackInAllRegions, std::move(hepEmRegionIDs),
m_verbosity);
288 G4int configuredWoodcockRegions = 0;
290 G4Region* woodcockRegion = G4RegionStore::GetInstance()->GetRegion(region,
false);
291 if (woodcockRegion ==
nullptr) {
292 warning(
"+++ Woodcock region not found in G4RegionStore: %s", region.c_str());
295 if (!trackInAllRegions
296 && resolvedHepEmRegionIDs.find(woodcockRegion->GetInstanceID()) == resolvedHepEmRegionIDs.end()) {
297 warning(
"+++ Ignoring Woodcock region '%s': region is outside HepEmRegions selection", region.c_str());
300 info(
"+++ Enabling Woodcock photon tracking in G4Region: %s", region.c_str());
301 tm->GetConfig()->SetWoodcockTrackingRegion(region);
302 ++configuredWoodcockRegions;
304 if (!trackInAllRegions && !
m_woodcockRegions.empty() && configuredWoodcockRegions == 0) {
305 warning(
"+++ No WoodcockRegions remain after applying HepEmRegions intersection.");
310 auto warnIfConflict = [&](G4ParticleDefinition* particle) {
311 if (particle->GetTrackingManager() !=
nullptr) {
312 warning(
"+++ Replacing existing tracking manager for %s with G4HepEmTrackingManager",
313 particle->GetParticleName().c_str());
316 warnIfConflict(G4Electron::Definition());
317 warnIfConflict(G4Positron::Definition());
318 warnIfConflict(G4Gamma::Definition());
320 G4Electron::Definition()->SetTrackingManager(tm);
321 G4Positron::Definition()->SetTrackingManager(tm);
322 G4Gamma::Definition() ->SetTrackingManager(tm);
324 info(
"+++ Installed G4HepEmTrackingManager for e-/e+/gamma");
330 #endif // DDG4_GEANT4HEPEMTRACKINGPHYSICS_H