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;