I encountered an issue while simulating the decay chain of 232Th. I enabled the decay physics process, which means the simulation follows the half-life of Th-232 (approximately 1e27 ns). Consequently, the time values in my subsequent hit records are incremented based on this scale. However, I’m unable to store such high-precision numbers accurately using a
“double” type, as it can only handle about 16 decimal digits. I need to obtain time data with nanosecond precision for comparison. Does anyone have any good suggestions or methods?
G4Track includes both GetGlobalTime() (which has exactly the problem you describe), as well as GetLocalTime() (the time since the track was created). In your case, you want to use local time for the daughters.
Another method would be to make use of a tracking action, and for daughters of radioactive decay, reset their own global time to zero. That only works well if you also check that the parentID = 1 (i.e., they’re daughters of the initial decay. If you reset global time for tracks later in the decay chain, you’ll have pileup hits that wouldn’t be there in real life.
Thank you very much for your reply. It has been extremely helpful to me. I am about to try setting the GlobalTime of particles with parentId = 1 to zero to see whether that works.
In our experiment, we did that with a WrapperProcess around RadioactiveDecay (so we could use TrackingAction for other purposes, and have other kinds of sources). It’s very convenient to have radiocontaminant events “start” with a decay at t=0.
I tried setting the global time to zero for tracks with parentID = 1, but I found that nothing changed. It seems that Geant4 does not allow users to manually modify the GlobalTime.
The PreUserTrackingAction occurs when the particle is born. PostUserTrackingAction occurs when the particle is killed, activates at rest processes, or leaves the world volume. You would want to grab the secondaries of the primary at the end of its track and set their time to zero. Recent example here but reposted below:
void TrackingAction::PostUserTrackingAction(const G4Track* track)
{
// Reset global time on first decay (to avoid waiting for half life of first decay)
if (track->GetParentID() == 0) { // This track belongs to a primary vertex
// ============Setting secondary tracks to zero global time==============
G4TrackVector* secondaries = fpTrackingManager->GimmeSecondaries();
size_t nSeco = secondaries->size();
if (nSeco > 0){
for(size_t i=0; i < nSeco; i++) {
(*secondaries)[i]->SetGlobalTime(0.);
}
}
}
Thank you very much for your reply. I tried this approach and found that it works — I am able to set the global time of secondary particles to zero. Previously, I attempted to set the time directly in PreUserTrackingAction, but that failed, which may be related to what you mentioned.
I would like to know if the time obtained from GetGlobalTime has a specific limit on the number of significant digits, because I found that when I set SetGlobalTime(0) for secondary particles with parentId == 2, many of the subsequent recorded times are identical. It seems like the precision is not sufficient.
Row * Instance * eventId * trackId * type * time * td *
The Thorium decay chain is very complex, it is entirely possible that those entries correspond to the same decay event with subsequent x-ray emission being emitted nearly instantaneously. It would depend on the actual states and the entries in Geant4’s tables. Also when are you recording these times?
The 6th significant digit in the timestamp corresponds to femtoseconds which is on the order of the time it takes light to move across a nucleus. You do not need higher precision.
If you’re looking at secondary or tertiary tracks, you should be recording both global time and local time. That will let you deal with the dynamic range (not precision).