Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/inclxx/incl_physics/src/G4INCLCascade.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 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 // INCL++ intra-nuclear cascade model
 27 // Alain Boudard, CEA-Saclay, France
 28 // Joseph Cugnon, University of Liege, Belgium
 29 // Jean-Christophe David, CEA-Saclay, France
 30 // Pekka Kaitaniemi, CEA-Saclay, France, and Helsinki Institute of Physics, Finland
 31 // Sylvie Leray, CEA-Saclay, France
 32 // Davide Mancusi, CEA-Saclay, France
 33 //
 34 #define INCLXX_IN_GEANT4_MODE 1
 35 
 36 #include "globals.hh"
 37 
 38 /** \file G4INCLCascade.cc
 39  *
 40  * INCL Cascade
 41  */
 42 #include "G4INCLCascade.hh"
 43 #include "G4INCLRandom.hh"
 44 #include "G4INCLStandardPropagationModel.hh"
 45 #include "G4INCLParticleTable.hh"
 46 #include "G4INCLParticle.hh"
 47 #include "G4INCLNuclearMassTable.hh"
 48 #include "G4INCLGlobalInfo.hh"
 49 #include "G4INCLNucleus.hh"
 50 
 51 #include "G4INCLPauliBlocking.hh"
 52 
 53 #include "G4INCLCrossSections.hh"
 54 
 55 #include "G4INCLPhaseSpaceGenerator.hh"
 56 
 57 #include "G4INCLLogger.hh"
 58 #include "G4INCLGlobals.hh"
 59 #include "G4INCLNuclearDensityFactory.hh"
 60 
 61 #include "G4INCLINuclearPotential.hh"
 62 
 63 #include "G4INCLCoulombDistortion.hh"
 64 
 65 #include "G4INCLClustering.hh"
 66 
 67 #include "G4INCLIntersection.hh"
 68 
 69 #include "G4INCLBinaryCollisionAvatar.hh"
 70 
 71 #include "G4INCLCascadeAction.hh"
 72 #include "G4INCLAvatarDumpAction.hh"
 73 
 74 #include <cstring> 
 75 #include <cstdlib>
 76 #include <numeric>
 77 
 78 #include "G4INCLPbarAtrestEntryChannel.hh"
 79 
 80 namespace G4INCL {
 81   
 82   INCL::INCL(Config const * const config)
 83     :propagationModel(0), theA(208), theZ(82), theS(0),
 84     targetInitSuccess(false),
 85     maxImpactParameter(0.),
 86     maxUniverseRadius(0.),
 87     maxInteractionDistance(0.),
 88     fixedImpactParameter(0.),
 89     theConfig(config),
 90     nucleus(NULL),
 91     forceTransparent(false),
 92     minRemnantSize(4)
 93   {
 94     // Set the logger object.
 95 #ifdef INCLXX_IN_GEANT4_MODE
 96     Logger::initVerbosityLevelFromEnvvar();
 97 #else // INCLXX_IN_GEANT4_MODE
 98     Logger::initialize(theConfig);
 99 #endif // INCLXX_IN_GEANT4_MODE
100 
101     // Set the random number generator algorithm. The system can support
102     // multiple different generator algorithms in a completely
103     // transparent way.
104     Random::initialize(theConfig);
105 
106     // Select the Pauli and CDPP blocking algorithms
107     Pauli::initialize(theConfig);
108 
109     // Set the cross-section set
110     CrossSections::initialize(theConfig);
111 
112     // Set the phase-space generator
113     PhaseSpaceGenerator::initialize(theConfig);
114 
115     // Select the Coulomb-distortion algorithm:
116     CoulombDistortion::initialize(theConfig);
117 
118     // Select the clustering algorithm:
119     Clustering::initialize(theConfig);
120 
121     // Initialize the INCL particle table:
122     ParticleTable::initialize(theConfig);
123 
124     // Initialize the value of cutNN in BinaryCollisionAvatar
125     BinaryCollisionAvatar::setCutNN(theConfig->getCutNN());
126 
127     // Initialize the value of strange cross section bias
128     BinaryCollisionAvatar::setBias(theConfig->getBias());
129 
130     // Propagation model is responsible for finding avatars and
131     // transporting the particles. In principle this step is "hidden"
132     // behind an abstract interface and the rest of the system does not
133     // care how the transportation and avatar finding is done. This
134     // should allow us to "easily" experiment with different avatar
135     // finding schemes and even to support things like curved
136     // trajectories in the future.
137     propagationModel = new StandardPropagationModel(theConfig->getLocalEnergyBBType(),theConfig->getLocalEnergyPiType(),theConfig->getHadronizationTime());
138     if(theConfig->getCascadeActionType() == AvatarDumpActionType)
139       cascadeAction = new AvatarDumpAction();
140     else
141       cascadeAction = new CascadeAction();
142     cascadeAction->beforeRunAction(theConfig);
143 
144     theGlobalInfo.cascadeModel = theConfig->getVersionString();
145     theGlobalInfo.deexcitationModel = theConfig->getDeExcitationString();
146 #ifdef INCL_ROOT_USE
147     theGlobalInfo.rootSelection = theConfig->getROOTSelectionString();
148 #endif
149 
150 #ifndef INCLXX_IN_GEANT4_MODE
151     // Fill in the global information
152     theGlobalInfo.At = theConfig->getTargetA();
153     theGlobalInfo.Zt = theConfig->getTargetZ();
154     theGlobalInfo.St = theConfig->getTargetS();
155     const ParticleSpecies theSpecies = theConfig->getProjectileSpecies();
156     theGlobalInfo.Ap = theSpecies.theA;
157     theGlobalInfo.Zp = theSpecies.theZ;
158     theGlobalInfo.Sp = theSpecies.theS;
159     theGlobalInfo.Ep = theConfig->getProjectileKineticEnergy();
160     theGlobalInfo.biasFactor = theConfig->getBias();
161 #endif
162 
163     fixedImpactParameter = theConfig->getImpactParameter();
164   }
165 
166   INCL::~INCL() {
167     InteractionAvatar::deleteBackupParticles();
168 #ifndef INCLXX_IN_GEANT4_MODE
169     NuclearMassTable::deleteTable();
170 #endif
171     PhaseSpaceGenerator::deletePhaseSpaceGenerator();
172     CrossSections::deleteCrossSections();
173     Pauli::deleteBlockers();
174     CoulombDistortion::deleteCoulomb();
175     Random::deleteGenerator();
176     Clustering::deleteClusteringModel();
177 #ifndef INCLXX_IN_GEANT4_MODE
178     Logger::deleteLoggerSlave();
179 #endif
180     NuclearDensityFactory::clearCache();
181     NuclearPotential::clearCache();
182     cascadeAction->afterRunAction();
183     delete cascadeAction;
184     delete propagationModel;
185     delete theConfig;
186   }
187 
188   G4bool INCL::prepareReaction(const ParticleSpecies &projectileSpecies, const G4double kineticEnergy, const G4int A, const G4int Z, const G4int S) {
189     if(A < 0 || A > 300 || Z < 1 || Z > 200) {
190       INCL_ERROR("Unsupported target: A = " << A << " Z = " << Z << " S = " << S << '\n'
191                  << "Target configuration rejected." << '\n');
192       return false;
193     }
194     if(projectileSpecies.theType==Composite &&
195        (projectileSpecies.theZ==projectileSpecies.theA || projectileSpecies.theZ==0)) {
196       INCL_ERROR("Unsupported projectile: A = " << projectileSpecies.theA << " Z = " << projectileSpecies.theZ << " S = " << projectileSpecies.theS << '\n'
197                  << "Projectile configuration rejected." << '\n');
198       return false;
199     }
200 
201     // Reset the forced-transparent flag
202     forceTransparent = false;
203 
204     // Initialise the maximum universe radius
205     initUniverseRadius(projectileSpecies, kineticEnergy, A, Z);
206     // Initialise the nucleus
207 
208 //D
209     //reset
210     G4bool ProtonIsTheVictim = false; 
211     G4bool NeutronIsTheVictim = false;
212     theEventInfo.annihilationP = false;
213     theEventInfo.annihilationN = false;
214 
215     //G4double AnnihilationBarrier = kineticEnergy;
216     if(projectileSpecies.theType == antiProton && kineticEnergy <= theConfig->getAtrestThreshold()){
217       G4double SpOverSn = 1.331;//from experiments with deuteron (E.Klempt)
218       //INCL_WARN("theA number set to A-1 from " << A <<'\n');
219 
220       G4double neutronprob;
221       if(theConfig->isNaturalTarget()){ // A = 0 in this case
222         theA = ParticleTable::drawRandomNaturalIsotope(Z) - 1; //43 and 61 are ok (Technetium and Promethium)
223         neutronprob = (theA + 1 - Z)/(theA + 1 - Z + SpOverSn*Z);  
224       }
225       else{
226         theA = A - 1;
227         neutronprob = (A - Z)/(A - Z + SpOverSn*Z);  //from experiments with deuteron (E.Klempt)
228       }
229 
230       theS = S;
231       
232       G4double rndm = Random::shoot();
233       if(rndm >= neutronprob){     //proton is annihilated
234         theEventInfo.annihilationP = true;
235         theZ = Z - 1;
236         ProtonIsTheVictim = true;
237         //INCL_WARN("theZ number set to Z-1 from " << Z << '\n');
238       }  
239       else{        //neutron is annihilated
240         theEventInfo.annihilationN = true;
241         theZ = Z;
242         NeutronIsTheVictim = true;
243       }  
244     }
245     else{ // not annihilation of pbar
246       theZ = Z;
247       theS = S;
248       if(theConfig->isNaturalTarget())
249         theA = ParticleTable::drawRandomNaturalIsotope(Z); //change order
250       else
251         theA = A;
252     }
253 
254     AnnihilationType theAType = Def;
255     if(ProtonIsTheVictim == true && NeutronIsTheVictim == false)
256     theAType = PType;
257     if(NeutronIsTheVictim == true && ProtonIsTheVictim == false)
258     theAType = NType;
259 
260 //D
261 
262     initializeTarget(theA, theZ, theS, theAType);
263     
264     // Set the maximum impact parameter
265     maxImpactParameter = CoulombDistortion::maxImpactParameter(projectileSpecies, kineticEnergy, nucleus);
266     INCL_DEBUG("Maximum impact parameter initialised: " << maxImpactParameter << '\n');
267 
268     // For forced CN events
269     initMaxInteractionDistance(projectileSpecies, kineticEnergy);
270 // Set the geometric cross sectiony section
271     if(projectileSpecies.theType == antiProton && kineticEnergy <= theConfig->getAtrestThreshold()){
272       G4int currentA = A;
273       if(theConfig->isNaturalTarget()){
274         currentA = ParticleTable::drawRandomNaturalIsotope(Z);
275       }
276       G4double kineticEnergy2=kineticEnergy;
277       if (kineticEnergy2 <= 0.) kineticEnergy2=0.001;
278       theGlobalInfo.geometricCrossSection = 9.7* //normalization factor from Corradini
279         Math::pi*std::pow((1.840 + 1.120*std::pow(currentA,(1./3.))),2)*
280         (1. + (Z*G4INCL::PhysicalConstants::eSquared*(currentA+1))/(currentA*kineticEnergy2*(1.840 + 1.120*std::pow(currentA,(1./3.))))); 
281          //xsection formula was borrowed from Corradini et al. https://doi.org/10.1016/j.physletb.2011.09.069    
282     }
283     else{
284       theGlobalInfo.geometricCrossSection =
285         Math::tenPi*std::pow(maxImpactParameter,2);
286     }
287 
288     // Set the minimum remnant size
289     if(projectileSpecies.theA > 0)
290       minRemnantSize = std::min(theA, 4);
291     else
292       minRemnantSize = std::min(theA-1, 4);
293     return true;
294   }
295 
296   G4bool INCL::initializeTarget(const G4int A, const G4int Z, const G4int S, AnnihilationType theAType) { 
297     delete nucleus;
298 
299     if (theAType==PType || theAType==NType) {
300       G4double newmaxUniverseRadius=0.;
301       if (theAType==PType) newmaxUniverseRadius=initUniverseRadiusForAntiprotonAtRest(A+1, Z+1);
302       else newmaxUniverseRadius=initUniverseRadiusForAntiprotonAtRest(A+1, Z);
303       nucleus = new Nucleus(A, Z, S, theConfig, newmaxUniverseRadius, theAType);
304     }
305     else{
306       nucleus = new Nucleus(A, Z, S, theConfig, maxUniverseRadius, theAType);
307     }
308     nucleus->getStore()->getBook().reset();
309     nucleus->initializeParticles();
310     propagationModel->setNucleus(nucleus);
311     return true;
312   }
313 
314   const EventInfo &INCL::processEvent(
315       ParticleSpecies const &projectileSpecies,
316       const G4double kineticEnergy,
317       const G4int targetA,
318       const G4int targetZ,
319       const G4int targetS
320       ) {
321 
322     ParticleList starlistH2;
323 
324     if (projectileSpecies.theType==antiProton && (targetA==1 || targetA==2) && targetZ==1 && targetS==0) {
325 
326       if (targetA==1) {
327         preCascade_pbarH1(projectileSpecies, kineticEnergy);
328       } else {
329         preCascade_pbarH2(projectileSpecies, kineticEnergy);
330         theEventInfo.annihilationP = false;
331         theEventInfo.annihilationN = false;
332 
333         G4double SpOverSn = 1.331;  //from experiments with deuteron (E.Klempt)
334 
335         ThreeVector dummy(0.,0.,0.);
336         G4double rndm = Random::shoot()*(SpOverSn+1);
337         if (rndm <= SpOverSn) {  //proton is annihilated
338           theEventInfo.annihilationP = true;
339           Particle *p2 = new Particle(Neutron, dummy, dummy);
340           starlistH2.push_back(p2);
341           //delete p2;
342         } else {                 //neutron is annihilated
343           theEventInfo.annihilationN = true;
344           Particle *p2 = new Particle(Proton, dummy, dummy);
345           starlistH2.push_back(p2);
346           //delete p2;
347         }
348       }
349 
350       // File names
351 #ifdef INCLXX_IN_GEANT4_MODE
352       if (!G4FindDataDir("G4INCLDATA") ) {
353         G4ExceptionDescription ed;
354         ed << " Data missing: set environment variable G4INCLDATA\n"
355            << " to point to the directory containing data files needed\n"
356            << " by the INCL++ model" << G4endl;
357         G4Exception("G4INCLDataFile::readData()","rawppbarFS.dat, ...", FatalException, ed);
358       }
359       const G4String& dataPath0(G4FindDataDir("G4INCLDATA"));
360       const G4String& dataPathppbar(dataPath0 + "/rawppbarFS.dat");
361 //      const G4String& dataPathnpbar(dataPath0 + "/rawnpbarFS.dat");  // NOT used!
362       const G4String& dataPathppbark(dataPath0 + "/rawppbarFSkaonic.dat");
363 //      const G4String& dataPathnpbark(dataPath0 + "/rawnpbarFSkaonic.dat");  // NOT used!
364 #else
365       std::string path;
366       if (theConfig) path = theConfig->getINCLXXDataFilePath();
367       const std::string& dataPathppbar(path + "/rawppbarFS.dat");
368       INCL_DEBUG("Reading https://doi.org/10.1016/0375-9474(92)90362-N ppbar final states" << dataPathppbar << '\n');
369       const std::string& dataPathnpbar(path + "/rawnpbarFS.dat");
370       INCL_DEBUG("Reading https://doi.org/10.1016/0375-9474(92)90362-N npbar final states" << dataPathnpbar << '\n');
371       const std::string& dataPathppbark(path + "/rawppbarFSkaonic.dat");
372       INCL_DEBUG("Reading https://doi.org/10.1016/j.physrep.2005.03.002 ppbar kaonic final states" << dataPathppbark << '\n');
373       const std::string& dataPathnpbark(path + "/rawnpbarFSkaonic.dat");
374       INCL_DEBUG("Reading https://doi.org/10.1007/BF02818764 and https://link.springer.com/article/10.1007/BF02754930 npbar kaonic final states" << dataPathnpbark << '\n');
375 #endif
376 
377       //read probabilities and particle types from file
378       std::vector<G4double> probabilities;  //will store each FS yield
379       std::vector<std::vector<G4String>> particle_types;  //will store particle names
380       G4double sum = 0.0;  //will contain a sum of probabilities of all FS in the file
381       G4double kaonicFSprob=0.05;  //probability to kave kaonic FS
382 
383       ParticleList starlist;
384       ThreeVector mommy;  //momentum to be assigned later
385 
386       G4double rdm = Random::shoot();
387       ThreeVector annihilationPosition(0.,0.,0.);
388       if (rdm < (1.-kaonicFSprob)) {  // pionic FS was chosen
389         INCL_DEBUG("pionic pp final state chosen" << '\n');
390         sum = read_file(dataPathppbar, probabilities, particle_types);
391         rdm = (rdm/(1.-kaonicFSprob))*sum;  //99.88 normalize by the sum of probabilities in the file
392         //now get the line number in the file where the FS particles are stored:
393         G4int n = findStringNumber(rdm, std::move(probabilities))-1;
394         if ( n < 0 ) return theEventInfo;
395         for (G4int j = 0; j < static_cast<G4int>(particle_types[n].size()); j++) {
396           if (particle_types[n][j] == "pi0") {
397             Particle *p = new Particle(PiZero, mommy, annihilationPosition);
398             starlist.push_back(p);
399           } else if (particle_types[n][j] == "pi-") {
400             Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
401             starlist.push_back(p);
402           } else if (particle_types[n][j] == "pi+") {
403             Particle *p = new Particle(PiPlus, mommy, annihilationPosition);
404             starlist.push_back(p);
405           } else if (particle_types[n][j] == "omega") {
406             Particle *p = new Particle(Omega, mommy, annihilationPosition);
407             starlist.push_back(p);
408           } else if (particle_types[n][j] == "eta") {
409             Particle *p = new Particle(Eta, mommy, annihilationPosition);
410             starlist.push_back(p);
411           } else if (particle_types[n][j] == "rho-") {
412             Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
413             starlist.push_back(p);
414             Particle *pp = new Particle(PiZero, mommy, annihilationPosition);
415             starlist.push_back(pp);
416           } else if (particle_types[n][j] == "rho+") {
417             Particle *p = new Particle(PiPlus, mommy, annihilationPosition);
418             starlist.push_back(p);
419             Particle *pp = new Particle(PiZero, mommy, annihilationPosition);
420             starlist.push_back(pp);
421           } else if (particle_types[n][j] == "rho0") {
422             Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
423             starlist.push_back(p);
424             Particle *pp = new Particle(PiPlus, mommy, annihilationPosition);
425             starlist.push_back(pp);
426           } else {
427             INCL_ERROR("Some non-existing FS particle detected when reading pbar FS files");
428             for (G4int jj = 0; jj < static_cast<G4int>(particle_types[n].size()); jj++) {
429 #ifdef INCLXX_IN_GEANT4_MODE
430               G4cout << "gotcha! " << particle_types[n][jj] << G4endl;
431 #else
432               std::cout << "gotcha! " << particle_types[n][jj] << std::endl;
433 #endif              
434             }
435 #ifdef INCLXX_IN_GEANT4_MODE
436             G4cout << "Some non-existing FS particle detected when reading pbar FS files" << G4endl;
437 #else
438             std::cout << "Some non-existing FS particle detected when reading pbar FS files" << std::endl;
439 #endif              
440           }
441         }
442       } else {
443         INCL_DEBUG("kaonic pp final state chosen" << '\n');
444         sum = read_file(dataPathppbark, probabilities, particle_types);
445         rdm = ((1.-rdm)/kaonicFSprob)*sum;  //2670 normalize by the sum of probabilities in the file
446         //now get the line number in the file where the FS particles are stored:
447         G4int n = findStringNumber(rdm, probabilities)-1;
448         if ( n < 0 ) return theEventInfo;
449         for (G4int j = 0; j < static_cast<G4int>(particle_types[n].size()); j++) {
450           if (particle_types[n][j] == "pi0") {
451             Particle *p = new Particle(PiZero, mommy, annihilationPosition);
452             starlist.push_back(p);
453           } else if (particle_types[n][j] == "pi-") {
454             Particle *p = new Particle(PiMinus, mommy, annihilationPosition);
455             starlist.push_back(p);
456           } else if (particle_types[n][j] == "pi+") {
457             Particle *p = new Particle(PiPlus, mommy, annihilationPosition);
458             starlist.push_back(p);
459           } else if (particle_types[n][j] == "omega") {
460             Particle *p = new Particle(Omega, mommy, annihilationPosition);
461             starlist.push_back(p);
462           } else if (particle_types[n][j] == "eta") {
463             Particle *p = new Particle(Eta, mommy, annihilationPosition);
464             starlist.push_back(p);
465           } else if (particle_types[n][j] == "K-") {
466             Particle *p = new Particle(KMinus, mommy, annihilationPosition);
467             starlist.push_back(p);
468           } else if (particle_types[n][j] == "K+") {
469             Particle *p = new Particle(KPlus, mommy, annihilationPosition);
470             starlist.push_back(p);
471           } else if (particle_types[n][j] == "K0") {
472             Particle *p = new Particle(KZero, mommy, annihilationPosition);
473             starlist.push_back(p);
474           } else if (particle_types[n][j] == "K0b") {
475             Particle *p = new Particle(KZeroBar, mommy, annihilationPosition);
476             starlist.push_back(p);
477           } else {
478             INCL_ERROR("Some non-existing FS particle detected when reading pbar FS files");
479             for (G4int jj = 0; jj < static_cast<G4int>(particle_types[n].size()); jj++) {
480 #ifdef INCLXX_IN_GEANT4_MODE
481               G4cout << "gotcha! " << particle_types[n][jj] << G4endl;
482 #else
483               std::cout << "gotcha! " << particle_types[n][jj] << std::endl;
484 #endif              
485             }
486 #ifdef INCLXX_IN_GEANT4_MODE
487             G4cout << "Some non-existing FS particle detected when reading pbar FS files" << G4endl;
488 #else
489             std::cout << "Some non-existing FS particle detected when reading pbar FS files" << std::endl;
490 #endif              
491           }
492         }
493       }
494 
495       //compute energies of mesons with a phase-space model
496       G4double energyOfMesonStar=ParticleTable::getRealMass(Proton)+ParticleTable::getRealMass(antiProton);
497       if (starlist.size() < 2) {
498         INCL_ERROR("should never happen, at least 2 final state particles!" << '\n');
499       } else if (starlist.size() == 2) {
500         ParticleIter first = starlist.begin();
501         ParticleIter last = std::next(first, 1);
502         G4double m1 = (*first)->getMass();
503         G4double m2 = (*last)->getMass();
504         G4double s = energyOfMesonStar*energyOfMesonStar;
505         G4double mom1 = std::sqrt(s/4. - (std::pow(m1,2) + std::pow(m2,2))/2. - std::pow(m1,2)*std::pow(m2,2)/s + (std::pow(m1,4) + 2.*std::pow(m1*m2,2) + std::pow(m2,4))/(4.*s));
506         ThreeVector momentello = Random::normVector(mom1);
507         (*first)->setMomentum(momentello);
508         (*first)->adjustEnergyFromMomentum();
509         (*last)->setMomentum(-momentello);
510         (*last)->adjustEnergyFromMomentum();
511       } else {
512         PhaseSpaceGenerator::generate(energyOfMesonStar, starlist);
513       }
514 
515       if (targetA==1) postCascade_pbarH1(starlist);
516       else            postCascade_pbarH2(starlist,starlistH2);
517 
518       theGlobalInfo.nShots++;
519       return theEventInfo;
520     }  // pbar on H1
521 
522     // ReInitialize the bias vector
523     Particle::INCLBiasVector.clear();
524     //Particle::INCLBiasVector.Clear();
525     Particle::nextBiasedCollisionID = 0;
526 
527     // Set the target and the projectile
528     targetInitSuccess = prepareReaction(projectileSpecies, kineticEnergy, targetA, targetZ, targetS);
529 
530     if(!targetInitSuccess) {
531       INCL_WARN("Target initialisation failed for A=" << targetA << ", Z=" << targetZ << ", S=" << targetS << '\n');
532       theEventInfo.transparent=true;
533       return theEventInfo;
534     }
535 
536     cascadeAction->beforeCascadeAction(propagationModel);
537 
538     const G4bool canRunCascade = preCascade(projectileSpecies, kineticEnergy);
539     if(canRunCascade) {
540       cascade();
541       postCascade(projectileSpecies, kineticEnergy);
542       cascadeAction->afterCascadeAction(nucleus);
543     }
544     updateGlobalInfo();
545     return theEventInfo;
546   }
547 
548   G4bool INCL::preCascade(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy) {
549     // Reset theEventInfo
550     theEventInfo.reset();
551     
552     EventInfo::eventNumber++;
553 
554     // Fill in the event information
555     theEventInfo.projectileType = projectileSpecies.theType;
556     theEventInfo.Ap = (Short_t)projectileSpecies.theA;
557     theEventInfo.Zp = (Short_t)projectileSpecies.theZ;
558     theEventInfo.Sp = (Short_t)projectileSpecies.theS;
559     theEventInfo.Ep = kineticEnergy;
560     theEventInfo.St = (Short_t)nucleus->getS();
561 
562     if(nucleus->getAnnihilationType()==PType){
563       theEventInfo.annihilationP = true;
564       theEventInfo.At = (Short_t)nucleus->getA()+1;
565       theEventInfo.Zt = (Short_t)nucleus->getZ()+1;
566     }
567     else if(nucleus->getAnnihilationType()==NType){
568       theEventInfo.annihilationN = true;
569       theEventInfo.At = (Short_t)nucleus->getA()+1;
570       theEventInfo.Zt = (Short_t)nucleus->getZ();
571     }
572     else {
573       theEventInfo.At = (Short_t)nucleus->getA();
574       theEventInfo.Zt = (Short_t)nucleus->getZ();
575     }
576     // Do nothing below the Coulomb barrier
577     if(maxImpactParameter<=0.) {
578       // Fill in the event information
579     //Particle *pbar = new Particle;
580     //PbarAtrestEntryChannel *obj = new PbarAtrestEntryChannel(nucleus, pbar);
581       if(projectileSpecies.theType == antiProton && kineticEnergy <= theConfig->getAtrestThreshold()){         //D
582         INCL_DEBUG("at rest annihilation" << '\n');
583         //theEventInfo.transparent = false;
584       } else {       
585         theEventInfo.transparent = true;
586         return false;
587       }
588     }
589     
590 
591     // Randomly draw an impact parameter or use a fixed value, depending on the
592     // Config option
593     G4double impactParameter, phi;
594     if(fixedImpactParameter<0.) {
595       impactParameter = maxImpactParameter * std::sqrt(Random::shoot0());
596       phi = Random::shoot() * Math::twoPi;
597     } else {
598       impactParameter = fixedImpactParameter;
599       phi = 0.;
600     }
601     INCL_DEBUG("Selected impact parameter: " << impactParameter << '\n');
602 
603     // Fill in the event information
604     theEventInfo.impactParameter = impactParameter;
605 
606     const G4double effectiveImpactParameter = propagationModel->shoot(projectileSpecies, kineticEnergy, impactParameter, phi);
607     if(effectiveImpactParameter < 0.) {
608       // Fill in the event information
609       theEventInfo.transparent = true;
610       return false;
611     }
612 
613     // Fill in the event information
614     theEventInfo.transparent = false;
615     theEventInfo.effectiveImpactParameter = effectiveImpactParameter;
616 
617     return true;
618   }
619 
620   void INCL::cascade() {
621     FinalState *finalState = new FinalState;
622 
623     unsigned long loopCounter = 0;
624     const unsigned long maxLoopCounter = 10000000;
625     do {
626       // Run book keeping actions that should take place before propagation:
627       cascadeAction->beforePropagationAction(propagationModel);
628 
629       // Get the avatar with the smallest time and propagate particles
630       // to that point in time.
631       IAvatar *avatar = propagationModel->propagate(finalState);
632 
633       finalState->reset();
634 
635       // Run book keeping actions that should take place after propagation:
636       cascadeAction->afterPropagationAction(propagationModel, avatar);
637 
638       if(avatar == 0) break; // No more avatars in the avatar list.
639 
640       // Run book keeping actions that should take place before avatar:
641       cascadeAction->beforeAvatarAction(avatar, nucleus);
642 
643       // Channel is responsible for calculating the outcome of the
644       // selected avatar. There are different kinds of channels. The
645       // class IChannel is, again, an abstract interface that defines
646       // the externally observable behavior of all interaction
647       // channels.
648       // The handling of the channel is transparent to the API.
649       // Final state tells what changed...
650       avatar->fillFinalState(finalState);
651       // Run book keeping actions that should take place after avatar:
652       cascadeAction->afterAvatarAction(avatar, nucleus, finalState);
653 
654       // So now we must give this information to the nucleus
655       nucleus->applyFinalState(finalState);
656       // and now we are ready to process the next avatar!
657 
658       delete avatar;
659 
660       ++loopCounter;
661     } while(continueCascade() && loopCounter<maxLoopCounter); /* Loop checking, 10.07.2015, D.Mancusi */
662     
663     delete finalState;
664   }
665 
666   void INCL::postCascade(const ParticleSpecies &projectileSpecies, const G4double kineticEnergy) {
667     // Fill in the event information
668     theEventInfo.stoppingTime = propagationModel->getCurrentTime();
669 
670     // The event bias
671     theEventInfo.eventBias = (Double_t) Particle::getTotalBias();
672 
673     // Forced CN?
674     if(!(projectileSpecies.theType==antiProton && kineticEnergy<=theConfig->getAtrestThreshold())){
675       if(nucleus->getTryCompoundNucleus()) {
676         INCL_DEBUG("Trying compound nucleus" << '\n');
677         makeCompoundNucleus();
678         theEventInfo.transparent = forceTransparent;
679       // Global checks of conservation laws
680 #ifndef INCLXX_IN_GEANT4_MODE
681       if(!theEventInfo.transparent) globalConservationChecks(true);
682 #endif
683       return;
684       }
685     }
686 
687     if(!(projectileSpecies.theType==antiProton && kineticEnergy<=theConfig->getAtrestThreshold())){
688       theEventInfo.transparent = forceTransparent || nucleus->isEventTransparent();
689     }
690 
691     if(theEventInfo.transparent) {
692       ProjectileRemnant * const projectileRemnant = nucleus->getProjectileRemnant();
693       if(projectileRemnant) {
694         // Clear the incoming list (particles will be deleted by the ProjectileRemnant)
695         nucleus->getStore()->clearIncoming();
696       } else {
697         // Delete particles in the incoming list
698         nucleus->getStore()->deleteIncoming();
699       }
700     } else {
701       
702       // Check if the nucleus contains strange particles
703       theEventInfo.sigmasInside = nucleus->containsSigma();
704       theEventInfo.antikaonsInside = nucleus->containsAntiKaon();
705       theEventInfo.lambdasInside = nucleus->containsLambda();
706       theEventInfo.kaonsInside = nucleus->containsKaon();
707       
708       // Capture antiKaons and Sigmas and produce Lambda instead
709       theEventInfo.absorbedStrangeParticle = nucleus->decayInsideStrangeParticles();
710       
711       // Emit strange particles still inside the nucleus
712       nucleus->emitInsideStrangeParticles();
713       theEventInfo.emitKaon = nucleus->emitInsideKaon();
714 
715 #ifdef INCLXX_IN_GEANT4_MODE
716       theEventInfo.emitLambda = nucleus->emitInsideLambda();
717 #endif // INCLXX_IN_GEANT4_MODE
718       
719       // Check if the nucleus contains deltas
720       theEventInfo.deltasInside = nucleus->containsDeltas();
721 
722       // Take care of any remaining deltas
723       theEventInfo.forcedDeltasOutside = nucleus->decayOutgoingDeltas();
724       theEventInfo.forcedDeltasInside = nucleus->decayInsideDeltas();
725 
726       // Take care of any remaining etas, omegas, neutral Sigmas and/or neutral kaons
727       G4double timeThreshold=theConfig->getDecayTimeThreshold();
728       theEventInfo.forcedPionResonancesOutside = nucleus->decayOutgoingPionResonances(timeThreshold);
729       nucleus->decayOutgoingSigmaZero(timeThreshold);
730       nucleus->decayOutgoingNeutralKaon();
731         
732       // Apply Coulomb distortion, if appropriate
733       // Note that this will apply Coulomb distortion also on pions emitted by
734       // unphysical remnants (see decayInsideDeltas). This is at variance with
735       // what INCL4.6 does, but these events are (should be!) so rare that
736       // whatever we do doesn't (shouldn't!) make any noticeable difference.
737       CoulombDistortion::distortOut(nucleus->getStore()->getOutgoingParticles(), nucleus);
738 
739       // If the normal cascade predicted complete fusion, use the tabulated
740       // masses to compute the excitation energy, the recoil, etc.
741       if(nucleus->getStore()->getOutgoingParticles().size()==0
742          && (!nucleus->getProjectileRemnant()
743              || nucleus->getProjectileRemnant()->getParticles().size()==0)) {
744 
745         INCL_DEBUG("Cascade resulted in complete fusion, using realistic fusion kinematics" << '\n');
746 
747         nucleus->useFusionKinematics();
748 
749         if(nucleus->getExcitationEnergy()<0.) {
750           // Complete fusion is energetically impossible, return a transparent
751           INCL_WARN("Complete-fusion kinematics yields negative excitation energy, returning a transparent!" << '\n');
752           theEventInfo.transparent = true;
753           return;
754         }
755 
756       } else { // Normal cascade here
757 
758         // Set the excitation energy
759         nucleus->setExcitationEnergy(nucleus->computeExcitationEnergy());
760 
761         // Make a projectile pre-fragment out of the geometrical and dynamical
762         // spectators
763         theEventInfo.nUnmergedSpectators = makeProjectileRemnant();
764 
765         // Compute recoil momentum, energy and spin of the nucleus
766         if(nucleus->getA()==1 && minRemnantSize>1) {
767           INCL_ERROR("Computing one-nucleon recoil kinematics. We should never be here nowadays, cascade should stop earlier than this." << '\n');
768         }
769         nucleus->computeRecoilKinematics();
770 
771 #ifndef INCLXX_IN_GEANT4_MODE
772         // Global checks of conservation laws
773         globalConservationChecks(false);
774 #endif
775 
776         // Make room for the remnant recoil by rescaling the energies of the
777         // outgoing particles.
778         if(nucleus->hasRemnant()) rescaleOutgoingForRecoil();
779 
780       }
781 
782       // Cluster decay
783       theEventInfo.clusterDecay = nucleus->decayOutgoingClusters() || nucleus->decayMe(); //D
784 
785 #ifndef INCLXX_IN_GEANT4_MODE
786       // Global checks of conservation laws
787       globalConservationChecks(true);
788 #endif
789 
790       // Fill the EventInfo structure
791       nucleus->fillEventInfo(&theEventInfo);
792 
793     }
794   }
795 
796   void INCL::makeCompoundNucleus() {
797     // If this is not a nucleus-nucleus collision, don't attempt to make a
798     // compound nucleus.
799     //
800     // Yes, even nucleon-nucleus collisions can lead to particles entering
801     // below the Fermi level. Take e.g. 1-MeV p + He4.
802     if(!nucleus->isNucleusNucleusCollision()) {
803       forceTransparent = true;
804       return;
805     }
806 
807     // Reset the internal Nucleus variables
808     nucleus->getStore()->clearIncoming();
809     nucleus->getStore()->clearOutgoing();
810     nucleus->getProjectileRemnant()->reset();
811     nucleus->setA(theEventInfo.At);
812     nucleus->setZ(theEventInfo.Zt);
813 
814     // CN kinematical variables
815     // Note: the CN orbital angular momentum is neglected in what follows. We
816     // should actually take it into account!
817     ThreeVector theCNMomentum = nucleus->getIncomingMomentum();
818     ThreeVector theCNSpin = nucleus->getIncomingAngularMomentum();
819     const G4double theTargetMass = ParticleTable::getTableMass(theEventInfo.At, theEventInfo.Zt, theEventInfo.St);
820     G4int theCNA=theEventInfo.At, theCNZ=theEventInfo.Zt, theCNS=theEventInfo.St;
821     Cluster * const theProjectileRemnant = nucleus->getProjectileRemnant();
822     G4double theCNEnergy = theTargetMass + theProjectileRemnant->getEnergy();
823 
824     // Loop over the potential participants
825     ParticleList const &initialProjectileComponents = theProjectileRemnant->getParticles();
826     std::vector<Particle *> shuffledComponents(initialProjectileComponents.begin(), initialProjectileComponents.end());
827     // Shuffle the list of potential participants
828     std::shuffle(shuffledComponents.begin(), shuffledComponents.end(), Random::getAdapter());
829 
830     G4bool success = true;
831     G4bool atLeastOneNucleonEntering = false;
832     for(std::vector<Particle*>::const_iterator p=shuffledComponents.begin(), e=shuffledComponents.end(); p!=e; ++p) {
833       // Skip particles that miss the interaction distance
834       Intersection intersectionInteractionDistance(IntersectionFactory::getEarlierTrajectoryIntersection(
835             (*p)->getPosition(),
836             (*p)->getPropagationVelocity(),
837             maxInteractionDistance));
838       if(!intersectionInteractionDistance.exists)
839         continue;
840 
841       // Build an entry avatar for this nucleon
842       atLeastOneNucleonEntering = true;
843       ParticleEntryAvatar *theAvatar = new ParticleEntryAvatar(0.0, nucleus, *p);
844       nucleus->getStore()->addParticleEntryAvatar(theAvatar);
845       FinalState *fs = theAvatar->getFinalState();
846       nucleus->applyFinalState(fs);
847       FinalStateValidity validity = fs->getValidity();
848       delete fs;
849       switch(validity) {
850         case ValidFS:
851         case ParticleBelowFermiFS:
852         case ParticleBelowZeroFS:
853           // Add the particle to the CN
854           theCNA++;
855           theCNZ += (*p)->getZ();
856           theCNS += (*p)->getS();
857           break;
858         case PauliBlockedFS:
859         case NoEnergyConservationFS:
860         default:
861           success = false;
862           break;
863       }
864     }
865 
866     if(!success || !atLeastOneNucleonEntering) {
867       INCL_DEBUG("No nucleon entering in forced CN, forcing a transparent" << '\n');
868       forceTransparent = true;
869       return;
870     }
871 
872 // assert(theCNA==nucleus->getA());
873 // assert(theCNA<=theEventInfo.At+theEventInfo.Ap);
874 // assert(theCNZ<=theEventInfo.Zt+theEventInfo.Zp);
875 // assert(theCNS>=theEventInfo.St+theEventInfo.Sp);
876 
877     // Update the kinematics of the CN
878     theCNEnergy -= theProjectileRemnant->getEnergy();
879     theCNMomentum -= theProjectileRemnant->getMomentum();
880 
881     // Deal with the projectile remnant
882     nucleus->finalizeProjectileRemnant(propagationModel->getCurrentTime());
883 
884     // Subtract the angular momentum of the projectile remnant
885 // assert(nucleus->getStore()->getOutgoingParticles().empty());
886     theCNSpin -= theProjectileRemnant->getAngularMomentum();
887 
888     // Compute the excitation energy of the CN
889     const G4double theCNMass = ParticleTable::getTableMass(theCNA,theCNZ,theCNS);
890     const G4double theCNInvariantMassSquared = theCNEnergy*theCNEnergy-theCNMomentum.mag2();
891     if(theCNInvariantMassSquared<0.) {
892       // Negative invariant mass squared, return a transparent
893       forceTransparent = true;
894       return;
895     }
896     const G4double theCNExcitationEnergy = std::sqrt(theCNInvariantMassSquared) - theCNMass;
897     if(theCNExcitationEnergy<0.) {
898       // Negative excitation energy, return a transparent
899       INCL_DEBUG("CN excitation energy is negative, forcing a transparent" << '\n'
900             << "  theCNA = " << theCNA << '\n'
901             << "  theCNZ = " << theCNZ << '\n'
902             << "  theCNS = " << theCNS << '\n'
903             << "  theCNEnergy = " << theCNEnergy << '\n'
904             << "  theCNMomentum = (" << theCNMomentum.getX() << ", "<< theCNMomentum.getY() << ", "  << theCNMomentum.getZ() << ")" << '\n'
905             << "  theCNExcitationEnergy = " << theCNExcitationEnergy << '\n'
906             << "  theCNSpin = (" << theCNSpin.getX() << ", "<< theCNSpin.getY() << ", "  << theCNSpin.getZ() << ")" << '\n'
907             );
908       forceTransparent = true;
909       return;
910     } else {
911       // Positive excitation energy, can make a CN
912       INCL_DEBUG("CN excitation energy is positive, forcing a CN" << '\n'
913             << "  theCNA = " << theCNA << '\n'
914             << "  theCNZ = " << theCNZ << '\n'
915             << "  theCNS = " << theCNS << '\n'
916             << "  theCNEnergy = " << theCNEnergy << '\n'
917             << "  theCNMomentum = (" << theCNMomentum.getX() << ", "<< theCNMomentum.getY() << ", "  << theCNMomentum.getZ() << ")" << '\n'
918             << "  theCNExcitationEnergy = " << theCNExcitationEnergy << '\n'
919             << "  theCNSpin = (" << theCNSpin.getX() << ", "<< theCNSpin.getY() << ", "  << theCNSpin.getZ() << ")" << '\n'
920             );
921       nucleus->setA(theCNA);
922       nucleus->setZ(theCNZ);
923       nucleus->setS(theCNS);
924       nucleus->setMomentum(theCNMomentum);
925       nucleus->setEnergy(theCNEnergy);
926       nucleus->setExcitationEnergy(theCNExcitationEnergy);
927       nucleus->setMass(theCNMass+theCNExcitationEnergy);
928       nucleus->setSpin(theCNSpin); // neglects any orbital angular momentum of the CN
929 
930       // Take care of any remaining deltas
931       theEventInfo.forcedDeltasOutside = nucleus->decayOutgoingDeltas();
932 
933       // Take care of any remaining etas and/or omegas
934       G4double timeThreshold=theConfig->getDecayTimeThreshold();
935       theEventInfo.forcedPionResonancesOutside = nucleus->decayOutgoingPionResonances(timeThreshold);
936       
937       // Take care of any remaining Kaons
938       theEventInfo.emitKaon = nucleus->emitInsideKaon();
939         
940       // Cluster decay
941       theEventInfo.clusterDecay = nucleus->decayOutgoingClusters() || nucleus->decayMe(); //D
942 
943       // Fill the EventInfo structure
944       nucleus->fillEventInfo(&theEventInfo);
945     }
946   }
947 
948   void INCL::rescaleOutgoingForRecoil() {
949     RecoilCMFunctor theRecoilFunctor(nucleus, theEventInfo);
950 
951     // Apply the root-finding algorithm
952     const RootFinder::Solution theSolution = RootFinder::solve(&theRecoilFunctor, 1.0);
953     if(theSolution.success) {
954       theRecoilFunctor(theSolution.x); // Apply the solution
955     } else {
956       INCL_WARN("Couldn't accommodate remnant recoil while satisfying energy conservation, root-finding algorithm failed." << '\n');
957     }
958   }
959 
960 #ifndef INCLXX_IN_GEANT4_MODE
961   void INCL::globalConservationChecks(G4bool afterRecoil) {
962     Nucleus::ConservationBalance theBalance = nucleus->getConservationBalance(theEventInfo,afterRecoil);
963 
964     // Global conservation checks
965     const G4double pLongBalance = theBalance.momentum.getZ();
966     const G4double pTransBalance = theBalance.momentum.perp();
967     if(theBalance.Z != 0) {
968       INCL_ERROR("Violation of charge conservation! ZBalance = " << theBalance.Z << " eventNumber=" << theEventInfo.eventNumber << '\n');
969     }
970     if(theBalance.A != 0) {
971       INCL_ERROR("Violation of baryon-number conservation! ABalance = " << theBalance.A << " Emit Lambda=" << theEventInfo.emitLambda << " eventNumber=" << theEventInfo.eventNumber << '\n');
972     }
973     if(theBalance.S != 0) {
974       INCL_ERROR("Violation of strange-number conservation! SBalance = " << theBalance.S << " eventNumber=" << theEventInfo.eventNumber << '\n');
975     }
976     G4double EThreshold, pLongThreshold, pTransThreshold;
977     if(afterRecoil) {
978       // Less stringent checks after accommodating recoil
979       EThreshold = 10.; // MeV
980       pLongThreshold = 1.; // MeV/c
981       pTransThreshold = 1.; // MeV/c
982     } else {
983       // More stringent checks before accommodating recoil
984       EThreshold = 0.1; // MeV
985       pLongThreshold = 0.1; // MeV/c
986       pTransThreshold = 0.1; // MeV/c
987     }
988     if(std::abs(theBalance.energy)>EThreshold) {
989       INCL_WARN("Violation of energy conservation > " << EThreshold << " MeV. EBalance = " << theBalance.energy << " Emit Lambda=" << theEventInfo.emitLambda << " afterRecoil = " << afterRecoil << " eventNumber=" << theEventInfo.eventNumber << '\n');
990     }
991     if(std::abs(pLongBalance)>pLongThreshold) {
992       INCL_WARN("Violation of longitudinal momentum conservation > " << pLongThreshold << " MeV/c. pLongBalance = " << pLongBalance << " afterRecoil = " << afterRecoil << " eventNumber=" << theEventInfo.eventNumber << '\n');
993     }
994     if(std::abs(pTransBalance)>pTransThreshold) {
995       INCL_WARN("Violation of transverse momentum conservation > " << pTransThreshold << " MeV/c. pTransBalance = " << pTransBalance << " afterRecoil = " << afterRecoil << " eventNumber=" << theEventInfo.eventNumber << '\n');
996     }
997 
998     // Feed the EventInfo variables
999     theEventInfo.EBalance = theBalance.energy;
1000     theEventInfo.pLongBalance = pLongBalance;
1001     theEventInfo.pTransBalance = pTransBalance;
1002   }
1003 #endif
1004 
1005   G4bool INCL::continueCascade() {
1006     // Stop if we have passed the stopping time
1007     if(propagationModel->getCurrentTime() > propagationModel->getStoppingTime()) {
1008       INCL_DEBUG("Cascade time (" << propagationModel->getCurrentTime()
1009           << ") exceeded stopping time (" << propagationModel->getStoppingTime()
1010           << "), stopping cascade" << '\n');
1011       return false;
1012     }
1013     // Stop if there are no participants and no pions inside the nucleus
1014     if(nucleus->getStore()->getBook().getCascading()==0 &&
1015         nucleus->getStore()->getIncomingParticles().empty()) {
1016       INCL_DEBUG("No participants in the nucleus and no incoming particles left, stopping cascade" << '\n');
1017       return false;
1018     }
1019     // Stop if the remnant is smaller than minRemnantSize
1020     if(nucleus->getA() <= minRemnantSize) {
1021       INCL_DEBUG("Remnant size (" << nucleus->getA()
1022           << ") smaller than or equal to minimum (" << minRemnantSize
1023           << "), stopping cascade" << '\n');
1024       return false;
1025     }
1026     // Stop if we have to try and make a compound nucleus or if we have to
1027     // force a transparent
1028     if(nucleus->getTryCompoundNucleus()) {
1029       INCL_DEBUG("Trying to make a compound nucleus, stopping cascade" << '\n');
1030       return false;
1031     }
1032 
1033     return true;
1034   }
1035 
1036   void INCL::finalizeGlobalInfo(Random::SeedVector const &initialSeeds) {
1037     const G4double normalisationFactor = theGlobalInfo.geometricCrossSection /
1038       ((G4double) theGlobalInfo.nShots);
1039     theGlobalInfo.nucleonAbsorptionCrossSection = normalisationFactor *
1040       ((G4double) theGlobalInfo.nNucleonAbsorptions);
1041     theGlobalInfo.pionAbsorptionCrossSection = normalisationFactor *
1042       ((G4double) theGlobalInfo.nPionAbsorptions);
1043     theGlobalInfo.reactionCrossSection = normalisationFactor *
1044       ((G4double) (theGlobalInfo.nShots - theGlobalInfo.nTransparents));
1045     theGlobalInfo.errorReactionCrossSection = normalisationFactor *
1046       std::sqrt((G4double) (theGlobalInfo.nShots - theGlobalInfo.nTransparents));
1047     theGlobalInfo.forcedCNCrossSection = normalisationFactor *
1048       ((G4double) theGlobalInfo.nForcedCompoundNucleus);
1049     theGlobalInfo.errorForcedCNCrossSection = normalisationFactor *
1050       std::sqrt((G4double) (theGlobalInfo.nForcedCompoundNucleus));
1051     theGlobalInfo.completeFusionCrossSection = normalisationFactor *
1052       ((G4double) theGlobalInfo.nCompleteFusion);
1053     theGlobalInfo.errorCompleteFusionCrossSection = normalisationFactor *
1054       std::sqrt((G4double) (theGlobalInfo.nCompleteFusion));
1055     theGlobalInfo.energyViolationInteractionCrossSection = normalisationFactor *
1056       ((G4double) theGlobalInfo.nEnergyViolationInteraction);
1057 
1058     theGlobalInfo.initialRandomSeeds.assign(initialSeeds.begin(), initialSeeds.end());
1059 
1060     Random::SeedVector theSeeds = Random::getSeeds();
1061     theGlobalInfo.finalRandomSeeds.assign(theSeeds.begin(), theSeeds.end());
1062   }
1063 
1064   G4int INCL::makeProjectileRemnant() {
1065     // Do nothing if this is not a nucleus-nucleus reaction
1066     if(!nucleus->getProjectileRemnant())
1067       return 0;
1068 
1069     // Get the spectators (geometrical+dynamical) from the Store
1070     ParticleList geomSpectators(nucleus->getProjectileRemnant()->getParticles());
1071     ParticleList dynSpectators(nucleus->getStore()->extractDynamicalSpectators());
1072 
1073     G4int nUnmergedSpectators = 0;
1074 
1075     // If there are no spectators, do nothing
1076     if(dynSpectators.empty() && geomSpectators.empty()) {
1077       return 0;
1078     } else if(dynSpectators.size()==1 && geomSpectators.empty()) {
1079       // No geometrical spectators, one dynamical spectator
1080       // Just put it back in the outgoing list
1081       nucleus->getStore()->addToOutgoing(dynSpectators.front());
1082     } else {
1083       // Make a cluster out of the geometrical spectators
1084       ProjectileRemnant *theProjectileRemnant = nucleus->getProjectileRemnant();
1085 
1086       // Add the dynamical spectators to the bunch
1087       ParticleList rejected = theProjectileRemnant->addAllDynamicalSpectators(dynSpectators);
1088       // Put back the rejected spectators into the outgoing list
1089       nUnmergedSpectators = (G4int)rejected.size();
1090       nucleus->getStore()->addToOutgoing(rejected);
1091 
1092       // Deal with the projectile remnant
1093       nucleus->finalizeProjectileRemnant(propagationModel->getCurrentTime());
1094 
1095     }
1096 
1097     return nUnmergedSpectators;
1098   }
1099 
1100   void INCL::initMaxInteractionDistance(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy) {
1101     if(projectileSpecies.theType != Composite) {
1102       maxInteractionDistance = 0.;
1103       return;
1104     }
1105 
1106     const G4double r0 = std::max(ParticleTable::getNuclearRadius(Proton, theA, theZ),
1107                                ParticleTable::getNuclearRadius(Neutron, theA, theZ));
1108 
1109     const G4double theNNDistance = CrossSections::interactionDistanceNN(projectileSpecies, kineticEnergy);
1110     maxInteractionDistance = r0 + theNNDistance;
1111     INCL_DEBUG("Initialised interaction distance: r0 = " << r0 << '\n'
1112           << "    theNNDistance = " << theNNDistance << '\n'
1113           << "    maxInteractionDistance = " << maxInteractionDistance << '\n');
1114   }
1115 
1116   void INCL::initUniverseRadius(ParticleSpecies const &p, const G4double kineticEnergy, const G4int A, const G4int Z) {
1117     G4double rMax = 0.0;
1118     if(A==0) {
1119       IsotopicDistribution const &anIsotopicDistribution =
1120         ParticleTable::getNaturalIsotopicDistribution(Z);
1121       IsotopeVector theIsotopes = anIsotopicDistribution.getIsotopes();
1122       for(IsotopeIter i=theIsotopes.begin(), e=theIsotopes.end(); i!=e; ++i) {
1123         const G4double pMaximumRadius = ParticleTable::getMaximumNuclearRadius(Proton, i->theA, Z);
1124         const G4double nMaximumRadius = ParticleTable::getMaximumNuclearRadius(Neutron, i->theA, Z);
1125         const G4double maximumRadius = std::max(pMaximumRadius, nMaximumRadius);
1126         rMax = std::max(maximumRadius, rMax);
1127       }
1128     } else {
1129       const G4double pMaximumRadius = ParticleTable::getMaximumNuclearRadius(Proton, A, Z);
1130       const G4double nMaximumRadius = ParticleTable::getMaximumNuclearRadius(Neutron, A, Z);
1131       const G4double maximumRadius = std::max(pMaximumRadius, nMaximumRadius);
1132       rMax = std::max(maximumRadius, rMax);
1133     }
1134     if(p.theType==Composite || p.theType==Proton || p.theType==Neutron) {
1135       const G4double interactionDistanceNN = CrossSections::interactionDistanceNN(p, kineticEnergy);
1136       maxUniverseRadius = rMax + interactionDistanceNN;
1137     } else if(p.theType==PiPlus
1138         || p.theType==PiZero
1139         || p.theType==PiMinus) {
1140       const G4double interactionDistancePiN = CrossSections::interactionDistancePiN(kineticEnergy);
1141       maxUniverseRadius = rMax + interactionDistancePiN;
1142     } else if(p.theType==KPlus
1143         || p.theType==KZero) {
1144       const G4double interactionDistanceKN = CrossSections::interactionDistanceKN(kineticEnergy);
1145       maxUniverseRadius = rMax + interactionDistanceKN;
1146     } else if(p.theType==KZeroBar
1147         || p.theType==KMinus) {
1148       const G4double interactionDistanceKbarN = CrossSections::interactionDistanceKbarN(kineticEnergy);
1149       maxUniverseRadius = rMax + interactionDistanceKbarN;
1150     } else if(p.theType==Lambda
1151         ||p.theType==SigmaPlus
1152         || p.theType==SigmaZero
1153         || p.theType==SigmaMinus) {
1154       const G4double interactionDistanceYN = CrossSections::interactionDistanceYN(kineticEnergy);
1155       maxUniverseRadius = rMax + interactionDistanceYN;
1156     }
1157       else if(p.theType==antiProton) {
1158       maxUniverseRadius = rMax;                 //check interaction distance!!!
1159     }
1160     INCL_DEBUG("Initialised universe radius: " << maxUniverseRadius << '\n');
1161   }
1162 
1163 
1164   G4double INCL::initUniverseRadiusForAntiprotonAtRest(const G4int A, const G4int Z) {
1165     G4double rMax = 0.0;
1166     if(A==0) {
1167       IsotopicDistribution const &anIsotopicDistribution =
1168         ParticleTable::getNaturalIsotopicDistribution(Z);
1169       IsotopeVector theIsotopes = anIsotopicDistribution.getIsotopes();
1170       for(IsotopeIter i=theIsotopes.begin(), e=theIsotopes.end(); i!=e; ++i) {
1171         const G4double pMaximumRadius = ParticleTable::getMaximumNuclearRadius(Proton, i->theA, Z);
1172         const G4double nMaximumRadius = ParticleTable::getMaximumNuclearRadius(Neutron, i->theA, Z);
1173         const G4double maximumRadius = std::max(pMaximumRadius, nMaximumRadius);
1174         rMax = std::max(maximumRadius, rMax);
1175       }
1176     } else {
1177       const G4double pMaximumRadius = ParticleTable::getMaximumNuclearRadius(Proton, A, Z);
1178       const G4double nMaximumRadius = ParticleTable::getMaximumNuclearRadius(Neutron, A, Z);
1179       const G4double maximumRadius = std::max(pMaximumRadius, nMaximumRadius);
1180       rMax = std::max(maximumRadius, rMax);
1181     }
1182     return rMax;                
1183     }
1184     
1185 
1186   void INCL::updateGlobalInfo() {
1187     // Increment the global counter for the number of shots
1188     theGlobalInfo.nShots++;
1189 
1190     if(theEventInfo.transparent) {
1191       // Increment the global counter for the number of transparents
1192       theGlobalInfo.nTransparents++;
1193       // Increment the global counter for the number of forced transparents
1194       if(forceTransparent)
1195         theGlobalInfo.nForcedTransparents++;
1196       return;
1197     }
1198 
1199     // Check if we have an absorption:
1200     if(theEventInfo.nucleonAbsorption) theGlobalInfo.nNucleonAbsorptions++;
1201     if(theEventInfo.pionAbsorption) theGlobalInfo.nPionAbsorptions++;
1202 
1203     // Count complete-fusion events
1204     if(theEventInfo.nCascadeParticles==0) theGlobalInfo.nCompleteFusion++;
1205 
1206     if(nucleus->getTryCompoundNucleus())
1207       theGlobalInfo.nForcedCompoundNucleus++;
1208 
1209     // Counters for the number of violations of energy conservation in
1210     // collisions
1211     theGlobalInfo.nEnergyViolationInteraction += theEventInfo.nEnergyViolationInteraction;
1212   }
1213 
1214   G4double INCL::read_file(std::string filename, std::vector<G4double>& probabilities, 
1215                            std::vector<std::vector<G4String>>& particle_types) {
1216     std::ifstream file(filename);
1217     G4double sum_probs = 0.0;
1218     if (file.is_open()) {
1219       G4String line;
1220       while (getline(file, line)) {
1221         std::istringstream iss(line);
1222         G4double prob;
1223         iss >> prob;
1224         sum_probs += prob;
1225         probabilities.push_back(prob);
1226         std::vector<G4String> types;
1227         G4String type;
1228         while (iss >> type) {
1229           types.push_back(type);
1230         }
1231         particle_types.push_back(std::move(types));
1232       }
1233     } else {
1234 #ifdef INCLXX_IN_GEANT4_MODE
1235       G4cout << "ERROR no fread_file " << filename << G4endl;
1236 #else
1237       std::cout << "ERROR no fread_file " << filename << std::endl;
1238 #endif              
1239     }
1240     return sum_probs;
1241   }
1242 
1243 
1244   G4int INCL::findStringNumber(G4double rdm, std::vector<G4double> yields) {
1245     G4int stringNumber = -1;
1246     G4double smallestsum = 0.0;
1247     G4double biggestsum = yields[0];
1248     //G4cout << "initial input " << rdm << G4endl;
1249     for (G4int i = 0; i < static_cast<G4int>(yields.size()-1); i++) {
1250       if (rdm >= smallestsum && rdm <= biggestsum) {
1251         //G4cout << smallestsum << " and " << biggestsum << G4endl;
1252         stringNumber = i+1;
1253       }
1254       smallestsum += yields[i];
1255       biggestsum += yields[i+1];
1256     }
1257     if(stringNumber==-1) stringNumber = static_cast<G4int>(yields.size());
1258     if(stringNumber==-1){
1259       INCL_ERROR("ERROR in findStringNumber (stringNumber=-1)");
1260 #ifdef INCLXX_IN_GEANT4_MODE
1261       G4cout << "ERROR in findStringNumber" << G4endl;
1262 #else
1263       std::cout << "ERROR in findStringNumber" << std::endl;
1264 #endif              
1265     }
1266     return stringNumber;
1267   }
1268 
1269 
1270   void INCL::preCascade_pbarH1(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy) {
1271     // Reset theEventInfo
1272     theEventInfo.reset();
1273 
1274     EventInfo::eventNumber++;
1275 
1276     // Fill in the event information
1277     theEventInfo.projectileType = projectileSpecies.theType;
1278     theEventInfo.Ap = -1;
1279     theEventInfo.Zp = -1;
1280     theEventInfo.Sp = 0;
1281     theEventInfo.Ep = kineticEnergy;
1282     theEventInfo.St = 0;
1283     theEventInfo.At = 1;
1284     theEventInfo.Zt = 1;
1285   }
1286 
1287 
1288   void INCL::postCascade_pbarH1(ParticleList const &outgoingParticles) {
1289     theEventInfo.nParticles = 0;
1290 
1291     // Reset the remnant counter
1292     theEventInfo.nRemnants = 0;
1293     theEventInfo.history.clear();
1294 
1295     for(ParticleIter i=outgoingParticles.begin(), e=outgoingParticles.end(); i!=e; ++i ) {
1296       theEventInfo.A[theEventInfo.nParticles] = (Short_t)(*i)->getA();
1297       theEventInfo.Z[theEventInfo.nParticles] = (Short_t)(*i)->getZ();
1298       theEventInfo.S[theEventInfo.nParticles] = (Short_t)(*i)->getS();
1299       theEventInfo.EKin[theEventInfo.nParticles] = (*i)->getKineticEnergy();
1300       ThreeVector mom = (*i)->getMomentum();
1301       theEventInfo.px[theEventInfo.nParticles] = mom.getX();
1302       theEventInfo.py[theEventInfo.nParticles] = mom.getY();
1303       theEventInfo.pz[theEventInfo.nParticles] = mom.getZ();
1304       theEventInfo.theta[theEventInfo.nParticles] = Math::toDegrees(mom.theta());
1305       theEventInfo.phi[theEventInfo.nParticles] = Math::toDegrees(mom.phi());
1306       theEventInfo.origin[theEventInfo.nParticles] = -1;
1307 #ifdef INCLXX_IN_GEANT4_MODE
1308       theEventInfo.parentResonancePDGCode[theEventInfo.nParticles] = (*i)->getParentResonancePDGCode();
1309       theEventInfo.parentResonanceID[theEventInfo.nParticles] = (*i)->getParentResonanceID();
1310 #endif
1311       theEventInfo.history.push_back("");
1312       ParticleSpecies pt((*i)->getType());
1313       theEventInfo.PDGCode[theEventInfo.nParticles] = pt.getPDGCode();
1314       theEventInfo.nParticles++;
1315     }
1316     theEventInfo.nCascadeParticles = theEventInfo.nParticles;
1317   }
1318 
1319 
1320   void INCL::preCascade_pbarH2(ParticleSpecies const &projectileSpecies, const G4double kineticEnergy) {
1321     // Reset theEventInfo
1322     theEventInfo.reset();
1323 
1324     EventInfo::eventNumber++;
1325 
1326     // Fill in the event information
1327     theEventInfo.projectileType = projectileSpecies.theType;
1328     theEventInfo.Ap = -1;
1329     theEventInfo.Zp = -1;
1330     theEventInfo.Sp = 0;
1331     theEventInfo.Ep = kineticEnergy;
1332     theEventInfo.St = 0;
1333     theEventInfo.At = 2;
1334     theEventInfo.Zt = 1;
1335   }
1336 
1337 
1338   void INCL::postCascade_pbarH2(ParticleList const &outgoingParticles, ParticleList const &H2Particles) {
1339     theEventInfo.nParticles = 0;
1340 
1341     // Reset the remnant counter
1342     theEventInfo.nRemnants = 0;
1343     theEventInfo.history.clear();
1344 
1345     for(ParticleIter i=outgoingParticles.begin(), e=outgoingParticles.end(); i!=e; ++i ) {
1346       theEventInfo.A[theEventInfo.nParticles] = (Short_t)(*i)->getA();
1347       theEventInfo.Z[theEventInfo.nParticles] = (Short_t)(*i)->getZ();
1348       theEventInfo.S[theEventInfo.nParticles] = (Short_t)(*i)->getS();
1349       theEventInfo.EKin[theEventInfo.nParticles] = (*i)->getKineticEnergy();
1350       ThreeVector mom = (*i)->getMomentum();
1351       theEventInfo.px[theEventInfo.nParticles] = mom.getX();
1352       theEventInfo.py[theEventInfo.nParticles] = mom.getY();
1353       theEventInfo.pz[theEventInfo.nParticles] = mom.getZ();
1354       theEventInfo.theta[theEventInfo.nParticles] = Math::toDegrees(mom.theta());
1355       theEventInfo.phi[theEventInfo.nParticles] = Math::toDegrees(mom.phi());
1356       theEventInfo.origin[theEventInfo.nParticles] = -1;
1357 #ifdef INCLXX_IN_GEANT4_MODE
1358       theEventInfo.parentResonancePDGCode[theEventInfo.nParticles] = (*i)->getParentResonancePDGCode();
1359       theEventInfo.parentResonanceID[theEventInfo.nParticles] = (*i)->getParentResonanceID();
1360 #endif
1361       theEventInfo.history.push_back("");
1362       ParticleSpecies pt((*i)->getType());
1363       theEventInfo.PDGCode[theEventInfo.nParticles] = pt.getPDGCode();
1364       theEventInfo.nParticles++;
1365     }
1366 
1367     for(ParticleIter i=H2Particles.begin(), e=H2Particles.end(); i!=e; ++i ) {
1368       theEventInfo.A[theEventInfo.nParticles] = (Short_t)(*i)->getA();
1369       theEventInfo.Z[theEventInfo.nParticles] = (Short_t)(*i)->getZ();
1370       theEventInfo.S[theEventInfo.nParticles] = (Short_t)(*i)->getS();
1371       theEventInfo.EKin[theEventInfo.nParticles] = (*i)->getKineticEnergy();
1372       ThreeVector mom = (*i)->getMomentum();
1373       theEventInfo.px[theEventInfo.nParticles] = mom.getX();
1374       theEventInfo.py[theEventInfo.nParticles] = mom.getY();
1375       theEventInfo.pz[theEventInfo.nParticles] = mom.getZ();
1376       theEventInfo.theta[theEventInfo.nParticles] = Math::toDegrees(mom.theta());
1377       theEventInfo.phi[theEventInfo.nParticles] = Math::toDegrees(mom.phi());
1378       theEventInfo.origin[theEventInfo.nParticles] = -1;
1379 #ifdef INCLXX_IN_GEANT4_MODE
1380       theEventInfo.parentResonancePDGCode[theEventInfo.nParticles] = (*i)->getParentResonancePDGCode();
1381       theEventInfo.parentResonanceID[theEventInfo.nParticles] = (*i)->getParentResonanceID();
1382 #endif
1383       theEventInfo.history.push_back("");
1384       ParticleSpecies pt((*i)->getType());
1385       theEventInfo.PDGCode[theEventInfo.nParticles] = pt.getPDGCode();
1386       theEventInfo.nParticles++;
1387     }
1388     theEventInfo.nCascadeParticles = theEventInfo.nParticles;
1389   }
1390 
1391 }
1392