Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/inclxx/interface/src/G4INCLXXInterface.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/models/inclxx/interface/src/G4INCLXXInterface.cc (Version 11.3.0) and /processes/hadronic/models/inclxx/interface/src/G4INCLXXInterface.cc (Version 10.2)


  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 // INCL++ intra-nuclear cascade model              26 // INCL++ intra-nuclear cascade model
 27 // Alain Boudard, CEA-Saclay, France               27 // Alain Boudard, CEA-Saclay, France
 28 // Joseph Cugnon, University of Liege, Belgium     28 // Joseph Cugnon, University of Liege, Belgium
 29 // Jean-Christophe David, CEA-Saclay, France       29 // Jean-Christophe David, CEA-Saclay, France
 30 // Pekka Kaitaniemi, CEA-Saclay, France, and H     30 // Pekka Kaitaniemi, CEA-Saclay, France, and Helsinki Institute of Physics, Finland
 31 // Sylvie Leray, CEA-Saclay, France                31 // Sylvie Leray, CEA-Saclay, France
 32 // Davide Mancusi, CEA-Saclay, France              32 // Davide Mancusi, CEA-Saclay, France
 33 //                                                 33 //
 34 #define INCLXX_IN_GEANT4_MODE 1                    34 #define INCLXX_IN_GEANT4_MODE 1
 35                                                    35 
 36 #include "globals.hh"                              36 #include "globals.hh"
 37                                                    37 
 38 #include <cmath>                                   38 #include <cmath>
 39                                                    39 
 40 #include "G4PhysicalConstants.hh"                  40 #include "G4PhysicalConstants.hh"
 41 #include "G4SystemOfUnits.hh"                      41 #include "G4SystemOfUnits.hh"
 42 #include "G4INCLXXInterface.hh"                    42 #include "G4INCLXXInterface.hh"
 43 #include "G4GenericIon.hh"                         43 #include "G4GenericIon.hh"
 44 #include "G4INCLCascade.hh"                        44 #include "G4INCLCascade.hh"
 45 #include "G4ReactionProductVector.hh"              45 #include "G4ReactionProductVector.hh"
 46 #include "G4ReactionProduct.hh"                    46 #include "G4ReactionProduct.hh"
 47 #include "G4HadSecondary.hh"                   << 
 48 #include "G4ParticleTable.hh"                  << 
 49 #include "G4INCLXXInterfaceStore.hh"               47 #include "G4INCLXXInterfaceStore.hh"
 50 #include "G4INCLXXVInterfaceTally.hh"              48 #include "G4INCLXXVInterfaceTally.hh"
 51 #include "G4String.hh"                             49 #include "G4String.hh"
 52 #include "G4PhysicalConstants.hh"                  50 #include "G4PhysicalConstants.hh"
 53 #include "G4SystemOfUnits.hh"                      51 #include "G4SystemOfUnits.hh"
 54 #include "G4HadronicInteractionRegistry.hh"        52 #include "G4HadronicInteractionRegistry.hh"
 55 #include "G4INCLVersion.hh"                        53 #include "G4INCLVersion.hh"
 56 #include "G4VEvaporation.hh"                       54 #include "G4VEvaporation.hh"
 57 #include "G4VEvaporationChannel.hh"                55 #include "G4VEvaporationChannel.hh"
 58 #include "G4CompetitiveFission.hh"                 56 #include "G4CompetitiveFission.hh"
 59 #include "G4FissionLevelDensityParameterINCLXX     57 #include "G4FissionLevelDensityParameterINCLXX.hh"
 60 #include "G4PhysicsModelCatalog.hh"            << 
 61                                                << 
 62 #include "G4HyperNucleiProperties.hh"          << 
 63 #include "G4HyperTriton.hh"                    << 
 64 #include "G4HyperH4.hh"                        << 
 65 #include "G4HyperAlpha.hh"                     << 
 66 #include "G4DoubleHyperH4.hh"                  << 
 67 #include "G4DoubleHyperDoubleNeutron.hh"       << 
 68 #include "G4HyperHe5.hh"                       << 
 69                                                    58 
 70 G4INCLXXInterface::G4INCLXXInterface(G4VPreCom     59 G4INCLXXInterface::G4INCLXXInterface(G4VPreCompoundModel * const aPreCompound) :
 71   G4VIntraNuclearTransportModel(G4INCLXXInterf     60   G4VIntraNuclearTransportModel(G4INCLXXInterfaceStore::GetInstance()->getINCLXXVersionName()),
 72   theINCLModel(NULL),                              61   theINCLModel(NULL),
 73   thePreCompoundModel(aPreCompound),               62   thePreCompoundModel(aPreCompound),
 74   theInterfaceStore(G4INCLXXInterfaceStore::Ge     63   theInterfaceStore(G4INCLXXInterfaceStore::GetInstance()),
 75   theTally(NULL),                                  64   theTally(NULL),
 76   complainedAboutBackupModel(false),               65   complainedAboutBackupModel(false),
 77   complainedAboutPreCompound(false),               66   complainedAboutPreCompound(false),
 78   theIonTable(G4IonTable::GetIonTable()),          67   theIonTable(G4IonTable::GetIonTable()),
 79   theINCLXXLevelDensity(NULL),                     68   theINCLXXLevelDensity(NULL),
 80   theINCLXXFissionProbability(NULL),           <<  69   theINCLXXFissionProbability(NULL)
 81   secID(-1)                                    << 
 82 {                                                  70 {
 83   if(!thePreCompoundModel) {                       71   if(!thePreCompoundModel) {
 84     G4HadronicInteraction* p =                     72     G4HadronicInteraction* p =
 85       G4HadronicInteractionRegistry::Instance(     73       G4HadronicInteractionRegistry::Instance()->FindModel("PRECO");
 86     thePreCompoundModel = static_cast<G4VPreCo     74     thePreCompoundModel = static_cast<G4VPreCompoundModel*>(p);
 87     if(!thePreCompoundModel) { thePreCompoundM     75     if(!thePreCompoundModel) { thePreCompoundModel = new G4PreCompoundModel; }
 88   }                                                76   }
 89                                                    77 
 90   // Use the environment variable G4INCLXX_NO_     78   // Use the environment variable G4INCLXX_NO_DE_EXCITATION to disable de-excitation
 91   if(std::getenv("G4INCLXX_NO_DE_EXCITATION")) <<  79   if(getenv("G4INCLXX_NO_DE_EXCITATION")) {
 92     G4String message = "de-excitation is compl     80     G4String message = "de-excitation is completely disabled!";
 93     theInterfaceStore->EmitWarning(message);       81     theInterfaceStore->EmitWarning(message);
 94     theDeExcitation = 0;                           82     theDeExcitation = 0;
 95   } else {                                         83   } else {
 96     G4HadronicInteraction* p =                     84     G4HadronicInteraction* p =
 97       G4HadronicInteractionRegistry::Instance(     85       G4HadronicInteractionRegistry::Instance()->FindModel("PRECO");
 98     theDeExcitation = static_cast<G4VPreCompou     86     theDeExcitation = static_cast<G4VPreCompoundModel*>(p);
 99     if(!theDeExcitation) { theDeExcitation = n     87     if(!theDeExcitation) { theDeExcitation = new G4PreCompoundModel; }
100                                                    88 
101     // set the fission parameters for G4Excita     89     // set the fission parameters for G4ExcitationHandler
102     G4VEvaporationChannel * const theFissionCh     90     G4VEvaporationChannel * const theFissionChannel =
103       theDeExcitation->GetExcitationHandler()-     91       theDeExcitation->GetExcitationHandler()->GetEvaporation()->GetFissionChannel();
104     G4CompetitiveFission * const theFissionCha     92     G4CompetitiveFission * const theFissionChannelCast = dynamic_cast<G4CompetitiveFission *>(theFissionChannel);
105     if(theFissionChannelCast) {                    93     if(theFissionChannelCast) {
106       theINCLXXLevelDensity = new G4FissionLev     94       theINCLXXLevelDensity = new G4FissionLevelDensityParameterINCLXX;
107       theFissionChannelCast->SetLevelDensityPa     95       theFissionChannelCast->SetLevelDensityParameter(theINCLXXLevelDensity);
108       theINCLXXFissionProbability = new G4Fiss     96       theINCLXXFissionProbability = new G4FissionProbability;
109       theINCLXXFissionProbability->SetFissionL     97       theINCLXXFissionProbability->SetFissionLevelDensityParameter(theINCLXXLevelDensity);
110       theFissionChannelCast->SetEmissionStrate     98       theFissionChannelCast->SetEmissionStrategy(theINCLXXFissionProbability);
111       theInterfaceStore->EmitBigWarning("INCL+     99       theInterfaceStore->EmitBigWarning("INCL++/G4ExcitationHandler uses its own level-density parameter for fission");
112     } else {                                      100     } else {
113       theInterfaceStore->EmitBigWarning("INCL+    101       theInterfaceStore->EmitBigWarning("INCL++/G4ExcitationHandler could not use its own level-density parameter for fission");
114     }                                             102     }
115   }                                               103   }
116                                                   104 
117   // use the envvar G4INCLXX_DUMP_REMNANT to d    105   // use the envvar G4INCLXX_DUMP_REMNANT to dump information about the
118   // remnants on stdout                           106   // remnants on stdout
119   if(std::getenv("G4INCLXX_DUMP_REMNANT"))     << 107   if(getenv("G4INCLXX_DUMP_REMNANT"))
120     dumpRemnantInfo = true;                       108     dumpRemnantInfo = true;
121   else                                            109   else
122     dumpRemnantInfo = false;                      110     dumpRemnantInfo = false;
123                                                   111 
124   theBackupModel = new G4BinaryLightIonReactio    112   theBackupModel = new G4BinaryLightIonReaction;
125   theBackupModelNucleon = new G4BinaryCascade;    113   theBackupModelNucleon = new G4BinaryCascade;
126   secID = G4PhysicsModelCatalog::GetModelID( " << 
127 }                                                 114 }
128                                                   115 
129 G4INCLXXInterface::~G4INCLXXInterface()           116 G4INCLXXInterface::~G4INCLXXInterface()
130 {                                                 117 {
131   delete theINCLXXLevelDensity;                   118   delete theINCLXXLevelDensity;
132   delete theINCLXXFissionProbability;             119   delete theINCLXXFissionProbability;
133 }                                                 120 }
134                                                   121 
135 G4bool G4INCLXXInterface::AccurateProjectile(c    122 G4bool G4INCLXXInterface::AccurateProjectile(const G4HadProjectile &aTrack, const G4Nucleus &theNucleus) const {
136   // Use direct kinematics if the projectile i    123   // Use direct kinematics if the projectile is a nucleon or a pion
137   const G4ParticleDefinition *projectileDef =     124   const G4ParticleDefinition *projectileDef = aTrack.GetDefinition();
138   if(std::abs(projectileDef->GetBaryonNumber() << 125   if(projectileDef == G4Proton::Proton()
                                                   >> 126      || projectileDef == G4Neutron::Neutron()
                                                   >> 127      || projectileDef == G4PionPlus::PionPlus()
                                                   >> 128      || projectileDef == G4PionZero::PionZero()
                                                   >> 129      || projectileDef == G4PionMinus::PionMinus())
139     return false;                                 130     return false;
140                                                   131 
141   // Here all projectiles should be nuclei        132   // Here all projectiles should be nuclei
142   const G4int pA = projectileDef->GetAtomicMas    133   const G4int pA = projectileDef->GetAtomicMass();
143   if(pA<=0) {                                     134   if(pA<=0) {
144     std::stringstream ss;                         135     std::stringstream ss;
145     ss << "the model does not know how to hand    136     ss << "the model does not know how to handle a collision between a "
146       << projectileDef->GetParticleName() << "    137       << projectileDef->GetParticleName() << " projectile and a Z="
147       << theNucleus.GetZ_asInt() << ", A=" <<     138       << theNucleus.GetZ_asInt() << ", A=" << theNucleus.GetA_asInt();
148     theInterfaceStore->EmitBigWarning(ss.str()    139     theInterfaceStore->EmitBigWarning(ss.str());
149     return true;                                  140     return true;
150   }                                               141   }
151                                                   142 
152   // If either nucleus is a LCP (A<=4), run th    143   // If either nucleus is a LCP (A<=4), run the collision as light on heavy
153   const G4int tA = theNucleus.GetA_asInt();       144   const G4int tA = theNucleus.GetA_asInt();
154   if(tA<=4 || pA<=4) {                            145   if(tA<=4 || pA<=4) {
155     if(pA<tA)                                     146     if(pA<tA)
156       return false;                               147       return false;
157     else                                          148     else
158       return true;                                149       return true;
159   }                                               150   }
160                                                   151 
161   // If one of the nuclei is heavier than theM    152   // If one of the nuclei is heavier than theMaxProjMassINCL, run the collision
162   // as light on heavy.                           153   // as light on heavy.
163   // Note that here we are sure that either th    154   // Note that here we are sure that either the projectile or the target is
164   // smaller than theMaxProjMass; otherwise th    155   // smaller than theMaxProjMass; otherwise theBackupModel would have been
165   // called.                                      156   // called.
166   const G4int theMaxProjMassINCL = theInterfac    157   const G4int theMaxProjMassINCL = theInterfaceStore->GetMaxProjMassINCL();
167   if(pA > theMaxProjMassINCL)                     158   if(pA > theMaxProjMassINCL)
168     return true;                                  159     return true;
169   else if(tA > theMaxProjMassINCL)                160   else if(tA > theMaxProjMassINCL)
170     return false;                                 161     return false;
171   else                                            162   else
172     // In all other cases, use the global sett    163     // In all other cases, use the global setting
173     return theInterfaceStore->GetAccurateProje    164     return theInterfaceStore->GetAccurateProjectile();
174 }                                                 165 }
175                                                   166 
176 G4HadFinalState* G4INCLXXInterface::ApplyYours    167 G4HadFinalState* G4INCLXXInterface::ApplyYourself(const G4HadProjectile& aTrack, G4Nucleus& theNucleus)
177 {                                                 168 {
178   G4ParticleDefinition const * const trackDefi    169   G4ParticleDefinition const * const trackDefinition = aTrack.GetDefinition();
179   const G4bool isIonTrack = trackDefinition->G    170   const G4bool isIonTrack = trackDefinition->GetParticleType()==G4GenericIon::GenericIon()->GetParticleType();
180   const G4int trackA = trackDefinition->GetAto    171   const G4int trackA = trackDefinition->GetAtomicMass();
181   const G4int trackZ = (G4int) trackDefinition    172   const G4int trackZ = (G4int) trackDefinition->GetPDGCharge();
182   const G4int trackL = trackDefinition->GetNum << 
183   const G4int nucleusA = theNucleus.GetA_asInt    173   const G4int nucleusA = theNucleus.GetA_asInt();
184   const G4int nucleusZ = theNucleus.GetZ_asInt    174   const G4int nucleusZ = theNucleus.GetZ_asInt();
185                                                   175 
186   // For reactions induced by weird projectile    176   // For reactions induced by weird projectiles (e.g. He2), bail out
187   if((isIonTrack && ((trackZ<=0 && trackL==0)  << 177   if((isIonTrack && (trackZ<=0 || trackA<=trackZ)) || (nucleusA>1 && (nucleusZ<=0 || nucleusA<=nucleusZ))) {
188                     (nucleusA>1 && (nucleusZ<= << 
189     theResult.Clear();                            178     theResult.Clear();
190     theResult.SetStatusChange(isAlive);           179     theResult.SetStatusChange(isAlive);
191     theResult.SetEnergyChange(aTrack.GetKineti    180     theResult.SetEnergyChange(aTrack.GetKineticEnergy());
192     theResult.SetMomentumChange(aTrack.Get4Mom    181     theResult.SetMomentumChange(aTrack.Get4Momentum().vect().unit());
193     return &theResult;                            182     return &theResult;
194   }                                               183   }
195                                                   184 
196   // For reactions on nucleons, use the backup << 185   // For reactions on nucleons, use the backup model (without complaining)
197   // except for anti_proton projectile (in thi << 186   if(trackA<=1 && nucleusA<=1) {
198   if(trackA<=1 && nucleusA<=1 && (trackZ>=0 || << 
199     return theBackupModelNucleon->ApplyYoursel    187     return theBackupModelNucleon->ApplyYourself(aTrack, theNucleus);
200   }                                               188   }
201                                                << 189 
202   // For systems heavier than theMaxProjMassIN    190   // For systems heavier than theMaxProjMassINCL, use another model (typically
203   // BIC)                                         191   // BIC)
204   const G4int theMaxProjMassINCL = theInterfac    192   const G4int theMaxProjMassINCL = theInterfaceStore->GetMaxProjMassINCL();
205   if(trackA > theMaxProjMassINCL && nucleusA >    193   if(trackA > theMaxProjMassINCL && nucleusA > theMaxProjMassINCL) {
206     if(!complainedAboutBackupModel) {             194     if(!complainedAboutBackupModel) {
207       complainedAboutBackupModel = true;          195       complainedAboutBackupModel = true;
208       std::stringstream ss;                       196       std::stringstream ss;
209       ss << "INCL++ refuses to handle reaction    197       ss << "INCL++ refuses to handle reactions between nuclei with A>"
210         << theMaxProjMassINCL                     198         << theMaxProjMassINCL
211         << ". A backup model ("                   199         << ". A backup model ("
212         << theBackupModel->GetModelName()         200         << theBackupModel->GetModelName()
213         << ") will be used instead.";             201         << ") will be used instead.";
214       theInterfaceStore->EmitBigWarning(ss.str    202       theInterfaceStore->EmitBigWarning(ss.str());
215     }                                             203     }
216     return theBackupModel->ApplyYourself(aTrac    204     return theBackupModel->ApplyYourself(aTrack, theNucleus);
217   }                                               205   }
218                                                   206 
219   // For energies lower than cascadeMinEnergyP    207   // For energies lower than cascadeMinEnergyPerNucleon, use PreCompound
220   const G4double cascadeMinEnergyPerNucleon =     208   const G4double cascadeMinEnergyPerNucleon = theInterfaceStore->GetCascadeMinEnergyPerNucleon();
221   const G4double trackKinE = aTrack.GetKinetic    209   const G4double trackKinE = aTrack.GetKineticEnergy();
222   if((trackDefinition==G4Neutron::NeutronDefin    210   if((trackDefinition==G4Neutron::NeutronDefinition() || trackDefinition==G4Proton::ProtonDefinition())
223       && trackKinE < cascadeMinEnergyPerNucleo    211       && trackKinE < cascadeMinEnergyPerNucleon) {
224     if(!complainedAboutPreCompound) {             212     if(!complainedAboutPreCompound) {
225       complainedAboutPreCompound = true;          213       complainedAboutPreCompound = true;
226       std::stringstream ss;                       214       std::stringstream ss;
227       ss << "INCL++ refuses to handle nucleon-    215       ss << "INCL++ refuses to handle nucleon-induced reactions below "
228         << cascadeMinEnergyPerNucleon / MeV       216         << cascadeMinEnergyPerNucleon / MeV
229         << " MeV. A PreCoumpound model ("         217         << " MeV. A PreCoumpound model ("
230         << thePreCompoundModel->GetModelName()    218         << thePreCompoundModel->GetModelName()
231         << ") will be used instead.";             219         << ") will be used instead.";
232       theInterfaceStore->EmitBigWarning(ss.str    220       theInterfaceStore->EmitBigWarning(ss.str());
233     }                                             221     }
234     return thePreCompoundModel->ApplyYourself(    222     return thePreCompoundModel->ApplyYourself(aTrack, theNucleus);
235   }                                               223   }
236                                                   224 
237   // Calculate the total four-momentum in the     225   // Calculate the total four-momentum in the entrance channel
238   const G4double theNucleusMass = theIonTable-    226   const G4double theNucleusMass = theIonTable->GetIonMass(nucleusZ, nucleusA);
239   const G4double theTrackMass = trackDefinitio    227   const G4double theTrackMass = trackDefinition->GetPDGMass();
240   const G4double theTrackEnergy = trackKinE +     228   const G4double theTrackEnergy = trackKinE + theTrackMass;
241   const G4double theTrackMomentumAbs2 = theTra    229   const G4double theTrackMomentumAbs2 = theTrackEnergy*theTrackEnergy - theTrackMass*theTrackMass;
242   const G4double theTrackMomentumAbs = ((theTr    230   const G4double theTrackMomentumAbs = ((theTrackMomentumAbs2>0.0) ? std::sqrt(theTrackMomentumAbs2) : 0.0);
243   const G4ThreeVector theTrackMomentum = aTrac    231   const G4ThreeVector theTrackMomentum = aTrack.Get4Momentum().getV().unit() * theTrackMomentumAbs;
244                                                   232 
245   G4LorentzVector goodTrack4Momentum(theTrackM    233   G4LorentzVector goodTrack4Momentum(theTrackMomentum, theTrackEnergy);
246   G4LorentzVector fourMomentumIn;                 234   G4LorentzVector fourMomentumIn;
247   fourMomentumIn.setE(theTrackEnergy + theNucl    235   fourMomentumIn.setE(theTrackEnergy + theNucleusMass);
248   fourMomentumIn.setVect(theTrackMomentum);       236   fourMomentumIn.setVect(theTrackMomentum);
249                                                   237 
250   // Check if inverse kinematics should be use    238   // Check if inverse kinematics should be used
251   const G4bool inverseKinematics = AccuratePro    239   const G4bool inverseKinematics = AccurateProjectile(aTrack, theNucleus);
252                                                   240 
253   // If we are running in inverse kinematics,     241   // If we are running in inverse kinematics, redefine aTrack and theNucleus
254   G4LorentzRotation *toInverseKinematics = NUL    242   G4LorentzRotation *toInverseKinematics = NULL;
255   G4LorentzRotation *toDirectKinematics = NULL    243   G4LorentzRotation *toDirectKinematics = NULL;
256   G4HadProjectile const *aProjectileTrack = &a    244   G4HadProjectile const *aProjectileTrack = &aTrack;
257   G4Nucleus *theTargetNucleus = &theNucleus;      245   G4Nucleus *theTargetNucleus = &theNucleus;
258   if(inverseKinematics) {                         246   if(inverseKinematics) {
259     G4ParticleDefinition *oldTargetDef = theIo    247     G4ParticleDefinition *oldTargetDef = theIonTable->GetIon(nucleusZ, nucleusA, 0);
260     const G4ParticleDefinition *oldProjectileD    248     const G4ParticleDefinition *oldProjectileDef = trackDefinition;
261                                                   249 
262     if(oldProjectileDef != 0 && oldTargetDef !    250     if(oldProjectileDef != 0 && oldTargetDef != 0) {
263       const G4int newTargetA = oldProjectileDe    251       const G4int newTargetA = oldProjectileDef->GetAtomicMass();
264       const G4int newTargetZ = oldProjectileDe    252       const G4int newTargetZ = oldProjectileDef->GetAtomicNumber();
265       const G4int newTargetL = oldProjectileDe << 253 
266       if(newTargetA > 0 && newTargetZ > 0) {      254       if(newTargetA > 0 && newTargetZ > 0) {
267         // This should give us the same energy    255         // This should give us the same energy per nucleon
268         theTargetNucleus = new G4Nucleus(newTa << 256         theTargetNucleus = new G4Nucleus(newTargetA, newTargetZ);
269         toInverseKinematics = new G4LorentzRot    257         toInverseKinematics = new G4LorentzRotation(goodTrack4Momentum.boostVector());
270         G4LorentzVector theProjectile4Momentum    258         G4LorentzVector theProjectile4Momentum(0.0, 0.0, 0.0, theNucleusMass);
271         G4DynamicParticle swappedProjectilePar    259         G4DynamicParticle swappedProjectileParticle(oldTargetDef, (*toInverseKinematics) * theProjectile4Momentum);
272         aProjectileTrack = new G4HadProjectile    260         aProjectileTrack = new G4HadProjectile(swappedProjectileParticle);
273       } else {                                    261       } else {
274         G4String message = "badly defined targ    262         G4String message = "badly defined target after swapping. Falling back to normal (non-swapped) mode.";
275         theInterfaceStore->EmitWarning(message    263         theInterfaceStore->EmitWarning(message);
276         toInverseKinematics = new G4LorentzRot    264         toInverseKinematics = new G4LorentzRotation;
277       }                                           265       }
278     } else {                                      266     } else {
279       G4String message = "oldProjectileDef or     267       G4String message = "oldProjectileDef or oldTargetDef was null";
280       theInterfaceStore->EmitWarning(message);    268       theInterfaceStore->EmitWarning(message);
281       toInverseKinematics = new G4LorentzRotat    269       toInverseKinematics = new G4LorentzRotation;
282     }                                             270     }
283   }                                               271   }
284                                                   272 
285   // INCL assumes the projectile particle is g    273   // INCL assumes the projectile particle is going in the direction of
286   // the Z-axis. Here we construct proper rota    274   // the Z-axis. Here we construct proper rotation to convert the
287   // momentum vectors of the outcoming particl    275   // momentum vectors of the outcoming particles to the original
288   // coordinate system.                           276   // coordinate system.
289   G4LorentzVector projectileMomentum = aProjec    277   G4LorentzVector projectileMomentum = aProjectileTrack->Get4Momentum();
290                                                   278 
291   // INCL++ assumes that the projectile is goi    279   // INCL++ assumes that the projectile is going in the direction of
292   // the z-axis. In principle, if the coordina    280   // the z-axis. In principle, if the coordinate system used by G4
293   // hadronic framework is defined differently    281   // hadronic framework is defined differently we need a rotation to
294   // transform the INCL++ reaction products to    282   // transform the INCL++ reaction products to the appropriate
295   // frame. Please note that it isn't necessar    283   // frame. Please note that it isn't necessary to apply this
296   // transform to the projectile because when     284   // transform to the projectile because when creating the INCL++
297   // projectile particle; \see{toINCLKineticEn    285   // projectile particle; \see{toINCLKineticEnergy} needs to use only the
298   // projectile energy (direction is simply as    286   // projectile energy (direction is simply assumed to be along z-axis).
299   G4RotationMatrix toZ;                           287   G4RotationMatrix toZ;
300   toZ.rotateZ(-projectileMomentum.phi());         288   toZ.rotateZ(-projectileMomentum.phi());
301   toZ.rotateY(-projectileMomentum.theta());       289   toZ.rotateY(-projectileMomentum.theta());
302   G4RotationMatrix toLabFrame3 = toZ.inverse()    290   G4RotationMatrix toLabFrame3 = toZ.inverse();
303   G4LorentzRotation toLabFrame(toLabFrame3);      291   G4LorentzRotation toLabFrame(toLabFrame3);
304   // However, it turns out that the projectile    292   // However, it turns out that the projectile given to us by G4
305   // hadronic framework is already going in th    293   // hadronic framework is already going in the direction of the
306   // z-axis so this rotation is actually unnec    294   // z-axis so this rotation is actually unnecessary. Both toZ and
307   // toLabFrame turn out to be unit matrices a    295   // toLabFrame turn out to be unit matrices as can be seen by
308   // uncommenting the folowing two lines:         296   // uncommenting the folowing two lines:
309   // G4cout <<"toZ = " << toZ << G4endl;          297   // G4cout <<"toZ = " << toZ << G4endl;
310   // G4cout <<"toLabFrame = " << toLabFrame <<    298   // G4cout <<"toLabFrame = " << toLabFrame << G4endl;
311                                                   299 
312   theResult.Clear(); // Make sure the output d    300   theResult.Clear(); // Make sure the output data structure is clean.
313   theResult.SetStatusChange(stopAndKill);         301   theResult.SetStatusChange(stopAndKill);
314                                                   302 
315   std::list<G4Fragment> remnants;                 303   std::list<G4Fragment> remnants;
316                                                   304 
317   const G4int maxTries = 200;                     305   const G4int maxTries = 200;
318   G4int nTries = 0;                               306   G4int nTries = 0;
319   // INCL can generate transparent events. How    307   // INCL can generate transparent events. However, this is meaningful
320   // only in the standalone code. In Geant4 we    308   // only in the standalone code. In Geant4 we must "force" INCL to
321   // produce a valid cascade.                     309   // produce a valid cascade.
322   G4bool eventIsOK = false;                       310   G4bool eventIsOK = false;
323   do {                                            311   do {
324     const G4INCL::ParticleSpecies theSpecies =    312     const G4INCL::ParticleSpecies theSpecies = toINCLParticleSpecies(*aProjectileTrack);
325     const G4double kineticEnergy = toINCLKinet    313     const G4double kineticEnergy = toINCLKineticEnergy(*aProjectileTrack);
326                                                   314 
327     // The INCL model will be created at the f    315     // The INCL model will be created at the first use
328     theINCLModel = G4INCLXXInterfaceStore::Get    316     theINCLModel = G4INCLXXInterfaceStore::GetInstance()->GetINCLModel();
329                                                   317 
330     const G4INCL::EventInfo eventInfo = theINC << 318     const G4INCL::EventInfo eventInfo = theINCLModel->processEvent(theSpecies, kineticEnergy, theTargetNucleus->GetA_asInt(), theTargetNucleus->GetZ_asInt());
331                    theTargetNucleus->GetA_asIn << 319     //    eventIsOK = !eventInfo.transparent && nTries < maxTries;
332                    theTargetNucleus->GetZ_asIn << 
333                    -theTargetNucleus->GetL()); << 
334     //    eventIsOK = !eventInfo.transparent & << 
335     eventIsOK = !eventInfo.transparent;           320     eventIsOK = !eventInfo.transparent;
336     if(eventIsOK) {                               321     if(eventIsOK) {
337                                                   322 
338       // If the collision was run in inverse k    323       // If the collision was run in inverse kinematics, prepare to boost back
339       // all the reaction products                324       // all the reaction products
340       if(inverseKinematics) {                     325       if(inverseKinematics) {
341         toDirectKinematics = new G4LorentzRota    326         toDirectKinematics = new G4LorentzRotation(toInverseKinematics->inverse());
342       }                                           327       }
343                                                   328 
344       G4LorentzVector fourMomentumOut;            329       G4LorentzVector fourMomentumOut;
345                                                   330 
346       for(G4int i = 0; i < eventInfo.nParticle    331       for(G4int i = 0; i < eventInfo.nParticles; ++i) {
347         G4int A = eventInfo.A[i];              << 332   G4int A = eventInfo.A[i];
348         G4int Z = eventInfo.Z[i];              << 333   G4int Z = eventInfo.Z[i];
349         G4int S = eventInfo.S[i];  // Strangen << 334   //  G4cout <<"INCL particle A = " << A << " Z = " << Z << G4endl;
350         G4int PDGCode = eventInfo.PDGCode[i];  << 335   G4double kinE = eventInfo.EKin[i];
351         G4double kinE = eventInfo.EKin[i];     << 336   G4double px = eventInfo.px[i];
352         G4double px = eventInfo.px[i];         << 337   G4double py = eventInfo.py[i];
353         G4double py = eventInfo.py[i];         << 338   G4double pz = eventInfo.pz[i];
354         G4double pz = eventInfo.pz[i];         << 339   G4DynamicParticle *p = toG4Particle(A, Z , kinE, px, py, pz);
355         G4DynamicParticle *p = toG4Particle(A, << 340   if(p != 0) {
356         if(p != 0) {                           << 341     G4LorentzVector momentum = p->Get4Momentum();
357           G4LorentzVector momentum = p->Get4Mo << 
358                                                   342 
359           // Apply the toLabFrame rotation        343           // Apply the toLabFrame rotation
360           momentum *= toLabFrame;                 344           momentum *= toLabFrame;
361           // Apply the inverse-kinematics boos    345           // Apply the inverse-kinematics boost
362           if(inverseKinematics) {                 346           if(inverseKinematics) {
363             momentum *= *toDirectKinematics;      347             momentum *= *toDirectKinematics;
364             momentum.setVect(-momentum.vect())    348             momentum.setVect(-momentum.vect());
365           }                                       349           }
366                                                   350 
367     // Set the four-momentum of the reaction p << 351     // Set the four-momentum of the reaction products
368           p->Set4Momentum(momentum);           << 352     p->Set4Momentum(momentum);
369           fourMomentumOut += momentum;            353           fourMomentumOut += momentum;
                                                   >> 354     theResult.AddSecondary(p);
370                                                   355 
371     // Propagate the particle's parent resonan << 356   } else {
372           G4HadSecondary secondary(p, 1.0, sec << 357     G4String message = "the model produced a particle that couldn't be converted to Geant4 particle.";
373           G4ParticleDefinition* parentResonanc << 
374           if ( eventInfo.parentResonancePDGCod << 
375             parentResonanceDef = G4ParticleTab << 
376           }                                    << 
377           secondary.SetParentResonanceDef(pare << 
378           secondary.SetParentResonanceID(event << 
379                                                << 
380           theResult.AddSecondary(secondary);   << 
381                                                << 
382         } else {                               << 
383           G4String message = "the model produc << 
384           theInterfaceStore->EmitWarning(messa    358           theInterfaceStore->EmitWarning(message);
385         }                                      << 359   }
386       }                                           360       }
387                                                   361 
388       for(G4int i = 0; i < eventInfo.nRemnants    362       for(G4int i = 0; i < eventInfo.nRemnants; ++i) {
389         const G4int A = eventInfo.ARem[i];     << 363   const G4int A = eventInfo.ARem[i];
390         const G4int Z = eventInfo.ZRem[i];     << 364   const G4int Z = eventInfo.ZRem[i];
391         const G4int S = eventInfo.SRem[i];     << 365   //  G4cout <<"INCL particle A = " << A << " Z = " << Z << G4endl;
392         // Check that the remnant is a physica << 366   const G4double kinE = eventInfo.EKinRem[i];
393         if(( Z == 0  &&  S == 0  &&  A > 1 ) | << 367   const G4double px = eventInfo.pxRem[i];
394            ( Z == 0  &&  S != 0  &&  A < 4 ) | << 368   const G4double py = eventInfo.pyRem[i];
395            ( Z != 0  &&  S != 0  &&  A == Z +  << 369   const G4double pz = eventInfo.pzRem[i];
396           std::stringstream ss;                << 
397           ss << "unphysical residual fragment  << 
398              << "  skipping it and resampling  << 
399           theInterfaceStore->EmitWarning(ss.st << 
400           eventIsOK = false;                   << 
401           continue;                            << 
402         }                                      << 
403         const G4double kinE = eventInfo.EKinRe << 
404         const G4double px = eventInfo.pxRem[i] << 
405         const G4double py = eventInfo.pyRem[i] << 
406         const G4double pz = eventInfo.pzRem[i] << 
407         G4ThreeVector spin(                       370         G4ThreeVector spin(
408             eventInfo.jxRem[i]*hbar_Planck,       371             eventInfo.jxRem[i]*hbar_Planck,
409             eventInfo.jyRem[i]*hbar_Planck,       372             eventInfo.jyRem[i]*hbar_Planck,
410             eventInfo.jzRem[i]*hbar_Planck        373             eventInfo.jzRem[i]*hbar_Planck
411             );                                    374             );
412         const G4double excitationE = eventInfo << 375   const G4double excitationE = eventInfo.EStarRem[i];
413         G4double nuclearMass = excitationE;    << 376   const G4double nuclearMass = G4NucleiProperties::GetNuclearMass(A, Z) + excitationE;
414         if ( S == 0 ) {                        << 377         const G4double scaling = remnant4MomentumScaling(nuclearMass,
415           nuclearMass += G4NucleiProperties::G << 378             kinE,
416         } else {                               << 379             px, py, pz);
417     // Assumed that the opposite of the strang << 380   G4LorentzVector fourMomentum(scaling * px, scaling * py, scaling * pz,
418           nuclearMass += G4HyperNucleiProperti << 381              nuclearMass + kinE);
419         }                                      << 382   if(std::abs(scaling - 1.0) > 0.01) {
420         const G4double scaling = remnant4Momen << 
421         G4LorentzVector fourMomentum(scaling * << 
422              nuclearMass + kinE);              << 
423         if(std::abs(scaling - 1.0) > 0.01) {   << 
424           std::stringstream ss;                   383           std::stringstream ss;
425           ss << "momentum scaling = " << scali    384           ss << "momentum scaling = " << scaling
426              << "\n                Lorentz vec << 385             << "\n                Lorentz vector = " << fourMomentum
427              << ")\n                A = " << A << 386             << ")\n                A = " << A << ", Z = " << Z
428              << "\n                E* = " << e << 387             << "\n                E* = " << excitationE << ", nuclearMass = " << nuclearMass
429              << "\n                remnant i=" << 388             << "\n                remnant i=" << i << ", nRemnants=" << eventInfo.nRemnants
430              << "\n                Reaction wa << 389             << "\n                Reaction was: " << aTrack.GetKineticEnergy()/MeV
431              << "-MeV " << trackDefinition->Ge << 390             << "-MeV " << trackDefinition->GetParticleName() << " + "
432              << theIonTable->GetIonName(theNuc << 391             << theIonTable->GetIonName(theNucleus.GetZ_asInt(), theNucleus.GetA_asInt(), 0)
433              << ", in " << (inverseKinematics  << 392             << ", in " << (inverseKinematics ? "inverse" : "direct") << " kinematics.";
434           theInterfaceStore->EmitWarning(ss.st    393           theInterfaceStore->EmitWarning(ss.str());
435         }                                      << 394   }
436                                                   395 
437         // Apply the toLabFrame rotation          396         // Apply the toLabFrame rotation
438         fourMomentum *= toLabFrame;               397         fourMomentum *= toLabFrame;
439         spin *= toLabFrame3;                      398         spin *= toLabFrame3;
440         // Apply the inverse-kinematics boost     399         // Apply the inverse-kinematics boost
441         if(inverseKinematics) {                   400         if(inverseKinematics) {
442           fourMomentum *= *toDirectKinematics;    401           fourMomentum *= *toDirectKinematics;
443           fourMomentum.setVect(-fourMomentum.v    402           fourMomentum.setVect(-fourMomentum.vect());
444         }                                         403         }
445                                                   404 
446         fourMomentumOut += fourMomentum;          405         fourMomentumOut += fourMomentum;
447         G4Fragment remnant(A, Z, std::abs(S),  << 406   G4Fragment remnant(A, Z, fourMomentum);
448         remnant.SetAngularMomentum(spin);         407         remnant.SetAngularMomentum(spin);
449         remnant.SetCreatorModelID(secID);      << 
450         if(dumpRemnantInfo) {                     408         if(dumpRemnantInfo) {
451           G4cerr << "G4INCLXX_DUMP_REMNANT: "     409           G4cerr << "G4INCLXX_DUMP_REMNANT: " << remnant << "  spin: " << spin << G4endl;
452         }                                         410         }
453         remnants.push_back(remnant);           << 411   remnants.push_back(remnant);
454       }                                           412       }
455                                                   413 
456       // Give up is the event is not ok (e.g.  << 414       // Check four-momentum conservation
457       if(!eventIsOK) {                         << 415       const G4LorentzVector violation4Momentum = fourMomentumOut - fourMomentumIn;
458         const G4int nSecondaries = (G4int)theR << 416       const G4double energyViolation = std::abs(violation4Momentum.e());
459         for(G4int j=0; j<nSecondaries; ++j) de << 417       const G4double momentumViolation = violation4Momentum.rho();
                                                   >> 418       if(energyViolation > G4INCLXXInterfaceStore::GetInstance()->GetConservationTolerance()) {
                                                   >> 419         std::stringstream ss;
                                                   >> 420         ss << "energy conservation violated by " << energyViolation/MeV << " MeV in "
                                                   >> 421           << aTrack.GetKineticEnergy()/MeV << "-MeV " << trackDefinition->GetParticleName()
                                                   >> 422           << " + " << theIonTable->GetIonName(theNucleus.GetZ_asInt(), theNucleus.GetA_asInt(), 0)
                                                   >> 423           << " inelastic reaction, in " << (inverseKinematics ? "inverse" : "direct") << " kinematics. Will resample.";
                                                   >> 424         theInterfaceStore->EmitWarning(ss.str());
                                                   >> 425         eventIsOK = false;
                                                   >> 426         const G4int nSecondaries = theResult.GetNumberOfSecondaries();
                                                   >> 427         for(G4int j=0; j<nSecondaries; ++j)
                                                   >> 428           delete theResult.GetSecondary(j)->GetParticle();
                                                   >> 429         theResult.Clear();
                                                   >> 430         theResult.SetStatusChange(stopAndKill);
                                                   >> 431         remnants.clear();
                                                   >> 432       } else if(momentumViolation > G4INCLXXInterfaceStore::GetInstance()->GetConservationTolerance()) {
                                                   >> 433         std::stringstream ss;
                                                   >> 434         ss << "momentum conservation violated by " << momentumViolation/MeV << " MeV in "
                                                   >> 435           << aTrack.GetKineticEnergy()/MeV << "-MeV " << trackDefinition->GetParticleName()
                                                   >> 436           << " + " << theIonTable->GetIonName(theNucleus.GetZ_asInt(), theNucleus.GetA_asInt(), 0)
                                                   >> 437           << " inelastic reaction, in " << (inverseKinematics ? "inverse" : "direct") << " kinematics. Will resample.";
                                                   >> 438         theInterfaceStore->EmitWarning(ss.str());
                                                   >> 439         eventIsOK = false;
                                                   >> 440         const G4int nSecondaries = theResult.GetNumberOfSecondaries();
                                                   >> 441         for(G4int j=0; j<nSecondaries; ++j)
                                                   >> 442           delete theResult.GetSecondary(j)->GetParticle();
460         theResult.Clear();                        443         theResult.Clear();
461         theResult.SetStatusChange(stopAndKill)    444         theResult.SetStatusChange(stopAndKill);
462         remnants.clear();                         445         remnants.clear();
463       } else {                                 << 
464         // Check four-momentum conservation    << 
465         const G4LorentzVector violation4Moment << 
466         const G4double energyViolation = std:: << 
467         const G4double momentumViolation = vio << 
468         if(energyViolation > G4INCLXXInterface << 
469           std::stringstream ss;                << 
470           ss << "energy conservation violated  << 
471              << aTrack.GetKineticEnergy()/MeV  << 
472              << " + " << theIonTable->GetIonNa << 
473              << " inelastic reaction, in " <<  << 
474           theInterfaceStore->EmitWarning(ss.st << 
475           eventIsOK = false;                   << 
476           const G4int nSecondaries = (G4int)th << 
477           for(G4int j=0; j<nSecondaries; ++j)  << 
478           theResult.Clear();                   << 
479           theResult.SetStatusChange(stopAndKil << 
480           remnants.clear();                    << 
481         } else if(momentumViolation > G4INCLXX << 
482           std::stringstream ss;                << 
483           ss << "momentum conservation violate << 
484              << aTrack.GetKineticEnergy()/MeV  << 
485              << " + " << theIonTable->GetIonNa << 
486              << " inelastic reaction, in " <<  << 
487           theInterfaceStore->EmitWarning(ss.st << 
488           eventIsOK = false;                   << 
489           const G4int nSecondaries = (G4int)th << 
490           for(G4int j=0; j<nSecondaries; ++j)  << 
491           theResult.Clear();                   << 
492           theResult.SetStatusChange(stopAndKil << 
493           remnants.clear();                    << 
494         }                                      << 
495       }                                           446       }
496     }                                             447     }
497     nTries++;                                     448     nTries++;
498   } while(!eventIsOK && nTries < maxTries); /*    449   } while(!eventIsOK && nTries < maxTries); /* Loop checking, 10.07.2015, D.Mancusi */
499                                                   450 
500   // Clean up the objects that we created for     451   // Clean up the objects that we created for the inverse kinematics
501   if(inverseKinematics) {                         452   if(inverseKinematics) {
502     delete aProjectileTrack;                      453     delete aProjectileTrack;
503     delete theTargetNucleus;                      454     delete theTargetNucleus;
504     delete toInverseKinematics;                   455     delete toInverseKinematics;
505     delete toDirectKinematics;                    456     delete toDirectKinematics;
506   }                                               457   }
507                                                   458 
508   if(!eventIsOK) {                                459   if(!eventIsOK) {
509     std::stringstream ss;                         460     std::stringstream ss;
510     ss << "maximum number of tries exceeded fo    461     ss << "maximum number of tries exceeded for the proposed "
511     << aTrack.GetKineticEnergy()/MeV << "-MeV     462     << aTrack.GetKineticEnergy()/MeV << "-MeV " << trackDefinition->GetParticleName()
512     << " + " << theIonTable->GetIonName(nucleu    463     << " + " << theIonTable->GetIonName(nucleusZ, nucleusA, 0)
513     << " inelastic reaction, in " << (inverseK    464     << " inelastic reaction, in " << (inverseKinematics ? "inverse" : "direct") << " kinematics.";
514     theInterfaceStore->EmitWarning(ss.str());     465     theInterfaceStore->EmitWarning(ss.str());
515     theResult.SetStatusChange(isAlive);           466     theResult.SetStatusChange(isAlive);
516     theResult.SetEnergyChange(aTrack.GetKineti    467     theResult.SetEnergyChange(aTrack.GetKineticEnergy());
517     theResult.SetMomentumChange(aTrack.Get4Mom    468     theResult.SetMomentumChange(aTrack.Get4Momentum().vect().unit());
518     return &theResult;                            469     return &theResult;
519   }                                               470   }
520                                                   471 
521   // De-excitation:                               472   // De-excitation:
522                                                   473 
523   if(theDeExcitation != 0) {                      474   if(theDeExcitation != 0) {
524     for(std::list<G4Fragment>::iterator i = re    475     for(std::list<G4Fragment>::iterator i = remnants.begin();
525   i != remnants.end(); ++i) {                  << 476   i != remnants.end(); ++i) {
526       G4ReactionProductVector *deExcitationRes    477       G4ReactionProductVector *deExcitationResult = theDeExcitation->DeExcite((*i));
527                                                   478 
528       for(G4ReactionProductVector::iterator fr    479       for(G4ReactionProductVector::iterator fragment = deExcitationResult->begin();
529     fragment != deExcitationResult->end(); ++f << 480     fragment != deExcitationResult->end(); ++fragment) {
530   const G4ParticleDefinition *def = (*fragment << 481   const G4ParticleDefinition *def = (*fragment)->GetDefinition();
531   if(def != 0) {                               << 482   if(def != 0) {
532     G4DynamicParticle *theFragment = new G4Dyn << 483     G4DynamicParticle *theFragment = new G4DynamicParticle(def, (*fragment)->GetMomentum());
533     theResult.AddSecondary(theFragment, (*frag << 484     theResult.AddSecondary(theFragment);
534   }                                            << 485   }
535       }                                           486       }
536                                                   487 
537       for(G4ReactionProductVector::iterator fr    488       for(G4ReactionProductVector::iterator fragment = deExcitationResult->begin();
538     fragment != deExcitationResult->end(); ++f << 489     fragment != deExcitationResult->end(); ++fragment) {
539   delete (*fragment);                          << 490   delete (*fragment);
540       }                                           491       }
541       deExcitationResult->clear();                492       deExcitationResult->clear();
542       delete deExcitationResult;                  493       delete deExcitationResult;
543     }                                             494     }
544   }                                               495   }
545                                                   496 
546   remnants.clear();                               497   remnants.clear();
547                                                   498 
548   if((theTally = theInterfaceStore->GetTally()    499   if((theTally = theInterfaceStore->GetTally()))
549     theTally->Tally(aTrack, theNucleus, theRes    500     theTally->Tally(aTrack, theNucleus, theResult);
550                                                   501 
551   return &theResult;                              502   return &theResult;
552 }                                                 503 }
553                                                   504 
554 G4ReactionProductVector* G4INCLXXInterface::Pr    505 G4ReactionProductVector* G4INCLXXInterface::Propagate(G4KineticTrackVector* , G4V3DNucleus* ) {
555   return 0;                                       506   return 0;
556 }                                                 507 }
557                                                   508 
558 G4INCL::ParticleType G4INCLXXInterface::toINCL    509 G4INCL::ParticleType G4INCLXXInterface::toINCLParticleType(G4ParticleDefinition const * const pdef) const {
559   if(     pdef == G4Proton::Proton())          << 510   if(     pdef == G4Proton::Proton())           return G4INCL::Proton;
560   else if(pdef == G4Neutron::Neutron())        << 511   else if(pdef == G4Neutron::Neutron())         return G4INCL::Neutron;
561   else if(pdef == G4PionPlus::PionPlus())      << 512   else if(pdef == G4PionPlus::PionPlus())       return G4INCL::PiPlus;
562   else if(pdef == G4PionMinus::PionMinus())    << 513   else if(pdef == G4PionMinus::PionMinus())     return G4INCL::PiMinus;
563   else if(pdef == G4PionZero::PionZero())      << 514   else if(pdef == G4PionZero::PionZero())       return G4INCL::PiZero;
564   else if(pdef == G4KaonPlus::KaonPlus())      << 515   else if(pdef == G4Deuteron::Deuteron())       return G4INCL::Composite;
565   else if(pdef == G4KaonZero::KaonZero())      << 516   else if(pdef == G4Triton::Triton())           return G4INCL::Composite;
566   else if(pdef == G4KaonMinus::KaonMinus())    << 517   else if(pdef == G4He3::He3())                 return G4INCL::Composite;
567   else if(pdef == G4AntiKaonZero::AntiKaonZero << 518   else if(pdef == G4Alpha::Alpha())             return G4INCL::Composite;
568   // For K0L & K0S we do not take into account << 
569   else if(pdef == G4KaonZeroLong::KaonZeroLong << 
570   else if(pdef == G4KaonZeroShort::KaonZeroSho << 
571   else if(pdef == G4Deuteron::Deuteron())      << 
572   else if(pdef == G4Triton::Triton())          << 
573   else if(pdef == G4He3::He3())                << 
574   else if(pdef == G4Alpha::Alpha())            << 
575   else if(pdef == G4AntiProton::AntiProton())  << 
576   else if(pdef->GetParticleType() == G4Generic    519   else if(pdef->GetParticleType() == G4GenericIon::GenericIon()->GetParticleType()) return G4INCL::Composite;
577   else                                         << 520   else                                            return G4INCL::UnknownParticle;
578 }                                                 521 }
579                                                   522 
580 G4INCL::ParticleSpecies G4INCLXXInterface::toI    523 G4INCL::ParticleSpecies G4INCLXXInterface::toINCLParticleSpecies(G4HadProjectile const &aTrack) const {
581   const G4ParticleDefinition *pdef = aTrack.Ge    524   const G4ParticleDefinition *pdef = aTrack.GetDefinition();
582   const G4INCL::ParticleType theType = toINCLP    525   const G4INCL::ParticleType theType = toINCLParticleType(pdef);
583   if(theType!=G4INCL::Composite)                  526   if(theType!=G4INCL::Composite)
584     return G4INCL::ParticleSpecies(theType);      527     return G4INCL::ParticleSpecies(theType);
585   else {                                          528   else {
586     G4INCL::ParticleSpecies theSpecies;           529     G4INCL::ParticleSpecies theSpecies;
587     theSpecies.theType=theType;                   530     theSpecies.theType=theType;
588     theSpecies.theA=pdef->GetAtomicMass();        531     theSpecies.theA=pdef->GetAtomicMass();
589     theSpecies.theZ=pdef->GetAtomicNumber();      532     theSpecies.theZ=pdef->GetAtomicNumber();
590     return theSpecies;                            533     return theSpecies;
591   }                                               534   }
592 }                                                 535 }
593                                                   536 
594 G4double G4INCLXXInterface::toINCLKineticEnerg    537 G4double G4INCLXXInterface::toINCLKineticEnergy(G4HadProjectile const &aTrack) const {
595   return aTrack.GetKineticEnergy();               538   return aTrack.GetKineticEnergy();
596 }                                                 539 }
597                                                   540 
598 G4ParticleDefinition *G4INCLXXInterface::toG4P << 541 G4ParticleDefinition *G4INCLXXInterface::toG4ParticleDefinition(G4int A, G4int Z) const {
599   if       (PDGCode == 2212) { return G4Proton << 542   if     (A == 1 && Z == 1)  return G4Proton::Proton();
600   } else if(PDGCode == 2112) { return G4Neutro << 543   else if(A == 1 && Z == 0)  return G4Neutron::Neutron();
601   } else if(PDGCode == 211)  { return G4PionPl << 544   else if(A == 0 && Z == 1)  return G4PionPlus::PionPlus();
602   } else if(PDGCode == 111)  { return G4PionZe << 545   else if(A == 0 && Z == -1) return G4PionMinus::PionMinus();
603   } else if(PDGCode == -211) { return G4PionMi << 546   else if(A == 0 && Z == 0)  return G4PionZero::PionZero();
604                                                << 547   else if(A == 2 && Z == 1)  return G4Deuteron::Deuteron();
605   } else if(PDGCode == 221)  { return G4Eta::E << 548   else if(A == 3 && Z == 1)  return G4Triton::Triton();
606   } else if(PDGCode == 22)   { return G4Gamma: << 549   else if(A == 3 && Z == 2)  return G4He3::He3();
607                                                << 550   else if(A == 4 && Z == 2)  return G4Alpha::Alpha();
608   } else if(PDGCode == 3122) { return G4Lambda << 551   else if(A > 0 && Z > 0 && A > Z) { // Returns ground state ion definition
609   } else if(PDGCode == 3222) { return G4SigmaP << 
610   } else if(PDGCode == 3212) { return G4SigmaZ << 
611   } else if(PDGCode == 3112) { return G4SigmaM << 
612   } else if(PDGCode == 321)  { return G4KaonPl << 
613   } else if(PDGCode == -321) { return G4KaonMi << 
614   } else if(PDGCode == 130)  { return G4KaonZe << 
615   } else if(PDGCode == 310)  { return G4KaonZe << 
616                                                << 
617   } else if(PDGCode == 1002) { return G4Deuter << 
618   } else if(PDGCode == 1003) { return G4Triton << 
619   } else if(PDGCode == 2003) { return G4He3::H << 
620   } else if(PDGCode == 2004) { return G4Alpha: << 
621                                                << 
622   } else if(PDGCode == -2212) { return G4AntiP << 
623   } else if(S != 0) {  // Assumed that -S give << 
624     if (A == 3 && Z == 1 && S == -1 ) return G << 
625     if (A == 4 && Z == 1 && S == -1 ) return G << 
626     if (A == 4 && Z == 2 && S == -1 ) return G << 
627     if (A == 4 && Z == 1 && S == -2 ) return G << 
628     if (A == 4 && Z == 0 && S == -2 ) return G << 
629     if (A == 5 && Z == 2 && S == -1 ) return G << 
630   } else if(A > 0 && Z > 0 && A > Z) { // Retu << 
631     return theIonTable->GetIon(Z, A, 0);          552     return theIonTable->GetIon(Z, A, 0);
                                                   >> 553   } else { // Error, unrecognized particle
                                                   >> 554     return 0;
632   }                                               555   }
633   return 0; // Error, unrecognized particle    << 
634 }                                                 556 }
635                                                   557 
636 G4DynamicParticle *G4INCLXXInterface::toG4Part << 558 G4DynamicParticle *G4INCLXXInterface::toG4Particle(G4int A, G4int Z,
637                G4double kinE, G4double px,     << 559              G4double kinE,
638                                                << 560              G4double px,
639   const G4ParticleDefinition *def = toG4Partic << 561                                                  G4double py, G4double pz) const {
                                                   >> 562   const G4ParticleDefinition *def = toG4ParticleDefinition(A, Z);
640   if(def == 0) { // Check if we have a valid p    563   if(def == 0) { // Check if we have a valid particle definition
641     return 0;                                     564     return 0;
642   }                                               565   }
643   const G4double energy = kinE * MeV;             566   const G4double energy = kinE * MeV;
644   const G4ThreeVector momentum(px, py, pz);       567   const G4ThreeVector momentum(px, py, pz);
645   const G4ThreeVector momentumDirection = mome    568   const G4ThreeVector momentumDirection = momentum.unit();
646   G4DynamicParticle *p = new G4DynamicParticle    569   G4DynamicParticle *p = new G4DynamicParticle(def, momentumDirection, energy);
647   return p;                                       570   return p;
648 }                                                 571 }
649                                                   572 
650 G4double G4INCLXXInterface::remnant4MomentumSc    573 G4double G4INCLXXInterface::remnant4MomentumScaling(G4double mass,
651               G4double kineticE,               << 574               G4double kineticE,
652               G4double px, G4double py,        << 575               G4double px, G4double py,
653               G4double pz) const {             << 576               G4double pz) const {
654   const G4double p2 = px*px + py*py + pz*pz;      577   const G4double p2 = px*px + py*py + pz*pz;
655   if(p2 > 0.0) {                                  578   if(p2 > 0.0) {
656     const G4double pnew2 = kineticE*kineticE +    579     const G4double pnew2 = kineticE*kineticE + 2.0*kineticE*mass;
657     return std::sqrt(pnew2)/std::sqrt(p2);        580     return std::sqrt(pnew2)/std::sqrt(p2);
658   } else {                                        581   } else {
659     return 1.0;                                   582     return 1.0;
660   }                                               583   }
661 }                                                 584 }
662                                                   585 
663 void G4INCLXXInterface::ModelDescription(std::    586 void G4INCLXXInterface::ModelDescription(std::ostream& outFile) const {
664    outFile                                        587    outFile
665      << "The Liège Intranuclear Cascade (INCL    588      << "The Liège Intranuclear Cascade (INCL++) is a model for reactions induced\n"
666      << "by nucleons, pions and light ion on a    589      << "by nucleons, pions and light ion on any nucleus. The reaction is\n"
667      << "described as an avalanche of binary n    590      << "described as an avalanche of binary nucleon-nucleon collisions, which can\n"
668      << "lead to the emission of energetic par    591      << "lead to the emission of energetic particles and to the formation of an\n"
669      << "excited thermalised nucleus (remnant)    592      << "excited thermalised nucleus (remnant). The de-excitation of the remnant is\n"
670      << "outside the scope of INCL++ and is ty    593      << "outside the scope of INCL++ and is typically described by another model.\n\n"
671      << "INCL++ has been reasonably well teste    594      << "INCL++ has been reasonably well tested for nucleon (~50 MeV to ~15 GeV),\n"
672      << "pion (idem) and light-ion projectiles    595      << "pion (idem) and light-ion projectiles (up to A=18, ~10A MeV to 1A GeV).\n"
673      << "Most tests involved target nuclei clo    596      << "Most tests involved target nuclei close to the stability valley, with\n"
674      << "numbers between 4 and 250.\n\n"          597      << "numbers between 4 and 250.\n\n"
675      << "Reference: D. Mancusi et al., Phys. R    598      << "Reference: D. Mancusi et al., Phys. Rev. C90 (2014) 054602\n\n";
676 }                                                 599 }
677                                                   600 
678 G4String const &G4INCLXXInterface::GetDeExcita    601 G4String const &G4INCLXXInterface::GetDeExcitationModelName() const {
679   return theDeExcitation->GetModelName();         602   return theDeExcitation->GetModelName();
680 }                                                 603 }
681                                                   604