_Geant4 Version:_11.2.1
_Operating System:_Ubuntu
_Compiler/Version:_11.4.0
_CMake Version:_3.22.1
Hi everyone,
I have a layered detector consisting of two different materials: BGO and EJ232 (Plastic). I am simulating the interaction of 511 keV gamma photons with this detector and tracking the energy deposition. Specifically, I want to track the kinetic energy that a primary photon transfers to secondary particles through both the photoelectric and Compton processes in each event.
However, I am encountering an issue: if a primary photon undergoes both Compton scattering and the photoelectric effect within the same event, my current tracking implementation only records the kinetic energy transferred during the first process (typically Compton scattering). As a result, I am unable to account for the total energy transferred by the primary photon to secondaries, which prevents me from achieving energy balance at the end of the simulation.
I have attached a code snippet of my tracking logic along with terminal output that illustrates the problem. In the output, you can see that the energy transfer is only recorded once, even when multiple interactions occur in the same event. How can I modify my tracking approach to ensure that the total energy transferred by the primary photon to secondaries is correctly recorded for each event?
G4StepPoint* preStep = step->GetPreStepPoint();
G4StepPoint* postStep = step->GetPostStepPoint();
// Get kinetic energy and energy deposition
G4double kinEnergy = preStep->GetKineticEnergy();
//G4double edep = step->GetTotalEnergyDeposit();
// Get layer ID and material
auto touchable = step->GetPreStepPoint()->GetTouchable();
G4int layerID = touchable->GetVolume(1)->GetCopyNo();
G4Material* material = step->GetPreStepPoint()->GetMaterial();
if (layerID < 0 || layerID >= fNofCells) return false;
// Track primary gamma interactions specifically
if (particleName == "gamma" && parentID == 0) {
auto edep = step->GetTotalEnergyDeposit();
G4double stepLength = step->GetStepLength();
G4double preStepEnergy = step->GetPreStepPoint()->GetTotalEnergy();
G4double postStepEnergy = step->GetPostStepPoint()->GetTotalEnergy();
// Initialize tracker for new primary gammas - only once per track
if (fPrimaryGammaTracker.find(trackID) == fPrimaryGammaTracker.end()) {
PrimaryGammaInfo info;
info.initialEnergy = preStepEnergy;
info.isFirstEntry = true;
info.initialMaterial = material->GetName();
info.initialLayerID = layerID;
info.hasExited = false;
info.depositedEnergy = 0.0;
info.transferredToSecondaries = 0.0;
info.exitEnergy = 0.0;
info.trackedSecondaries = std::set<G4int>();
fPrimaryGammaTracker[trackID] = info;
// Print initial energy only once
/* G4cout << "Primary gamma entered detector: Track ID = " << trackID
<< ", Initial Energy = " << preStepEnergy / CLHEP::keV << " keV" << G4endl;*/
}
G4cout << "Step: PreStep Volume = " << preStep->GetPhysicalVolume()->GetName()
<< ", PostStep Volume = " << (postStep->GetPhysicalVolume() ? postStep->GetPhysicalVolume()->GetName() : "nullptr")
<< ", Step Status = " << postStep->GetStepStatus()
<< ", PreStep Energy = " << preStepEnergy / CLHEP::keV << " keV"
<< ", PostStep Energy = " << postStepEnergy / CLHEP::keV << " keV" << G4endl;
// Add deposited energy to the tracker
fPrimaryGammaTracker[trackID].depositedEnergy += edep;
// Check for detector exit (when particle leaves world volume)
if (postStep->GetStepStatus() == fWorldBoundary ||
postStep->GetPhysicalVolume() == nullptr ||
postStep->GetPhysicalVolume()->GetName() == "OutOfWorld") {
// Only update exit info if it hasn't been marked as exited yet
if (!fPrimaryGammaTracker[trackID].hasExited) {
fPrimaryGammaTracker[trackID].exitEnergy = preStepEnergy;
fPrimaryGammaTracker[trackID].hasExited = true;
// Debug: Print exit energy
G4cout << "Primary gamma exited detector: Track ID = " << trackID
<< ", Exit Energy = " << preStepEnergy / CLHEP::keV << " keV" << G4endl;
}
}
else if (postStep->GetPhysicalVolume()->GetName() != "BGO" &&
postStep->GetPhysicalVolume()->GetName() != "EJ232") {
// Gamma is transitioning between detector components
/* G4cout << "Primary gamma transitioning: Track ID = " << trackID
<< ", Current Energy = " << postStepEnergy / CLHEP::keV
<< " keV, Entering volume: " << postStep->GetPhysicalVolume()->GetName() << G4endl; */
}
// Record energy based on material
if (material->GetName() == "BGO") {
fBGOPrimarygammaEnergy[layerID] += edep;
} else if (material->GetName() == "EJ232") {
fEJ232PrimarygammaEnergy[layerID] += edep;
}
// Track energy transferred to secondaries - avoid double counting
const G4TrackVector* secondaries = step->GetSecondary();
if (secondaries && secondaries->size() > 0) {
G4double newEnergyTransferred = 0.0;
for (size_t i = 0; i < secondaries->size(); i++) {
G4Track* secTrack = (*secondaries)[i];
G4int secTrackID = secTrack->GetTrackID();
// Only count secondaries we haven't seen before
if (fPrimaryGammaTracker[trackID].trackedSecondaries.find(secTrackID) ==
fPrimaryGammaTracker[trackID].trackedSecondaries.end()) {
newEnergyTransferred += secTrack->GetKineticEnergy();
fPrimaryGammaTracker[trackID].trackedSecondaries.insert(secTrackID);
}
}
if (newEnergyTransferred > 0) {
fPrimaryGammaTracker[trackID].transferredToSecondaries += newEnergyTransferred;
}
// Debug: Print energy transferred to new secondaries
G4cout << "Primary gamma Track ID = " << trackID
<< ", New Energy Transferred = " << newEnergyTransferred / CLHEP::keV << " keV"
<< ", Total Energy Transferred = " << fPrimaryGammaTracker[trackID].transferredToSecondaries / CLHEP::keV << " keV"
<< G4endl;
}
}