Problem 2612

Summary: level re-evaluation in G4ParticleHPInelasticCompFS::CompositeApply()
Product: Geant4 Reporter: Artem Zontikov <zontikov.a>
Component: processes/hadronic/models/neutron_hpAssignee: dennis.herbert.wright
Status: ASSIGNED ---    
Severity: minor CC: Alberto.Ribon
Priority: P4    
Version: 11.2   
Hardware: All   
OS: All   

Description Artem Zontikov 2024-05-21 12:23:31 CEST
Hello. 
I have revisited the code in G4ParticleHPInelasticCompFS::CompositeApply() after switching to G4ParticleHPNucLevel. That bug at G4ParticleHPInelasticCompFS.cc:419 is pretty resilient. Consider the replacement of 

419       if (useQI) {
420         eExcitation = std::max(0., QI[0] - QI[it]);  // Bug fix 2333
421 
422         // Re-evaluate iLevel based on this eExcitation
423         iLevel = 0;
424         G4bool find = false;
425         const G4double level_tolerance = 1.0 * CLHEP::keV;
426 
427         // VI: the first level is ground
428         if (0 < imaxEx) {
429           for (iLevel = 1; iLevel <= imaxEx; ++iLevel) {
430             G4double elevel = theGammas.GetLevelEnergy(iLevel);
431             if (std::abs(eExcitation - elevel) < level_tolerance) {
432               find = true;
433               break;
434             }
435             if (eExcitation < elevel) {
436               find = true;
437               iLevel = std::max(iLevel - 1, 0);
438               break;
439             }
440           }
441 
442           // If proper level cannot be found, use the maximum level
443           if (!find) iLevel = imaxEx;
444         }
445       }

with just this:

if (useQI) {
    eExcitation = std::max(0., QI[0] - QI[it]);  // Bug fix 2333
    iLevel = (theTrack.GetDefinition() == aDefinition) ? 1 : 0;
    G4bool find = false;
    for ( ; iLevel < imaxEx; ++iLevel) {
        G4double dE = std::abs(eExcitation - theGammas.GetLevelEnergy(iLevel));
        G4double dE_next = std::abs(eExcitation - 
        theGammas.GetLevelEnergy(iLevel+1));
        if (dE_next > dE) {
            find = true;
            break;
        }
    }
    if (!find) iLevel = imaxEx;
} 

The loop starts from the level #1 if there is a (n,n'). Otherwise, e.g. (n,p), (n,a), it starts from the ground level. When dE_next becomes larger than dE, it means that the minimum level difference is met and the correct level is found. See #1789, #1838 for previous discussion. 
There could be some errors due to unordered levels (see #2332, it has not been fixed yet, G4NDL4.7 still contains old data).