Example or documentation on mapping UserPrimaryInfo to UserTrackInfo

Geant4 Version: 10.07.p04, 11.4.1
Operating System: Any
Compiler/Version: Any
CMake Version: Any


In the G4CMP library, we make use of G4VUserTrackInformation containers to carry along some of the semiconductor-specific parameters we need for phonon and charge-carrier transport/scattering.

We have recently encountered a situation (anisotropic hole bands, for the experts) where we will need to initialize those special parameters in the primary particle, rather than being able to compute them via inverse functions from the normal Geant4 kinematics.

We can do that by defining G4VUserPrimaryParticleInformation containers for our generators, but it’s not obvious to me where the right place is to transfer information from the PrimaryInfo into a new TrackInfo. Should we do that in a StackingAction? TrackingAction? (How do we keep from interfering with those actions that might be defined in a users’ application)? Is there a hook available in the underlying Geant4 code that converts primaries into tracks?

I wasn’t able to find an example that addresses this part of the issue. The extended Par02 example has a PrimaryInfo, but it only seems to use it at the end of the track (PostUserTrackingAction()). A pointer to a different example or documentation would be much appreciated.

Hi @mkelsey

One possibility is that you may not need to explicitly transfer the information from G4VUserPrimaryParticleInformation to a G4VUserTrackInformation object.

A G4Track provides access to its G4DynamicParticle, which in turn can access the associated G4PrimaryParticle. From there, the attached G4VUserPrimaryParticleInformation can be retrieved.

So, if the information is only needed for the primary track, you may be able to access it directly through the track rather than copying it into a separate G4VUserTrackInformation object.

I am not sure whether this fully addresses your use case, since you may still want a dedicated G4VUserTrackInformation object for performance reasons or to propagate the information independently of the primary-particle object. However, it might avoid the need for a special transfer step altogether.

Best,
Alvaro

We have to have the TrackInfo objects because the stored information is dynamic. It can be updated along every step (and we have open JIRA tickets to move away from doing this ad hoc, and instead have proper ParticleChangeFor classes to handle it.

My issue is how to initialize those TrackInfo objects. We have a possibly unresolvable problem that some of the parameters can’t be “back-computed” just from G4 kinematics, but that’s a separate issue. What I’m dealing with here is, “we have control over creating primaries,” so we can create and fill a PrimaryInfo object with starting values of the dynamical parameters.

My question is where should we copy the PrimaryInfo content into TrackInfo? More specifically, do the Geant4 experts have a recommended place where that copying is best/most efficiently done? We have a StackingAction already, so we could put it there (especially since we can get from the G4Track back to the G4PrimaryParticle). But is that recommended? Should we do it in TrackingAction instead? Is there a dedicated Action class, or pointer we should register, to do it in the PrimaryGenerator processing?

Technically I do not think there is a significant difference. However, I would prefer `TrackingAction::PreUserTrackingAction()` because it clearly communicates that the TrackInfo is being initialized as part of the track setup phase, whereas StackingAction is intended for track classification and stack management.

I’d also be happy to hear opinions from more experienced Geant4 users on whether there is a preferred location for this kind of initialization.

Does every track need (or need to modify) this information, or can you instead use G4VUserEventInformation and just attach the PrimaryInfo to the event?

We started with just the TrackInfo, which doesget modified every step – wavevector, electron valley, etc. Now we need to do an initial assignment to primaries, then carry that over to the tracks.

Then what I would do is create a G4VUserEventInformation and do a primary check in the PreUserTrackingAction(), if it is a primary get the required information from the EventInformation and fill the TrackInformation as needed. In the PostUserTrackingAction() check if the track produced any secondaries (GimmeSecondaries()) and if it did you can fill their TrackInformation with whatever information you need from the mother track.