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 9.5.p2)


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