Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/management/src/G4HadronicProcess.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /processes/hadronic/management/src/G4HadronicProcess.cc (Version 11.3.0) and /processes/hadronic/management/src/G4HadronicProcess.cc (Version 10.7.p3)


  1 //                                                  1 //
  2 // *******************************************      2 // ********************************************************************
  3 // * License and Disclaimer                         3 // * License and Disclaimer                                           *
  4 // *                                                4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of th      5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided      6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License      7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/      8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.           9 // * include a list of copyright holders.                             *
 10 // *                                               10 // *                                                                  *
 11 // * Neither the authors of this software syst     11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing fin     12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warran     13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assum     14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file      15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitatio     16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                               17 // *                                                                  *
 18 // * This  code  implementation is the result      18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboratio     19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distri     20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  ag     21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publicati     22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Sof     23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // *******************************************     24 // ********************************************************************
 25 //                                                 25 //
 26 //                                                 26 //
 27 // -------------------------------------------     27 // -------------------------------------------------------------------
 28 //                                                 28 //
 29 // GEANT4 Class source file                        29 // GEANT4 Class source file
 30 //                                                 30 //
 31 // G4HadronicProcess                               31 // G4HadronicProcess
 32 //                                                 32 //
 33 // original by H.P.Wellisch                        33 // original by H.P.Wellisch
 34 // J.L. Chuma, TRIUMF, 10-Mar-1997                 34 // J.L. Chuma, TRIUMF, 10-Mar-1997
 35 //                                                 35 //
 36 // Modifications:                                  36 // Modifications:
 37 // 05-Jul-2010 V.Ivanchenko cleanup commented      37 // 05-Jul-2010 V.Ivanchenko cleanup commented lines
 38 // 20-Jul-2011 M.Kelsey -- null-pointer checks     38 // 20-Jul-2011 M.Kelsey -- null-pointer checks in DumpState()
 39 // 24-Sep-2011 M.Kelsey -- Use envvar G4HADRON     39 // 24-Sep-2011 M.Kelsey -- Use envvar G4HADRONIC_RANDOM_FILE to save random
 40 //    engine state before each model call          40 //    engine state before each model call
 41 // 18-Oct-2011 M.Kelsey -- Handle final-state      41 // 18-Oct-2011 M.Kelsey -- Handle final-state cases in conservation checks.
 42 // 14-Mar-2012 G.Folger -- enhance checks for      42 // 14-Mar-2012 G.Folger -- enhance checks for conservation of energy, etc.
 43 // 28-Jul-2012 M.Maire  -- add function GetTar     43 // 28-Jul-2012 M.Maire  -- add function GetTargetDefinition() 
 44 // 14-Sep-2012 Inherit from RestDiscrete, use      44 // 14-Sep-2012 Inherit from RestDiscrete, use subtype code (now in ctor) to
 45 //    configure base-class                         45 //    configure base-class
 46 // 28-Sep-2012 Restore inheritance from G4VDis     46 // 28-Sep-2012 Restore inheritance from G4VDiscreteProcess, remove enable-flag
 47 //    changing, remove warning message from or     47 //    changing, remove warning message from original ctor.
 48 // 21-Aug-2019 V.Ivanchenko leave try/catch on     48 // 21-Aug-2019 V.Ivanchenko leave try/catch only for ApplyYourself(..), cleanup 
 49                                                    49 
 50 #include "G4HadronicProcess.hh"                    50 #include "G4HadronicProcess.hh"
 51                                                    51 
 52 #include "G4Types.hh"                              52 #include "G4Types.hh"
 53 #include "G4SystemOfUnits.hh"                      53 #include "G4SystemOfUnits.hh"
 54 #include "G4HadProjectile.hh"                      54 #include "G4HadProjectile.hh"
 55 #include "G4ElementVector.hh"                      55 #include "G4ElementVector.hh"
 56 #include "G4Track.hh"                              56 #include "G4Track.hh"
 57 #include "G4Step.hh"                               57 #include "G4Step.hh"
 58 #include "G4Element.hh"                            58 #include "G4Element.hh"
 59 #include "G4ParticleChange.hh"                     59 #include "G4ParticleChange.hh"
 60 #include "G4ProcessVector.hh"                      60 #include "G4ProcessVector.hh"
 61 #include "G4ProcessManager.hh"                     61 #include "G4ProcessManager.hh"
 62 #include "G4NucleiProperties.hh"                   62 #include "G4NucleiProperties.hh"
 63                                                    63 
 64 #include "G4HadronicException.hh"                  64 #include "G4HadronicException.hh"
 65 #include "G4HadronicProcessStore.hh"               65 #include "G4HadronicProcessStore.hh"
 66 #include "G4HadronicParameters.hh"             << 
 67 #include "G4VCrossSectionDataSet.hh"               66 #include "G4VCrossSectionDataSet.hh"
 68                                                    67 
 69 #include "G4NistManager.hh"                        68 #include "G4NistManager.hh"
                                                   >>  69 #include "G4PhysicsModelCatalog.hh"
 70 #include "G4VLeadingParticleBiasing.hh"            70 #include "G4VLeadingParticleBiasing.hh"
 71 #include "G4HadXSHelper.hh"                    << 
 72 #include "G4Threading.hh"                      << 
 73 #include "G4Exp.hh"                                71 #include "G4Exp.hh"
 74                                                    72 
 75 #include <typeinfo>                                73 #include <typeinfo>
 76 #include <sstream>                                 74 #include <sstream>
 77 #include <iostream>                                75 #include <iostream>
 78                                                    76 
 79 namespace                                      <<  77 // File-scope variable to capture environment variable at startup
 80 {                                              <<  78 
 81   constexpr G4double lambdaFactor = 0.8;       <<  79 static const char* G4Hadronic_Random_File = std::getenv("G4HADRONIC_RANDOM_FILE");
 82   constexpr G4double invLambdaFactor = 1.0/lam << 
 83 }                                              << 
 84                                                    80 
 85 //////////////////////////////////////////////     81 //////////////////////////////////////////////////////////////////
 86                                                    82 
 87 G4HadronicProcess::G4HadronicProcess(const G4S     83 G4HadronicProcess::G4HadronicProcess(const G4String& processName,
 88                                      G4Process     84                                      G4ProcessType procType)
 89  : G4VDiscreteProcess(processName, procType)       85  : G4VDiscreteProcess(processName, procType)
 90 {                                                  86 {
 91   SetProcessSubType(fHadronInelastic);  // Def     87   SetProcessSubType(fHadronInelastic);  // Default unless subclass changes
 92   InitialiseLocal();                               88   InitialiseLocal();
 93 }                                                  89 }
 94                                                    90 
                                                   >>  91 //////////////////////////////////////////////////////////////////
                                                   >>  92 
 95 G4HadronicProcess::G4HadronicProcess(const G4S     93 G4HadronicProcess::G4HadronicProcess(const G4String& processName,
 96                                      G4Hadroni     94                                      G4HadronicProcessType aHadSubType)
 97  : G4VDiscreteProcess(processName, fHadronic)      95  : G4VDiscreteProcess(processName, fHadronic)
 98 {                                                  96 {
 99   SetProcessSubType(aHadSubType);                  97   SetProcessSubType(aHadSubType);
100   InitialiseLocal();                               98   InitialiseLocal();
101 }                                                  99 }
102                                                   100 
103 G4HadronicProcess::~G4HadronicProcess()           101 G4HadronicProcess::~G4HadronicProcess()
104 {                                                 102 {
105   theProcessStore->DeRegister(this);              103   theProcessStore->DeRegister(this);
106   delete theTotalResult;                          104   delete theTotalResult;
107   delete theCrossSectionDataStore;                105   delete theCrossSectionDataStore;
108   if(isMaster) {                               << 
109     if (fXSpeaks != nullptr) {                 << 
110       for (auto const& e : *fXSpeaks ) {       << 
111         delete e;                              << 
112       }                                        << 
113     }                                          << 
114     delete fXSpeaks;                           << 
115     delete theEnergyOfCrossSectionMax;         << 
116   }                                            << 
117 }                                                 106 }
118                                                   107 
119 void G4HadronicProcess::InitialiseLocal() {       108 void G4HadronicProcess::InitialiseLocal() {  
120   theTotalResult = new G4ParticleChange();        109   theTotalResult = new G4ParticleChange();
121   theTotalResult->SetSecondaryWeightByProcess(    110   theTotalResult->SetSecondaryWeightByProcess(true);
                                                   >> 111   theInteraction = nullptr;
122   theCrossSectionDataStore = new G4CrossSectio    112   theCrossSectionDataStore = new G4CrossSectionDataStore();
123   theProcessStore = G4HadronicProcessStore::In    113   theProcessStore = G4HadronicProcessStore::Instance();
124   theProcessStore->Register(this);                114   theProcessStore->Register(this);
125   minKinEnergy = 1*CLHEP::MeV;                 << 115   theInitialNumberOfInteractionLength = 0.0;
126                                                << 116   aScaleFactor = 1.0;
127   G4HadronicParameters* param = G4HadronicPara << 117   fWeight = 1.0;
128   epReportLevel = param->GetEPReportLevel();   << 118   nMatWarn = nKaonWarn = 0;
129   epCheckLevels.first = param->GetEPRelativeLe << 119   useIntegralXS = true;
130   epCheckLevels.second = param->GetEPAbsoluteL << 120   theLastCrossSection = 0.0;
131                                                << 121   nICelectrons = 0;
132   unitVector.set(0.0, 0.0, 0.1);               << 122   idxIC = -1;
133   if(G4Threading::IsWorkerThread()) { isMaster << 123   G4HadronicProcess_debug_flag = false;
                                                   >> 124   levelsSetByProcess = false;
                                                   >> 125   epReportLevel = 0;
                                                   >> 126   epCheckLevels.first = DBL_MAX;
                                                   >> 127   epCheckLevels.second = DBL_MAX;
                                                   >> 128   GetEnergyMomentumCheckEnvvars();
                                                   >> 129 }
                                                   >> 130 
                                                   >> 131 void G4HadronicProcess::GetEnergyMomentumCheckEnvvars() {
                                                   >> 132   if ( std::getenv("G4Hadronic_epReportLevel") ) {
                                                   >> 133     epReportLevel = std::strtol(std::getenv("G4Hadronic_epReportLevel"),0,10);
                                                   >> 134   }
                                                   >> 135   if ( std::getenv("G4Hadronic_epCheckRelativeLevel") ) {
                                                   >> 136     epCheckLevels.first = std::strtod(std::getenv("G4Hadronic_epCheckRelativeLevel"),0);
                                                   >> 137   }
                                                   >> 138   if ( std::getenv("G4Hadronic_epCheckAbsoluteLevel") ) {
                                                   >> 139     epCheckLevels.second = std::strtod(std::getenv("G4Hadronic_epCheckAbsoluteLevel"),0);
                                                   >> 140   }
134 }                                                 141 }
135                                                   142 
136 void G4HadronicProcess::RegisterMe( G4Hadronic    143 void G4HadronicProcess::RegisterMe( G4HadronicInteraction *a )
137 {                                                 144 {
138   if(nullptr == a) { return; }                 << 145   if(!a) { return; }
139   theEnergyRangeManager.RegisterMe( a );          146   theEnergyRangeManager.RegisterMe( a );
140   G4HadronicProcessStore::Instance()->Register    147   G4HadronicProcessStore::Instance()->RegisterInteraction(this, a);
141 }                                                 148 }
142                                                   149 
143 G4double                                          150 G4double 
144 G4HadronicProcess::GetElementCrossSection(cons << 151 G4HadronicProcess::GetElementCrossSection(const G4DynamicParticle * part,
145             const G4Element * elm,                152             const G4Element * elm, 
146             const G4Material* mat)                153             const G4Material* mat)
147 {                                                 154 {
148   if(nullptr == mat)                           << 155   if(!mat) 
149   {                                               156   {
150     static const G4int nmax = 5;                  157     static const G4int nmax = 5;
151     if(nMatWarn < nmax) {                         158     if(nMatWarn < nmax) {
152       ++nMatWarn;                                 159       ++nMatWarn;
153       G4ExceptionDescription ed;                  160       G4ExceptionDescription ed;
154       ed << "Cannot compute Element x-section     161       ed << "Cannot compute Element x-section for " << GetProcessName()
155    << " because no material defined \n"           162    << " because no material defined \n"
156    << " Please, specify material pointer or de    163    << " Please, specify material pointer or define simple material"
157    << " for Z= " << elm->GetZasInt();             164    << " for Z= " << elm->GetZasInt();
158       G4Exception("G4HadronicProcess::GetEleme    165       G4Exception("G4HadronicProcess::GetElementCrossSection", "had066", 
159       JustWarning, ed);                           166       JustWarning, ed);
160     }                                             167     }
161   }                                               168   }
162   return theCrossSectionDataStore->GetCrossSec << 169   return
                                                   >> 170     std::max(theCrossSectionDataStore->GetCrossSection(part, elm, mat),0.0);
163 }                                                 171 }
164                                                   172 
165 void G4HadronicProcess::PreparePhysicsTable(co    173 void G4HadronicProcess::PreparePhysicsTable(const G4ParticleDefinition& p)
166 {                                                 174 {
167   if(nullptr == firstParticle) { firstParticle << 175   if(std::getenv("G4HadronicProcess_debug")) {
                                                   >> 176     G4HadronicProcess_debug_flag = true;
                                                   >> 177   }
168   theProcessStore->RegisterParticle(this, &p);    178   theProcessStore->RegisterParticle(this, &p);
169 }                                                 179 }
170                                                   180 
171 void G4HadronicProcess::BuildPhysicsTable(cons    181 void G4HadronicProcess::BuildPhysicsTable(const G4ParticleDefinition& p)
172 {                                                 182 {
173   if(firstParticle != &p) { return; }          << 
174                                                << 
175   theCrossSectionDataStore->BuildPhysicsTable(    183   theCrossSectionDataStore->BuildPhysicsTable(p);
176   theEnergyRangeManager.BuildPhysicsTable(p);     184   theEnergyRangeManager.BuildPhysicsTable(p);
177   G4HadronicParameters* param = G4HadronicPara << 
178                                                << 
179   G4int subtype = GetProcessSubType();         << 
180   if(useIntegralXS) {                          << 
181     if(subtype == fHadronInelastic) {          << 
182       useIntegralXS = param->EnableIntegralIne << 
183     } else if(subtype == fHadronElastic) {     << 
184       useIntegralXS = param->EnableIntegralEla << 
185     }                                          << 
186   }                                            << 
187   fXSType = fHadNoIntegral;                    << 
188                                                << 
189   if(nullptr == masterProcess) {               << 
190     masterProcess = dynamic_cast<const G4Hadro << 
191   }                                            << 
192   if(nullptr == masterProcess) {               << 
193     if(1 < param->GetVerboseLevel()) {         << 
194       G4ExceptionDescription ed;               << 
195       ed << "G4HadronicProcess::BuildPhysicsTa << 
196    << GetProcessName() << " for " << p.GetPart << 
197    << " fail due to undefined pointer to the m << 
198    << "  ThreadID= " << G4Threading::G4GetThre << 
199    << "  initialisation of worker started befo << 
200       G4Exception("G4HadronicProcess::BuildPhy << 
201       JustWarning, ed);                        << 
202     }                                          << 
203   }                                            << 
204                                                << 
205   // check particle for integral method        << 
206   if(isMaster || nullptr == masterProcess) {   << 
207     G4double charge = p.GetPDGCharge()/eplus;  << 
208                                                << 
209     // select cross section shape              << 
210     if(charge != 0.0 && useIntegralXS) {       << 
211       G4double tmax = param->GetMaxEnergy();   << 
212       currentParticle = firstParticle;         << 
213       // initialisation in the master thread   << 
214       G4int pdg = p.GetPDGEncoding();          << 
215       if (std::abs(pdg) == 211) {              << 
216   fXSType = fHadTwoPeaks;                      << 
217       } else if (pdg == 321) {                 << 
218   fXSType = fHadOnePeak;                       << 
219       } else if (pdg == -321) {                << 
220   fXSType = fHadDecreasing;                    << 
221       } else if (pdg == 2212) {                << 
222   fXSType = fHadTwoPeaks;                      << 
223       } else if (pdg == -2212 || pdg == -10000 << 
224      pdg == -1000020030 || pdg == -1000020040) << 
225   fXSType = fHadDecreasing;                    << 
226       } else if (charge > 0.0 || pdg == 11 ||  << 
227   fXSType = fHadIncreasing;                    << 
228       }                                        << 
229                                                << 
230       delete theEnergyOfCrossSectionMax;       << 
231       theEnergyOfCrossSectionMax = nullptr;    << 
232       if(fXSType == fHadTwoPeaks) {            << 
233         if (fXSpeaks != nullptr) {             << 
234           for (auto const& e : *fXSpeaks ) {   << 
235             delete e;                          << 
236           }                                    << 
237         }                                      << 
238   delete fXSpeaks;                             << 
239   fXSpeaks =                                   << 
240     G4HadXSHelper::FillPeaksStructure(this, &p << 
241   if(nullptr == fXSpeaks) {                    << 
242     fXSType = fHadOnePeak;                     << 
243   }                                            << 
244       }                                        << 
245       if(fXSType == fHadOnePeak) {             << 
246   theEnergyOfCrossSectionMax =                 << 
247     G4HadXSHelper::FindCrossSectionMax(this, & << 
248   if(nullptr == theEnergyOfCrossSectionMax) {  << 
249     fXSType = fHadIncreasing;                  << 
250   }                                            << 
251       }                                        << 
252     }                                          << 
253   } else {                                     << 
254     // initialisation in worker threads        << 
255     fXSType = masterProcess->CrossSectionType( << 
256     fXSpeaks = masterProcess->TwoPeaksXS();    << 
257     theEnergyOfCrossSectionMax = masterProcess << 
258   }                                            << 
259   if(isMaster && 1 < param->GetVerboseLevel()) << 
260     G4cout << "G4HadronicProcess::BuildPhysics << 
261      << GetProcessName() << " and " << p.GetPa << 
262      << " typeXS=" << fXSType << G4endl;       << 
263   }                                            << 
264   G4HadronicProcessStore::Instance()->PrintInf    185   G4HadronicProcessStore::Instance()->PrintInfo(&p);
265 }                                                 186 }
266                                                   187 
267 void G4HadronicProcess::StartTracking(G4Track* << 188 G4double G4HadronicProcess::
                                                   >> 189 GetMeanFreePath(const G4Track &aTrack, G4double, G4ForceCondition *)
268 {                                                 190 {
269   currentMat = nullptr;                        << 191   //G4cout << "GetMeanFreePath " << aTrack.GetDefinition()->GetParticleName()
270   currentParticle = track->GetDefinition();    << 192   //   << " Ekin= " << aTrack.GetKineticEnergy() << G4endl;
271   fDynParticle = track->GetDynamicParticle();  << 193   theLastCrossSection = aScaleFactor*theCrossSectionDataStore
272   theNumberOfInteractionLengthLeft = -1.0;     << 
273 }                                              << 
274                                                << 
275 G4double G4HadronicProcess::PostStepGetPhysica << 
276                              const G4Track& tr << 
277            G4double previousStepSize,          << 
278                              G4ForceCondition* << 
279 {                                              << 
280   *condition = NotForced;                      << 
281                                                << 
282   const G4Material* mat = track.GetMaterial(); << 
283   if(mat != currentMat) {                      << 
284     currentMat = mat;                          << 
285     mfpKinEnergy = DBL_MAX;                    << 
286     matIdx = (G4int)track.GetMaterial()->GetIn << 
287   }                                            << 
288   UpdateCrossSectionAndMFP(track.GetKineticEne << 
289                                                << 
290   // zero cross section                        << 
291   if(theLastCrossSection <= 0.0) {             << 
292     theNumberOfInteractionLengthLeft = -1.0;   << 
293     currentInteractionLength = DBL_MAX;        << 
294     return DBL_MAX;                            << 
295   }                                            << 
296                                                << 
297   // non-zero cross section                    << 
298   if (theNumberOfInteractionLengthLeft < 0.0)  << 
299     theNumberOfInteractionLengthLeft = -G4Log( << 
300     theInitialNumberOfInteractionLength = theN << 
301   } else {                                     << 
302     theNumberOfInteractionLengthLeft -=        << 
303       previousStepSize/currentInteractionLengt << 
304     theNumberOfInteractionLengthLeft =         << 
305       std::max(theNumberOfInteractionLengthLef << 
306   }                                            << 
307   currentInteractionLength = theMFP;           << 
308   return theNumberOfInteractionLengthLeft*theM << 
309 }                                              << 
310                                                << 
311 G4double G4HadronicProcess::GetMeanFreePath(   << 
312                             const G4Track &aTr << 
313                             G4ForceCondition*) << 
314 {                                              << 
315   G4double xs = aScaleFactor*theCrossSectionDa << 
316      ->ComputeCrossSection(aTrack.GetDynamicPa    194      ->ComputeCrossSection(aTrack.GetDynamicParticle(),aTrack.GetMaterial());
317   return (xs > 0.0) ? 1.0/xs : DBL_MAX;        << 195   G4double res = (theLastCrossSection>0.0) ? 1.0/theLastCrossSection : DBL_MAX;
                                                   >> 196   //G4cout << "         xsection= " << theLastCrossSection << G4endl;
                                                   >> 197   return res;
318 }                                                 198 }
319                                                   199 
320 G4VParticleChange*                                200 G4VParticleChange*
321 G4HadronicProcess::PostStepDoIt(const G4Track&    201 G4HadronicProcess::PostStepDoIt(const G4Track& aTrack, const G4Step&)
322 {                                                 202 {
323   theNumberOfInteractionLengthLeft = -1.0;     << 
324                                                << 
325   //G4cout << "PostStepDoIt " << aTrack.GetDef    203   //G4cout << "PostStepDoIt " << aTrack.GetDefinition()->GetParticleName()
326   //   << " Ekin= " << aTrack.GetKineticEnergy    204   //   << " Ekin= " << aTrack.GetKineticEnergy() << G4endl;
327   // if primary is not Alive then do nothing      205   // if primary is not Alive then do nothing
328   theTotalResult->Clear();                        206   theTotalResult->Clear();
329   theTotalResult->Initialize(aTrack);             207   theTotalResult->Initialize(aTrack);
330   fWeight = aTrack.GetWeight();                   208   fWeight = aTrack.GetWeight();
331   theTotalResult->ProposeWeight(fWeight);         209   theTotalResult->ProposeWeight(fWeight);
332   if(aTrack.GetTrackStatus() != fAlive) { retu    210   if(aTrack.GetTrackStatus() != fAlive) { return theTotalResult; }
333                                                   211 
334   // Find cross section at end of step and che    212   // Find cross section at end of step and check if <= 0
335   //                                              213   //
336   const G4DynamicParticle* aParticle = aTrack.    214   const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
337   const G4Material* aMaterial = aTrack.GetMate    215   const G4Material* aMaterial = aTrack.GetMaterial();
338                                                   216 
339   // check only for charged particles             217   // check only for charged particles
340   if(fXSType != fHadNoIntegral) {              << 218   if(aParticle->GetDefinition()->GetPDGCharge() != 0.0) {
341     mfpKinEnergy = DBL_MAX;                    << 
342     G4double xs = aScaleFactor*                   219     G4double xs = aScaleFactor*
343       theCrossSectionDataStore->ComputeCrossSe    220       theCrossSectionDataStore->ComputeCrossSection(aParticle,aMaterial);
344     //G4cout << "xs=" << xs << " xs0=" << theL << 221     if(xs <= 0.0 || xs < theLastCrossSection*G4UniformRand()) {
345     //     << "  " << aMaterial->GetName() <<  << 
346     if(xs < theLastCrossSection*G4UniformRand( << 
347       // No interaction                           222       // No interaction
348       return theTotalResult;                      223       return theTotalResult;
349     }                                             224     }    
350   }                                               225   }
351                                                   226 
352   const G4Element* anElement =                    227   const G4Element* anElement = 
353     theCrossSectionDataStore->SampleZandA(aPar    228     theCrossSectionDataStore->SampleZandA(aParticle,aMaterial,targetNucleus);
354                                                   229 
355   // Next check for illegal track status          230   // Next check for illegal track status
356   //                                              231   //
357   if (aTrack.GetTrackStatus() != fAlive &&        232   if (aTrack.GetTrackStatus() != fAlive && 
358       aTrack.GetTrackStatus() != fSuspend) {      233       aTrack.GetTrackStatus() != fSuspend) {
359     if (aTrack.GetTrackStatus() == fStopAndKil    234     if (aTrack.GetTrackStatus() == fStopAndKill ||
360         aTrack.GetTrackStatus() == fKillTrackA    235         aTrack.GetTrackStatus() == fKillTrackAndSecondaries ||
361         aTrack.GetTrackStatus() == fPostponeTo    236         aTrack.GetTrackStatus() == fPostponeToNextEvent) {
362       G4ExceptionDescription ed;                  237       G4ExceptionDescription ed;
363       ed << "G4HadronicProcess: track in unusa    238       ed << "G4HadronicProcess: track in unusable state - "
364    << aTrack.GetTrackStatus() << G4endl;          239    << aTrack.GetTrackStatus() << G4endl;
365       ed << "G4HadronicProcess: returning unch    240       ed << "G4HadronicProcess: returning unchanged track " << G4endl;
366       DumpState(aTrack,"PostStepDoIt",ed);        241       DumpState(aTrack,"PostStepDoIt",ed);
367       G4Exception("G4HadronicProcess::PostStep    242       G4Exception("G4HadronicProcess::PostStepDoIt", "had004", JustWarning, ed);
368     }                                             243     }
369     // No warning for fStopButAlive which is a    244     // No warning for fStopButAlive which is a legal status here
370     return theTotalResult;                        245     return theTotalResult;
371   }                                               246   }
372                                                   247 
373   // Initialize the hadronic projectile from t    248   // Initialize the hadronic projectile from the track
374   thePro.Initialise(aTrack);                      249   thePro.Initialise(aTrack);
375                                                   250 
376   theInteraction = ChooseHadronicInteraction(t    251   theInteraction = ChooseHadronicInteraction(thePro, targetNucleus, 
377                                              a    252                                              aMaterial, anElement);
378   if(nullptr == theInteraction) {              << 253   if(!theInteraction) {
379     G4ExceptionDescription ed;                    254     G4ExceptionDescription ed;
380     ed << "Target element "<<anElement->GetNam    255     ed << "Target element "<<anElement->GetName()<<"  Z= "
381        << targetNucleus.GetZ_asInt() << "  A=     256        << targetNucleus.GetZ_asInt() << "  A= "
382        << targetNucleus.GetA_asInt() << G4endl    257        << targetNucleus.GetA_asInt() << G4endl;
383     DumpState(aTrack,"ChooseHadronicInteractio    258     DumpState(aTrack,"ChooseHadronicInteraction",ed);
384     ed << " No HadronicInteraction found out"     259     ed << " No HadronicInteraction found out" << G4endl;
385     G4Exception("G4HadronicProcess::PostStepDo << 260     G4Exception("G4HadronicProcess::PostStepDoIt", "had005", FatalException, ed);
386                 FatalException, ed);           << 
387     return theTotalResult;                        261     return theTotalResult;
388   }                                               262   }
389                                                   263 
390   G4HadFinalState* result = nullptr;              264   G4HadFinalState* result = nullptr;
391   G4int reentryCount = 0;                         265   G4int reentryCount = 0;
392   /*                                           << 266   /* 
393   G4cout << "### " << aParticle->GetDefinition    267   G4cout << "### " << aParticle->GetDefinition()->GetParticleName() 
394    << "  Ekin(MeV)= " << aParticle->GetKinetic    268    << "  Ekin(MeV)= " << aParticle->GetKineticEnergy()
395    << "  Z= " << targetNucleus.GetZ_asInt()       269    << "  Z= " << targetNucleus.GetZ_asInt() 
396    << "  A= " << targetNucleus.GetA_asInt()       270    << "  A= " << targetNucleus.GetA_asInt()
397    << "  by " << theInteraction->GetModelName(    271    << "  by " << theInteraction->GetModelName() 
398    << G4endl;                                     272    << G4endl;
399   */                                              273   */
400   do                                              274   do
401   {                                               275   {
402     try                                           276     try
403     {                                             277     {
                                                   >> 278       // Save random engine if requested for debugging
                                                   >> 279       if (G4Hadronic_Random_File) {
                                                   >> 280          CLHEP::HepRandom::saveEngineStatus(G4Hadronic_Random_File);
                                                   >> 281       }
404       // Call the interaction                     282       // Call the interaction
405       result = theInteraction->ApplyYourself(     283       result = theInteraction->ApplyYourself( thePro, targetNucleus);
406       ++reentryCount;                             284       ++reentryCount;
407     }                                             285     }
408     catch(G4HadronicException & aR)               286     catch(G4HadronicException & aR)
409     {                                             287     {
410       G4ExceptionDescription ed;                  288       G4ExceptionDescription ed;
411       aR.Report(ed);                              289       aR.Report(ed);
412       ed << "Call for " << theInteraction->Get    290       ed << "Call for " << theInteraction->GetModelName() << G4endl;
413       ed << "Target element "<<anElement->GetN    291       ed << "Target element "<<anElement->GetName()<<"  Z= "
414    << targetNucleus.GetZ_asInt()                  292    << targetNucleus.GetZ_asInt()
415    << "  A= " << targetNucleus.GetA_asInt() <<    293    << "  A= " << targetNucleus.GetA_asInt() << G4endl;
416       DumpState(aTrack,"ApplyYourself",ed);       294       DumpState(aTrack,"ApplyYourself",ed);
417       ed << " ApplyYourself failed" << G4endl;    295       ed << " ApplyYourself failed" << G4endl;
418       G4Exception("G4HadronicProcess::PostStep    296       G4Exception("G4HadronicProcess::PostStepDoIt", "had006", FatalException,
419       ed);                                        297       ed);
420     }                                             298     }
421                                                   299 
422     // Check the result for catastrophic energ    300     // Check the result for catastrophic energy non-conservation
423     result = CheckResult(thePro, targetNucleus    301     result = CheckResult(thePro, targetNucleus, result);
424                                                   302 
425     if(reentryCount>100) {                        303     if(reentryCount>100) {
426       G4ExceptionDescription ed;                  304       G4ExceptionDescription ed;
427       ed << "Call for " << theInteraction->Get    305       ed << "Call for " << theInteraction->GetModelName() << G4endl;
428       ed << "Target element "<<anElement->GetN    306       ed << "Target element "<<anElement->GetName()<<"  Z= "
429    << targetNucleus.GetZ_asInt()                  307    << targetNucleus.GetZ_asInt()
430    << "  A= " << targetNucleus.GetA_asInt() <<    308    << "  A= " << targetNucleus.GetA_asInt() << G4endl;
431       DumpState(aTrack,"ApplyYourself",ed);       309       DumpState(aTrack,"ApplyYourself",ed);
432       ed << " ApplyYourself does not completed    310       ed << " ApplyYourself does not completed after 100 attempts" << G4endl;
433       G4Exception("G4HadronicProcess::PostStep    311       G4Exception("G4HadronicProcess::PostStepDoIt", "had006", FatalException,
434       ed);                                        312       ed);
435     }                                             313     }
436   }                                               314   }
437   while(!result);  /* Loop checking, 30-Oct-20    315   while(!result);  /* Loop checking, 30-Oct-2015, G.Folger */
438                                                   316 
439   // Check whether kaon0 or anti_kaon0 are pre    317   // Check whether kaon0 or anti_kaon0 are present between the secondaries: 
440   // if this is the case, transform them into     318   // if this is the case, transform them into either kaon0S or kaon0L,
441   // with equal, 50% probability, keeping thei    319   // with equal, 50% probability, keeping their dynamical masses (and
442   // the other kinematical properties).           320   // the other kinematical properties). 
443   // When this happens - very rarely - a "Just    321   // When this happens - very rarely - a "JustWarning" exception is thrown.
444   // Because Fluka-Cern produces kaon0 and ant << 322   G4int nSec = result->GetNumberOfSecondaries();
445   // of warnings to max 1 per thread.          << 
446   G4int nSec = (G4int)result->GetNumberOfSecon << 
447   if ( nSec > 0 ) {                               323   if ( nSec > 0 ) {
448     for ( G4int i = 0; i < nSec; ++i ) {          324     for ( G4int i = 0; i < nSec; ++i ) {
449       auto dynamicParticle = result->GetSecond << 325       G4DynamicParticle* dynamicParticle = result->GetSecondary(i)->GetParticle();
450       auto part = dynamicParticle->GetParticle << 326       const G4ParticleDefinition* particleDefinition = 
451       if ( part == G4KaonZero::Definition() || << 327         dynamicParticle->GetParticleDefinition();
452            part == G4AntiKaonZero::Definition( << 328       if ( particleDefinition == G4KaonZero::Definition() || 
                                                   >> 329            particleDefinition == G4AntiKaonZero::Definition() ) {
453         G4ParticleDefinition* newPart;            330         G4ParticleDefinition* newPart;
454         if ( G4UniformRand() > 0.5 ) { newPart << 331         if( G4UniformRand() > 0.5 ) { newPart = G4KaonZeroShort::Definition(); }
455         else { newPart = G4KaonZeroLong::Defin    332         else { newPart = G4KaonZeroLong::Definition(); }
456         dynamicParticle->SetDefinition( newPar    333         dynamicParticle->SetDefinition( newPart );
457   if ( nKaonWarn < 1 ) {                       << 334   if(nKaonWarn < 5) {
458     ++nKaonWarn;                                  335     ++nKaonWarn;
459     G4ExceptionDescription ed;                    336     G4ExceptionDescription ed;
460     ed << " Hadronic model " << theInteraction    337     ed << " Hadronic model " << theInteraction->GetModelName() << G4endl;
461     ed << " created " << part->GetParticleName << 338     ed << " created " << particleDefinition->GetParticleName() << G4endl;
462     ed << " -> forced to be " << newPart->GetP    339     ed << " -> forced to be " << newPart->GetParticleName() << G4endl;
463     G4Exception( "G4HadronicProcess::PostStepD    340     G4Exception( "G4HadronicProcess::PostStepDoIt", "had007", JustWarning, ed );
464   }                                               341   }
465       }                                           342       }
466     }                                             343     }
467   }                                               344   }
468                                                   345 
469   result->SetTrafoToLab(thePro.GetTrafoToLab()    346   result->SetTrafoToLab(thePro.GetTrafoToLab());
                                                   >> 347 
                                                   >> 348   ClearNumberOfInteractionLengthLeft();
                                                   >> 349 
470   FillResult(result, aTrack);                     350   FillResult(result, aTrack);
471                                                   351 
472   if (epReportLevel != 0) {                       352   if (epReportLevel != 0) {
473     CheckEnergyMomentumConservation(aTrack, ta    353     CheckEnergyMomentumConservation(aTrack, targetNucleus);
474   }                                               354   }
475   //G4cout << "PostStepDoIt done nICelectrons=    355   //G4cout << "PostStepDoIt done nICelectrons= " << nICelectrons << G4endl;
476   return theTotalResult;                          356   return theTotalResult;
477 }                                                 357 }
478                                                   358 
479 void G4HadronicProcess::ProcessDescription(std    359 void G4HadronicProcess::ProcessDescription(std::ostream& outFile) const
480 {                                                 360 {
481   outFile << "The description for this process    361   outFile << "The description for this process has not been written yet.\n";
482 }                                                 362 }
483                                                   363 
                                                   >> 364 
484 G4double G4HadronicProcess::XBiasSurvivalProba    365 G4double G4HadronicProcess::XBiasSurvivalProbability()
485 {                                                 366 {
486   G4double nLTraversed = GetTotalNumberOfInter    367   G4double nLTraversed = GetTotalNumberOfInteractionLengthTraversed();
487   G4double biasedProbability = 1.-G4Exp(-nLTra    368   G4double biasedProbability = 1.-G4Exp(-nLTraversed);
488   G4double realProbability = 1-G4Exp(-nLTraver    369   G4double realProbability = 1-G4Exp(-nLTraversed/aScaleFactor);
489   G4double result = (biasedProbability-realPro    370   G4double result = (biasedProbability-realProbability)/biasedProbability;
490   return result;                                  371   return result;
491 }                                                 372 }
492                                                   373 
493 G4double G4HadronicProcess::XBiasSecondaryWeig    374 G4double G4HadronicProcess::XBiasSecondaryWeight()
494 {                                                 375 {
495   G4double nLTraversed = GetTotalNumberOfInter    376   G4double nLTraversed = GetTotalNumberOfInteractionLengthTraversed();
496   G4double result =                               377   G4double result =
497      1./aScaleFactor*G4Exp(-nLTraversed/aScale    378      1./aScaleFactor*G4Exp(-nLTraversed/aScaleFactor*(1-1./aScaleFactor));
498   return result;                                  379   return result;
499 }                                                 380 }
500                                                   381 
501 void                                              382 void
502 G4HadronicProcess::FillResult(G4HadFinalState     383 G4HadronicProcess::FillResult(G4HadFinalState * aR, const G4Track & aT)
503 {                                                 384 {
504   theTotalResult->ProposeLocalEnergyDeposit(aR    385   theTotalResult->ProposeLocalEnergyDeposit(aR->GetLocalEnergyDeposit());
505   const G4ThreeVector& dir = aT.GetMomentumDir    386   const G4ThreeVector& dir = aT.GetMomentumDirection();
506                                                   387 
507   G4double efinal = std::max(aR->GetEnergyChan    388   G4double efinal = std::max(aR->GetEnergyChange(), 0.0);
508                                                   389 
509   // check status of primary                      390   // check status of primary
510   if(aR->GetStatusChange() == stopAndKill) {      391   if(aR->GetStatusChange() == stopAndKill) {
511     theTotalResult->ProposeTrackStatus(fStopAn    392     theTotalResult->ProposeTrackStatus(fStopAndKill);
512     theTotalResult->ProposeEnergy( 0.0 );         393     theTotalResult->ProposeEnergy( 0.0 );
513                                                   394 
514     // check its final energy                     395     // check its final energy
515   } else if(0.0 == efinal) {                      396   } else if(0.0 == efinal) {
516     theTotalResult->ProposeEnergy( 0.0 );         397     theTotalResult->ProposeEnergy( 0.0 );
517     if(aT.GetParticleDefinition()->GetProcessM    398     if(aT.GetParticleDefinition()->GetProcessManager()
518        ->GetAtRestProcessVector()->size() > 0)    399        ->GetAtRestProcessVector()->size() > 0)
519          { theTotalResult->ProposeTrackStatus(    400          { theTotalResult->ProposeTrackStatus(fStopButAlive); }
520     else { theTotalResult->ProposeTrackStatus(    401     else { theTotalResult->ProposeTrackStatus(fStopAndKill); }
521                                                   402 
522     // primary is not killed apply rotation an    403     // primary is not killed apply rotation and Lorentz transformation
523   } else  {                                       404   } else  {
524     theTotalResult->ProposeTrackStatus(fAlive)    405     theTotalResult->ProposeTrackStatus(fAlive);
525     G4ThreeVector newDir = aR->GetMomentumChan    406     G4ThreeVector newDir = aR->GetMomentumChange();
526     newDir.rotateUz(dir);                         407     newDir.rotateUz(dir);
527     theTotalResult->ProposeMomentumDirection(n    408     theTotalResult->ProposeMomentumDirection(newDir);
528     theTotalResult->ProposeEnergy(efinal);        409     theTotalResult->ProposeEnergy(efinal);
529   }                                               410   }
530   //G4cout << "FillResult: Efinal= " << efinal    411   //G4cout << "FillResult: Efinal= " << efinal << " status= " 
531   //   << theTotalResult->GetTrackStatus()        412   //   << theTotalResult->GetTrackStatus() 
532   //   << "  fKill= " << fStopAndKill << G4end    413   //   << "  fKill= " << fStopAndKill << G4endl;
533                                                   414  
534   // check secondaries                            415   // check secondaries 
535   nICelectrons = 0;                               416   nICelectrons = 0;
536   G4int nSec = (G4int)aR->GetNumberOfSecondari << 417   if(idxIC == -1) { 
                                                   >> 418     G4int idx = G4PhysicsModelCatalog::GetIndex("e-InternalConvertion");
                                                   >> 419     idxIC =  -1 == idx ? -2 : idx; 
                                                   >> 420   } 
                                                   >> 421   G4int nSec = aR->GetNumberOfSecondaries();
537   theTotalResult->SetNumberOfSecondaries(nSec)    422   theTotalResult->SetNumberOfSecondaries(nSec);
538   G4double time0 = aT.GetGlobalTime();            423   G4double time0 = aT.GetGlobalTime();
539                                                   424 
540   for (G4int i = 0; i < nSec; ++i) {              425   for (G4int i = 0; i < nSec; ++i) {
541     G4DynamicParticle* dynParticle = aR->GetSe    426     G4DynamicParticle* dynParticle = aR->GetSecondary(i)->GetParticle();
542                                                   427 
543     // apply rotation                             428     // apply rotation
544     G4ThreeVector newDir = dynParticle->GetMom    429     G4ThreeVector newDir = dynParticle->GetMomentumDirection();
545     newDir.rotateUz(dir);                         430     newDir.rotateUz(dir);
546     dynParticle->SetMomentumDirection(newDir);    431     dynParticle->SetMomentumDirection(newDir);
547                                                   432 
548     // check if secondary is on the mass shell    433     // check if secondary is on the mass shell
549     const G4ParticleDefinition* part = dynPart    434     const G4ParticleDefinition* part = dynParticle->GetDefinition();
550     G4double mass = part->GetPDGMass();           435     G4double mass = part->GetPDGMass();
551     G4double dmass= dynParticle->GetMass();       436     G4double dmass= dynParticle->GetMass();
552     const G4double delta_mass_lim = 1.0*CLHEP:    437     const G4double delta_mass_lim = 1.0*CLHEP::keV;
553     const G4double delta_ekin = 0.001*CLHEP::e    438     const G4double delta_ekin = 0.001*CLHEP::eV;
554     if(std::abs(dmass - mass) > delta_mass_lim    439     if(std::abs(dmass - mass) > delta_mass_lim) {
555       G4double e =                             << 440       G4double e = std::max(dynParticle->GetKineticEnergy() + dmass - mass, delta_ekin);
556         std::max(dynParticle->GetKineticEnergy << 441       if(G4HadronicProcess_debug_flag) {
557       if(verboseLevel > 1) {                   << 
558   G4ExceptionDescription ed;                      442   G4ExceptionDescription ed;
559   ed << "TrackID= "<< aT.GetTrackID()             443   ed << "TrackID= "<< aT.GetTrackID()
560      << "  " << aT.GetParticleDefinition()->Ge    444      << "  " << aT.GetParticleDefinition()->GetParticleName()
561      << " Target Z= " << targetNucleus.GetZ_as    445      << " Target Z= " << targetNucleus.GetZ_asInt() << "  A= "
562      << targetNucleus.GetA_asInt()                446      << targetNucleus.GetA_asInt() 
563      << " Ekin(GeV)= " << aT.GetKineticEnergy(    447      << " Ekin(GeV)= " << aT.GetKineticEnergy()/CLHEP::GeV
564      << "\n Secondary is out of mass shell: "     448      << "\n Secondary is out of mass shell: " << part->GetParticleName()
565      << "  EkinNew(MeV)= " << e                   449      << "  EkinNew(MeV)= " << e  
566      << " DeltaMass(MeV)= " << dmass - mass <<    450      << " DeltaMass(MeV)= " << dmass - mass << G4endl;
567   G4Exception("G4HadronicProcess::FillResults"    451   G4Exception("G4HadronicProcess::FillResults", "had012", JustWarning, ed);
568       }                                           452       }
569       dynParticle->SetKineticEnergy(e);           453       dynParticle->SetKineticEnergy(e);
570       dynParticle->SetMass(mass);                 454       dynParticle->SetMass(mass);               
571     }                                             455     }
572     G4int idModel = aR->GetSecondary(i)->GetCr << 456     G4int idxModel = aR->GetSecondary(i)->GetCreatorModelType(); 
                                                   >> 457     //if(idxIC == idxModel) { ++nICelectrons; }
573     if(part->GetPDGEncoding() == 11) { ++nICel    458     if(part->GetPDGEncoding() == 11) { ++nICelectrons; }
574                                                   459       
575     // time of interaction starts from zero +     460     // time of interaction starts from zero + global time
576     G4double time = std::max(aR->GetSecondary(    461     G4double time = std::max(aR->GetSecondary(i)->GetTime(), 0.0) + time0;
577                                                   462 
578     G4Track* track = new G4Track(dynParticle,     463     G4Track* track = new G4Track(dynParticle, time, aT.GetPosition());
579     track->SetCreatorModelID(idModel);         << 464     track->SetCreatorModelIndex(idxModel);
580     track->SetParentResonanceDef(aR->GetSecond << 
581     track->SetParentResonanceID(aR->GetSeconda << 
582     G4double newWeight = fWeight*aR->GetSecond    465     G4double newWeight = fWeight*aR->GetSecondary(i)->GetWeight();
583     track->SetWeight(newWeight);                  466     track->SetWeight(newWeight);
584     track->SetTouchableHandle(aT.GetTouchableH    467     track->SetTouchableHandle(aT.GetTouchableHandle());
585     theTotalResult->AddSecondary(track);          468     theTotalResult->AddSecondary(track);
                                                   >> 469     if (G4HadronicProcess_debug_flag) {
                                                   >> 470       G4double e = dynParticle->GetKineticEnergy();
                                                   >> 471       if (e == 0.0) {
                                                   >> 472   G4ExceptionDescription ed;
                                                   >> 473   DumpState(aT,"Secondary has zero energy",ed);
                                                   >> 474   ed << "Secondary " << part->GetParticleName()
                                                   >> 475      << G4endl;
                                                   >> 476   G4Exception("G4HadronicProcess::FillResults", "had011", 
                                                   >> 477           JustWarning,ed);
                                                   >> 478       }
                                                   >> 479     }
586   }                                               480   }
587   aR->Clear();                                    481   aR->Clear();
588   // G4cout << "FillResults done nICe= " << nI    482   // G4cout << "FillResults done nICe= " << nICelectrons << G4endl;
589 }                                                 483 }
590                                                   484 
591 void G4HadronicProcess::MultiplyCrossSectionBy    485 void G4HadronicProcess::MultiplyCrossSectionBy(G4double factor)
592 {                                                 486 {
593   BiasCrossSectionByFactor(factor);               487   BiasCrossSectionByFactor(factor);
594 }                                                 488 }
595                                                   489 
596 void G4HadronicProcess::BiasCrossSectionByFact    490 void G4HadronicProcess::BiasCrossSectionByFactor(G4double aScale)
597 {                                                 491 {
598   if (aScale <= 0.0) {                            492   if (aScale <= 0.0) {
599     G4ExceptionDescription ed;                    493     G4ExceptionDescription ed;
600     ed << " Wrong biasing factor " << aScale <    494     ed << " Wrong biasing factor " << aScale << " for " << GetProcessName();
601     G4Exception("G4HadronicProcess::BiasCrossS    495     G4Exception("G4HadronicProcess::BiasCrossSectionByFactor", "had010", 
602                 JustWarning, ed, "Cross-sectio    496                 JustWarning, ed, "Cross-section bias is ignored");
603   } else {                                        497   } else {
604     aScaleFactor = aScale;                        498     aScaleFactor = aScale;
605   }                                               499   }
606 }                                                 500 }
607                                                   501 
608 G4HadFinalState* G4HadronicProcess::CheckResul    502 G4HadFinalState* G4HadronicProcess::CheckResult(const G4HadProjectile & aPro,
609             const G4Nucleus &aNucleus,            503             const G4Nucleus &aNucleus, 
610             G4HadFinalState * result)             504             G4HadFinalState * result)
611 {                                                 505 {
612   // check for catastrophic energy non-conserv    506   // check for catastrophic energy non-conservation
613   // to re-sample the interaction                 507   // to re-sample the interaction
                                                   >> 508 
614   G4HadronicInteraction * theModel = GetHadron    509   G4HadronicInteraction * theModel = GetHadronicInteraction();
615   G4double nuclearMass(0);                        510   G4double nuclearMass(0);
616   if (nullptr != theModel) {                   << 511   if (theModel) {
617                                                   512 
618     // Compute final-state total energy           513     // Compute final-state total energy
619     G4double finalE(0.);                          514     G4double finalE(0.);
620     G4int nSec = (G4int)result->GetNumberOfSec << 515     G4int nSec = result->GetNumberOfSecondaries();
621                                                   516 
622     nuclearMass = G4NucleiProperties::GetNucle    517     nuclearMass = G4NucleiProperties::GetNuclearMass(aNucleus.GetA_asInt(),
623                  aNucleus.GetZ_asInt());          518                  aNucleus.GetZ_asInt());
624     if (result->GetStatusChange() != stopAndKi    519     if (result->GetStatusChange() != stopAndKill) {
625       // Interaction didn't complete, returned    520       // Interaction didn't complete, returned "do nothing" state 
626       // and reset nucleus or the primary surv    521       // and reset nucleus or the primary survived the interaction 
627       // (e.g. electro-nuclear ) => keep  nucl    522       // (e.g. electro-nuclear ) => keep  nucleus
628       finalE=result->GetLocalEnergyDeposit() +    523       finalE=result->GetLocalEnergyDeposit() +
629              aPro.GetDefinition()->GetPDGMass(    524              aPro.GetDefinition()->GetPDGMass() + result->GetEnergyChange();
630       if( nSec == 0 ){                            525       if( nSec == 0 ){
631          // Since there are no secondaries, th    526          // Since there are no secondaries, there is no recoil nucleus.
632          // To check energy balance we must ne    527          // To check energy balance we must neglect the initial nucleus too.
633         nuclearMass=0.0;                          528         nuclearMass=0.0;
634       }                                           529       }
635     }                                             530     }
636     for (G4int i = 0; i < nSec; ++i) {         << 531     for (G4int i = 0; i < nSec; i++) {
637       G4DynamicParticle *pdyn=result->GetSecon    532       G4DynamicParticle *pdyn=result->GetSecondary(i)->GetParticle();
638       finalE += pdyn->GetTotalEnergy();           533       finalE += pdyn->GetTotalEnergy();
639       G4double mass_pdg=pdyn->GetDefinition()-    534       G4double mass_pdg=pdyn->GetDefinition()->GetPDGMass();
640       G4double mass_dyn=pdyn->GetMass();          535       G4double mass_dyn=pdyn->GetMass();
641       if ( std::abs(mass_pdg - mass_dyn) > 0.1    536       if ( std::abs(mass_pdg - mass_dyn) > 0.1*mass_pdg + 1.*MeV ) {
642         // If it is shortlived, then a differe    537         // If it is shortlived, then a difference less than 3 times the width is acceptable
643         if ( pdyn->GetDefinition()->IsShortLiv    538         if ( pdyn->GetDefinition()->IsShortLived()  &&
644              std::abs(mass_pdg - mass_dyn) < 3    539              std::abs(mass_pdg - mass_dyn) < 3.0*pdyn->GetDefinition()->GetPDGWidth() ) {
645           continue;                               540           continue;
646         }                                         541         }
647   result->Clear();                                542   result->Clear();
648   result = nullptr;                               543   result = nullptr;
649   G4ExceptionDescription desc;                    544   G4ExceptionDescription desc;
650   desc << "Warning: Secondary with off-shell d    545   desc << "Warning: Secondary with off-shell dynamic mass detected:  " 
651        << G4endl                                  546        << G4endl
652        << " " << pdyn->GetDefinition()->GetPar    547        << " " << pdyn->GetDefinition()->GetParticleName()
653        << ", PDG mass: " << mass_pdg << ", dyn    548        << ", PDG mass: " << mass_pdg << ", dynamic mass: "
654        << mass_dyn << G4endl                      549        << mass_dyn << G4endl
655        << (epReportLevel<0 ? "abort the event"    550        << (epReportLevel<0 ? "abort the event" 
656      : "re-sample the interaction") << G4endl     551      : "re-sample the interaction") << G4endl
657        << " Process / Model: " <<  GetProcessN    552        << " Process / Model: " <<  GetProcessName()<< " / "
658        << theModel->GetModelName() << G4endl      553        << theModel->GetModelName() << G4endl
659        << " Primary: " << aPro.GetDefinition()    554        << " Primary: " << aPro.GetDefinition()->GetParticleName()
660        << " (" << aPro.GetDefinition()->GetPDG    555        << " (" << aPro.GetDefinition()->GetPDGEncoding() << "), "
661        << " E= " <<  aPro.Get4Momentum().e()      556        << " E= " <<  aPro.Get4Momentum().e()
662        << ", target nucleus (" << aNucleus.Get    557        << ", target nucleus (" << aNucleus.GetZ_asInt() << ", "
663        << aNucleus.GetA_asInt() << ")" << G4en    558        << aNucleus.GetA_asInt() << ")" << G4endl;
664   G4Exception("G4HadronicProcess:CheckResult()    559   G4Exception("G4HadronicProcess:CheckResult()", "had012",
665         epReportLevel<0 ? EventMustBeAborted :    560         epReportLevel<0 ? EventMustBeAborted : JustWarning,desc);
666   // must return here.....                        561   // must return here.....
667   return result;                                  562   return result;
668       }                                           563       }
669     }                                             564     }
670     G4double deltaE= nuclearMass +  aPro.GetTo    565     G4double deltaE= nuclearMass +  aPro.GetTotalEnergy() -  finalE;
671                                                   566 
672     std::pair<G4double, G4double> checkLevels     567     std::pair<G4double, G4double> checkLevels = 
673       theModel->GetFatalEnergyCheckLevels();      568       theModel->GetFatalEnergyCheckLevels();  // (relative, absolute)
674     if (std::abs(deltaE) > checkLevels.second     569     if (std::abs(deltaE) > checkLevels.second && 
675         std::abs(deltaE) > checkLevels.first*a    570         std::abs(deltaE) > checkLevels.first*aPro.GetKineticEnergy()){
676       // do not delete result, this is a point    571       // do not delete result, this is a pointer to a data member;
677       result->Clear();                            572       result->Clear();
678       result = nullptr;                           573       result = nullptr;
679       G4ExceptionDescription desc;                574       G4ExceptionDescription desc;
680       desc << "Warning: Bad energy non-conserv    575       desc << "Warning: Bad energy non-conservation detected, will "
681      << (epReportLevel<0 ? "abort the event"      576      << (epReportLevel<0 ? "abort the event" 
682          :  "re-sample the interaction") << G4    577          :  "re-sample the interaction") << G4endl
683      << " Process / Model: " <<  GetProcessNam    578      << " Process / Model: " <<  GetProcessName()<< " / " 
684      << theModel->GetModelName() << G4endl        579      << theModel->GetModelName() << G4endl
685      << " Primary: " << aPro.GetDefinition()->    580      << " Primary: " << aPro.GetDefinition()->GetParticleName()
686      << " (" << aPro.GetDefinition()->GetPDGEn    581      << " (" << aPro.GetDefinition()->GetPDGEncoding() << "), "
687      << " E= " <<  aPro.Get4Momentum().e()        582      << " E= " <<  aPro.Get4Momentum().e()
688      << ", target nucleus (" << aNucleus.GetZ_    583      << ", target nucleus (" << aNucleus.GetZ_asInt() << ", "
689      << aNucleus.GetA_asInt() << ")" << G4endl    584      << aNucleus.GetA_asInt() << ")" << G4endl
690      << " E(initial - final) = " << deltaE <<     585      << " E(initial - final) = " << deltaE << " MeV." << G4endl;
691       G4Exception("G4HadronicProcess:CheckResu    586       G4Exception("G4HadronicProcess:CheckResult()", "had012", 
692       epReportLevel<0 ? EventMustBeAborted : J    587       epReportLevel<0 ? EventMustBeAborted : JustWarning,desc);
693     }                                             588     }
694   }                                               589   }
695   return result;                                  590   return result;
696 }                                                 591 }
697                                                   592 
698 void                                              593 void
699 G4HadronicProcess::CheckEnergyMomentumConserva    594 G4HadronicProcess::CheckEnergyMomentumConservation(const G4Track& aTrack,
700                                                   595                                                    const G4Nucleus& aNucleus)
701 {                                                 596 {
702   G4int target_A=aNucleus.GetA_asInt();           597   G4int target_A=aNucleus.GetA_asInt();
703   G4int target_Z=aNucleus.GetZ_asInt();           598   G4int target_Z=aNucleus.GetZ_asInt();
704   G4double targetMass = G4NucleiProperties::Ge    599   G4double targetMass = G4NucleiProperties::GetNuclearMass(target_A,target_Z);
705   G4LorentzVector target4mom(0, 0, 0, targetMa    600   G4LorentzVector target4mom(0, 0, 0, targetMass 
706            + nICelectrons*CLHEP::electron_mass    601            + nICelectrons*CLHEP::electron_mass_c2);
707                                                   602 
708   G4LorentzVector projectile4mom = aTrack.GetD    603   G4LorentzVector projectile4mom = aTrack.GetDynamicParticle()->Get4Momentum();
709   G4int track_A = aTrack.GetDefinition()->GetB    604   G4int track_A = aTrack.GetDefinition()->GetBaryonNumber();
710   G4int track_Z = G4lrint(aTrack.GetDefinition    605   G4int track_Z = G4lrint(aTrack.GetDefinition()->GetPDGCharge());
711                                                   606 
712   G4int initial_A = target_A + track_A;           607   G4int initial_A = target_A + track_A;
713   G4int initial_Z = target_Z + track_Z - nICel    608   G4int initial_Z = target_Z + track_Z - nICelectrons;
714                                                   609 
715   G4LorentzVector initial4mom = projectile4mom    610   G4LorentzVector initial4mom = projectile4mom + target4mom;
716                                                   611 
717   // Compute final-state momentum for scatteri    612   // Compute final-state momentum for scattering and "do nothing" results
718   G4LorentzVector final4mom;                      613   G4LorentzVector final4mom;
719   G4int final_A(0), final_Z(0);                   614   G4int final_A(0), final_Z(0);
720                                                   615 
721   G4int nSec = theTotalResult->GetNumberOfSeco    616   G4int nSec = theTotalResult->GetNumberOfSecondaries();
722   if (theTotalResult->GetTrackStatus() != fSto    617   if (theTotalResult->GetTrackStatus() != fStopAndKill) {  // If it is Alive
723     // Either interaction didn't complete, ret    618     // Either interaction didn't complete, returned "do nothing" state
724     //  or    the primary survived the interac    619     //  or    the primary survived the interaction (e.g. electro-nucleus )
725                                                   620 
726     // Interaction didn't complete, returned "    621     // Interaction didn't complete, returned "do nothing" state
727     //   - or suppressed recoil  (e.g. Neutron    622     //   - or suppressed recoil  (e.g. Neutron elastic )
728     final4mom = initial4mom;                      623     final4mom = initial4mom;
729     final_A = initial_A;                          624     final_A = initial_A;
730     final_Z = initial_Z;                          625     final_Z = initial_Z;
731     if (nSec > 0) {                               626     if (nSec > 0) {
732       // The primary remains in final state (e    627       // The primary remains in final state (e.g. electro-nucleus )
733       // Use the final energy / momentum          628       // Use the final energy / momentum
734       const G4ThreeVector& v = *theTotalResult    629       const G4ThreeVector& v = *theTotalResult->GetMomentumDirection();
735       G4double ekin = theTotalResult->GetEnerg    630       G4double ekin = theTotalResult->GetEnergy();
736       G4double mass = aTrack.GetDefinition()->    631       G4double mass = aTrack.GetDefinition()->GetPDGMass();
737       G4double ptot = std::sqrt(ekin*(ekin + 2    632       G4double ptot = std::sqrt(ekin*(ekin + 2*mass));
738       final4mom.set(ptot*v.x(), ptot*v.y(), pt    633       final4mom.set(ptot*v.x(), ptot*v.y(), ptot*v.z(), mass + ekin);
739       final_A = track_A;                          634       final_A = track_A;
740       final_Z = track_Z;                          635       final_Z = track_Z;
741       // Expect that the target nucleus will h    636       // Expect that the target nucleus will have interacted,
742       //  and its products, including recoil,     637       //  and its products, including recoil, will be included in secondaries.
743     }                                             638     }
744   }                                               639   }
745   if( nSec > 0 ) {                                640   if( nSec > 0 ) {
746     G4Track* sec;                                 641     G4Track* sec;
747                                                   642 
748     for (G4int i = 0; i < nSec; i++) {            643     for (G4int i = 0; i < nSec; i++) {
749       sec = theTotalResult->GetSecondary(i);      644       sec = theTotalResult->GetSecondary(i);
750       final4mom += sec->GetDynamicParticle()->    645       final4mom += sec->GetDynamicParticle()->Get4Momentum();
751       final_A += sec->GetDefinition()->GetBary    646       final_A += sec->GetDefinition()->GetBaryonNumber();
752       final_Z += G4lrint(sec->GetDefinition()-    647       final_Z += G4lrint(sec->GetDefinition()->GetPDGCharge());
753     }                                             648     }
754   }                                               649   }
755                                                   650 
756   // Get level-checking information (used to c    651   // Get level-checking information (used to cut-off relative checks)
757   G4String processName = GetProcessName();        652   G4String processName = GetProcessName();
758   G4HadronicInteraction* theModel = GetHadroni    653   G4HadronicInteraction* theModel = GetHadronicInteraction();
759   G4String modelName("none");                     654   G4String modelName("none");
760   if (theModel) modelName = theModel->GetModel    655   if (theModel) modelName = theModel->GetModelName();
761   std::pair<G4double, G4double> checkLevels =     656   std::pair<G4double, G4double> checkLevels = epCheckLevels;
762   if (!levelsSetByProcess) {                      657   if (!levelsSetByProcess) {
763     if (theModel) checkLevels = theModel->GetE    658     if (theModel) checkLevels = theModel->GetEnergyMomentumCheckLevels();
764     checkLevels.first= std::min(checkLevels.fi    659     checkLevels.first= std::min(checkLevels.first,  epCheckLevels.first);
765     checkLevels.second=std::min(checkLevels.se    660     checkLevels.second=std::min(checkLevels.second, epCheckLevels.second);
766   }                                               661   }
767                                                   662 
768   // Compute absolute total-energy difference,    663   // Compute absolute total-energy difference, and relative kinetic-energy
769   G4bool checkRelative = (aTrack.GetKineticEne    664   G4bool checkRelative = (aTrack.GetKineticEnergy() > checkLevels.second);
770                                                   665 
771   G4LorentzVector diff = initial4mom - final4m    666   G4LorentzVector diff = initial4mom - final4mom;
772   G4double absolute = diff.e();                   667   G4double absolute = diff.e();
773   G4double relative = checkRelative ? absolute    668   G4double relative = checkRelative ? absolute/aTrack.GetKineticEnergy() : 0.;
774                                                   669 
775   G4double absolute_mom = diff.vect().mag();      670   G4double absolute_mom = diff.vect().mag();
776   G4double relative_mom = checkRelative ? abso    671   G4double relative_mom = checkRelative ? absolute_mom/aTrack.GetMomentum().mag() : 0.;
777                                                   672 
778   // Evaluate relative and absolute conservati    673   // Evaluate relative and absolute conservation
779   G4bool relPass = true;                          674   G4bool relPass = true;
780   G4String relResult = "pass";                    675   G4String relResult = "pass";
781   if (  std::abs(relative) > checkLevels.first    676   if (  std::abs(relative) > checkLevels.first
782    || std::abs(relative_mom) > checkLevels.fir    677    || std::abs(relative_mom) > checkLevels.first) {
783     relPass = false;                              678     relPass = false;
784     relResult = checkRelative ? "fail" : "N/A"    679     relResult = checkRelative ? "fail" : "N/A";
785   }                                               680   }
786                                                   681 
787   G4bool absPass = true;                          682   G4bool absPass = true;
788   G4String absResult = "pass";                    683   G4String absResult = "pass";
789   if (   std::abs(absolute) > checkLevels.seco    684   if (   std::abs(absolute) > checkLevels.second
790       || std::abs(absolute_mom) > checkLevels.    685       || std::abs(absolute_mom) > checkLevels.second ) {
791     absPass = false ;                             686     absPass = false ;
792     absResult = "fail";                           687     absResult = "fail";
793   }                                               688   }
794                                                   689 
795   G4bool chargePass = true;                       690   G4bool chargePass = true;
796   G4String chargeResult = "pass";                 691   G4String chargeResult = "pass";
797   if (   (initial_A-final_A)!=0                   692   if (   (initial_A-final_A)!=0
798       || (initial_Z-final_Z)!=0 ) {               693       || (initial_Z-final_Z)!=0 ) {
799     chargePass = checkLevels.second < DBL_MAX     694     chargePass = checkLevels.second < DBL_MAX ? false : true;
800     chargeResult = "fail";                        695     chargeResult = "fail";
801    }                                              696    }
802                                                   697 
803   G4bool conservationPass = (relPass || absPas    698   G4bool conservationPass = (relPass || absPass) && chargePass;
804                                                   699 
805   std::stringstream Myout;                        700   std::stringstream Myout;
806   G4bool Myout_notempty(false);                   701   G4bool Myout_notempty(false);
807   // Options for level of reporting detail:       702   // Options for level of reporting detail:
808   //  0. off                                      703   //  0. off
809   //  1. report only when E/p not conserved       704   //  1. report only when E/p not conserved
810   //  2. report regardless of E/p conservation    705   //  2. report regardless of E/p conservation
811   //  3. report only when E/p not conserved, w    706   //  3. report only when E/p not conserved, with model names, process names, and limits
812   //  4. report regardless of E/p conservation    707   //  4. report regardless of E/p conservation, with model names, process names, and limits
813   //  negative -1.., as above, but send output    708   //  negative -1.., as above, but send output to stderr
814                                                   709 
815   if(   std::abs(epReportLevel) == 4              710   if(   std::abs(epReportLevel) == 4
816   ||  ( std::abs(epReportLevel) == 3 && ! cons    711   ||  ( std::abs(epReportLevel) == 3 && ! conservationPass ) ){
817       Myout << " Process: " << processName <<     712       Myout << " Process: " << processName << " , Model: " <<  modelName << G4endl;
818       Myout << " Primary: " << aTrack.GetParti    713       Myout << " Primary: " << aTrack.GetParticleDefinition()->GetParticleName()
819             << " (" << aTrack.GetParticleDefin    714             << " (" << aTrack.GetParticleDefinition()->GetPDGEncoding() << "),"
820             << " E= " <<  aTrack.GetDynamicPar    715             << " E= " <<  aTrack.GetDynamicParticle()->Get4Momentum().e()
821       << ", target nucleus (" << aNucleus.GetZ    716       << ", target nucleus (" << aNucleus.GetZ_asInt() << ","
822       << aNucleus.GetA_asInt() << ")" << G4end    717       << aNucleus.GetA_asInt() << ")" << G4endl;
823       Myout_notempty=true;                        718       Myout_notempty=true;
824   }                                               719   }
825   if (  std::abs(epReportLevel) == 4              720   if (  std::abs(epReportLevel) == 4
826    || std::abs(epReportLevel) == 2                721    || std::abs(epReportLevel) == 2
827    || ! conservationPass ){                       722    || ! conservationPass ){
828                                                   723 
829       Myout << "   "<< relResult  <<" relative    724       Myout << "   "<< relResult  <<" relative, limit " << checkLevels.first << ", values E/T(0) = "
830              << relative << " p/p(0)= " << rel    725              << relative << " p/p(0)= " << relative_mom  << G4endl;
831       Myout << "   "<< absResult << " absolute    726       Myout << "   "<< absResult << " absolute, limit (MeV) " << checkLevels.second/MeV << ", values E / p (MeV) = "
832              << absolute/MeV << " / " << absol    727              << absolute/MeV << " / " << absolute_mom/MeV << " 3mom: " << (diff.vect())*1./MeV <<  G4endl;
833       Myout << "   "<< chargeResult << " charg    728       Myout << "   "<< chargeResult << " charge/baryon number balance " << (initial_Z-final_Z) << " / " << (initial_A-final_A) << " "<<  G4endl;
834       Myout_notempty=true;                        729       Myout_notempty=true;
835                                                   730 
836   }                                               731   }
837   Myout.flush();                                  732   Myout.flush();
838   if ( Myout_notempty ) {                         733   if ( Myout_notempty ) {
839      if (epReportLevel > 0)      G4cout << Myo    734      if (epReportLevel > 0)      G4cout << Myout.str()<< G4endl;
840      else if (epReportLevel < 0) G4cerr << Myo    735      else if (epReportLevel < 0) G4cerr << Myout.str()<< G4endl;
841   }                                               736   }
842 }                                                 737 }
843                                                   738 
844 void G4HadronicProcess::DumpState(const G4Trac    739 void G4HadronicProcess::DumpState(const G4Track& aTrack,
845           const G4String& method,                 740           const G4String& method,
846           G4ExceptionDescription& ed)             741           G4ExceptionDescription& ed)
847 {                                                 742 {
848   ed << "Unrecoverable error in the method " <    743   ed << "Unrecoverable error in the method " << method << " of "
849      << GetProcessName() << G4endl;               744      << GetProcessName() << G4endl;
850   ed << "TrackID= "<< aTrack.GetTrackID() << "    745   ed << "TrackID= "<< aTrack.GetTrackID() << "  ParentID= "
851      << aTrack.GetParentID()                      746      << aTrack.GetParentID()
852      << "  " << aTrack.GetParticleDefinition()    747      << "  " << aTrack.GetParticleDefinition()->GetParticleName()
853      << G4endl;                                   748      << G4endl;
854   ed << "Ekin(GeV)= " << aTrack.GetKineticEner    749   ed << "Ekin(GeV)= " << aTrack.GetKineticEnergy()/CLHEP::GeV
855      << ";  direction= " << aTrack.GetMomentum    750      << ";  direction= " << aTrack.GetMomentumDirection() << G4endl;
856   ed << "Position(mm)= " << aTrack.GetPosition    751   ed << "Position(mm)= " << aTrack.GetPosition()/CLHEP::mm << ";";
857                                                   752 
858   if (aTrack.GetMaterial()) {                     753   if (aTrack.GetMaterial()) {
859     ed << "  material " << aTrack.GetMaterial(    754     ed << "  material " << aTrack.GetMaterial()->GetName();
860   }                                               755   }
861   ed << G4endl;                                   756   ed << G4endl;
862                                                   757 
863   if (aTrack.GetVolume()) {                       758   if (aTrack.GetVolume()) {
864     ed << "PhysicalVolume  <" << aTrack.GetVol    759     ed << "PhysicalVolume  <" << aTrack.GetVolume()->GetName()
865        << ">" << G4endl;                          760        << ">" << G4endl;
866   }                                               761   }
867 }                                                 762 }
868                                                   763 
869 void G4HadronicProcess::DumpPhysicsTable(const    764 void G4HadronicProcess::DumpPhysicsTable(const G4ParticleDefinition& p)
870 {                                                 765 { 
871   theCrossSectionDataStore->DumpPhysicsTable(p    766   theCrossSectionDataStore->DumpPhysicsTable(p); 
872 }                                                 767 }
873                                                   768 
874 void G4HadronicProcess::AddDataSet(G4VCrossSec    769 void G4HadronicProcess::AddDataSet(G4VCrossSectionDataSet * aDataSet)
875 {                                                 770 { 
876   theCrossSectionDataStore->AddDataSet(aDataSe    771   theCrossSectionDataStore->AddDataSet(aDataSet);
877 }                                                 772 }
878                                                   773 
879 std::vector<G4HadronicInteraction*>&              774 std::vector<G4HadronicInteraction*>& 
880 G4HadronicProcess::GetHadronicInteractionList(    775 G4HadronicProcess::GetHadronicInteractionList()
881 {                                                 776 { 
882   return theEnergyRangeManager.GetHadronicInte    777   return theEnergyRangeManager.GetHadronicInteractionList(); 
883 }                                                 778 }
884                                                   779 
885 G4HadronicInteraction*                            780 G4HadronicInteraction*
886 G4HadronicProcess::GetHadronicModel(const G4St    781 G4HadronicProcess::GetHadronicModel(const G4String& modelName)
887 {                                                 782 { 
888   std::vector<G4HadronicInteraction*>& list       783   std::vector<G4HadronicInteraction*>& list
889         = theEnergyRangeManager.GetHadronicInt    784         = theEnergyRangeManager.GetHadronicInteractionList();
890   for (auto & mod : list) {                    << 785   for (size_t li=0; li<list.size(); li++) {
891     if (mod->GetModelName() == modelName) retu << 786     if (list[li]->GetModelName() == modelName) return list[li];
892   }                                               787   }
893   return nullptr;                                 788   return nullptr;
894 }                                              << 
895                                                << 
896 G4double                                       << 
897 G4HadronicProcess::ComputeCrossSection(const G << 
898                const G4Material* mat,          << 
899                const G4double kinEnergy)       << 
900 {                                              << 
901   auto dp = new G4DynamicParticle(part, unitVe << 
902   G4double xs = theCrossSectionDataStore->Comp << 
903   delete dp;                                   << 
904   return xs;                                   << 
905 }                                              << 
906                                                << 
907 void G4HadronicProcess::RecomputeXSandMFP(cons << 
908 {                                              << 
909   auto dp = new G4DynamicParticle(currentParti << 
910   theLastCrossSection = aScaleFactor*          << 
911     theCrossSectionDataStore->ComputeCrossSect << 
912   theMFP = (theLastCrossSection > 0.0) ? 1.0/t << 
913   delete dp;                                   << 
914 }                                              << 
915                                                << 
916 void G4HadronicProcess::UpdateCrossSectionAndM << 
917 {                                              << 
918   if(fXSType == fHadNoIntegral) {              << 
919     DefineXSandMFP();                          << 
920                                                << 
921   } else if(fXSType == fHadIncreasing) {       << 
922     if(e*invLambdaFactor < mfpKinEnergy) {     << 
923       mfpKinEnergy = e;                        << 
924       ComputeXSandMFP();                       << 
925     }                                          << 
926                                                << 
927   } else if(fXSType == fHadDecreasing) {       << 
928     if(e < mfpKinEnergy && mfpKinEnergy > minK << 
929       G4double e1 = std::max(e*lambdaFactor, m << 
930       mfpKinEnergy = e1;                       << 
931       RecomputeXSandMFP(e1);                   << 
932     }                                          << 
933                                                << 
934   } else if(fXSType == fHadOnePeak) {          << 
935     G4double epeak = (*theEnergyOfCrossSection << 
936     if(e <= epeak) {                           << 
937       if(e*invLambdaFactor < mfpKinEnergy) {   << 
938         mfpKinEnergy = e;                      << 
939   ComputeXSandMFP();                           << 
940       }                                        << 
941     } else if(e < mfpKinEnergy) {              << 
942       G4double e1 = std::max(epeak, e*lambdaFa << 
943       mfpKinEnergy = e1;                       << 
944       RecomputeXSandMFP(e1);                   << 
945     }                                          << 
946                                                << 
947   } else if(fXSType == fHadTwoPeaks) {         << 
948     G4TwoPeaksHadXS* xs = (*fXSpeaks)[matIdx]; << 
949     const G4double e1peak = xs->e1peak;        << 
950                                                << 
951     // below the 1st peak                      << 
952     if(e <= e1peak) {                          << 
953       if(e*invLambdaFactor < mfpKinEnergy) {   << 
954         mfpKinEnergy = e;                      << 
955   ComputeXSandMFP();                           << 
956       }                                        << 
957       return;                                  << 
958     }                                          << 
959     const G4double e1deep = xs->e1deep;        << 
960     // above the 1st peak, below the deep      << 
961     if(e <= e1deep) {                          << 
962       if(mfpKinEnergy >= e1deep || e <= mfpKin << 
963         const G4double e1 = std::max(e1peak, e << 
964         mfpKinEnergy = e1;                     << 
965   RecomputeXSandMFP(e1);                       << 
966       }                                        << 
967       return;                                  << 
968     }                                          << 
969     const G4double e2peak = xs->e2peak;        << 
970     // above the deep, below 2nd peak          << 
971     if(e <= e2peak) {                          << 
972       if(e*invLambdaFactor < mfpKinEnergy) {   << 
973         mfpKinEnergy = e;                      << 
974   ComputeXSandMFP();                           << 
975       }                                        << 
976       return;                                  << 
977     }                                          << 
978     const G4double e2deep = xs->e2deep;        << 
979     // above the 2nd peak, below the deep      << 
980     if(e <= e2deep) {                          << 
981       if(mfpKinEnergy >= e2deep || e <= mfpKin << 
982         const G4double e1 = std::max(e2peak, e << 
983         mfpKinEnergy = e1;                     << 
984   RecomputeXSandMFP(e1);                       << 
985       }                                        << 
986       return;                                  << 
987     }                                          << 
988     const G4double e3peak = xs->e3peak;        << 
989     // above the deep, below 3d peak           << 
990     if(e <= e3peak) {                          << 
991       if(e*invLambdaFactor < mfpKinEnergy) {   << 
992         mfpKinEnergy = e;                      << 
993   ComputeXSandMFP();                           << 
994       }                                        << 
995       return;                                  << 
996     }                                          << 
997     // above 3d peak                           << 
998     if(e <= mfpKinEnergy) {                    << 
999       const G4double e1 = std::max(e3peak, e*l << 
1000       mfpKinEnergy = e1;                      << 
1001       RecomputeXSandMFP(e1);                  << 
1002     }                                         << 
1003                                               << 
1004   } else {                                    << 
1005     DefineXSandMFP();                         << 
1006   }                                           << 
1007 }                                                789 }
1008                                                  790