Problem 1283 - Secondary track weighting is still grossly wrong
Summary: Secondary track weighting is still grossly wrong
Status: RESOLVED FIXED
Alias: None
Product: Geant4
Classification: Unclassified
Component: track (show other problems)
Version: 9.5
Hardware: All All
: P5 critical
Assignee: kurasige
URL:
Depends on:
Blocks:
 
Reported: 2012-01-25 22:54 CET by Tom Roberts
Modified: 2014-10-12 08:59 CEST (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this problem.
Description Tom Roberts 2012-01-25 22:54:35 CET
I reported problem 1273 on Geant4.9.4.p03. basically G4VParticleChange::fSetSecondaryWeightByProcess became initialized to true by the fix to problem 1243, but it should have remained initialized to false.

In Geant4.9.5, G4VParticleChange::fSetSecondaryWeightByProcess is still initialized to true. But worse, the 1-line workaround of modifying the source to initialize it to false does not work (it worked in Geant4.9.4.p03).

I do not know what was changed in response to these bug reports, but I do know that Geant4.9.5 is wrong: pions with weight=3 decay into secondaries with weight=1. Many of my regression tests fail.

This was a simple 1-line fix to Geant4.9.4.p03. It is not so simple in Geant4.9.5. This is blocking me from using 9.5.

By comparing a grep for SetSecondaryWeightByProcess between geant4.9.3.p02 and geant4.9.5, I conclude:
 * geant4.9.3.p02 initialized G4VParticleChange::fSetSecondaryWeightByProcess
   to false
 * geant4.9.5 initializes G4VParticleChange::fSetSecondaryWeightByProcess
   to true
 * No process calls SetSecondaryWeightByProcess() differently between them
 * several G4ParticleChange* classes now have conditionals on
   if(!fSetSecondaryWeightByProcess) surrounding setting the secondary
   particles' weights to theParentWeight. This looks OK.

There are reasons for initializing fSetSecondaryWeightByProcess to true, and there are also reasons for initializing it to false. I point out that in geant4.9.5 it is initialized to true, BUT MOST OF THE PROCESSES (IMPLICITLY) ASSUME IT IS INITIALIZED TO FALSE, including Decay.

And I am astounded that the above workaround that initializes it to false does not work. I have no idea why this is so. Presumably the developer who worked on bug 1273 will know or can figure it out.
Comment 1 John Apostolakis 2012-01-26 09:54:44 CET
Reassigning to track category.
Comment 2 Tom Roberts 2012-01-28 01:40:53 CET
Unfortunately, problem 1273 did not actually find the root of the problem, nor did my initial description here. A half hour with a debugger showed me where the problem actually lies (followed by some code comparisons between Geant4 versions).

The root of the problem is in the implementations of UpdateStepForPostStep(), and probably also UpdateStepForAlongStep() and UpdateStepForAtRest(). This problem was present in Geant4.9.4.p03. It was not in geant4.9.3.p02 but that had a different bug that was reported in problem 1243 -- the weight was updated in pPostStepPoint rather than in the track itself. So I believe that this was introduced in the fix to problem 1243.

In UpdateStepForPostStep(), the code to update track weights is inside an if(!fSetSecondaryWeightByProcess), which is right, but that if is inside an if(isParentWeightProposed), and that is wrong. If fSetSecondaryWeightByProcess is false, then the weights of the secondaries should be set to the weight of the parent, regardless of whether this process changed the parent's weight. 

Processes that generate secondaries and don't kill the parent should call SetSecondaryWeightByProcess(true) and handle the weights themselves (because in general it is not obvious what to do, and whatever choice is made in G4VParticleChange will be wrong for some process -- presumably this is why this function is available).

I was surprised that the code to update a secondary's weight was not in G4VParticleChange::AddSecondary() -- that seems like the logical place for it, and it is as close as possible to the point in the code where the process would set the weight if the process had called SetSecondaryWeightByProcess(true). The old method of updating the weight in pPostStepPoint has a high likelihood of over-writing the weight that the process set (and it cannot be correct for processes that generate secondaries but don't kill the parent).

I note that not all UpdateStepForPostStep(), UpdateStepForAlongStep(), and UpdateStepForAtRest() have the code to update the secondaries' weights. In the current approach, EVERY ONE of these functions must update the secondaries' weights if fSetSecondaryWeightByProcess is false, so there are a lot of bugs that have not yet been noticed.

