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 10.2.p1)


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