33 #define INCLXX_IN_GEANT4_MODE 1 
   81     :propagationModel(0), theA(208), theZ(82),
 
   82     targetInitSuccess(false),
 
   83     maxImpactParameter(0.),
 
   84     maxUniverseRadius(0.),
 
   85     maxInteractionDistance(0.),
 
   86     fixedImpactParameter(0.),
 
   98 #ifdef INCLXX_IN_GEANT4_MODE 
  102 #endif // INCLXX_IN_GEANT4_MODE 
  154 #ifndef INCLXX_IN_GEANT4_MODE 
  159     theGlobalInfo.
Ap = theSpecies.
theA;
 
  160     theGlobalInfo.
Zp = theSpecies.
theZ;
 
  163     INFO(theConfig->
echo() << std::endl);
 
  177     delete propagationAction;
 
  179     delete propagationModel;
 
  184     if(A < 0 || A > 300 || Z < 1 || Z > 200) {
 
  185       ERROR(
"Unsupported target: A = " << A << 
" Z = " << Z << std::endl);
 
  186       ERROR(
"Target configuration rejected." << std::endl);
 
  191     initUniverseRadius(projectileSpecies, kineticEnergy, A, Z);
 
  203     initMaxInteractionDistance(projectileSpecies, kineticEnergy); 
 
  210     if(projectileSpecies.
theA > 0)
 
  211       minRemnantSize = std::min(theA, 4);
 
  213       minRemnantSize = std::min(theA-1, 4);
 
  221     nucleus = 
new Nucleus(A, Z, theConfig, maxUniverseRadius);
 
  236     targetInitSuccess = 
prepareReaction(projectileSpecies, kineticEnergy, targetA, targetZ);
 
  238     if(!targetInitSuccess) {
 
  239       WARN(
"Target initialisation failed for A=" << targetA << 
", Z=" << targetZ << std::endl);
 
  244     const G4bool canRunCascade = preCascade(projectileSpecies, kineticEnergy);
 
  254     theEventInfo.
reset();
 
  263     theEventInfo.
Ap = projectileSpecies.
theA;
 
  264     theEventInfo.
Zp = projectileSpecies.
theZ;
 
  265     theEventInfo.
Ep = kineticEnergy;
 
  266     theEventInfo.
At = nucleus->
getA();
 
  267     theEventInfo.
Zt = nucleus->
getZ();
 
  270     if(maxImpactParameter<=0.) {
 
  283     if(fixedImpactParameter<0.) {
 
  284       impactParameter = maxImpactParameter * std::sqrt(
Random::shoot0());
 
  287       impactParameter = fixedImpactParameter;
 
  294     const G4double effectiveImpactParameter = propagationModel->
shoot(projectileSpecies, kineticEnergy, impactParameter, phi);
 
  295     if(effectiveImpactParameter < 0.) {
 
  312   void INCL::cascade() {
 
  324       if(avatar == 0) 
break; 
 
  347     } 
while(continueCascade());
 
  351   void INCL::postCascade() {
 
  357       DEBUG(
"Trying compound nucleus" << std::endl);
 
  358       makeCompoundNucleus();
 
  360 #ifndef INCLXX_IN_GEANT4_MODE 
  361       if(!theEventInfo.
transparent) globalConservationChecks(
true);
 
  374       if(projectileRemnant) {
 
  404         DEBUG(
"Cascade resulted in complete fusion, using realistic fusion kinematics" << std::endl);
 
  411           WARN(
"Complete-fusion kinematics yields negative excitation energy, returning a transparent!" << std::endl);
 
  428 #ifndef INCLXX_IN_GEANT4_MODE 
  430         globalConservationChecks(
false);
 
  435         if(nucleus->
hasRemnant()) rescaleOutgoingForRecoil();
 
  442 #ifndef INCLXX_IN_GEANT4_MODE 
  444       globalConservationChecks(
true);
 
  456   void INCL::makeCompoundNucleus() {
 
  461     nucleus->
setA(theEventInfo.
At);
 
  462     nucleus->
setZ(theEventInfo.
Zt);
 
  470     G4int theCNA=theEventInfo.
At, theCNZ=theEventInfo.
Zt;
 
  475     ParticleList initialProjectileComponents = theProjectileRemnant->getParticles();
 
  476     std::vector<Particle *> shuffledComponents(initialProjectileComponents.begin(), initialProjectileComponents.end());
 
  481     G4bool atLeastOneNucleonEntering = 
false;
 
  482     for(std::vector<Particle*>::const_iterator 
p=shuffledComponents.begin(); 
p!=shuffledComponents.end(); ++
p) {
 
  486             (*p)->getPropagationVelocity(),
 
  488       if(!intersectionUniverse.exists)
 
  494             (*p)->getPropagationVelocity(),
 
  495             maxInteractionDistance));
 
  496       if(intersectionInteraction.exists)
 
  497         atLeastOneNucleonEntering = 
true;
 
  500       ParticleEntryAvatar theAvatar(0.0, nucleus, *
p);
 
  501       FinalState *fs = theAvatar.getFinalState();
 
  510           theCNZ += (*p)->getZ();
 
  521     if(!success || !atLeastOneNucleonEntering) {
 
  522       DEBUG(
"No nucleon entering in forced CN, or some nucleons entering below zero, forcing a transparent" << std::endl);
 
  535     theCNEnergy -= theProjectileRemnant->getEnergy();
 
  536     theCNMomentum -= theProjectileRemnant->getMomentum();
 
  544     for(
ParticleIter i=outgoing.begin(); i!=outgoing.end(); ++i) {
 
  545       theCNSpin -= (*i)->getAngularMomentum();
 
  550     const G4double theCNInvariantMassSquared = theCNEnergy*theCNEnergy-theCNMomentum.mag2();
 
  551     if(theCNInvariantMassSquared<0.) {
 
  558     const G4double theCNExcitationEnergy = std::sqrt(theCNInvariantMassSquared) - theCNMass;
 
  559     if(theCNExcitationEnergy<0.) {
 
  567       nucleus->
setA(theCNA);
 
  568       nucleus->
setZ(theCNZ);
 
  572       nucleus->
setMass(theCNMass+theCNExcitationEnergy);
 
  587   void INCL::rescaleOutgoingForRecoil() {
 
  588     RecoilCMFunctor theRecoilFunctor(nucleus, theEventInfo);
 
  594       theRecoilFunctor(theSolution.first); 
 
  596       WARN(
"Couldn't accommodate remnant recoil while satisfying energy conservation, root-finding algorithm failed." << std::endl);
 
  601 #ifndef INCLXX_IN_GEANT4_MODE 
  602   void INCL::globalConservationChecks(
G4bool afterRecoil) {
 
  607     const G4double pTransBalance = theBalance.momentum.perp();
 
  608     if(theBalance.Z != 0) {
 
  609       ERROR(
"Violation of charge conservation! ZBalance = " << theBalance.Z << std::endl);
 
  611     if(theBalance.A != 0) {
 
  612       ERROR(
"Violation of baryon-number conservation! ABalance = " << theBalance.A << std::endl);
 
  614     G4double EThreshold, pLongThreshold, pTransThreshold;
 
  619       pTransThreshold = 1.; 
 
  623       pLongThreshold = 0.1; 
 
  624       pTransThreshold = 0.1; 
 
  626     if(std::abs(theBalance.energy)>EThreshold) {
 
  627       WARN(
"Violation of energy conservation > " << EThreshold << 
" MeV. EBalance = " << theBalance.energy << 
" afterRecoil = " << afterRecoil << 
" eventNumber=" << theEventInfo.
eventNumber << std::endl);
 
  629     if(std::abs(pLongBalance)>pLongThreshold) {
 
  630       WARN(
"Violation of longitudinal momentum conservation > " << pLongThreshold << 
" MeV/c. pLongBalance = " << pLongBalance << 
" afterRecoil = " << afterRecoil << 
" eventNumber=" << theEventInfo.
eventNumber << std::endl);
 
  632     if(std::abs(pTransBalance)>pTransThreshold) {
 
  633       WARN(
"Violation of transverse momentum conservation > " << pTransThreshold << 
" MeV/c. pTransBalance = " << pTransBalance << 
" afterRecoil = " << afterRecoil << 
" eventNumber=" << theEventInfo.
eventNumber << std::endl);
 
  637     theEventInfo.
EBalance = theBalance.energy;
 
  643   G4bool INCL::continueCascade() {
 
  648           << 
"), stopping cascade" << std::endl);
 
  654       DEBUG(
"No participants in the nucleus and no incoming particles left, stopping cascade" << std::endl);
 
  658     if(nucleus->
getA() <= minRemnantSize) {
 
  659       DEBUG(
"Remnant size (" << nucleus->
getA()
 
  660           << 
") smaller than or equal to minimum (" << minRemnantSize
 
  661           << 
"), stopping cascade" << std::endl);
 
  667       DEBUG(
"Trying to make a compound nucleus, stopping cascade" << std::endl);
 
  671       DEBUG(
"Forcing a transparent, stopping cascade" << std::endl);
 
  691   G4int INCL::makeProjectileRemnant() {
 
  692     G4int nUnmergedSpectators = 0;
 
  703     if(dynSpectators.empty() && geomSpectators.empty()) {
 
  706     } 
else if(geomSpectators.size()+dynSpectators.size()==1) {
 
  707       if(dynSpectators.empty()) {
 
  710 #if !defined(NDEBUG) && !defined(INCLXX_IN_GEANT4_MODE) 
  711         Particle *theSpectator = geomSpectators.front();
 
  726       ParticleList rejected = theProjectileRemnant->addMostDynamicalSpectators(dynSpectators);
 
  728       nUnmergedSpectators = rejected.size();
 
  736     return nUnmergedSpectators;
 
  739   void INCL::initMaxInteractionDistance(ParticleSpecies 
const &projectileSpecies, 
const G4double kineticEnergy) {
 
  740     if(projectileSpecies.theType != 
Composite) {
 
  741       maxInteractionDistance = 0.;
 
  745     const G4double projectileKineticEnergyPerNucleon = kineticEnergy/projectileSpecies.theA;
 
  751   void INCL::initUniverseRadius(ParticleSpecies 
const &
p, 
const G4double kineticEnergy, 
const G4int A, 
const G4int Z) {
 
  754       IsotopicDistribution 
const &anIsotopicDistribution =
 
  756       IsotopeVector theIsotopes = anIsotopicDistribution.getIsotopes();
 
  757       for(
IsotopeIter i=theIsotopes.begin(); i!=theIsotopes.end(); ++i) {
 
  760           FATAL(
"NULL density in initUniverseRadius. " 
  761                 << 
"Projectile type=" << p.theType
 
  764                 << 
", kinE=" << kineticEnergy
 
  765                 << 
", target A=" << A
 
  769         rMax = std::max(theDensity->getMaximumRadius(), rMax);
 
  774         FATAL(
"NULL density in initUniverseRadius. " 
  775               << 
"Projectile type=" << p.theType
 
  778               << 
", kinE=" << kineticEnergy
 
  779               << 
", target A=" << A
 
  783       rMax = theDensity->getMaximumRadius();
 
  786       maxUniverseRadius = rMax;
 
  790         maxUniverseRadius = rMax
 
  792           + interactionDistanceNN;
 
  794         maxUniverseRadius = rMax;
 
  795     } 
else if(p.theType==
PiPlus 
  800         maxUniverseRadius = rMax
 
  802           + interactionDistancePiN;
 
  804         maxUniverseRadius = rMax;