I suggest removing this code from all the UpdateStepFor*() functions and putting it into G4VParticleChange::AddSecondary(). While there are several derived classes that override the base-class implementation, they all call G4VParticleChange::AddSecondary() to actually add the secondary track. So this would collapse 24 copies of the code to a single implementation (there are 8 classes derived from G4VParticleChange that implement the three UpdateStepFor* functions). It would also put the code where I believe it belongs (though your developers probably have a better handle on such things than I).
Comment 3 Tom Roberts 2012-04-13 17:08:42 CEST
Just a quick note: Geant4.9.5.p01 did not fix this (no surprise, as it is still ASSIGNED). So I have to re-do all my edits, and there are a lot of them :-(.
Comment 4 Tom Roberts 2012-04-13 18:42:20 CEST
Here are the files of geant4.9.5.p01 I modified related to this bug. In all cases the change is marked //TJR:
geant4.9.5.p01/source/track/src/G4ParticleChange.cc
geant4.9.5.p01/source/track/src/G4ParticleChangeForDecay.cc
geant4.9.5.p01/source/track/src/G4ParticleChangeForGamma.cc
geant4.9.5.p01/source/track/src/G4ParticleChangeForLoss.cc
geant4.9.5.p01/source/track/src/G4VParticleChange.cc

As mentioned in my second comment, there are other G4ParticleChangeFor... files which do not ever set the secondaries' weight. These are bugs waiting to be noticed. My modifications below fix them, too, by moving the setting of a secondary's weight from a loop over secondaries in G4ParticleChangeFor... to G4VParticleChange::AddSecondary(), where I believe it belongs.

The following code has been pasted multiple times into each file named above, and must be removed. Every instance is inside an "if (isParentWeightProposed) { }", which is the problem, as the secondary weight must be set even if this process did not modify the parent's weight.

 //TJR    if (!fSetSecondaryWeightByProcess) {
 //TJR      // Set weight of secondary tracks
 //TJR      for (G4int index= 0; index<theNumberOfSecondaries; index++){
 //TJR   if ( (*theListOfSecondaries)[index] ) {
 //TJR     ((*theListOfSecondaries)[index])->SetWeight(theParentWeight); ;
 //TJR   }
 //TJR      }
 //TJR    }


In file geant4.9.5.p01/source/track/src/G4VParticleChange.cc there is another change, which sets the secondary weight for every secondary (two new lines marked //TJR); note that all derived-class AddSecondary() functions call this one:

void G4VParticleChange::AddSecondary(G4Track *aTrack)
{
  if (debugFlag) CheckSecondary(*aTrack);

  // add a secondary after size check
  if (theSizeOftheListOfSecondaries > theNumberOfSecondaries) {
    if (!fSetSecondaryWeightByProcess)          //TJR
          aTrack->SetWeight(theParentWeight);   //TJR
    theListOfSecondaries->SetElement(theNumberOfSecondaries, aTrack);
    theNumberOfSecondaries++;
  } else {
    delete aTrack;

#ifdef G4VERBOSE
    if (verboseLevel>0) {
      G4cout << "G4VParticleChange::AddSecondary() Warning  ";
      G4cout << "theListOfSecondaries is full !! " << G4endl;
      G4cout << " The track is deleted " << G4endl;
    }
#endif
    G4Exception("G4VParticleChange::AddSecondary",
                "TRACK101", JustWarning,
                "Secondary Bug is full. The track is deleted");
  }
}


I see that geant4.9.5.p01 changed fSetSecondaryWeightByProcess back to be initialized to false; that is necessary, but is insufficient to fix this bug.


(I'm describing this rather than just attaching a patch file, because Geant4 developers need to look at this and consider the ramifications.)
Comment 5 kurasige 2012-05-15 11:48:07 CEST
 Sorry for late response. 
  I need time to discuss with developers concerned. 

  The solution proposed seems good
    http://bugzilla-geant4.kek.jp/show_bug.cgi?id=1283
  I've made a bug-fixed tag of track-V09-05-08.

  Modifications are following:
- In default (fSecondaryWeightByProcess flag is false),
  the weight of secondary tracks will be set to the parent weight,
  regardless of whether this process changed the parent's weight.
- If fSecondaryWeightByProcess flag is true,
  the weight of secondary tracks will not be changed
  by the ParticleChange
  (i.e. the process should set the secondary weight)
- Weight of Secondaries is set in AddSecondary
  (not in UpdateXXStep as before releases)
- Weight of parent track is set always
  if a new weight is proposed by process
  (i.e. isParentWeightSetByProcess is obsolete)
- Weight of parent track is set in accumulated manner same as
  other properties.
  i.e.) If two processes propose weight of W1 and W2 respectively
  for the track with initial weight of W0
  the final weight is set to  (W1/W0) * (W2/W0) * W0

Thank you very much for your help to point out and fix this problem.

Hisaya
Comment 6 Tom Roberts 2012-11-26 20:09:19 CET
I have just tried using geant4.9.5.p02; this is NOT fixed.

My regression tests still fail: secondary electrons and neutrinos from muon decay have weight=1 rather than the initial muon's weight.

I don't have time to investigate right now, and am staying with geant4.9.5.p01, with my fix.
Comment 7 kurasige 2014-10-12 08:59:03 CEST
The problem was fixed in 9.6 release