Neutron Energy in SteppingAction

GetTotalEnergyDeposit() from step gives me a zero when filtered for particle type and whether the particle is within a volume.

However when I GetKineticEnergy() in pre and post step point and subtract the values and feed them into event action where they are summed it looks like I am able to obtain the energy spectrum of the particle of interest in the volume.

Why is GetTotalEnergyDeposit always 0?

The energy deposited in any detector is only from charged particles. Neutrons and gammas “indirectly” deposit energy through collisions/interactions with charged particles like nuclei or electrons. If you summed the total deposited energy from a neutral particle for all of its secondaries it would give you the expected values.

So doing it via the delta of the kinetic energy I described is correct for neutrons? To me it seemed like GetTotalEnergyDeposit accounts for all processes.

For neutrons the primary means by which they transfer energy to charged particles is by nuclear collisions/reactions. The process goes like this:

  1. Neutron takes a step - No energy loss from charged interactions
  2. If there is a collision/reaction with the material you will create secondaries.
  3. If the range of these secondaries is less than their production cuts, deposit all the energy “locally”. This is then part of the “energy loss” for the neutron’s step which you would be part of total energy deposit
  4. If the range of these secondaries is greater than their production cuts, there are now new secondary tracks that will be handled and passed to TrackingAction. They will lose energy by their own physics interactions with the material. These will not be part of the energy loss that would be factored into the neutron’s total energy deposited.
  5. Geant4 particles do not know their histories out of the box. That is something you’d have to write yourself. Once the particle reaches the end of its track it is “forgotten”. It also does not project into the future. So the secondaries from (4) would be handled after the neutron had been removed completely from the stack.

If you filter on neutrons you will lose the ability to account for deposited energy from (4). It will be appear missing. With charged particles, most of the energy loss is actually in (1) which would be part of total energy deposited. Typically sensitive detectors record all energy deposited by all particles to avoid that problem. You could also set the range cuts for electrons, protons, positrons, and gammas to a kilometer and that would push nearly every secondary into (3) if you wanted but this approach is very inflexible.

I think I am happy to get the energy of the neutrons I am interested in from the GetKineticEnergy function, though what you write isn’t immediately obvious in the manual. I should take another look. Thanks for your help.

I have another question, that I am struggling with. When I obtain the deposited energy in the volume im interested in from each primary particle, I get the same number of entries in my histogram as primary events due to no primaries being fully absorbed prior to reaching the physical volume of interest.
However when I try to obtain the energy of those particles in tracking action only once and on entry to the Physical Volume I am interested in, I only get a number of entries equal to the number of reaction events. I am filtering on the primary particle type and volume pointer. Shouldn’t this give me the energy of the primary on entry? Instead it seems to give me the energy of the primaries that ended up causing a reaction, which is a bit useful but not quite what I want. Any help with solving this logic error would be most welcome.
Cheers

What experiment are you trying to simulate? It will help to answer your questions since the answer might depend on what you are doing.

Expected.

You cannot use TrackingAction for this. It is only called at particle creation and particle destruction including AtRest processes. The reactions happen in your volume so that is why they are likely passing your logic check.

You will have to do this in the SteppingAction. Some variation of:

void SteppingAction::UserSteppingAction(const G4Step* step){ 

     G4LogicalVolume* volume = step->GetPostStepPoint()->GetTouchableHandle()->GetVolume()->GetLogicalVolume();
     const G4int particleID = step->GetTrack()->GetTrackID();
     // Your code here...

     if ((step->GetPostStepPoint()->GetStepStatus()==fGeomBoundary) && (volume==fVolume)){
           // fVolume is a pointer to the logical volume you care about, passed from detector construction
           // First statement checks that you are about to enter a new volume, second checks that you are entering the volume you care about
        
     }

}

You can get the energy there then use the PostUserTrackingAction to find the energy when the particle is killed either from reactions or leaving the world volume. You could also throw in an added check that its your primary. A far more better way to do that is to just check the TrackID which is zero for primaries and no other particles. I have included it above for the stepping action.

1 Like

A secondary neutron field that is generated by a reaction and to which I want to expose a sample. I have split the geometry into a simple case to check I am able to record the data I want from the theoretically produced neutrons and a more realistic geometry that generates said neutrons and record the reaction product I am ultimately interested in. That is why I want the spectrum of the neutrons entering the sample and ultimately the intensity as a function of the position and the effective spectrum in the sample (probably as a function of sample depth). I am also trying to develop my ability in geant4 so I do want to get to grips with the ins and outs of the toolkit and its nicer to have someone to talk to (apologies for any lazy questions though I am trying to avoid it).

I will try this and update.

This is exactly the use case for a SensitiveDetector object. You write it yourself, so that you can record exactly what you want to record, with whatever if statements you need. Almost every example has one; you can find an example and pick it apart with a find pipe like this:

$ cd <my-geant4-area>/examples
$ find . -name '*.hh" | xargs grep -l 'public G4VSensitiveDetector'

That will show you every single SD class included in every example. Pick the one you like!

In your SD, you can record the energy on entry to your volume by testing the G4Step preStepPoint for fGeomBoundary status, and record the kinetic energy odf the preStepPoint. You can record the energy deposit during the step by calling G4Step::GetTotalEnergyDeposit() (which is generally zero for neutrons, but might not be if you have production cuts!). You can collect the energy transferred to secondaries by looping over the secondaries attached to the G4Step and recording their kinetic energies.

1 Like