Problem 2593 - occurrence biasing particle change not initialized with track
Summary: occurrence biasing particle change not initialized with track
Status: NEW
Alias: None
Product: Geant4
Classification: Unclassified
Component: processes/biasing (show other problems)
Version: 10.2
Hardware: All All
: P4 minor
Assignee: alexander.howard
URL:
Depends on:
Blocks:
 
Reported: 2024-02-07 16:49 CET by Tom Eichlersmith
Modified: 2024-02-07 20:37 CET (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this problem.
Description Tom Eichlersmith 2024-02-07 16:49:07 CET
The `G4ParticleChangeForOccurenceBiasing` never has its `Initialize(G4Track&)` method called. This means that its internal member variables (specifically the ones that are inherited from `G4VParticleChange`) are just the default-constructed values which can lead to odd behavior in some simulation configurations.

Good News
---------
This bug is not affecting the physics of the occurrence biasing as far as I can tell.

The `G4SteppingManager` is what calls the `*DoIt` functions in its `Invoke*` family of functions and uses the returned `G4VParticleChange` pointer. The function `G4VParticleChange::UpdateStepForPostStep` is then called to copy the particle change data into the steps which is then passed onto the track with `G4Step::UpdateTrack`. The secondaries are also retrieved using `GetNumberOfSecondaries` and `GetSecondary`.

- The `UpdateStepFor*` calls within `G4ParticleChangeForOccurenceBiasing` are all passed down to the wrapped particle change `fWrappedParticleChange` while changing the weight value (if need be).
- The calls related to the secondaries are NOT passed down to the wrapped particle change, but before they are used by the stepping manager, we move the secondaries from the wrapped particle change into the occurrence biasing particle change with `StealSecondaries`.

So, as far as I can tell, all the changes to the tracks and their secondaries are appropriately handled by G4 10.2 biasing.

Bad News
--------
Since the internal members are just their default-constructed values, some of the internal checks for consistency fail. Specifically, in my case, we have our primary particles start with a negative time so that global time t=0 aligns with the particles arriving at our target volume. This means if we use the occurrence biasing in a region upstream of the target, the particles will have negative global time and the `theParentGlobalTime` member of the occurrence biasing particle change will be zero, so the check on if the secondaries have a time coming _after_ the parent time will fail and the event will be aborted due to illegal kinematics (see `G4VParticleChange::CheckSecondary`).

One funky thing is that **I don't know** how the `debugFlag` member of the `G4VParticleChange` gets set to true. This is required for the `CheckSecondary` function to be called. I suspect some memory funkiness is happening since, when I use gdb to watch the variable, it gets changed from `false` to a positive integer within `G4VParticleChange::SetNumberOfSecondaries`. (gdb snippet below, this could be a red-herring since I am not fluent with gdb and could be doing it wrong).

> Hardware watchpoint 3: ((G4GammaConversionToMuons * const) 0x55cdfa52b050)->aParticleChange.debugFlag
> Old value = false
> New value = 2
> G4VParticleChange::SetNumberOfSecondaries (this=0x55cdfa52b0b0, totSecondaries=2) at /home/tom/code/ldmx/dimuon/geant4/source/track/include/G4VParticleChange.icc:274

Fix
---
The fix is rather simple, just making sure to initialize the occurrence biasing particle change within the `G4BiasingProcessInterface` makes sure that the internal members of that particle change align with the wrapped particle change so that any checks that occur are appropriate.

> diff --git a/source/processes/biasing/generic/src/G4BiasingProcessInterface.cc b/source/processes/biasing/generic/src/G4BiasingProcessInterface.cc
> index 270258fcf0..8ef5dd7541 100644
> --- a/source/processes/biasing/generic/src/G4BiasingProcessInterface.cc
> +++ b/source/processes/biasing/generic/src/G4BiasingProcessInterface.cc
> @@ -490,6 +490,7 @@ G4VParticleChange* G4BiasingProcessInterface::PostStepDoIt(const G4Track& track,
>                                                                   fFinalStateBiasingOperation, finalStateParticleChange );
>  
>  
> +  fOccurenceBiasingParticleChange->Initialize(track);
>    fOccurenceBiasingParticleChange->SetOccurenceWeightForInteraction( weightForInteraction );
>    fOccurenceBiasingParticleChange->SetSecondaryWeightByProcess( true );
>    fOccurenceBiasingParticleChange->SetWrappedParticleChange( finalStateParticleChange );

Additional Context
------------------
I ran into this bug while working on implementing the generation of a specific sample type for our experiment. We've pinned our Geant4 version to a slightly modified copy of 10.2.3. The code is on GitHub and I've linked our fork of Geant4 along with some of the GitHub issues where I've put more of my notes.
- https://github.com/LDMX-Software/geant4/releases/tag/LDMX.10.2.3_v0.5
- https://github.com/tomeichlersmith/ldmx-dimuon/issues/5
- https://github.com/LDMX-Software/geant4/issues/13
Comment 1 Tom Eichlersmith 2024-02-07 20:37:43 CET
Disregard the comment about the `debugFlag` member of the `G4VParticleChange` objects. I was using a build of Geant4 with `G4VERBOSE` defined (`GEANT4_BUILD_VERBOSE_CODE=ON`) and so it is expected for `debugFlag` to be true.