Geant4 Cross Reference

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


  1 //                                                  1 
  2 // *******************************************    
  3 // * License and Disclaimer                       
  4 // *                                              
  5 // * The  Geant4 software  is  copyright of th    
  6 // * the Geant4 Collaboration.  It is provided    
  7 // * conditions of the Geant4 Software License    
  8 // * LICENSE and available at  http://cern.ch/    
  9 // * include a list of copyright holders.         
 10 // *                                              
 11 // * Neither the authors of this software syst    
 12 // * institutes,nor the agencies providing fin    
 13 // * work  make  any representation or  warran    
 14 // * regarding  this  software system or assum    
 15 // * use.  Please see the license in the file     
 16 // * for the full disclaimer and the limitatio    
 17 // *                                              
 18 // * This  code  implementation is the result     
 19 // * technical work of the GEANT4 collaboratio    
 20 // * By using,  copying,  modifying or  distri    
 21 // * any work based  on the software)  you  ag    
 22 // * use  in  resulting  scientific  publicati    
 23 // * acceptance of all terms of the Geant4 Sof    
 24 // *******************************************    
 25 //                                                
 26 // INCL++ intra-nuclear cascade model             
 27 // Alain Boudard, CEA-Saclay, France              
 28 // Joseph Cugnon, University of Liege, Belgium    
 29 // Jean-Christophe David, CEA-Saclay, France      
 30 // Pekka Kaitaniemi, CEA-Saclay, France, and H    
 31 // Sylvie Leray, CEA-Saclay, France               
 32 // Davide Mancusi, CEA-Saclay, France             
 33 //                                                
 34 #define INCLXX_IN_GEANT4_MODE 1                   
 35                                                   
 36 #include "globals.hh"                             
 37                                                   
 38 /*                                                
 39  * G4INCLNucleus.cc                               
 40  *                                                
 41  *  \date Jun 5, 2009                             
 42  * \author Pekka Kaitaniemi                       
 43  */                                               
 44                                                   
 45 #ifndef G4INCLNucleus_hh                          
 46 #define G4INCLNucleus_hh 1                        
 47                                                   
 48 #include "G4INCLGlobals.hh"                       
 49 #include "G4INCLLogger.hh"                        
 50 #include "G4INCLParticle.hh"                      
 51 #include "G4INCLIAvatar.hh"                       
 52 #include "G4INCLNucleus.hh"                       
 53 #include "G4INCLKinematicsUtils.hh"               
 54 #include "G4INCLDecayAvatar.hh"                   
 55 #include "G4INCLStrangeAbsorbtionChannel.hh"      
 56 #include "G4INCLCluster.hh"                       
 57 #include "G4INCLClusterDecay.hh"                  
 58 #include "G4INCLDeJongSpin.hh"                    
 59 #include "G4INCLParticleSpecies.hh"               
 60 #include "G4INCLParticleTable.hh"                 
 61 #include <iterator>                               
 62 #include <cstdlib>                                
 63 #include <sstream>                                
 64 // #include <cassert>                             
 65 #include "G4INCLPbarAtrestEntryChannel.hh"        
 66 #include "G4INCLBinaryCollisionAvatar.hh"         
 67                                                   
 68 namespace G4INCL {                                
 69                                                   
 70   Nucleus::Nucleus(G4int mass, G4int charge, G    
 71     AnnihilationType AType) //D                   
 72     : Cluster(charge,mass,strangess,true),        
 73      theInitialZ(charge), theInitialA(mass), t    
 74      theNpInitial(0), theNnInitial(0),            
 75      theNpionplusInitial(0), theNpionminusInit    
 76      theNkaonplusInitial(0), theNkaonminusInit    
 77      theNantiprotonInitial(0),                    
 78      initialInternalEnergy(0.),                   
 79      incomingAngularMomentum(0.,0.,0.), incomi    
 80      initialCenterOfMass(0.,0.,0.),               
 81      remnant(true),                               
 82      initialEnergy(0.),                           
 83      tryCN(false),                                
 84      theUniverseRadius(universeRadius),           
 85      isNucleusNucleus(false),                     
 86      theProjectileRemnant(NULL),                  
 87      theDensity(NULL),                            
 88      thePotential(NULL),                          
 89      theAType(AType)                              
 90   {                                               
 91     PotentialType potentialType;                  
 92     G4bool pionPotential;                         
 93     if(conf) {                                    
 94       potentialType = conf->getPotentialType()    
 95       pionPotential = conf->getPionPotential()    
 96     } else { // By default we don't use energy    
 97       // potential. This is convenient for som    
 98       potentialType = IsospinPotential;           
 99       pionPotential = true;                       
100     }                                             
101                                                   
102     thePotential = NuclearPotential::createPot    
103                                                   
104     ParticleTable::setProtonSeparationEnergy(t    
105     ParticleTable::setNeutronSeparationEnergy(    
106                                                   
107     if (theAType==PType) theDensity = NuclearD    
108     else if (theAType==NType) theDensity = Nuc    
109     else                                          
110     theDensity = NuclearDensityFactory::create    
111                                                   
112     theParticleSampler->setPotential(thePotent    
113     theParticleSampler->setDensity(theDensity)    
114                                                   
115     if(theUniverseRadius<0)                       
116       theUniverseRadius = theDensity->getMaxim    
117     theStore = new Store(conf);                   
118   }                                               
119                                                   
120   Nucleus::~Nucleus() {                           
121     delete theStore;                              
122     deleteProjectileRemnant();                    
123     /* We don't delete the potential and the d    
124      * are caching them                           
125     delete thePotential;                          
126     delete theDensity;*/                          
127   }                                               
128                                                   
129   AnnihilationType Nucleus::getAType() const {    
130     return theAType;                              
131   }                                               
132                                                   
133   void Nucleus::setAType(AnnihilationType type    
134     theAType = type;                              
135   }                                               
136                                                   
137   void Nucleus::initializeParticles() {           
138     // Reset the variables connected with the     
139     delete theProjectileRemnant;                  
140     theProjectileRemnant = NULL;                  
141     Cluster::initializeParticles();               
142                                                   
143     for(ParticleIter i=particles.begin(), e=pa    
144       updatePotentialEnergy(*i);                  
145     }                                             
146     theStore->add(particles);                     
147     particles.clear();                            
148     initialInternalEnergy = computeTotalEnergy    
149     initialCenterOfMass = thePosition;            
150   }                                               
151                                                   
152   void Nucleus::applyFinalState(FinalState *fi    
153     if(!finalstate) // do nothing if no final     
154       return;                                     
155                                                   
156     G4double totalEnergy = 0.0;                   
157                                                   
158     FinalStateValidity const validity = finals    
159     if(validity == ValidFS) {                     
160                                                   
161       ParticleList const &created = finalstate    
162       for(ParticleIter iter=created.begin(), e    
163         theStore->add((*iter));                   
164         if(!(*iter)->isOutOfWell()) {             
165           totalEnergy += (*iter)->getEnergy()     
166         }                                         
167       }                                           
168                                                   
169       ParticleList const &deleted = finalstate    
170       for(ParticleIter iter=deleted.begin(), e    
171         theStore->particleHasBeenDestroyed(*it    
172       }                                           
173                                                   
174       ParticleList const &modified = finalstat    
175       for(ParticleIter iter=modified.begin(),     
176         theStore->particleHasBeenUpdated(*iter    
177         totalEnergy += (*iter)->getEnergy() -     
178       }                                           
179                                                   
180       ParticleList const &out = finalstate->ge    
181       for(ParticleIter iter=out.begin(), e=out    
182         if((*iter)->isCluster()) {                
183       Cluster *clusterOut = dynamic_cast<Clust    
184 // assert(clusterOut);                            
185 #ifdef INCLXX_IN_GEANT4_MODE                      
186           if(!clusterOut)                         
187             continue;                             
188 #endif                                            
189           ParticleList const &components = clu    
190           for(ParticleIter in=components.begin    
191             theStore->particleHasBeenEjected(*    
192         } else {                                  
193           theStore->particleHasBeenEjected(*it    
194         }                                         
195         totalEnergy += (*iter)->getEnergy();      
196         theA -= (*iter)->getA();                  
197         theZ -= (*iter)->getZ();                  
198         theS -= (*iter)->getS();                  
199         theStore->addToOutgoing(*iter);           
200         (*iter)->setEmissionTime(theStore->get    
201       }                                           
202                                                   
203       ParticleList const &entering = finalstat    
204       for(ParticleIter iter=entering.begin(),     
205         insertParticle(*iter);                    
206         totalEnergy += (*iter)->getEnergy() -     
207       }                                           
208                                                   
209       // actually perform the removal of the s    
210       theStore->removeScheduledAvatars();         
211     } else if(validity == ParticleBelowFermiFS    
212       INCL_DEBUG("A Particle is entering below    
213       tryCN = true;                               
214       ParticleList const &entering = finalstat    
215       for(ParticleIter iter=entering.begin(),     
216         insertParticle(*iter);                    
217       }                                           
218     }                                             
219                                                   
220     if(validity==ValidFS &&                       
221         std::abs(totalEnergy - finalstate->get    
222       INCL_ERROR("Energy nonconservation! Ener    
223           << finalstate->getTotalEnergyBeforeI    
224           <<" and after interaction = "           
225           << totalEnergy << '\n'                  
226           << finalstate->print());                
227     }                                             
228   }                                               
229                                                   
230   void Nucleus::propagateParticles(G4double /*    
231     INCL_WARN("Useless Nucleus::propagateParti    
232   }                                               
233                                                   
234   G4double Nucleus::computeTotalEnergy() const    
235     G4double totalEnergy = 0.0;                   
236     ParticleList const &inside = theStore->get    
237     for(ParticleIter p=inside.begin(), e=insid    
238       if((*p)->isNucleon()) // Ugly: we should    
239         totalEnergy += (*p)->getKineticEnergy(    
240       else if((*p)->isResonance())                
241         totalEnergy += (*p)->getEnergy() - (*p    
242       else if((*p)->isHyperon())                  
243         totalEnergy += (*p)->getEnergy() - (*p    
244       else if((*p)->isAntiNucleon())              
245         totalEnergy += (*p)->getEnergy() - (*p    
246       else if((*p)->isAntiLambda())               
247         totalEnergy += (*p)->getEnergy() - (*p    
248         //std::cout << ParticleTable::getRealM    
249       else                                        
250         totalEnergy += (*p)->getEnergy() - (*p    
251     }                                             
252                                                   
253     return totalEnergy;                           
254   }                                               
255                                                   
256   void Nucleus::computeRecoilKinematics() {       
257     // If the remnant consists of only one nuc    
258     // procedure to put it on mass shell.         
259     if(theA==1) {                                 
260       emitInsidePions();                          
261       computeOneNucleonRecoilKinematics();        
262       remnant=false;                              
263       return;                                     
264     }                                             
265                                                   
266     // Compute the recoil momentum and angular    
267     theMomentum = incomingMomentum;               
268     theSpin = incomingAngularMomentum;            
269                                                   
270     ParticleList const &outgoing = theStore->g    
271     for(ParticleIter p=outgoing.begin(), e=out    
272       theMomentum -= (*p)->getMomentum();         
273       theSpin -= (*p)->getAngularMomentum();      
274     }                                             
275     if(theProjectileRemnant) {                    
276       theMomentum -= theProjectileRemnant->get    
277       theSpin -= theProjectileRemnant->getAngu    
278     }                                             
279                                                   
280     // Subtract orbital angular momentum          
281     thePosition = computeCenterOfMass();          
282     theSpin -= (thePosition-initialCenterOfMas    
283                                                   
284     setMass(ParticleTable::getTableMass(theA,t    
285     adjustEnergyFromMomentum();                   
286     remnant=true;                                 
287   }                                               
288                                                   
289   ThreeVector Nucleus::computeCenterOfMass() c    
290     ThreeVector cm(0.,0.,0.);                     
291     G4double totalMass = 0.0;                     
292     ParticleList const &inside = theStore->get    
293     for(ParticleIter p=inside.begin(), e=insid    
294       const G4double mass = (*p)->getMass();      
295       cm += (*p)->getPosition() * mass;           
296       totalMass += mass;                          
297     }                                             
298     cm /= totalMass;                              
299     return cm;                                    
300   }                                               
301                                                   
302   G4double Nucleus::computeExcitationEnergy()     
303     const G4double totalEnergy = computeTotalE    
304     const G4double separationEnergies = comput    
305                                                   
306 G4double eSep = 0;                                
307 if (getAType() == AnnihilationType::Def) {        
308 } else if (getAType()  == AnnihilationType::PT    
309 } else if (getAType()  == AnnihilationType::NT    
310 } else if (getAType()  == AnnihilationType::PT    
311   eSep = ParticleTable::getProtonSeparationEne    
312 } else if (getAType()  == AnnihilationType::NT    
313   eSep = ParticleTable::getNeutronSeparationEn    
314 } else if (getAType()  == AnnihilationType::Nb    
315   eSep = ParticleTable::getProtonSeparationEne    
316 } else if (getAType()  == AnnihilationType::Nb    
317   eSep = ParticleTable::getNeutronSeparationEn    
318 }                                                 
319                                                   
320   if (eSep > 0. && (totalEnergy - initialInter    
321      INCL_DEBUG("Negative Excitation Energy du    
322   }                                               
323                                                   
324   return totalEnergy - initialInternalEnergy -    
325                                                   
326   }                                               
327                                                   
328 //thePotential->getSeparationEnergy(Proton)       
329                                                   
330   std::string Nucleus::print()                    
331   {                                               
332     std::stringstream ss;                         
333     ss << "Particles in the nucleus:" << '\n'     
334       << "Inside:" << '\n';                       
335     G4int counter = 1;                            
336     ParticleList const &inside = theStore->get    
337     for(ParticleIter p=inside.begin(), e=insid    
338       ss << "index = " << counter << '\n'         
339         << (*p)->print();                         
340       counter++;                                  
341     }                                             
342     ss <<"Outgoing:" << '\n';                     
343     ParticleList const &outgoing = theStore->g    
344     for(ParticleIter p=outgoing.begin(), e=out    
345       ss << (*p)->print();                        
346                                                   
347     return ss.str();                              
348   }                                               
349                                                   
350   G4bool Nucleus::decayOutgoingDeltas() {         
351     ParticleList const &out = theStore->getOut    
352     ParticleList deltas;                          
353     for(ParticleIter i=out.begin(), e=out.end(    
354       if((*i)->isDelta()) deltas.push_back((*i    
355     }                                             
356     if(deltas.empty()) return false;              
357                                                   
358     for(ParticleIter i=deltas.begin(), e=delta    
359       INCL_DEBUG("Decay outgoing delta particl    
360           << (*i)->print() << '\n');              
361       const ThreeVector beta = -(*i)->boostVec    
362       const G4double deltaMass = (*i)->getMass    
363                                                   
364       // Set the delta momentum to zero and sa    
365       // This makes life simpler if we are usi    
366       (*i)->setMomentum(ThreeVector());           
367       (*i)->setEnergy((*i)->getMass());           
368                                                   
369       // Use a DecayAvatar                        
370       IAvatar *decay = new DecayAvatar((*i), 0    
371       FinalState *fs = decay->getFinalState();    
372       Particle * const pion = fs->getCreatedPa    
373       Particle * const nucleon = fs->getModifi    
374                                                   
375       // Adjust the decay momentum if we are u    
376       const G4double decayMomentum = Kinematic    
377           nucleon->getTableMass(),                
378           pion->getTableMass());                  
379       ThreeVector newMomentum = pion->getMomen    
380       newMomentum *= decayMomentum / newMoment    
381                                                   
382       pion->setTableMass();                       
383       pion->setMomentum(newMomentum);             
384       pion->adjustEnergyFromMomentum();           
385       pion->setEmissionTime(nucleon->getEmissi    
386       pion->boost(beta);                          
387       pion->setBiasCollisionVector(nucleon->ge    
388                                                   
389       nucleon->setTableMass();                    
390       nucleon->setMomentum(-newMomentum);         
391       nucleon->adjustEnergyFromMomentum();        
392       nucleon->boost(beta);                       
393                                                   
394       theStore->addToOutgoing(pion);              
395                                                   
396       delete fs;                                  
397       delete decay;                               
398     }                                             
399                                                   
400     return true;                                  
401   }                                               
402                                                   
403   G4bool Nucleus::decayInsideDeltas() {           
404     /* If there is a pion potential, do nothin    
405      * excitation energy).                        
406      * If, however, the remnant is unphysical     
407      * decay and get rid of all the pions. In     
408      * end up with Z<0 or Z>A if the remnant c    
409      * more pi+ than neutrons, respectively.      
410      */                                           
411     const G4bool unphysicalRemnant = (theZ<0 |    
412     if(thePotential->hasPionPotential() && !un    
413       return false;                               
414                                                   
415     // Build a list of deltas (avoid modifying    
416     ParticleList const &inside = theStore->get    
417     ParticleList deltas;                          
418     for(ParticleIter i=inside.begin(), e=insid    
419       if((*i)->isDelta()) deltas.push_back((*i    
420                                                   
421     // Loop over the deltas, make them decay      
422     for(ParticleIter i=deltas.begin(), e=delta    
423       INCL_DEBUG("Decay inside delta particle:    
424           << (*i)->print() << '\n');              
425       // Create a forced-decay avatar. Note th    
426       // also that if the remnant is unphysica    
427       // up energy conservation and CDPP by pa    
428       // nucleus.                                 
429       IAvatar *decay;                             
430       if(unphysicalRemnant) {                     
431         INCL_WARN("Forcing delta decay inside     
432              << ", Z=" << theZ << "). Might le    
433              << '\n');                            
434         decay = new DecayAvatar((*i), 0.0, NUL    
435       } else                                      
436         decay = new DecayAvatar((*i), 0.0, thi    
437       FinalState *fs = decay->getFinalState();    
438                                                   
439       // The pion can be ejected only if we ma    
440       // conservation and if pion emission doe    
441       // energies.                                
442       if(fs->getValidity()==ValidFS) {            
443         // Apply the final state to the nucleu    
444         applyFinalState(fs);                      
445       }                                           
446       delete fs;                                  
447       delete decay;                               
448     }                                             
449                                                   
450     // If the remnant is unphysical, emit all     
451     if(unphysicalRemnant) {                       
452       INCL_DEBUG("Remnant is unphysical: Z=" <    
453       emitInsidePions();                          
454     }                                             
455                                                   
456     return true;                                  
457   }                                               
458                                                   
459   G4bool Nucleus::decayInsideStrangeParticles(    
460                                                   
461     /* Transform each strange particles into a    
462      * Every Kaon (KPlus and KZero) are emited    
463      */                                           
464     const G4bool unphysicalRemnant = (theZ<0 |    
465     if(unphysicalRemnant){                        
466         emitInsideStrangeParticles();             
467         INCL_WARN("Remnant is unphysical: Z="     
468         return false;                             
469     }                                             
470                                                   
471     /* Build a list of particles with a strang    
472      * and two other one for proton and neutro    
473      */                                           
474     ParticleList const &inside = theStore->get    
475     ParticleList stranges;                        
476     ParticleList protons;                         
477     ParticleList neutrons;                        
478     for(ParticleIter i=inside.begin(), e=insid    
479         if((*i)->isSigma() || (*i)->isAntiKaon    
480         else if((*i)->isNucleon() && (*i)->get    
481         else if((*i)->isNucleon() && (*i)->get    
482     }                                             
483                                                   
484     if((stranges.size() > protons.size()) || (    
485         INCL_WARN("Remnant is unphysical: Npro    
486         emitInsideStrangeParticles();             
487         return false;                             
488     }                                             
489                                                   
490     // Loop over the strange particles, make t    
491     ParticleIter protonIter = protons.begin();    
492     ParticleIter neutronIter = neutrons.begin(    
493     for(ParticleIter i=stranges.begin(), e=str    
494       INCL_DEBUG("Absorbe inside strange parti    
495           << (*i)->print() << '\n');              
496       IAvatar *decay;                             
497       if((*i)->getType() == SigmaMinus){          
498           decay = new DecayAvatar((*protonIter    
499           ++protonIter;                           
500       }                                           
501       else if((*i)->getType() == SigmaPlus){      
502           decay = new DecayAvatar((*neutronIte    
503           ++neutronIter;                          
504       }                                           
505       else if(Random::shoot()*(protons.size()     
506           decay = new DecayAvatar((*protonIter    
507           ++protonIter;                           
508       }                                           
509       else {                                      
510           decay = new DecayAvatar((*neutronIte    
511           ++neutronIter;                          
512       }                                           
513       FinalState *fs = decay->getFinalState();    
514       applyFinalState(fs);                        
515       delete fs;                                  
516       delete decay;                               
517     }                                             
518                                                   
519     return true;                                  
520   }                                               
521                                                   
522   G4bool Nucleus::decayOutgoingPionResonances(    
523         ParticleList const &out = theStore->ge    
524         ParticleList pionResonances;              
525         for(ParticleIter i=out.begin(), e=out.    
526 //            if((*i)->isEta() || (*i)->isOmeg    
527             if(((*i)->isEta() && timeThreshold    
528         }                                         
529         if(pionResonances.empty()) return fals    
530                                                   
531         for(ParticleIter i=pionResonances.begi    
532             INCL_DEBUG("Decay outgoing pionRes    
533                        << (*i)->print() << '\n    
534             const ThreeVector beta = -(*i)->bo    
535             const G4double pionResonanceMass =    
536                                                   
537             // Set the pionResonance momentum     
538             // This makes life simpler if we a    
539             (*i)->setMomentum(ThreeVector());     
540             (*i)->setEnergy((*i)->getMass());     
541                                                   
542             // Use a DecayAvatar                  
543             IAvatar *decay = new DecayAvatar((    
544             FinalState *fs = decay->getFinalSt    
545                                                   
546             Particle * const theModifiedPartic    
547             ParticleList const &created = fs->    
548             Particle * const theCreatedParticl    
549                                                   
550             if (created.size() == 1) {            
551                                                   
552                 // Adjust the decay momentum i    
553                 const G4double decayMomentum =    
554                 ThreeVector newMomentum = theC    
555                 newMomentum *= decayMomentum /    
556                                                   
557                 theCreatedParticle1->setTableM    
558                 theCreatedParticle1->setMoment    
559                 theCreatedParticle1->adjustEne    
560                 //theCreatedParticle1->setEmis    
561                 theCreatedParticle1->boost(bet    
562                 theCreatedParticle1->setBiasCo    
563                                                   
564                 theModifiedParticle->setTableM    
565                 theModifiedParticle->setMoment    
566                 theModifiedParticle->adjustEne    
567                 theModifiedParticle->boost(bet    
568                                                   
569                 theStore->addToOutgoing(theCre    
570             }                                     
571             else if (created.size() == 2) {       
572                 Particle * const theCreatedPar    
573                                                   
574                 theCreatedParticle1->boost(bet    
575                 theCreatedParticle1->setBiasCo    
576                 theCreatedParticle2->boost(bet    
577                 theCreatedParticle2->setBiasCo    
578                 theModifiedParticle->boost(bet    
579                                                   
580                 theStore->addToOutgoing(theCre    
581                 theStore->addToOutgoing(theCre    
582             }                                     
583             else {                                
584                 INCL_ERROR("Wrong number (< 2)    
585             }                                     
586             delete fs;                            
587             delete decay;                         
588         }                                         
589                                                   
590         return true;                              
591     }                                             
592                                                   
593   G4bool Nucleus::decayOutgoingSigmaZero(G4dou    
594         ParticleList const &out = theStore->ge    
595         ParticleList neutralsigma;                
596         for(ParticleIter i=out.begin(), e=out.    
597             if((*i)->getType() == SigmaZero &&    
598         }                                         
599         if(neutralsigma.empty()) return false;    
600                                                   
601         for(ParticleIter i=neutralsigma.begin(    
602             INCL_DEBUG("Decay outgoing neutral    
603                        << (*i)->print() << '\n    
604             const ThreeVector beta = -(*i)->bo    
605             const G4double neutralsigmaMass =     
606                                                   
607             // Set the neutral sigma momentum     
608             // This makes life simpler if we a    
609             (*i)->setMomentum(ThreeVector());     
610             (*i)->setEnergy((*i)->getMass());     
611                                                   
612             // Use a DecayAvatar                  
613             IAvatar *decay = new DecayAvatar((    
614             FinalState *fs = decay->getFinalSt    
615                                                   
616             Particle * const theModifiedPartic    
617             ParticleList const &created = fs->    
618             Particle * const theCreatedParticl    
619                                                   
620             if (created.size() == 1) {            
621                                                   
622                 // Adjust the decay momentum i    
623                 const G4double decayMomentum =    
624                 ThreeVector newMomentum = theC    
625                 newMomentum *= decayMomentum /    
626                                                   
627                 theCreatedParticle->setTableMa    
628                 theCreatedParticle->setMomentu    
629                 theCreatedParticle->adjustEner    
630                 theCreatedParticle->boost(beta    
631                 theCreatedParticle->setBiasCol    
632                                                   
633                 theModifiedParticle->setTableM    
634                 theModifiedParticle->setMoment    
635                 theModifiedParticle->adjustEne    
636                 theModifiedParticle->boost(bet    
637                                                   
638                 theStore->addToOutgoing(theCre    
639             }                                     
640             else {                                
641                 INCL_ERROR("Wrong number (!= 1    
642             }                                     
643             delete fs;                            
644             delete decay;                         
645         }                                         
646                                                   
647         return true;                              
648     }                                             
649                                                   
650   G4bool Nucleus::decayOutgoingNeutralKaon() {    
651         ParticleList const &out = theStore->ge    
652         ParticleList neutralkaon;                 
653         for(ParticleIter i=out.begin(), e=out.    
654             if((*i)->getType() == KZero  || (*    
655         }                                         
656         if(neutralkaon.empty()) return false;     
657                                                   
658         for(ParticleIter i=neutralkaon.begin()    
659             INCL_DEBUG("Transform outgoing neu    
660                        << (*i)->print() << '\n    
661                                                   
662             // Use a DecayAvatar                  
663             IAvatar *decay = new DecayAvatar((    
664             FinalState *fs = decay->getFinalSt    
665                                                   
666             delete fs;                            
667             delete decay;                         
668         }                                         
669                                                   
670         return true;                              
671     }                                             
672                                                   
673   G4bool Nucleus::decayOutgoingClusters() {       
674     ParticleList const &out = theStore->getOut    
675     ParticleList clusters;                        
676     for(ParticleIter i=out.begin(), e=out.end(    
677       if((*i)->isCluster()) clusters.push_back    
678     }                                             
679     if(clusters.empty()) return false;            
680                                                   
681     for(ParticleIter i=clusters.begin(), e=clu    
682       Cluster *cluster = dynamic_cast<Cluster*    
683 // assert(cluster);                               
684 #ifdef INCLXX_IN_GEANT4_MODE                      
685       if(!cluster)                                
686         continue;                                 
687 #endif                                            
688       cluster->deleteParticles(); // Don't nee    
689       ParticleList decayProducts = ClusterDeca    
690       for(ParticleIter j=decayProducts.begin()    
691         (*j)->setBiasCollisionVector(cluster->    
692         theStore->addToOutgoing(*j);              
693       }                                           
694     }                                             
695     return true;                                  
696   }                                               
697                                                   
698   G4bool Nucleus::decayMe() {                     
699     // Do the phase-space decay only if Z=0 or    
700     if(theA<=1 || (theZ!=0 && (theA+theS)!=the    
701       return false;                               
702                                                   
703     ParticleList decayProducts = ClusterDecay:    
704     for(ParticleIter j=decayProducts.begin(),     
705       (*j)->setBiasCollisionVector(this->getBi    
706       theStore->addToOutgoing(*j);                
707     }                                             
708                                                   
709     return true;                                  
710   }                                               
711                                                   
712   void Nucleus::emitInsidePions() {               
713     /* Forcing emissions of all pions in the n    
714      * energy conservation (although the compu    
715      * might sweep this under the carpet).        
716      */                                           
717     INCL_WARN("Forcing emissions of all pions     
718                                                   
719     // Emit the pions with this kinetic energy    
720     const G4double tinyPionEnergy = 0.1; // Me    
721                                                   
722     // Push out the emitted pions                 
723     ParticleList const &inside = theStore->get    
724     ParticleList toEject;                         
725     for(ParticleIter i=inside.begin(), e=insid    
726       if((*i)->isPion()) {                        
727         Particle * const thePion = *i;            
728         INCL_DEBUG("Forcing emission of the fo    
729                    << thePion->print() << '\n'    
730         thePion->setEmissionTime(theStore->get    
731         // Correction for real masses             
732         const G4double theQValueCorrection = t    
733         const G4double kineticEnergyOutside =     
734         thePion->setTableMass();                  
735         if(kineticEnergyOutside > 0.0)            
736           thePion->setEnergy(thePion->getMass(    
737         else                                      
738           thePion->setEnergy(thePion->getMass(    
739         thePion->adjustMomentumFromEnergy();      
740         thePion->setPotentialEnergy(0.);          
741         theZ -= thePion->getZ();                  
742         toEject.push_back(thePion);               
743       }                                           
744     }                                             
745     for(ParticleIter i=toEject.begin(), e=toEj    
746       theStore->particleHasBeenEjected(*i);       
747       theStore->addToOutgoing(*i);                
748       (*i)->setParticleBias(Particle::getTotal    
749     }                                             
750   }                                               
751                                                   
752   void Nucleus::emitInsideStrangeParticles() {    
753     /* Forcing emissions of Sigmas and antiKao    
754      * This probably violates energy conservat    
755      * (although the computation of the recoil    
756      * might sweep this under the carpet).        
757      */                                           
758     INCL_DEBUG("Forcing emissions of all stran    
759                                                   
760     // Emit the strange particles with this ki    
761     const G4double tinyEnergy = 0.1; // MeV       
762                                                   
763     // Push out the emitted strange particles     
764     ParticleList const &inside = theStore->get    
765     ParticleList toEject;                         
766     for(ParticleIter i=inside.begin(), e=insid    
767       if((*i)->isSigma() || (*i)->isAntiKaon()    
768         Particle * const theParticle = *i;        
769         INCL_DEBUG("Forcing emission of the fo    
770                    << theParticle->print() <<     
771         theParticle->setEmissionTime(theStore-    
772         // Correction for real masses             
773         const G4double theQValueCorrection = t    
774         const G4double kineticEnergyOutside =     
775         theParticle->setTableMass();              
776         if(kineticEnergyOutside > 0.0)            
777           theParticle->setEnergy(theParticle->    
778         else                                      
779           theParticle->setEnergy(theParticle->    
780         theParticle->adjustMomentumFromEnergy(    
781         theParticle->setPotentialEnergy(0.);      
782         theA -= theParticle->getA();              
783         theZ -= theParticle->getZ();              
784         theS -= theParticle->getS();              
785         toEject.push_back(theParticle);           
786       }                                           
787     }                                             
788     for(ParticleIter i=toEject.begin(), e=toEj    
789       theStore->particleHasBeenEjected(*i);       
790       theStore->addToOutgoing(*i);                
791       (*i)->setParticleBias(Particle::getTotal    
792     }                                             
793   }                                               
794                                                   
795   G4int Nucleus::emitInsideLambda() {             
796     /* Forcing emissions of all Lambda in the     
797      * This probably violates energy conservat    
798      * (although the computation of the recoil    
799      * might sweep this under the carpet).        
800      */                                           
801     INCL_DEBUG("Forcing emissions of all Lambd    
802                                                   
803     // Emit the Lambda with this kinetic energ    
804     const G4double tinyEnergy = 0.1; // MeV       
805                                                   
806     // Push out the emitted Lambda                
807     ParticleList const &inside = theStore->get    
808     ParticleList toEject;                         
809     for(ParticleIter i=inside.begin(), e=insid    
810       if((*i)->isLambda()) {                      
811         Particle * const theLambda = *i;          
812         INCL_DEBUG("Forcing emission of the fo    
813                    << theLambda->print() << '\    
814         theLambda->setEmissionTime(theStore->g    
815         // Correction for real masses             
816         const G4double theQValueCorrection = t    
817         const G4double kineticEnergyOutside =     
818         theLambda->setTableMass();                
819         if(kineticEnergyOutside > 0.0)            
820           theLambda->setEnergy(theLambda->getM    
821         else                                      
822           theLambda->setEnergy(theLambda->getM    
823         theLambda->adjustMomentumFromEnergy();    
824         theLambda->setPotentialEnergy(0.);        
825         theA -= theLambda->getA();                
826         theS -= theLambda->getS();                
827         toEject.push_back(theLambda);             
828       }                                           
829     }                                             
830     for(ParticleIter i=toEject.begin(), e=toEj    
831       theStore->particleHasBeenEjected(*i);       
832       theStore->addToOutgoing(*i);                
833       (*i)->setParticleBias(Particle::getTotal    
834     }                                             
835     return (G4int)toEject.size();                 
836   }                                               
837                                                   
838   G4bool Nucleus::emitInsideKaon() {              
839     /* Forcing emissions of all Kaon (not anti    
840      * This probably violates energy conservat    
841      * (although the computation of the recoil    
842      * might sweep this under the carpet).        
843      */                                           
844     INCL_DEBUG("Forcing emissions of all Kaon     
845                                                   
846     // Emit the Kaon with this kinetic energy     
847     const G4double tinyEnergy = 0.1; // MeV       
848                                                   
849     // Push out the emitted kaon                  
850     ParticleList const &inside = theStore->get    
851     ParticleList toEject;                         
852     for(ParticleIter i=inside.begin(), e=insid    
853       if((*i)->isKaon()) {                        
854         Particle * const theKaon = *i;            
855         INCL_DEBUG("Forcing emission of the fo    
856                    << theKaon->print() << '\n'    
857         theKaon->setEmissionTime(theStore->get    
858         // Correction for real masses             
859         const G4double theQValueCorrection = t    
860         const G4double kineticEnergyOutside =     
861         theKaon->setTableMass();                  
862         if(kineticEnergyOutside > 0.0)            
863           theKaon->setEnergy(theKaon->getMass(    
864         else                                      
865           theKaon->setEnergy(theKaon->getMass(    
866         theKaon->adjustMomentumFromEnergy();      
867         theKaon->setPotentialEnergy(0.);          
868         theZ -= theKaon->getZ();                  
869         theS -= theKaon->getS();                  
870         toEject.push_back(theKaon);               
871       }                                           
872     }                                             
873     for(ParticleIter i=toEject.begin(), e=toEj    
874       theStore->particleHasBeenEjected(*i);       
875       theStore->addToOutgoing(*i);                
876       (*i)->setParticleBias(Particle::getTotal    
877     }                                             
878     theNKaon -= 1;                                
879     return toEject.size() != 0;                   
880   }                                               
881                                                   
882   G4bool Nucleus::isEventTransparent() const {    
883                                                   
884     Book const &theBook = theStore->getBook();    
885     const G4int nEventCollisions = theBook.get    
886     const G4int nEventDecays = theBook.getAcce    
887     const G4int nEventClusters = theBook.getEm    
888     if(nEventCollisions==0 && nEventDecays==0     
889       return true;                                
890                                                   
891     return false;                                 
892                                                   
893   }                                               
894                                                   
895   void Nucleus::computeOneNucleonRecoilKinemat    
896     // We should be here only if the nucleus c    
897 // assert(theStore->getParticles().size()==1);    
898                                                   
899     // No excitation energy!                      
900     theExcitationEnergy = 0.0;                    
901                                                   
902     // Move the nucleon to the outgoing list      
903     Particle *remN = theStore->getParticles().    
904     theA -= remN->getA();                         
905     theZ -= remN->getZ();                         
906     theS -= remN->getS();                         
907     theStore->particleHasBeenEjected(remN);       
908     theStore->addToOutgoing(remN);                
909     remN->setEmissionTime(theStore->getBook().    
910                                                   
911     // Treat the special case of a remaining d    
912     if(remN->isDelta()) {                         
913       IAvatar *decay = new DecayAvatar(remN, 0    
914       FinalState *fs = decay->getFinalState();    
915       // Eject the pion                           
916       ParticleList const &created = fs->getCre    
917       for(ParticleIter j=created.begin(), e=cr    
918         theStore->addToOutgoing(*j);              
919       delete fs;                                  
920       delete decay;                               
921     }                                             
922                                                   
923     // Do different things depending on how ma    
924     ParticleList const &outgoing = theStore->g    
925     if(outgoing.size() == 2) {                    
926                                                   
927       INCL_DEBUG("Two particles in the outgoin    
928                                                   
929       // Can apply exact 2-body kinematics her    
930       // the first particle.                      
931       Particle *p1 = outgoing.front(), *p2 = o    
932       const ThreeVector aBoostVector = incomin    
933       // Boost to the initial CM                  
934       p1->boost(aBoostVector);                    
935       const G4double sqrts = std::sqrt(initial    
936       const G4double pcm = KinematicsUtils::mo    
937       const G4double scale = pcm/(p1->getMomen    
938       // Reset the momenta                        
939       p1->setMomentum(p1->getMomentum()*scale)    
940       p2->setMomentum(-p1->getMomentum());        
941       p1->adjustEnergyFromMomentum();             
942       p2->adjustEnergyFromMomentum();             
943       // Unboost                                  
944       p1->boost(-aBoostVector);                   
945       p2->boost(-aBoostVector);                   
946                                                   
947     } else {                                      
948                                                   
949       INCL_DEBUG("Trying to adjust final-state    
950                                                   
951       const G4int maxIterations=8;                
952       G4double totalEnergy, energyScale;          
953       G4double val=1.E+100, oldVal=1.E+100, ol    
954       ThreeVector totalMomentum, deltaP;          
955       std::vector<ThreeVector> minMomenta;  //    
956                                                   
957       // Reserve the vector size                  
958       minMomenta.reserve(outgoing.size());        
959                                                   
960       // Compute the initial total momentum       
961       totalMomentum.setX(0.0);                    
962       totalMomentum.setY(0.0);                    
963       totalMomentum.setZ(0.0);                    
964       for(ParticleIter i=outgoing.begin(), e=o    
965         totalMomentum += (*i)->getMomentum();     
966                                                   
967       // Compute the initial total energy         
968       totalEnergy = 0.0;                          
969       for(ParticleIter i=outgoing.begin(), e=o    
970         totalEnergy += (*i)->getEnergy();         
971                                                   
972       // Iterative algorithm starts here:         
973       for(G4int iterations=0; iterations < max    
974                                                   
975         // Save the old merit-function values     
976         oldOldOldVal = oldOldVal;                 
977         oldOldVal = oldVal;                       
978         oldVal = val;                             
979                                                   
980         if(iterations%2 == 0) {                   
981           INCL_DEBUG("Momentum step" << '\n');    
982           // Momentum step: modify all the par    
983           deltaP = incomingMomentum - totalMom    
984           G4double pOldTot = 0.0;                 
985           for(ParticleIter i=outgoing.begin(),    
986             pOldTot += (*i)->getMomentum().mag    
987           for(ParticleIter i=outgoing.begin(),    
988             const ThreeVector mom = (*i)->getM    
989             (*i)->setMomentum(mom + deltaP*mom    
990             (*i)->adjustEnergyFromMomentum();     
991           }                                       
992         } else {                                  
993           INCL_DEBUG("Energy step" << '\n');      
994           // Energy step: modify all the parti    
995           energyScale = initialEnergy/totalEne    
996           for(ParticleIter i=outgoing.begin(),    
997             const ThreeVector mom = (*i)->getM    
998             G4double pScale = ((*i)->getEnergy    
999             if(pScale>0) {                        
1000               (*i)->setEnergy((*i)->getEnergy    
1001               (*i)->adjustMomentumFromEnergy(    
1002             }                                    
1003           }                                      
1004         }                                        
1005                                                  
1006         // Compute the current total momentum    
1007         totalMomentum.setX(0.0);                 
1008         totalMomentum.setY(0.0);                 
1009         totalMomentum.setZ(0.0);                 
1010         totalEnergy = 0.0;                       
1011         for(ParticleIter i=outgoing.begin(),     
1012           totalMomentum += (*i)->getMomentum(    
1013           totalEnergy += (*i)->getEnergy();      
1014         }                                        
1015                                                  
1016         // Merit factor                          
1017         val = std::pow(totalEnergy - initialE    
1018           0.25*(totalMomentum - incomingMomen    
1019         INCL_DEBUG("Merit function: val=" <<     
1020                                                  
1021         // Store the minimum                     
1022         if(val < oldVal) {                       
1023           INCL_DEBUG("New minimum found, stor    
1024           minMomenta.clear();                    
1025           for(ParticleIter i=outgoing.begin()    
1026             minMomenta.push_back((*i)->getMom    
1027         }                                        
1028                                                  
1029         // Stop the algorithm if the search d    
1030         if(val > oldOldVal && oldVal > oldOld    
1031           INCL_DEBUG("Search is diverging, br    
1032           break;                                 
1033         }                                        
1034       }                                          
1035                                                  
1036       // We should have made at least one suc    
1037 // assert(minMomenta.size()==outgoing.size())    
1038                                                  
1039       // Apply the optimal momenta               
1040       INCL_DEBUG("Applying the solution" << '    
1041       std::vector<ThreeVector>::const_iterato    
1042       for(ParticleIter i=outgoing.begin(), e=    
1043         (*i)->setMomentum(*v);                   
1044         (*i)->adjustEnergyFromMomentum();        
1045         INCL_DATABLOCK((*i)->print());           
1046       }                                          
1047                                                  
1048     }                                            
1049                                                  
1050   }                                              
1051                                                  
1052   void Nucleus::fillEventInfo(EventInfo *even    
1053     eventInfo->nParticles = 0;                   
1054     G4bool isNucleonAbsorption = false;          
1055     G4bool isPionAbsorption = false;             
1056     // It is possible to have pion absorption    
1057     // projectile is pion.                       
1058     if(eventInfo->projectileType == PiPlus ||    
1059        eventInfo->projectileType == PiMinus |    
1060        eventInfo->projectileType == PiZero) {    
1061       isPionAbsorption = true;                   
1062     }                                            
1063                                                  
1064     // Forced CN                                 
1065     eventInfo->forcedCompoundNucleus = tryCN;    
1066                                                  
1067     // Outgoing particles                        
1068     ParticleList const &outgoingParticles = g    
1069                                                  
1070     // Check if we have a nucleon absorption     
1071     // and no ejected particles.                 
1072     if(outgoingParticles.size() == 0 &&          
1073        (eventInfo->projectileType == Proton |    
1074     eventInfo->projectileType == Neutron)) {     
1075       isNucleonAbsorption = true;                
1076     }                                            
1077                                                  
1078     // Reset the remnant counter                 
1079     eventInfo->nRemnants = 0;                    
1080     eventInfo->history.clear();                  
1081                                                  
1082     for(ParticleIter i=outgoingParticles.begi    
1083       // We have a pion absorption event only    
1084       // pion and there are no ejected pions.    
1085       if(isPionAbsorption) {                     
1086         if((*i)->isPion()) {                     
1087           isPionAbsorption = false;              
1088         }                                        
1089       }                                          
1090                                                  
1091       eventInfo->ParticleBias[eventInfo->nPar    
1092                                                  
1093 #ifdef INCLXX_IN_GEANT4_MODE                     
1094       eventInfo->A[eventInfo->nParticles] = (    
1095       eventInfo->Z[eventInfo->nParticles] = (    
1096       eventInfo->S[eventInfo->nParticles] = (    
1097 #else                                            
1098       eventInfo->A[eventInfo->nParticles] = (    
1099       eventInfo->Z[eventInfo->nParticles] = (    
1100       eventInfo->S[eventInfo->nParticles] = (    
1101 #endif                                           
1102       eventInfo->emissionTime[eventInfo->nPar    
1103       eventInfo->EKin[eventInfo->nParticles]     
1104       ThreeVector mom = (*i)->getMomentum();     
1105       eventInfo->px[eventInfo->nParticles] =     
1106       eventInfo->py[eventInfo->nParticles] =     
1107       eventInfo->pz[eventInfo->nParticles] =     
1108       eventInfo->theta[eventInfo->nParticles]    
1109       eventInfo->phi[eventInfo->nParticles] =    
1110       eventInfo->origin[eventInfo->nParticles    
1111 #ifdef INCLXX_IN_GEANT4_MODE                     
1112       eventInfo->parentResonancePDGCode[event    
1113       eventInfo->parentResonanceID[eventInfo-    
1114 #endif                                           
1115       eventInfo->history.push_back("");          
1116       if ((*i)->getType() != Composite) {        
1117         ParticleSpecies pt((*i)->getType());     
1118         eventInfo->PDGCode[eventInfo->nPartic    
1119       }                                          
1120       else {                                     
1121         ParticleSpecies pt((*i)->getA(), (*i)    
1122         eventInfo->PDGCode[eventInfo->nPartic    
1123       }                                          
1124       eventInfo->nParticles++;                   
1125     }                                            
1126     eventInfo->nucleonAbsorption = isNucleonA    
1127     eventInfo->pionAbsorption = isPionAbsorpt    
1128     eventInfo->nCascadeParticles = eventInfo-    
1129                                                  
1130     // Projectile-like remnant characteristic    
1131     if(theProjectileRemnant && theProjectileR    
1132 #ifdef INCLXX_IN_GEANT4_MODE                     
1133       eventInfo->ARem[eventInfo->nRemnants] =    
1134       eventInfo->ZRem[eventInfo->nRemnants] =    
1135       eventInfo->SRem[eventInfo->nRemnants] =    
1136 #else                                            
1137       eventInfo->ARem[eventInfo->nRemnants] =    
1138       eventInfo->ZRem[eventInfo->nRemnants] =    
1139       eventInfo->SRem[eventInfo->nRemnants] =    
1140 #endif                                           
1141       G4double eStar = theProjectileRemnant->    
1142       if(std::abs(eStar)<1E-10)                  
1143         eStar = 0.0; // blame rounding and se    
1144       eventInfo->EStarRem[eventInfo->nRemnant    
1145       if(eventInfo->EStarRem[eventInfo->nRemn    
1146     INCL_WARN("Negative excitation energy in     
1147       }                                          
1148       const ThreeVector &spin = theProjectile    
1149       if(eventInfo->ARem[eventInfo->nRemnants    
1150     eventInfo->JRem[eventInfo->nRemnants] = (    
1151       } else { // odd-A nucleus                  
1152     eventInfo->JRem[eventInfo->nRemnants] = (    
1153       }                                          
1154       eventInfo->EKinRem[eventInfo->nRemnants    
1155       const ThreeVector &mom = theProjectileR    
1156       eventInfo->pxRem[eventInfo->nRemnants]     
1157       eventInfo->pyRem[eventInfo->nRemnants]     
1158       eventInfo->pzRem[eventInfo->nRemnants]     
1159       eventInfo->jxRem[eventInfo->nRemnants]     
1160       eventInfo->jyRem[eventInfo->nRemnants]     
1161       eventInfo->jzRem[eventInfo->nRemnants]     
1162       eventInfo->thetaRem[eventInfo->nRemnant    
1163       eventInfo->phiRem[eventInfo->nRemnants]    
1164       eventInfo->nRemnants++;                    
1165     }                                            
1166                                                  
1167     // Target-like remnant characteristics       
1168     if(hasRemnant()) {                           
1169 #ifdef INCLXX_IN_GEANT4_MODE                     
1170       eventInfo->ARem[eventInfo->nRemnants] =    
1171       eventInfo->ZRem[eventInfo->nRemnants] =    
1172       eventInfo->SRem[eventInfo->nRemnants] =    
1173 #else                                            
1174       eventInfo->ARem[eventInfo->nRemnants] =    
1175       eventInfo->ZRem[eventInfo->nRemnants] =    
1176       eventInfo->SRem[eventInfo->nRemnants] =    
1177 #endif                                           
1178       eventInfo->EStarRem[eventInfo->nRemnant    
1179       if(eventInfo->EStarRem[eventInfo->nRemn    
1180     INCL_WARN("Negative excitation energy in     
1181       }                                          
1182       const ThreeVector &spin = getSpin();       
1183       if(eventInfo->ARem[eventInfo->nRemnants    
1184     eventInfo->JRem[eventInfo->nRemnants] = (    
1185       } else { // odd-A nucleus                  
1186     eventInfo->JRem[eventInfo->nRemnants] = (    
1187       }                                          
1188       eventInfo->EKinRem[eventInfo->nRemnants    
1189       const ThreeVector &mom = getMomentum();    
1190       eventInfo->pxRem[eventInfo->nRemnants]     
1191       eventInfo->pyRem[eventInfo->nRemnants]     
1192       eventInfo->pzRem[eventInfo->nRemnants]     
1193       eventInfo->jxRem[eventInfo->nRemnants]     
1194       eventInfo->jyRem[eventInfo->nRemnants]     
1195       eventInfo->jzRem[eventInfo->nRemnants]     
1196       eventInfo->thetaRem[eventInfo->nRemnant    
1197       eventInfo->phiRem[eventInfo->nRemnants]    
1198       eventInfo->nRemnants++;                    
1199     }                                            
1200                                                  
1201     // Global counters, flags, etc.              
1202     Book const &theBook = theStore->getBook()    
1203     eventInfo->nCollisions = theBook.getAccep    
1204     eventInfo->nBlockedCollisions = theBook.g    
1205     eventInfo->nDecays = theBook.getAcceptedD    
1206     eventInfo->nBlockedDecays = theBook.getBl    
1207     eventInfo->firstCollisionTime = theBook.g    
1208     eventInfo->firstCollisionXSec = theBook.g    
1209     eventInfo->firstCollisionSpectatorPositio    
1210     eventInfo->firstCollisionSpectatorMomentu    
1211     eventInfo->firstCollisionIsElastic = theB    
1212     eventInfo->nReflectionAvatars = theBook.g    
1213     eventInfo->nCollisionAvatars = theBook.ge    
1214     eventInfo->nDecayAvatars = theBook.getAva    
1215     eventInfo->nEnergyViolationInteraction =     
1216   }                                              
1217                                                  
1218                                                  
1219                                                  
1220   Nucleus::ConservationBalance Nucleus::getCo    
1221     ConservationBalance theBalance;              
1222     // Initialise balance variables with the     
1223     INCL_DEBUG("theEventInfo " << theEventInf    
1224     theBalance.Z = theEventInfo.Zp + theEvent    
1225     theBalance.A = theEventInfo.Ap + theEvent    
1226     theBalance.S = theEventInfo.Sp + theEvent    
1227     INCL_DEBUG("theBalance Z and A " << theBa    
1228     theBalance.energy = getInitialEnergy();      
1229     theBalance.momentum = getIncomingMomentum    
1230                                                  
1231     // Process outgoing particles                
1232     ParticleList const &outgoingParticles = t    
1233     for(ParticleIter i=outgoingParticles.begi    
1234       theBalance.Z -= (*i)->getZ();              
1235       theBalance.A -= (*i)->getA();              
1236       theBalance.S -= (*i)->getS();              
1237       // For outgoing clusters, the total ene    
1238       // excitation energy                       
1239       theBalance.energy -= (*i)->getEnergy();    
1240       theBalance.momentum -= (*i)->getMomentu    
1241     }                                            
1242                                                  
1243     // Projectile-like remnant contribution,     
1244     if(theProjectileRemnant && theProjectileR    
1245       theBalance.Z -= theProjectileRemnant->g    
1246       theBalance.A -= theProjectileRemnant->g    
1247       theBalance.S -= theProjectileRemnant->g    
1248       theBalance.energy -= ParticleTable::get    
1249         theProjectileRemnant->getExcitationEn    
1250       theBalance.energy -= theProjectileRemna    
1251       theBalance.momentum -= theProjectileRem    
1252     }                                            
1253                                                  
1254     // Target-like remnant contribution, if p    
1255     if(hasRemnant()) {                           
1256       theBalance.Z -= getZ();                    
1257       theBalance.A -= getA();                    
1258       theBalance.S -= getS();                    
1259       theBalance.energy -= ParticleTable::get    
1260         getExcitationEnergy();                   
1261       if(afterRecoil)                            
1262         theBalance.energy -= getKineticEnergy    
1263       theBalance.momentum -= getMomentum();      
1264     }                                            
1265                                                  
1266     return theBalance;                           
1267   }                                              
1268                                                  
1269   void Nucleus::useFusionKinematics() {          
1270     setEnergy(initialEnergy);                    
1271     setMomentum(incomingMomentum);               
1272     setSpin(incomingAngularMomentum);            
1273     theExcitationEnergy = std::sqrt(theEnergy    
1274     setMass(getTableMass() + theExcitationEne    
1275   }                                              
1276                                                  
1277   void Nucleus::finalizeProjectileRemnant(con    
1278     // Deal with the projectile remnant          
1279     const G4int prA = theProjectileRemnant->g    
1280     if(prA>=1) {                                 
1281       // Set the mass                            
1282       const G4double aMass = theProjectileRem    
1283       theProjectileRemnant->setMass(aMass);      
1284                                                  
1285       // Compute the excitation energy from t    
1286       const G4double anExcitationEnergy = aMa    
1287         - ParticleTable::getTableMass(prA, th    
1288                                                  
1289       // Set the excitation energy               
1290       theProjectileRemnant->setExcitationEner    
1291                                                  
1292       // No spin!                                
1293       theProjectileRemnant->setSpin(ThreeVect    
1294                                                  
1295       // Set the emission time                   
1296       theProjectileRemnant->setEmissionTime(a    
1297     }                                            
1298   }                                              
1299                                                  
1300 }                                                
1301                                                  
1302 #endif                                           
1303