I have a class which inherits from G4UserStackingAction, and I’ve noticed that the same track gets processed by the ClassifyNewTrack function multiple times. Stepping through an event with gdb, I’ve seen the same track many times. Is this an expected behavior, is it documented somewhere in the application developer or toolkit developer guides?
How could you identify the same track appears more than once? By pointer?
Within a single event, one track won’t be examined by ClassifyNewTrack method more than once unless 1) it is suspended by your steppingAction, or 2) you request ReClassify().
It’s the same track ID (also the same particle type, creator process, etc.), I haven’t compared pointers. This from breaking in ClassifyNewtrack with gdb on a single event run (e.g. /run/beamOn 1).
My stepping action isn’t suspending anything. The stepping action simply creates some local variable which I can examine in the debugger.
My stacking action method is meant to just count particles. It leaves all tracks in the urgent stack, and I haven’t made any calls to ReClassify anywhere in my codebase.
Given G4Track uses G4Allocator, exactly same address can be reused. So seeing same address itself is not a strange thing. And it seems you have electromagnetic shower, you would have many electrons, positrons and gammas. But the track ID has to be different to each track. Could you please double-check you really see tracks with the same track ID many times? Parent Track ID can be common for many tracks, as one track may generate many secondaries.
I ran gdb breaking at ClassifyNewTrack for a particular track id of a single event.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00007ffff7b67a87 in SSEStackingAction::ClassifyNewTrack(G4Track const*) at src/SSEStackingAction.cc:35
stop only if id == 73
breakpoint already hit 38 times
It’s a little sloppy since I’ve been making several changes during my debugging.
#include "SSEStackingAction.h"
#include "G4Track.hh"
#include "G4SDManager.hh"
#include "G4RunManager.hh"
#include "SSEAbsorberHit.h"
SSEStackingAction::SSEStackingAction()
:G4UserStackingAction()
{ }
SSEStackingAction::~SSEStackingAction()
{ }
G4ClassificationOfNewTrack SSEStackingAction::ClassifyNewTrack(const G4Track * track)
{
// check if the track is in the absorber, break out if not
auto logvol = track->GetLogicalVolumeAtVertex();
auto pv = track->GetVolume();
auto pvn = track->GetNextVolume();
int pdg = track->GetParticleDefinition()->GetPDGEncoding();
auto name = track->GetParticleDefinition()->GetParticleName();
auto id = track->GetTrackID();
auto pid = track->GetParentID();
G4String procname;
if ( track->GetCreatorProcess() )
procname = track->GetCreatorProcess()->GetProcessName();
if ( pv) {
const G4String & logName = pv->GetLogicalVolume()->GetName();
if ( logName == "Box" ) {
// get the run manager and the current event
G4RunManager* runMan = G4RunManager::GetRunManager();
const G4Event* event = runMan->GetCurrentEvent();
G4SDManager* SDMan = G4SDManager::GetSDMpointer();
G4int colID = SDMan->GetCollectionID("SSEAbsorber");
// get the hit collection for this event
G4HCofThisEvent *hce = event->GetHCofThisEvent();
// get the hit collection for the absorber
auto abshit = (SSEAbsorberHitsCollection*)hce->GetHC(colID);
// increment count of tracks
(*abshit)[0]->AddTrack(track);
}
}
// return everyting to the urgent stack
return fUrgent;
}
void SSEStackingAction::NewStage()
{ }
void SSEStackingAction::PrepareNewEvent()
{ }
I don’t see anything wrong in your code except one suggestion that is NOT related to the current issue so I will write it in the footnote.
To diagnose the issue, could you please run one event (don’t run more than one) with the following two UI commands and post the output?
/event/verbose 2
/event/stack/verbose 2
/run/beamOn 1
Output may be long. So, please make a text file and upload.
Footnote:
GetCollectionID(“SSEAbsorber”) is a heavy operation. I’d suggest to make colID as a private data member of your SSEStackingAction class and initialize it to -1. Then access to GetCollectionID() method only if collide is negative.
I set breakpoint conditions for the first few in the list, here is what I see in gdb:
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x00007ffff7b67a87 in SSEStackingAction::ClassifyNewTrack(G4Track const*) at src/SSEStackingAction.cc:35
stop only if id == 1
breakpoint already hit 267 times
ignore next 435 hits
2 breakpoint keep y 0x00007ffff7b67a87 in SSEStackingAction::ClassifyNewTrack(G4Track const*) at src/SSEStackingAction.cc:35
stop only if id == 73
breakpoint already hit 38 times
ignore next 62 hits
3 breakpoint keep y 0x00007ffff7b67a87 in SSEStackingAction::ClassifyNewTrack(G4Track const*) at src/SSEStackingAction.cc:35
stop only if id == 72
breakpoint already hit 80 times
ignore next 20 hits
4 breakpoint keep y 0x00007ffff7b67a87 in SSEStackingAction::ClassifyNewTrack(G4Track const*) at src/SSEStackingAction.cc:35
stop only if id == 199
breakpoint already hit 18 times
ignore next 82 hits
OK, now mystery is really close to be solved. Stopping code 4 is “fSuspended” of G4TrackStatus. So, for sure someone is suspending a track in the middle of its way. And once a track is suspended, it is sent back to the stack and hence sent to G4UserStackingAction::ClassifyNewTrack.
If you don’t set fSuspend by yourself in your stepping action, it may be suspended by a process that generates optical photons. As I asked in my previous question, do you have any physics process that generates optical photons?
Optical processes suspend any charged track if there are enough number of optical photons are generated along the way of that charged track. Being suspended are the charged tracks, not optical photon tracks.
OK. That seems solve the mystery. I haven’t been able to trace the process which suspends the track. It must use a different method to suspend the track than SetTrackStatus.
So,
1 Is there a way to keep the ClassifyNewTrack only ones when I use G4OpticalPhysics?
2 Another question, is the opticalphoton always only trigger ClassifyNewTrack once at any situation?
because I use ClassifyNewTrack to calculation thinning of optical photons