Final position of particle in meterial

Hello! I’m a newbie in Geant4 using. I’m trying to obtain an information about depth of penetration of proton in material. So the final position of proton is needed. I’ve created a detector boxes. I’ve also created class “MySensitiveDetector” that derive from “G4VSensitiveDetector”. This is the method “ProcessHits(G4Step *aStep, G4TouchableHistory *ROhist)”:

G4bool MySensitiveDetector::ProcessHits(G4Step *aStep, G4TouchableHistory *ROhist)
{
    G4Track *track = aStep->GetTrack();

    //track->SetTrackStatus(fStopAndKill);

    G4StepPoint *preStepPoint = aStep->GetPreStepPoint();
    G4StepPoint *postStepPoint = aStep->GetPostStepPoint();

    G4ThreeVector posPhoton = preStepPoint->GetPosition();
    //G4ThreeVector posPhoton = postStepPoint->GetPosition();

    G4cout << "hao mao dao, pourt mourt " << G4endl;
    G4cout << "Proton position: " << posPhoton << G4endl;

    const G4VTouchable *touchable = preStepPoint->GetTouchable();

    G4int copyno = touchable->GetCopyNumber();

    G4cout << "Copy number: " << copyno << G4endl;

    G4VPhysicalVolume *physVol = touchable->GetVolume();
    G4ThreeVector posDetector = physVol->GetTranslation();

    G4cout << "Detector position: " << posDetector << G4endl;
}

I don’t understand how it works. If detector boxes are behind the material and proton has an enough energy to pass through the substance then detectors register this proton. If detectors in front of material, they don’t detect the proton. If the material inside of sensitive detectors volume then on condition that proton gets stuck in the material, detectors also don’t register it. In short, it seems that detectors spot only particles that interacted with material but pass through its all thickness. How can I capture the position where the proton is stuck in the material? How tracking and sensitive detectors in particular work in Geant4?

Thank you in advance!

_Geant4 Version:_11.2.2
_Operating System:_Linux Mint 21.3
_Compiler/Version:_gcc 11.4.0
_CMake Version:_3.22.1


What cuts are you using for the protons? What energy?

Edit - If you want to know only the final location of the particle you could just use the PostUserTrackingAction. That will give you the “end of life” of all tracks but if you filter based on being a proton you can record the last step of the track before it is killed because it is too slow or has undergone some nuclear reaction (depending on your proton energy).

Thank you for your response.

Protons have an energy about 30 keV in my case. Material is the alkali-silicate glass.

If I understand correctly PostUserTrackingAction is the method of G4UserTrackingAction class. How to implement this method into program? Do I need sensitive detectors for this? I’m so sorry, I still don’t know much about tracking in Geant4.

What is the range cut for protons? 30 keV is extremely low energy and so I suspect that you are running into issues related to range cuts. You will need to set it much lower, but it will also slow down your simulation. That is a tradeoff with charged particles.

Sensitive Detectors are overkill for what you are trying to do here. Instead of a “detector” you can just use a single logical box and then in the SteppingAction or TrackingAction just check that it is in that volume and where it stops.

This is where you can find examples that implement TrackingAction. It involves overriding the abstract methods PreUserTrackingAction and PostUserTrackingAction. You want the latter probably. RE01, RE05, RE07 are the best to look at first. Rdecay02 once you get familiar with it since it is probably the example closest to how you might want to output the values.

I’ve set a proton cut value to 0*mm. It turned out that after the proton entered the sample tracking continued to reaching the boundaries of the sample even if kinetic energy became zero in the previous steps. It is a little unexpected. So I monitor position where kinetic energy become zero in SteppingAction. But I am puzzled by another problem. I get position by G4ThreeVector postPos = postStepPoint->GetPosition();and write it to .txt file. All coordinates are recorded with an accuracy of 5 decimal places in mm. And it is not enough for me, I need more accuracy. So my question is how to increase accuracy when obtaining the particle position?

Physics processes are only enabled for certain energies with non zero default energy cutoffs. If you inform the simulation that the range is 0 then the physics processes responsible for killing “at rest” particles will not properly kill the proton. And if there is no time cut the particle will slowly drift forever. You should set that cut to a very small but nonzero value.

All coordinates are recorded with an accuracy of 5 decimal places in mm. And it is not enough for me, I need more accuracy.

You can scale the output by Geant4 units including um, nm, etc. There are also ways to change the significant figures of the output but do keep in mind the double precision issues. I am not quite sure why such precision would be necessary. Machining and manufacturing tolerances will not be that level and if you are dealing with nm or smaller scale effects then a wave optic simulation would probably be more appropriate.

It’s your choice of writing to a text file which is limiting you. Geant4, of course, is using doubles internally, so you’ve got 16-17 decimal digits of accuracy. If you want more of that in your text file, you could use setprecision() or the other ostream modifiers.

In my case protons actually penetrate into the sample by hundreds of nanometers. I’ve tried to change cut value for proton. But even if it matches the size of the sample or very small (a few nm), nothing changes anyway.

Your range cuts can be set arbitrarily low but that is separate from the lower energy limit for physics processes, which would be the EM physics. The default is 990 keV. So any range cut below that energy in your material will not change the range.

How about:

G4EmParameters* emParams = G4EmParameters::Instance();
emParams->SetMinEnergy(1.0 *eV);

This cannot be set to zero but something to try.

To be honest, the particles continue to drift after a complete loss of kinetic energy, even with your last advice. So I manually track the moment when the kinetic energy becomes zero and kill this particle.

Thank you for helping me figure out the tracking!

There is one other quick thing you could do which is kill the particle (and record its position) based on the local or global time. Geant will follow the particle forever until an at rest process kills it. If the particle truly is drifting near zero energy you could just record its position after several seconds. Which is an eternity for a proton slowing down but much shorter than drifting.
But in any case, good luck!