Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/inclxx/incl_physics/src/G4INCLStandardPropagationModel.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/incl_physics/src/G4INCLStandardPropagationModel.cc (Version 11.3.0) and /processes/hadronic/models/inclxx/incl_physics/src/G4INCLStandardPropagationModel.cc (Version 10.0.p1)


  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 // Pekka Kaitaniemi, CEA and Helsinki Institute of Physics
 28 // Joseph Cugnon, University of Liege, Belgium <<  28 // Davide Mancusi, CEA
 29 // Jean-Christophe David, CEA-Saclay, France   <<  29 // Alain Boudard, CEA
 30 // Pekka Kaitaniemi, CEA-Saclay, France, and H <<  30 // Sylvie Leray, CEA
 31 // Sylvie Leray, CEA-Saclay, France            <<  31 // Joseph Cugnon, University of Liege
 32 // Davide Mancusi, CEA-Saclay, France          << 
 33 //                                                 32 //
 34 #define INCLXX_IN_GEANT4_MODE 1                    33 #define INCLXX_IN_GEANT4_MODE 1
 35                                                    34 
 36 #include "globals.hh"                              35 #include "globals.hh"
 37                                                    36 
 38 /*                                                 37 /*
 39  * StandardPropagationModel.cpp                    38  * StandardPropagationModel.cpp
 40  *                                                 39  *
 41  *  \date 4 juin 2009                              40  *  \date 4 juin 2009
 42  * \author Pekka Kaitaniemi                        41  * \author Pekka Kaitaniemi
 43  */                                                42  */
 44                                                    43 
 45 #include "G4INCLStandardPropagationModel.hh"       44 #include "G4INCLStandardPropagationModel.hh"
 46 #include "G4INCLPbarAtrestEntryChannel.hh"     << 
 47 #include "G4INCLSurfaceAvatar.hh"                  45 #include "G4INCLSurfaceAvatar.hh"
 48 #include "G4INCLBinaryCollisionAvatar.hh"          46 #include "G4INCLBinaryCollisionAvatar.hh"
 49 #include "G4INCLDecayAvatar.hh"                    47 #include "G4INCLDecayAvatar.hh"
 50 #include "G4INCLCrossSections.hh"                  48 #include "G4INCLCrossSections.hh"
 51 #include "G4INCLRandom.hh"                         49 #include "G4INCLRandom.hh"
 52 #include <iostream>                                50 #include <iostream>
 53 #include <algorithm>                               51 #include <algorithm>
 54 #include "G4INCLLogger.hh"                         52 #include "G4INCLLogger.hh"
 55 #include "G4INCLGlobals.hh"                        53 #include "G4INCLGlobals.hh"
 56 #include "G4INCLKinematicsUtils.hh"                54 #include "G4INCLKinematicsUtils.hh"
 57 #include "G4INCLCoulombDistortion.hh"              55 #include "G4INCLCoulombDistortion.hh"
 58 #include "G4INCLDeltaDecayChannel.hh"              56 #include "G4INCLDeltaDecayChannel.hh"
 59 #include "G4INCLSigmaZeroDecayChannel.hh"      << 
 60 #include "G4INCLPionResonanceDecayChannel.hh"  << 
 61 #include "G4INCLParticleEntryAvatar.hh"            57 #include "G4INCLParticleEntryAvatar.hh"
 62 #include "G4INCLIntersection.hh"                   58 #include "G4INCLIntersection.hh"
 63 #include <vector>                              << 
 64                                                    59 
 65 namespace G4INCL {                                 60 namespace G4INCL {
 66                                                    61 
 67     StandardPropagationModel::StandardPropagat <<  62     StandardPropagationModel::StandardPropagationModel(LocalEnergyType localEnergyType, LocalEnergyType localEnergyDeltaType)
 68       :theNucleus(0), maximumTime(70.0), curre <<  63       :theNucleus(0), maximumTime(70.0), currentTime(0.0), firstAvatar(true),
 69       hadronizationTime(hTime),                << 
 70       firstAvatar(true),                       << 
 71       theLocalEnergyType(localEnergyType),         64       theLocalEnergyType(localEnergyType),
 72       theLocalEnergyDeltaType(localEnergyDelta     65       theLocalEnergyDeltaType(localEnergyDeltaType)
 73     {                                              66     {
 74     }                                              67     }
 75                                                    68 
 76     StandardPropagationModel::~StandardPropaga     69     StandardPropagationModel::~StandardPropagationModel()
 77     {                                              70     {
 78       delete theNucleus;                           71       delete theNucleus;
 79     }                                              72     }
 80                                                    73 
 81     G4INCL::Nucleus* StandardPropagationModel:     74     G4INCL::Nucleus* StandardPropagationModel::getNucleus()
 82     {                                              75     {
 83       return theNucleus;                           76       return theNucleus;
 84     }                                              77     }
 85                                                    78 
 86 //D                                            <<  79     G4double StandardPropagationModel::shoot(ParticleSpecies const projectileSpecies, const G4double kineticEnergy, const G4double impactParameter, const G4double phi) {
 87                                                <<  80       if(projectileSpecies.theType==Composite)
 88     G4double StandardPropagationModel::shoot(P << 
 89       if(projectileSpecies.theType==Composite) << 
 90         return shootComposite(projectileSpecie     81         return shootComposite(projectileSpecies, kineticEnergy, impactParameter, phi);
 91       }                                        <<  82       else
 92       else if(projectileSpecies.theType==antiP << 
 93         return shootAtrest(projectileSpecies.t << 
 94       }                                        << 
 95       else{                                    << 
 96         return shootParticle(projectileSpecies     83         return shootParticle(projectileSpecies.theType, kineticEnergy, impactParameter, phi);
 97       }                                        << 
 98     }                                              84     }
 99                                                    85 
100 //D                                            << 
101                                                << 
102     G4double StandardPropagationModel::shootAt << 
103       theNucleus->setParticleNucleusCollision( << 
104       currentTime = 0.0;                       << 
105                                                << 
106       // Create final state particles          << 
107       const G4double projectileMass = Particle << 
108       G4double energy = kineticEnergy + projec << 
109       G4double momentumZ = std::sqrt(energy*en << 
110       ThreeVector momentum(0.0, 0.0, momentumZ << 
111       Particle *pb = new G4INCL::Particle(t, e << 
112       PbarAtrestEntryChannel *obj = new PbarAt << 
113       ParticleList fslist = obj->makeMesonStar << 
114       const G4bool isProton = obj->ProtonIsThe << 
115       delete pb;                               << 
116                                                << 
117       //set Stopping time according to highest << 
118       G4double temfin;                         << 
119       G4double TLab;                           << 
120       std::vector<G4double> energies;          << 
121       std::vector<G4double> projections;       << 
122       ThreeVector ab, cd;                      << 
123                                                << 
124       for(ParticleIter pit = fslist.begin(), e << 
125         energies.push_back((*pit)->getKineticE << 
126         ab = (*pit)->boostVector();            << 
127         cd = (*pit)->getPosition();            << 
128         projections.push_back(ab.dot(cd)); //p << 
129       }// make vector of energies              << 
130                                                << 
131       temfin = 30.18 * std::pow(theNucleus->ge << 
132       TLab = *max_element(energies.begin(), en << 
133                                                << 
134       // energy-dependent stopping time above  << 
135       if(TLab>2000.)                           << 
136         temfin *= (5.8E4-TLab)/5.6E4;          << 
137                                                << 
138       maximumTime = temfin;                    << 
139                                                << 
140       // If the incoming particle is slow, use << 
141       const G4double rMax = theNucleus->getUni << 
142       const G4double distance = 2.*rMax;       << 
143       const G4double maxMesonVelocityProjectio << 
144       const G4double traversalTime = distance  << 
145       if(maximumTime < traversalTime)          << 
146         maximumTime = traversalTime;           << 
147       INCL_DEBUG("Cascade stopping time is " < << 
148                                                << 
149                                                << 
150       // Fill in the relevant kinematic variab << 
151       theNucleus->setIncomingAngularMomentum(G << 
152       theNucleus->setIncomingMomentum(G4INCL:: << 
153       if(isProton){                            << 
154         theNucleus->setInitialEnergy(pb->getMa << 
155           + ParticleTable::getTableMass(theNuc << 
156       }                                        << 
157       else{                                    << 
158         theNucleus->setInitialEnergy(pb->getMa << 
159           + ParticleTable::getTableMass(theNuc << 
160       }                                        << 
161       //kinetic energy excluded from the balan << 
162                                                << 
163       for(ParticleIter p = fslist.begin(), e = << 
164         (*p)->makeProjectileSpectator();       << 
165       }                                        << 
166                                                << 
167       generateAllAvatars();                    << 
168       firstAvatar = false;                     << 
169                                                << 
170       // Get the entry avatars for mesons      << 
171       IAvatarList theAvatarList = obj->bringMe << 
172       delete obj;                              << 
173       theNucleus->getStore()->addParticleEntry << 
174       INCL_DEBUG("Avatars added" << '\n');     << 
175                                                << 
176       return 99.;                              << 
177     }                                          << 
178                                                << 
179 //D                                            << 
180                                                << 
181     G4double StandardPropagationModel::shootPa     86     G4double StandardPropagationModel::shootParticle(ParticleType const type, const G4double kineticEnergy, const G4double impactParameter, const G4double phi) {
182       theNucleus->setParticleNucleusCollision(     87       theNucleus->setParticleNucleusCollision();
183       currentTime = 0.0;                           88       currentTime = 0.0;
184                                                    89 
185       // Create the projectile particle            90       // Create the projectile particle
186       const G4double projectileMass = Particle     91       const G4double projectileMass = ParticleTable::getTableParticleMass(type);
187       G4double energy = kineticEnergy + projec     92       G4double energy = kineticEnergy + projectileMass;
188       G4double momentumZ = std::sqrt(energy*en     93       G4double momentumZ = std::sqrt(energy*energy - projectileMass*projectileMass);
189       ThreeVector momentum(0.0, 0.0, momentumZ     94       ThreeVector momentum(0.0, 0.0, momentumZ);
190       Particle *p= new G4INCL::Particle(type,      95       Particle *p= new G4INCL::Particle(type, energy, momentum, ThreeVector());
191                                                    96 
192       G4double temfin;                         <<  97       G4double temfin = 0.0;
193       G4double TLab;                           <<  98       if( p->isNucleon() )
194       if( p->isMeson()) {                      << 
195         temfin = 30.18 * std::pow(theNucleus-> << 
196         TLab = p->getKineticEnergy();          << 
197       } else {                                 << 
198         temfin = 29.8 * std::pow(theNucleus->g     99         temfin = 29.8 * std::pow(theNucleus->getA(), 0.16);
199         TLab = p->getKineticEnergy()/p->getA() << 100       else {
                                                   >> 101         const G4double tlab = p->getEnergy() - p->getMass();
                                                   >> 102         temfin = 30.18 * std::pow(theNucleus->getA(), 0.17*(1.0 - 5.7E-5*tlab));
200       }                                           103       }
201                                                   104 
202       // energy-dependent stopping time above  << 
203       if(TLab>2000.)                           << 
204         temfin *= (5.8E4-TLab)/5.6E4;          << 
205                                                << 
206       maximumTime = temfin;                       105       maximumTime = temfin;
207                                                   106 
208       // If the incoming particle is slow, use    107       // If the incoming particle is slow, use a larger stopping time
209       const G4double rMax = theNucleus->getUni    108       const G4double rMax = theNucleus->getUniverseRadius();
210       const G4double distance = 2.*rMax;          109       const G4double distance = 2.*rMax;
211       const G4double projectileVelocity = p->b    110       const G4double projectileVelocity = p->boostVector().mag();
212       const G4double traversalTime = distance     111       const G4double traversalTime = distance / projectileVelocity;
213       if(maximumTime < traversalTime)             112       if(maximumTime < traversalTime)
214         maximumTime = traversalTime;              113         maximumTime = traversalTime;
215       INCL_DEBUG("Cascade stopping time is " < << 114       INCL_DEBUG("Cascade stopping time is " << maximumTime << std::endl);
216                                                   115 
217       // If Coulomb is activated, do not proce    116       // If Coulomb is activated, do not process events with impact
218       // parameter larger than the maximum imp    117       // parameter larger than the maximum impact parameter, taking into
219       // account Coulomb distortion.              118       // account Coulomb distortion.
220       if(impactParameter>CoulombDistortion::ma    119       if(impactParameter>CoulombDistortion::maxImpactParameter(p->getSpecies(), kineticEnergy, theNucleus)) {
221         INCL_DEBUG("impactParameter>CoulombDis << 120         INCL_DEBUG("impactParameter>CoulombDistortion::maxImpactParameter" << std::endl);
222         delete p;                                 121         delete p;
223         return -1.;                               122         return -1.;
224       }                                           123       }
225                                                   124 
226       ThreeVector position(impactParameter * s    125       ThreeVector position(impactParameter * std::cos(phi),
227           impactParameter * std::sin(phi),        126           impactParameter * std::sin(phi),
228           0.);                                    127           0.);
229       p->setPosition(position);                   128       p->setPosition(position);
230                                                   129 
231       // Fill in the relevant kinematic variab    130       // Fill in the relevant kinematic variables
232       theNucleus->setIncomingAngularMomentum(p    131       theNucleus->setIncomingAngularMomentum(p->getAngularMomentum());
233       theNucleus->setIncomingMomentum(p->getMo    132       theNucleus->setIncomingMomentum(p->getMomentum());
234       theNucleus->setInitialEnergy(p->getEnerg    133       theNucleus->setInitialEnergy(p->getEnergy()
235           + ParticleTable::getTableMass(theNuc << 134           + ParticleTable::getTableMass(theNucleus->getA(),theNucleus->getZ()));
236                                                   135 
237       // Reset the particle kinematics to the     136       // Reset the particle kinematics to the INCL values
238       p->setINCLMass();                           137       p->setINCLMass();
239       p->setEnergy(p->getMass() + kineticEnerg    138       p->setEnergy(p->getMass() + kineticEnergy);
240       p->adjustMomentumFromEnergy();              139       p->adjustMomentumFromEnergy();
241                                                   140 
242       p->makeProjectileSpectator();               141       p->makeProjectileSpectator();
243       generateAllAvatars();                       142       generateAllAvatars();
244       firstAvatar = false;                        143       firstAvatar = false;
245                                                   144 
246       // Get the entry avatars from Coulomb an    145       // Get the entry avatars from Coulomb and put them in the Store
247       ParticleEntryAvatar *theEntryAvatar = Co    146       ParticleEntryAvatar *theEntryAvatar = CoulombDistortion::bringToSurface(p, theNucleus);
248       if(theEntryAvatar) {                        147       if(theEntryAvatar) {
249         theNucleus->getStore()->addParticleEnt    148         theNucleus->getStore()->addParticleEntryAvatar(theEntryAvatar);
250                                                   149 
                                                   >> 150         theNucleus->setProjectileChargeNumber(p->getZ());
                                                   >> 151         theNucleus->setProjectileMassNumber(p->getA());
                                                   >> 152 
251         return p->getTransversePosition().mag(    153         return p->getTransversePosition().mag();
252       } else {                                    154       } else {
253         delete p;                                 155         delete p;
254         return -1.;                               156         return -1.;
255       }                                           157       }
256     }                                             158     }
257                                                   159 
258     G4double StandardPropagationModel::shootCo << 160     G4double StandardPropagationModel::shootComposite(ParticleSpecies const species, const G4double kineticEnergy, const G4double impactParameter, const G4double phi) {
259       theNucleus->setNucleusNucleusCollision()    161       theNucleus->setNucleusNucleusCollision();
260       currentTime = 0.0;                          162       currentTime = 0.0;
261                                                   163 
262       // Create the ProjectileRemnant object      164       // Create the ProjectileRemnant object
263       ProjectileRemnant *pr = new ProjectileRe    165       ProjectileRemnant *pr = new ProjectileRemnant(species, kineticEnergy);
264                                                   166 
265       // Same stopping time as for nucleon-nuc    167       // Same stopping time as for nucleon-nucleus
266       maximumTime = 29.8 * std::pow(theNucleus    168       maximumTime = 29.8 * std::pow(theNucleus->getA(), 0.16);
267                                                   169 
268       // If the incoming cluster is slow, use     170       // If the incoming cluster is slow, use a larger stopping time
269       const G4double rms = ParticleTable::getL    171       const G4double rms = ParticleTable::getLargestNuclearRadius(pr->getA(), pr->getZ());
270       const G4double rMax = theNucleus->getUni    172       const G4double rMax = theNucleus->getUniverseRadius();
271       const G4double distance = 2.*rMax + 2.72    173       const G4double distance = 2.*rMax + 2.725*rms;
272       const G4double projectileVelocity = pr->    174       const G4double projectileVelocity = pr->boostVector().mag();
273       const G4double traversalTime = distance     175       const G4double traversalTime = distance / projectileVelocity;
274       if(maximumTime < traversalTime)             176       if(maximumTime < traversalTime)
275         maximumTime = traversalTime;              177         maximumTime = traversalTime;
276       INCL_DEBUG("Cascade stopping time is " < << 178       INCL_DEBUG("Cascade stopping time is " << maximumTime << std::endl);
277                                                   179 
278       // If Coulomb is activated, do not proce    180       // If Coulomb is activated, do not process events with impact
279       // parameter larger than the maximum imp    181       // parameter larger than the maximum impact parameter, taking into
280       // account Coulomb distortion.              182       // account Coulomb distortion.
281       if(impactParameter>CoulombDistortion::ma    183       if(impactParameter>CoulombDistortion::maxImpactParameter(pr,theNucleus)) {
282         INCL_DEBUG("impactParameter>CoulombDis << 184         INCL_DEBUG("impactParameter>CoulombDistortion::maxImpactParameter" << std::endl);
283         delete pr;                                185         delete pr;
284         return -1.;                               186         return -1.;
285       }                                           187       }
286                                                   188 
287       // Position the cluster at the right imp    189       // Position the cluster at the right impact parameter
288       ThreeVector position(impactParameter * s    190       ThreeVector position(impactParameter * std::cos(phi),
289           impactParameter * std::sin(phi),        191           impactParameter * std::sin(phi),
290           0.);                                    192           0.);
291       pr->setPosition(position);                  193       pr->setPosition(position);
292                                                   194 
293       // Fill in the relevant kinematic variab    195       // Fill in the relevant kinematic variables
294       theNucleus->setIncomingAngularMomentum(p    196       theNucleus->setIncomingAngularMomentum(pr->getAngularMomentum());
295       theNucleus->setIncomingMomentum(pr->getM    197       theNucleus->setIncomingMomentum(pr->getMomentum());
296       theNucleus->setInitialEnergy(pr->getEner    198       theNucleus->setInitialEnergy(pr->getEnergy()
297           + ParticleTable::getTableMass(theNuc << 199           + ParticleTable::getTableMass(theNucleus->getA(),theNucleus->getZ()));
298                                                   200 
299       generateAllAvatars();                       201       generateAllAvatars();
300       firstAvatar = false;                        202       firstAvatar = false;
301                                                   203 
302       // Get the entry avatars from Coulomb       204       // Get the entry avatars from Coulomb
303       IAvatarList theAvatarList                   205       IAvatarList theAvatarList
304         = CoulombDistortion::bringToSurface(pr    206         = CoulombDistortion::bringToSurface(pr, theNucleus);
305                                                   207 
306       if(theAvatarList.empty()) {                 208       if(theAvatarList.empty()) {
307         INCL_DEBUG("No ParticleEntryAvatar fou << 209         INCL_DEBUG("No ParticleEntryAvatar found, transparent event" << std::endl);
308         delete pr;                                210         delete pr;
309         return -1.;                               211         return -1.;
310       }                                           212       }
311                                                   213 
312       /* Store the internal kinematics of the     214       /* Store the internal kinematics of the projectile remnant.
313        *                                          215        *
314        * Note that this is at variance with th    216        * Note that this is at variance with the Fortran version, which stores
315        * the initial kinematics of the particl    217        * the initial kinematics of the particles *after* putting the spectators
316        * on mass shell, but *before* removing     218        * on mass shell, but *before* removing the same energy from the
317        * participants. Due to the different co    219        * participants. Due to the different code flow, doing so in the C++
318        * version leads to wrong excitation ene    220        * version leads to wrong excitation energies for the forced compound
319        * nucleus.                                 221        * nucleus.
320        */                                         222        */
321       pr->storeComponents();                      223       pr->storeComponents();
322                                                   224 
323       // Tell the Nucleus about the Projectile    225       // Tell the Nucleus about the ProjectileRemnant
324       theNucleus->setProjectileRemnant(pr);       226       theNucleus->setProjectileRemnant(pr);
325                                                   227 
                                                   >> 228       // Set the number of projectile particles
                                                   >> 229       theNucleus->setProjectileChargeNumber(pr->getZ());
                                                   >> 230       theNucleus->setProjectileMassNumber(pr->getA());
                                                   >> 231 
326       // Register the ParticleEntryAvatars        232       // Register the ParticleEntryAvatars
327       theNucleus->getStore()->addParticleEntry    233       theNucleus->getStore()->addParticleEntryAvatars(theAvatarList);
328                                                   234 
329       return pr->getTransversePosition().mag()    235       return pr->getTransversePosition().mag();
330     }                                             236     }
331                                                   237 
332     G4double StandardPropagationModel::getStop    238     G4double StandardPropagationModel::getStoppingTime() {
333       return maximumTime;                         239       return maximumTime;
334     }                                             240     }
335                                                   241 
336     void StandardPropagationModel::setStopping    242     void StandardPropagationModel::setStoppingTime(G4double time) {
337 // assert(time>0.0);                              243 // assert(time>0.0);
338       maximumTime = time;                         244       maximumTime = time;
339     }                                             245     }
340                                                   246 
341     G4double StandardPropagationModel::getCurr    247     G4double StandardPropagationModel::getCurrentTime() {
342       return currentTime;                         248       return currentTime;
343     }                                             249     }
344                                                   250 
345     void StandardPropagationModel::setNucleus(    251     void StandardPropagationModel::setNucleus(G4INCL::Nucleus *nucleus)
346     {                                             252     {
347       theNucleus = nucleus;                       253       theNucleus = nucleus;
348     }                                             254     }
349                                                   255 
350     void StandardPropagationModel::registerAva    256     void StandardPropagationModel::registerAvatar(G4INCL::IAvatar *anAvatar)
351     {                                             257     {
352       if(anAvatar) theNucleus->getStore()->add    258       if(anAvatar) theNucleus->getStore()->add(anAvatar);
353     }                                             259     }
354                                                   260 
355     IAvatar *StandardPropagationModel::generat    261     IAvatar *StandardPropagationModel::generateBinaryCollisionAvatar(Particle * const p1, Particle * const p2) {
356       // Is either particle a participant?        262       // Is either particle a participant?
357       if(!p1->isParticipant() && !p2->isPartic    263       if(!p1->isParticipant() && !p2->isParticipant() && p1->getParticipantType()==p2->getParticipantType()) return NULL;
358                                                   264 
359       // Is it a pi-resonance collision (we do    265       // Is it a pi-resonance collision (we don't treat them)?
360       if((p1->isResonance() && p2->isPion()) |    266       if((p1->isResonance() && p2->isPion()) || (p1->isPion() && p2->isResonance()))
361         return NULL;                              267         return NULL;
362                                                   268 
363       // Is it a photon collision (we don't tr << 
364       if(p1->isPhoton() || p2->isPhoton())     << 
365         return NULL;                           << 
366                                                << 
367       // Will the avatar take place between no    269       // Will the avatar take place between now and the end of the cascade?
368       G4double minDistOfApproachSquared = 0.0;    270       G4double minDistOfApproachSquared = 0.0;
369       G4double t = getTime(p1, p2, &minDistOfA    271       G4double t = getTime(p1, p2, &minDistOfApproachSquared);
370       if(t>maximumTime || t<currentTime+hadron << 272       if(t>maximumTime || t<currentTime) return NULL;
371                                                   273 
372       // Local energy. Jump through some hoops    274       // Local energy. Jump through some hoops to calculate the cross section
373       // at the collision point, and clean up     275       // at the collision point, and clean up after yourself afterwards.
374       G4bool hasLocalEnergy;                      276       G4bool hasLocalEnergy;
375       if(p1->isPion() || p2->isPion())            277       if(p1->isPion() || p2->isPion())
376         hasLocalEnergy = ((theLocalEnergyDelta    278         hasLocalEnergy = ((theLocalEnergyDeltaType == FirstCollisionLocalEnergy &&
377               theNucleus->getStore()->getBook(    279               theNucleus->getStore()->getBook().getAcceptedCollisions()==0) ||
378             theLocalEnergyDeltaType == AlwaysL    280             theLocalEnergyDeltaType == AlwaysLocalEnergy);
379       else                                        281       else
380         hasLocalEnergy = ((theLocalEnergyType     282         hasLocalEnergy = ((theLocalEnergyType == FirstCollisionLocalEnergy &&
381               theNucleus->getStore()->getBook(    283               theNucleus->getStore()->getBook().getAcceptedCollisions()==0) ||
382             theLocalEnergyType == AlwaysLocalE    284             theLocalEnergyType == AlwaysLocalEnergy);
383       const G4bool p1HasLocalEnergy = (hasLoca << 285       const G4bool p1HasLocalEnergy = (hasLocalEnergy && !p1->isPion());
384       const G4bool p2HasLocalEnergy = (hasLoca << 286       const G4bool p2HasLocalEnergy = (hasLocalEnergy && !p2->isPion());
385                                                   287 
386       if(p1HasLocalEnergy) {                      288       if(p1HasLocalEnergy) {
387         backupParticle1 = *p1;                    289         backupParticle1 = *p1;
388         p1->propagate(t - currentTime);           290         p1->propagate(t - currentTime);
389         if(p1->getPosition().mag() > theNucleu    291         if(p1->getPosition().mag() > theNucleus->getSurfaceRadius(p1)) {
390           *p1 = backupParticle1;                  292           *p1 = backupParticle1;
391           return NULL;                            293           return NULL;
392         }                                         294         }
393         KinematicsUtils::transformToLocalEnerg    295         KinematicsUtils::transformToLocalEnergyFrame(theNucleus, p1);
394       }                                        << 296       }
395       if(p2HasLocalEnergy) {                      297       if(p2HasLocalEnergy) {
396         backupParticle2 = *p2;                    298         backupParticle2 = *p2;
397         p2->propagate(t - currentTime);           299         p2->propagate(t - currentTime);
398         if(p2->getPosition().mag() > theNucleu    300         if(p2->getPosition().mag() > theNucleus->getSurfaceRadius(p2)) {
399           *p2 = backupParticle2;                  301           *p2 = backupParticle2;
400           if(p1HasLocalEnergy) {                  302           if(p1HasLocalEnergy) {
401             *p1 = backupParticle1;                303             *p1 = backupParticle1;
402           }                                       304           }
403           return NULL;                            305           return NULL;
404         }                                         306         }
405         KinematicsUtils::transformToLocalEnerg    307         KinematicsUtils::transformToLocalEnergyFrame(theNucleus, p2);
406       }                                           308       }
407                                                   309 
408       // Compute the total cross section          310       // Compute the total cross section
409       const G4double totalCrossSection = Cross    311       const G4double totalCrossSection = CrossSections::total(p1, p2);
410       const G4double squareTotalEnergyInCM = K    312       const G4double squareTotalEnergyInCM = KinematicsUtils::squareTotalEnergyInCM(p1,p2);
411                                                   313 
412       // Restore particles to their state befo    314       // Restore particles to their state before the local-energy tweak
413       if(p1HasLocalEnergy) {                      315       if(p1HasLocalEnergy) {
414         *p1 = backupParticle1;                    316         *p1 = backupParticle1;
415       }                                           317       }
416       if(p2HasLocalEnergy) {                      318       if(p2HasLocalEnergy) {
417         *p2 = backupParticle2;                    319         *p2 = backupParticle2;
418       }                                           320       }
419                                                   321 
420       // Is the CM energy > cutNN? (no cutNN o    322       // Is the CM energy > cutNN? (no cutNN on the first collision)
421       if(theNucleus->getStore()->getBook().get    323       if(theNucleus->getStore()->getBook().getAcceptedCollisions()>0
422           && p1->isNucleon() && p2->isNucleon(    324           && p1->isNucleon() && p2->isNucleon()
423           && squareTotalEnergyInCM < BinaryCol    325           && squareTotalEnergyInCM < BinaryCollisionAvatar::getCutNNSquared()) return NULL;
424                                                   326 
425       // Do the particles come close enough to    327       // Do the particles come close enough to each other?
426       if(Math::tenPi*minDistOfApproachSquared     328       if(Math::tenPi*minDistOfApproachSquared > totalCrossSection) return NULL;
427                                                   329 
428       // Bomb out if the two collision partner    330       // Bomb out if the two collision partners are the same particle
429 // assert(p1->getID() != p2->getID());            331 // assert(p1->getID() != p2->getID());
430                                                   332 
431       // Return a new avatar, then!               333       // Return a new avatar, then!
432       return new G4INCL::BinaryCollisionAvatar    334       return new G4INCL::BinaryCollisionAvatar(t, totalCrossSection, theNucleus, p1, p2);
433     }                                             335     }
434                                                   336 
435     G4double StandardPropagationModel::getRefl    337     G4double StandardPropagationModel::getReflectionTime(G4INCL::Particle const * const aParticle) {
436       Intersection theIntersection(               338       Intersection theIntersection(
437           IntersectionFactory::getLaterTraject    339           IntersectionFactory::getLaterTrajectoryIntersection(
438             aParticle->getPosition(),             340             aParticle->getPosition(),
439             aParticle->getPropagationVelocity(    341             aParticle->getPropagationVelocity(),
440             theNucleus->getSurfaceRadius(aPart    342             theNucleus->getSurfaceRadius(aParticle)));
441       G4double time;                              343       G4double time;
442       if(theIntersection.exists) {                344       if(theIntersection.exists) {
443         time = currentTime + theIntersection.t    345         time = currentTime + theIntersection.time;
444       } else {                                    346       } else {
445         INCL_ERROR("Imaginary reflection time  << 347         INCL_ERROR("Imaginary reflection time for particle: " << std::endl
446           << aParticle->print());                 348           << aParticle->print());
447         time = 10000.0;                           349         time = 10000.0;
448       }                                           350       }
449       return time;                                351       return time;
450     }                                             352     }
451                                                   353 
452     G4double StandardPropagationModel::getTime    354     G4double StandardPropagationModel::getTime(G4INCL::Particle const * const particleA,
453                G4INCL::Particle const * const     355                G4INCL::Particle const * const particleB, G4double *minDistOfApproach) const
454     {                                             356     {
455       G4double time;                              357       G4double time;
456       G4INCL::ThreeVector t13 = particleA->get    358       G4INCL::ThreeVector t13 = particleA->getPropagationVelocity();
457       t13 -= particleB->getPropagationVelocity    359       t13 -= particleB->getPropagationVelocity();
458       G4INCL::ThreeVector distance = particleA    360       G4INCL::ThreeVector distance = particleA->getPosition();
459       distance -= particleB->getPosition();       361       distance -= particleB->getPosition();
460       const G4double t7 = t13.dot(distance);      362       const G4double t7 = t13.dot(distance);
461       const G4double dt = t13.mag2();             363       const G4double dt = t13.mag2();
462       if(dt <= 1.0e-10) {                         364       if(dt <= 1.0e-10) {
463         (*minDistOfApproach) = 100000.0;          365         (*minDistOfApproach) = 100000.0;
464         return currentTime + 100000.0;            366         return currentTime + 100000.0;
465       } else {                                    367       } else {
466         time = -t7/dt;                            368         time = -t7/dt;
467       }                                           369       }
468       (*minDistOfApproach) = distance.mag2() +    370       (*minDistOfApproach) = distance.mag2() + time * t7;
469       return currentTime + time;                  371       return currentTime + time;
470     }                                             372     }
471                                                   373 
472     void StandardPropagationModel::generateUpd    374     void StandardPropagationModel::generateUpdatedCollisions(const ParticleList &updatedParticles, const ParticleList &particles) {
473                                                   375 
474       // Loop over all the updated particles      376       // Loop over all the updated particles
475       for(ParticleIter updated=updatedParticle    377       for(ParticleIter updated=updatedParticles.begin(), e=updatedParticles.end(); updated!=e; ++updated)
476       {                                           378       {
477         // Loop over all the particles            379         // Loop over all the particles
478         for(ParticleIter particle=particles.be    380         for(ParticleIter particle=particles.begin(), end=particles.end(); particle!=end; ++particle)
479         {                                         381         {
480           /* Consider the generation of a coll    382           /* Consider the generation of a collision avatar only if (*particle)
481            * is not one of the updated particl    383            * is not one of the updated particles.
482            * The criterion makes sure that you    384            * The criterion makes sure that you don't generate avatars between
483            * updated particles. */                385            * updated particles. */
484           if(updatedParticles.contains(*partic << 386           if((*particle)->isInList(updatedParticles)) continue;
485                                                   387 
486           registerAvatar(generateBinaryCollisi    388           registerAvatar(generateBinaryCollisionAvatar(*particle,*updated));
487         }                                         389         }
488       }                                           390       }
489     }                                             391     }
490                                                   392 
491     void StandardPropagationModel::generateCol    393     void StandardPropagationModel::generateCollisions(const ParticleList &particles) {
492       // Loop over all the particles              394       // Loop over all the particles
493       for(ParticleIter p1=particles.begin(), e    395       for(ParticleIter p1=particles.begin(), e=particles.end(); p1!=e; ++p1) {
494         // Loop over the rest of the particles    396         // Loop over the rest of the particles
495         for(ParticleIter p2 = p1 + 1; p2 != pa    397         for(ParticleIter p2 = p1 + 1; p2 != particles.end(); ++p2) {
496           registerAvatar(generateBinaryCollisi    398           registerAvatar(generateBinaryCollisionAvatar(*p1,*p2));
497         }                                         399         }
498       }                                           400       }
499     }                                             401     }
500                                                   402 
501     void StandardPropagationModel::generateCol    403     void StandardPropagationModel::generateCollisions(const ParticleList &particles, const ParticleList &except) {
502                                                   404 
503       const G4bool haveExcept = !except.empty(    405       const G4bool haveExcept = !except.empty();
504                                                   406 
505       // Loop over all the particles              407       // Loop over all the particles
506       for(ParticleIter p1=particles.begin(), e    408       for(ParticleIter p1=particles.begin(), e=particles.end(); p1!=e; ++p1)
507       {                                           409       {
508         // Loop over the rest of the particles    410         // Loop over the rest of the particles
509         ParticleIter p2 = p1;                     411         ParticleIter p2 = p1;
510         for(++p2; p2 != particles.end(); ++p2)    412         for(++p2; p2 != particles.end(); ++p2)
511         {                                         413         {
512           // Skip the collision if both partic    414           // Skip the collision if both particles must be excluded
513           if(haveExcept && except.contains(*p1 << 415           if(haveExcept && (*p1)->isInList(except) && (*p2)->isInList(except)) continue;
514                                                   416 
515           registerAvatar(generateBinaryCollisi    417           registerAvatar(generateBinaryCollisionAvatar(*p1,*p2));
516         }                                         418         }
517       }                                           419       }
518                                                   420 
519     }                                             421     }
520                                                   422 
521     void StandardPropagationModel::updateAvata    423     void StandardPropagationModel::updateAvatars(const ParticleList &particles) {
522                                                   424 
523       for(ParticleIter iter=particles.begin(),    425       for(ParticleIter iter=particles.begin(), e=particles.end(); iter!=e; ++iter) {
524         G4double time = this->getReflectionTim    426         G4double time = this->getReflectionTime(*iter);
525         if(time <= maximumTime) registerAvatar    427         if(time <= maximumTime) registerAvatar(new SurfaceAvatar(*iter, time, theNucleus));
526       }                                           428       }
527       ParticleList const &p = theNucleus->getS    429       ParticleList const &p = theNucleus->getStore()->getParticles();
528       generateUpdatedCollisions(particles, p);    430       generateUpdatedCollisions(particles, p);             // Predict collisions with spectators and participants
529     }                                             431     }
530                                                   432 
531     void StandardPropagationModel::generateAll    433     void StandardPropagationModel::generateAllAvatars() {
532       ParticleList const &particles = theNucle    434       ParticleList const &particles = theNucleus->getStore()->getParticles();
533 // assert(!particles.empty());                    435 // assert(!particles.empty());
534       G4double time;                           << 
535       for(ParticleIter i=particles.begin(), e=    436       for(ParticleIter i=particles.begin(), e=particles.end(); i!=e; ++i) {
536         time = this->getReflectionTime(*i);    << 437         G4double time = this->getReflectionTime(*i);
537         if(time <= maximumTime) registerAvatar    438         if(time <= maximumTime) registerAvatar(new SurfaceAvatar(*i, time, theNucleus));
538       }                                           439       }
539       generateCollisions(particles);              440       generateCollisions(particles);
540       generateDecays(particles);                  441       generateDecays(particles);
541     }                                             442     }
542                                                   443 
543 #ifdef INCL_REGENERATE_AVATARS                    444 #ifdef INCL_REGENERATE_AVATARS
544     void StandardPropagationModel::generateAll << 445     void StandardPropagationModel::generateAllAvatarsExceptUpdated() {
545       ParticleList const &particles = theNucle    446       ParticleList const &particles = theNucleus->getStore()->getParticles();
546 // assert(!particles.empty());                    447 // assert(!particles.empty());
547       for(ParticleIter i=particles.begin(), e=    448       for(ParticleIter i=particles.begin(), e=particles.end(); i!=e; ++i) {
548         G4double time = this->getReflectionTim    449         G4double time = this->getReflectionTime(*i);
549         if(time <= maximumTime) registerAvatar    450         if(time <= maximumTime) registerAvatar(new SurfaceAvatar(*i, time, theNucleus));
550       }                                           451       }
551       ParticleList except = fs->getModifiedPar << 452       ParticleList except = theNucleus->getUpdatedParticles();
552       ParticleList const &entering = fs->getEn << 
553       except.insert(except.end(), entering.beg << 
554       generateCollisions(particles,except);       453       generateCollisions(particles,except);
555       generateDecays(particles);                  454       generateDecays(particles);
556     }                                             455     }
557 #endif                                            456 #endif
558                                                   457 
559     void StandardPropagationModel::generateDec    458     void StandardPropagationModel::generateDecays(const ParticleList &particles) {
560       for(ParticleIter i=particles.begin(), e=    459       for(ParticleIter i=particles.begin(), e=particles.end(); i!=e; ++i) {
561          if((*i)->isDelta()) {                 << 460   if((*i)->isDelta()) {
562              G4double decayTime = DeltaDecayCh << 461     G4double decayTime = DeltaDecayChannel::computeDecayTime((*i));
563            G4double time = currentTime + decay << 462     G4double time = currentTime + decayTime;
564            if(time <= maximumTime) {           << 463     if(time <= maximumTime) {
565              registerAvatar(new DecayAvatar((* << 464       registerAvatar(new DecayAvatar((*i), time, theNucleus));
566            }                                   << 465     }
567          }                                     << 466   }
568          else if((*i)->getType() == SigmaZero) << 
569            G4double decayTime = SigmaZeroDecay << 
570            G4double time = currentTime + decay << 
571            if(time <= maximumTime) {           << 
572              registerAvatar(new DecayAvatar((* << 
573            }                                   << 
574          }                                     << 
575         if((*i)->isOmega()) {                  << 
576           G4double decayTimeOmega = PionResona << 
577           G4double timeOmega = currentTime + d << 
578           if(timeOmega <= maximumTime) {       << 
579             registerAvatar(new DecayAvatar((*i << 
580           }                                    << 
581         }                                      << 
582       }                                           467       }
583     }                                             468     }
584                                                   469 
585     G4INCL::IAvatar* StandardPropagationModel: << 470     G4INCL::IAvatar* StandardPropagationModel::propagate()
586     {                                             471     {
587       if(fs) {                                 << 472       // We update only the information related to particles that were updated
588         // We update only the information rela << 473       // by the previous avatar.
589         // by the previous avatar.             << 
590 #ifdef INCL_REGENERATE_AVATARS                    474 #ifdef INCL_REGENERATE_AVATARS
591 #warning "The INCL_REGENERATE_AVATARS code has    475 #warning "The INCL_REGENERATE_AVATARS code has not been tested in a while. Use it at your peril."
592         if(!fs->getModifiedParticles().empty() << 476       if(theNucleus->getUpdatedParticles().size()!=0 || theNucleus->getCreatedParticles().size()!=0) {
593           // Regenerates the entire avatar lis << 477         // Regenerates the entire avatar list, skipping collisions between
594           // updated particles                 << 478         // updated particles
595           theNucleus->getStore()->clearAvatars << 479         theNucleus->getStore()->clearAvatars();
596           theNucleus->getStore()->initialisePa << 480         theNucleus->getStore()->initialiseParticleAvatarConnections();
597           generateAllAvatarsExceptUpdated(fs); << 481         generateAllAvatarsExceptUpdated();
598         }                                      << 482       }
599 #else                                             483 #else
600         ParticleList const &updatedParticles = << 484       // Deltas are created by transforming nucleon into a delta for
601         if(fs->getValidity()==PauliBlockedFS)  << 485       // efficiency reasons
602           // This final state might represents << 486       Particle * const blockedDelta = theNucleus->getBlockedDelta();
603           // decay                             << 487       ParticleList updatedParticles = theNucleus->getUpdatedParticles();
604 // assert(updatedParticles.empty() || (updated << 488       if(blockedDelta)
605 // assert(fs->getEnteringParticles().empty() & << 489         updatedParticles.push_back(blockedDelta);
606           generateDecays(updatedParticles);    << 490       generateDecays(updatedParticles);
607         } else {                               << 491 
608           ParticleList const &entering = fs->g << 492       ParticleList needNewAvatars = theNucleus->getUpdatedParticles();
609           generateDecays(updatedParticles);    << 493       ParticleList const &created = theNucleus->getCreatedParticles();
610           generateDecays(entering);            << 494       needNewAvatars.insert(needNewAvatars.end(), created.begin(), created.end());
611                                                << 495       updateAvatars(needNewAvatars);
612           ParticleList const &created = fs->ge << 
613           if(created.empty() && entering.empty << 
614             updateAvatars(updatedParticles);   << 
615           else {                               << 
616             ParticleList updatedParticlesCopy  << 
617             updatedParticlesCopy.insert(update << 
618             updatedParticlesCopy.insert(update << 
619             updateAvatars(updatedParticlesCopy << 
620           }                                    << 
621         }                                      << 
622 #endif                                            496 #endif
623       }                                        << 
624                                                   497 
625       G4INCL::IAvatar *theAvatar = theNucleus-    498       G4INCL::IAvatar *theAvatar = theNucleus->getStore()->findSmallestTime();
626       if(theAvatar == 0) return 0; // Avatar l    499       if(theAvatar == 0) return 0; // Avatar list is empty
627       //      theAvatar->dispose();               500       //      theAvatar->dispose();
628                                                   501 
629       if(theAvatar->getTime() < currentTime) {    502       if(theAvatar->getTime() < currentTime) {
630         INCL_ERROR("Avatar time = " << theAvat << 503         INCL_ERROR("Avatar time = " << theAvatar->getTime() << ", currentTime = " << currentTime << std::endl);
631         return 0;                                 504         return 0;
632       } else if(theAvatar->getTime() > current    505       } else if(theAvatar->getTime() > currentTime) {
633         theNucleus->getStore()->timeStep(theAv    506         theNucleus->getStore()->timeStep(theAvatar->getTime() - currentTime);
634                                                   507 
635         currentTime = theAvatar->getTime();       508         currentTime = theAvatar->getTime();
636         theNucleus->getStore()->getBook().setC    509         theNucleus->getStore()->getBook().setCurrentTime(currentTime);
637       }                                           510       }
638                                                   511 
639       return theAvatar;                           512       return theAvatar;
                                                   >> 513     }
                                                   >> 514 
                                                   >> 515     void StandardPropagationModel::putSpectatorsOnShell(IAvatarList const &entryAvatars, ParticleList const &spectators) {
                                                   >> 516       G4double deltaE = 0.0;
                                                   >> 517       for(ParticleIter p=spectators.begin(), e=spectators.end(); p!=e; ++p) {
                                                   >> 518         // put the spectators on shell (conserving their momentum)
                                                   >> 519         const G4double oldEnergy = (*p)->getEnergy();
                                                   >> 520         (*p)->setTableMass();
                                                   >> 521         (*p)->adjustEnergyFromMomentum();
                                                   >> 522         deltaE += (*p)->getEnergy() - oldEnergy;
                                                   >> 523       }
                                                   >> 524 
                                                   >> 525       deltaE /= entryAvatars.size(); // energy to remove from each participant
                                                   >> 526 
                                                   >> 527       for(IAvatarIter a=entryAvatars.begin(), e=entryAvatars.end(); a!=e; ++a) {
                                                   >> 528         // remove the energy from the participant
                                                   >> 529         Particle *p = (*a)->getParticles().front();
                                                   >> 530         ParticleType const t = p->getType();
                                                   >> 531         // we also need to slightly correct the participant mass
                                                   >> 532         const G4double energy = p->getEnergy() - deltaE
                                                   >> 533           - ParticleTable::getTableParticleMass(t) + ParticleTable::getINCLMass(t);
                                                   >> 534         p->setEnergy(energy);
                                                   >> 535         const G4double newMass = std::sqrt(energy*energy - p->getMomentum().mag2());
                                                   >> 536         p->setMass(newMass);
                                                   >> 537       }
640     }                                             538     }
641 }                                                 539 }
642                                                   540