34 #define INCLXX_IN_GEANT4_MODE 1
45 #ifndef G4INCLNucleus_hh
46 #define G4INCLNucleus_hh 1
68 theInitialZ(charge), theInitialA(mass),
69 theNpInitial(0), theNnInitial(0),
70 initialInternalEnergy(0.),
71 incomingAngularMomentum(0.,0.,0.), incomingMomentum(0.,0.,0.),
72 initialCenterOfMass(0.,0.,0.),
76 theUniverseRadius(universeRadius),
77 isNucleusNucleus(false),
78 theProjectileRemnant(NULL),
103 if(theUniverseRadius<0)
104 theUniverseRadius = theDensity->getMaximumRadius();
105 theStore =
new Store(conf);
119 delete theProjectileRemnant;
120 theProjectileRemnant = NULL;
142 for(
ParticleIter iter=created.begin(), e=created.end(); iter!=e; ++iter) {
143 theStore->
add((*iter));
144 if(!(*iter)->isOutOfWell()) {
145 totalEnergy += (*iter)->getEnergy() - (*iter)->getPotentialEnergy();
150 for(
ParticleIter iter=deleted.begin(), e=deleted.end(); iter!=e; ++iter) {
155 for(
ParticleIter iter=modified.begin(), e=modified.end(); iter!=e; ++iter) {
157 totalEnergy += (*iter)->getEnergy() - (*iter)->getPotentialEnergy();
161 for(
ParticleIter iter=out.begin(), e=out.end(); iter!=e; ++iter) {
162 if((*iter)->isCluster()) {
165 #ifdef INCLXX_IN_GEANT4_MODE
170 for(
ParticleIter in=components.begin(), end=components.end(); in!=end; ++in)
175 totalEnergy += (*iter)->getEnergy();
176 theA -= (*iter)->getA();
177 theZ -= (*iter)->getZ();
183 for(
ParticleIter iter=entering.begin(), e=entering.end(); iter!=e; ++iter) {
185 totalEnergy += (*iter)->getEnergy() - (*iter)->getPotentialEnergy();
191 INCL_DEBUG(
"A Particle is entering below the Fermi sea:" <<
'\n' << finalstate->
print() <<
'\n');
194 for(
ParticleIter iter=entering.begin(), e=entering.end(); iter!=e; ++iter) {
201 INCL_ERROR(
"Energy nonconservation! Energy at the beginning of the event = "
203 <<
" and after interaction = "
204 << totalEnergy <<
'\n'
205 << finalstate->
print());
210 INCL_WARN(
"Useless Nucleus::propagateParticles -method called." <<
'\n');
217 if((*p)->isNucleon())
218 totalEnergy += (*p)->getKineticEnergy() - (*p)->getPotentialEnergy();
219 else if((*p)->isResonance())
222 totalEnergy += (*p)->getEnergy() - (*p)->getPotentialEnergy();
232 computeOneNucleonRecoilKinematics();
239 theSpin = incomingAngularMomentum;
244 theSpin -= (*p)->getAngularMomentum();
246 if(theProjectileRemnant) {
265 const G4double mass = (*p)->getMass();
266 cm += (*p)->getPosition() * mass;
277 return totalEnergy - initialInternalEnergy - separationEnergies;
282 std::stringstream ss;
283 ss <<
"Particles in the nucleus:" <<
'\n'
284 <<
"Inside:" <<
'\n';
288 ss <<
"index = " << counter <<
'\n'
292 ss <<
"Outgoing:" <<
'\n';
303 for(
ParticleIter i=out.begin(), e=out.end(); i!=e; ++i) {
304 if((*i)->isDelta()) deltas.push_back((*i));
306 if(deltas.empty())
return false;
308 for(
ParticleIter i=deltas.begin(), e=deltas.end(); i!=e; ++i) {
309 INCL_DEBUG(
"Decay outgoing delta particle:" <<
'\n'
310 << (*i)->print() <<
'\n');
312 const G4double deltaMass = (*i)->getMass();
317 (*i)->setEnergy((*i)->getMass());
330 newMomentum *= decayMomentum / newMomentum.
mag();
341 nucleon->
boost(beta);
360 const G4bool unphysicalRemnant = (theZ<0 || theZ>
theA);
367 for(
ParticleIter i=inside.begin(), e=inside.end(); i!=e; ++i)
368 if((*i)->isDelta()) deltas.push_back((*i));
371 for(
ParticleIter i=deltas.begin(), e=deltas.end(); i!=e; ++i) {
372 INCL_DEBUG(
"Decay inside delta particle:" <<
'\n'
373 << (*i)->print() <<
'\n');
379 if(unphysicalRemnant) {
380 INCL_WARN(
"Forcing delta decay inside an unphysical remnant (A=" <<
theA
381 <<
", Z=" <<
theZ <<
"). Might lead to energy-violation warnings."
400 if(unphysicalRemnant) {
401 INCL_DEBUG(
"Remnant is unphysical: Z=" <<
theZ <<
", A=" <<
theA <<
", emitting all the pions" <<
'\n');
411 for(
ParticleIter i=out.begin(), e=out.end(); i!=e; ++i) {
415 if(pionResonances.empty())
return false;
417 for(
ParticleIter i=pionResonances.begin(), e=pionResonances.end(); i!=e; ++i) {
418 INCL_DEBUG(
"Decay outgoing pionResonances particle:" <<
'\n'
419 << (*i)->print() <<
'\n');
421 const G4double pionResonanceMass = (*i)->getMass();
426 (*i)->setEnergy((*i)->getMass());
434 Particle *
const theCreatedParticle1 = created.front();
436 if (created.size() == 1) {
441 newMomentum *= decayMomentum / newMomentum.
mag();
447 theCreatedParticle1->
boost(beta);
452 theModifiedParticle->
boost(beta);
456 else if (created.size() == 2) {
457 Particle *
const theCreatedParticle2 = created.back();
459 theCreatedParticle1->
boost(beta);
460 theCreatedParticle2->
boost(beta);
461 theModifiedParticle->
boost(beta);
467 INCL_ERROR(
"Wrong number (< 2) of created particles during the decay of a pion resonance");
479 for(
ParticleIter i=out.begin(), e=out.end(); i!=e; ++i) {
480 if((*i)->isCluster()) clusters.push_back((*i));
482 if(clusters.empty())
return false;
484 for(
ParticleIter i=clusters.begin(), e=clusters.end(); i!=e; ++i) {
487 #ifdef INCLXX_IN_GEANT4_MODE
493 for(
ParticleIter j=decayProducts.begin(), end=decayProducts.end(); j!=end; ++j)
505 for(
ParticleIter j=decayProducts.begin(), e=decayProducts.end(); j!=e; ++j)
516 INCL_WARN(
"Forcing emissions of all pions in the nucleus." <<
'\n');
519 const G4double tinyPionEnergy = 0.1;
524 for(
ParticleIter i=inside.begin(), e=inside.end(); i!=e; ++i) {
527 INCL_DEBUG(
"Forcing emission of the following particle: "
528 << thePion->
print() <<
'\n');
534 if(kineticEnergyOutside > 0.0)
541 toEject.push_back(thePion);
544 for(
ParticleIter i=toEject.begin(), e=toEject.end(); i!=e; ++i) {
556 if(nEventCollisions==0 && nEventDecays==0 && nEventClusters==0)
563 void Nucleus::computeOneNucleonRecoilKinematics() {
584 for(
ParticleIter j=created.begin(), e=created.end(); j!=e; ++j)
592 if(outgoing.size() == 2) {
594 INCL_DEBUG(
"Two particles in the outgoing channel, applying exact two-body kinematics" <<
'\n');
598 Particle *p1 = outgoing.front(), *p2 = outgoing.back();
599 const ThreeVector aBoostVector = incomingMomentum / initialEnergy;
601 p1->boost(aBoostVector);
602 const G4double sqrts = std::sqrt(initialEnergy*initialEnergy - incomingMomentum.
mag2());
604 const G4double scale = pcm/(p1->getMomentum().mag());
606 p1->setMomentum(p1->getMomentum()*scale);
607 p2->setMomentum(-p1->getMomentum());
608 p1->adjustEnergyFromMomentum();
609 p2->adjustEnergyFromMomentum();
611 p1->boost(-aBoostVector);
612 p2->boost(-aBoostVector);
616 INCL_DEBUG(
"Trying to adjust final-state momenta to achieve energy and momentum conservation" <<
'\n');
618 const G4int maxIterations=8;
620 G4double val=1.E+100, oldVal=1.E+100, oldOldVal=1.E+100, oldOldOldVal;
621 ThreeVector totalMomentum, deltaP;
622 std::vector<ThreeVector> minMomenta;
625 minMomenta.reserve(outgoing.size());
628 totalMomentum.setX(0.0);
629 totalMomentum.setY(0.0);
630 totalMomentum.setZ(0.0);
631 for(
ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i)
632 totalMomentum += (*i)->getMomentum();
636 for(
ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i)
637 totalEnergy += (*i)->getEnergy();
640 for(
G4int iterations=0; iterations < maxIterations; ++iterations) {
643 oldOldOldVal = oldOldVal;
647 if(iterations%2 == 0) {
650 deltaP = incomingMomentum - totalMomentum;
652 for(
ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i)
653 pOldTot += (*i)->getMomentum().
mag();
654 for(
ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i) {
655 const ThreeVector mom = (*i)->getMomentum();
656 (*i)->setMomentum(mom + deltaP*mom.mag()/pOldTot);
657 (*i)->adjustEnergyFromMomentum();
662 energyScale = initialEnergy/totalEnergy;
663 for(
ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i) {
664 const ThreeVector mom = (*i)->getMomentum();
665 G4double pScale = ((*i)->getEnergy()*energyScale - std::pow((*i)->getMass(),2))/mom.mag2();
667 (*i)->setEnergy((*i)->getEnergy()*energyScale);
668 (*i)->adjustMomentumFromEnergy();
674 totalMomentum.setX(0.0);
675 totalMomentum.setY(0.0);
676 totalMomentum.setZ(0.0);
678 for(
ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i) {
679 totalMomentum += (*i)->getMomentum();
680 totalEnergy += (*i)->getEnergy();
684 val = std::pow(totalEnergy - initialEnergy,2) +
685 0.25*(totalMomentum - incomingMomentum).mag2();
686 INCL_DEBUG(
"Merit function: val=" << val <<
", oldVal=" << oldVal <<
", oldOldVal=" << oldOldVal <<
", oldOldOldVal=" << oldOldOldVal <<
'\n');
690 INCL_DEBUG(
"New minimum found, storing the particle momenta" <<
'\n');
692 for(
ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i)
693 minMomenta.push_back((*i)->getMomentum());
697 if(val > oldOldVal && oldVal > oldOldOldVal) {
698 INCL_DEBUG(
"Search is diverging, breaking out of the iteration loop: val=" << val <<
", oldVal=" << oldVal <<
", oldOldVal=" << oldOldVal <<
", oldOldOldVal=" << oldOldOldVal <<
'\n');
708 std::vector<ThreeVector>::const_iterator v = minMomenta.begin();
709 for(
ParticleIter i=outgoing.begin(), e=outgoing.end(); i!=e; ++i, ++v) {
710 (*i)->setMomentum(*v);
711 (*i)->adjustEnergyFromMomentum();
721 G4bool isNucleonAbsorption =
false;
723 G4bool isPionAbsorption =
false;
729 isPionAbsorption =
true;
740 if(outgoingParticles.size() == 0 &&
743 isNucleonAbsorption =
true;
750 for(
ParticleIter i=outgoingParticles.begin(), e=outgoingParticles.end(); i!=e; ++i ) {
753 if(isPionAbsorption) {
755 isPionAbsorption =
false;
759 eventInfo->
A[eventInfo->
nParticles] = (*i)->getA();
760 eventInfo->
Z[eventInfo->
nParticles] = (*i)->getZ();
762 eventInfo->
EKin[eventInfo->
nParticles] = (*i)->getKineticEnergy();
770 eventInfo->
history.push_back(
"");
786 if(theProjectileRemnant && theProjectileRemnant->
getA()>0) {
790 if(std::abs(eStar)<1E-10)
794 INCL_WARN(
"Negative excitation energy in projectile-like remnant! EStarRem = " << eventInfo->
EStarRem[eventInfo->
nRemnants] <<
'\n');
821 INCL_WARN(
"Negative excitation energy in target-like remnant! EStarRem = " << eventInfo->
EStarRem[eventInfo->
nRemnants] <<
'\n');
862 theBalance.
Z = theEventInfo.
Zp + theEventInfo.
Zt;
863 theBalance.
A = theEventInfo.
Ap + theEventInfo.
At;
870 for(
ParticleIter i=outgoingParticles.begin(), e=outgoingParticles.end(); i!=e; ++i ) {
871 theBalance.
Z -= (*i)->getZ();
872 theBalance.
A -= (*i)->getA();
875 theBalance.
energy -= (*i)->getEnergy();
876 theBalance.
momentum -= (*i)->getMomentum();
880 if(theProjectileRemnant && theProjectileRemnant->
getA()>0) {
881 theBalance.
Z -= theProjectileRemnant->
getZ();
882 theBalance.
A -= theProjectileRemnant->
getA();
891 theBalance.
Z -=
getZ();
892 theBalance.
A -=
getA();
906 setSpin(incomingAngularMomentum);
913 const G4int prA = theProjectileRemnant->
getA();
917 theProjectileRemnant->
setMass(aMass);
920 const G4double anExcitationEnergy = aMass
Short_t Zp
Charge number of the projectile nucleus.
G4int getA() const
Returns the baryon number.
ConservationBalance getConservationBalance(EventInfo const &theEventInfo, const G4bool afterRecoil) const
Compute charge, mass, energy and momentum balance.
void initializeParticles()
Short_t nRemnants
Number of remnants.
Bool_t nucleonAbsorption
True if the event is a nucleon absorption.
void setMass(G4double mass)
void updatePotentialEnergy(Particle *p) const
Update the particle potential energy.
G4double getFirstCollisionSpectatorMomentum() const
FinalStateValidity getValidity() const
virtual G4double getTableMass() const
Get the real particle mass.
G4double getFirstCollisionSpectatorPosition() const
Simple class implementing De Jong's spin model for nucleus-nucleus collisions.
G4double getMass() const
Get the cached particle mass.
Int_t PDGCode[maxSizeParticles]
PDG numbering of the particles.
Int_t nEnergyViolationInteraction
Number of attempted collisions/decays for which the energy-conservation algorithm failed to find a so...
ParticleList const & getParticles() const
Float_t firstCollisionTime
Time of the first collision [fm/c].
G4int getEmittedClusters() const
G4int getAcceptedCollisions() const
Float_t emissionTime[maxSizeParticles]
Emission time [fm/c].
const ThreeVector & getIncomingMomentum() const
Get the incoming momentum vector.
ParticleList const & getParticles() const
G4double getEmissionTime()
Int_t nCollisions
Number of accepted two-body collisions.
Float_t py[maxSizeParticles]
Particle momentum, y component [MeV/c].
G4bool decayOutgoingClusters()
Force the decay of unstable outgoing clusters.
Float_t firstCollisionXSec
Cross section of the first collision (mb)
ParticleList const & getModifiedParticles() const
void setEmissionTime(G4double t)
Static class for carrying out cluster decays.
void applyFinalState(FinalState *)
const G4double hc
[MeV*fm]
void boost(const ThreeVector &aBoostVector)
const G4INCL::ThreeVector & getMomentum() const
G4double adjustEnergyFromMomentum()
Recompute the energy to match the momentum.
Bool_t forcedCompoundNucleus
True if the event is a forced CN.
Float_t jzRem[maxSizeRemnants]
Remnant angular momentum, z component [ ].
G4bool isDelta() const
Is it a Delta?
std::string print() const
Int_t nBlockedCollisions
Number of two-body collisions blocked by Pauli or CDPP.
Struct for conservation laws.
Bool_t pionAbsorption
True if the event is a pion absorption.
G4double toDegrees(G4double radians)
Float_t EKin[maxSizeParticles]
Particle kinetic energy [MeV].
G4bool hasRemnant() const
Does the nucleus give a cascade remnant?
G4double momentumInCM(Particle const *const p1, Particle const *const p2)
gives the momentum in the CM frame of two particles.
Float_t JRem[maxSizeRemnants]
Remnant spin [ ].
Int_t nReflectionAvatars
Number of reflection avatars.
Float_t EKinRem[maxSizeRemnants]
Remnant kinetic energy [MeV].
G4int getBlockedCollisions() const
void setProtonSeparationEnergy(const G4double s)
Setter for protonSeparationEnergy.
G4double getFirstCollisionTime() const
Float_t pyRem[maxSizeRemnants]
Remnant momentum, y component [MeV/c].
G4double getPotentialEnergy() const
Get the particle potential energy.
Int_t nCollisionAvatars
Number of collision avatars.
Float_t pz[maxSizeParticles]
Particle momentum, z component [MeV/c].
G4double getInvariantMass() const
Get the the particle invariant mass.
Short_t At
Mass number of the target nucleus.
void setEnergy(G4double energy)
Short_t ZRem[maxSizeRemnants]
Remnant charge number.
G4INCL::ThreeVector getAngularMomentum() const
Get the total angular momentum (orbital + spin)
ParticleList const & getOutgoingParticles() const
Short_t ARem[maxSizeRemnants]
Remnant mass number.
ParticleList const & getCreatedParticles() const
Short_t Zt
Charge number of the target nucleus.
G4int getAvatars(AvatarType type) const
void removeScheduledAvatars()
Remove avatars that have been scheduled.
Float_t theta[maxSizeParticles]
Particle momentum polar angle [radians].
void useFusionKinematics()
Adjust the kinematics for complete-fusion events.
G4double getInitialEnergy() const
Get the initial energy.
G4double getSeparationEnergy(const Particle *const p) const
Return the separation energy for a particle.
ParticleList decay(Cluster *const c)
Carries out a cluster decay.
G4bool decayOutgoingDeltas()
Force the decay of outgoing deltas.
ParticleList const & getOutgoingParticles() const
Short_t Z[maxSizeParticles]
Particle charge number.
void setDensity(NuclearDensity const *const d)
Setter for theDensity.
Short_t nParticles
Number of particles in the final state.
G4bool nucleon(G4int ityp)
G4int getBlockedDecays() const
void particleHasBeenDestroyed(Particle *const)
Float_t jxRem[maxSizeRemnants]
Remnant angular momentum, x component [ ].
virtual void initializeParticles()
Initialise the NuclearDensity pointer and sample the particles.
void particleHasBeenEjected(Particle *const)
Float_t pzRem[maxSizeRemnants]
Remnant momentum, z component [MeV/c].
static constexpr double cm
G4int getZ() const
Returns the charge number.
G4bool getPionPotential() const
Do we want the pion potential?
void setPotentialEnergy(G4double v)
Set the particle potential energy.
Float_t EStarRem[maxSizeRemnants]
Remnant excitation energy [MeV].
G4double computeSeparationEnergyBalance() const
Outgoing - incoming separation energies.
G4double getExcitationEnergy() const
Get the excitation energy of the nucleus.
NuclearDensity const * createDensity(const G4int A, const G4int Z)
G4double computeExcitationEnergy() const
Compute the current excitation energy.
Int_t nDecayAvatars
Number of decay avatars.
void deleteProjectileRemnant()
Delete the projectile remnant.
G4INCL::ThreeVector thePosition
G4bool decayMe()
Force the phase-space decay of the Nucleus.
G4int getAcceptedDecays() const
Float_t jyRem[maxSizeRemnants]
Remnant angular momentum, y component [ ].
ParticleSampler * theParticleSampler
Float_t firstCollisionSpectatorPosition
Position of the spectator on the first collision (fm)
Float_t phiRem[maxSizeRemnants]
Remnant momentum azimuthal angle [radians].
G4bool getFirstCollisionIsElastic() const
Int_t nBlockedDecays
Number of decays blocked by Pauli or CDPP.
G4bool hasPionPotential() const
Do we have a pion potential?
ThreeVector computeCenterOfMass() const
Compute the current center-of-mass position.
G4double getTotalEnergyBeforeInteraction() const
G4double getFirstCollisionXSec() const
Float_t pxRem[maxSizeRemnants]
Remnant momentum, x component [MeV/c].
Short_t A[maxSizeParticles]
Particle mass number.
Int_t nDecays
Number of accepted Delta decays.
Bool_t firstCollisionIsElastic
True if the first collision was elastic.
G4double theExcitationEnergy
void particleHasBeenUpdated(Particle *const)
Notify the Store about a particle update.
G4double getWidth(const ParticleType t)
Get particle width (in s)
void propagateParticles(G4double step)
G4bool decayInsideDeltas()
Force the decay of deltas inside the nucleus.
void finalizeProjectileRemnant(const G4double emissionTime)
Finalise the projectile remnant.
PotentialType getPotentialType() const
Get the type of the potential for nucleons.
std::string print() const
void emitInsidePions()
Force emission of all pions inside the nucleus.
G4ThreadLocal NuclearMassFn getTableMass
Static pointer to the mass function for nuclei.
void setTableMass()
Set the mass of the Particle to its table mass.
ParticleList const & getEnteringParticles() const
ParticleList const & getDestroyedParticles() const
void setPotential(NuclearPotential::INuclearPotential const *const p)
Setter for thePotential.
Float_t thetaRem[maxSizeRemnants]
Remnant momentum polar angle [radians].
G4bool isEventTransparent() const
Is the event transparent?
FinalState * getFinalState()
void fillEventInfo(EventInfo *eventInfo)
G4double computeTotalEnergy() const
Compute the current total energy.
G4INCL::ThreeVector theMomentum
ThreeVector const & getSpin() const
Get the spin of the nucleus.
virtual G4double getTableMass() const
Get the tabulated particle mass.
G4double getExcitationEnergy() const
Get the excitation energy of the cluster.
G4double getKineticEnergy() const
Get the particle kinetic energy.
void insertParticle(Particle *p)
Insert a new particle (e.g. a projectile) in the nucleus.
Float_t phi[maxSizeParticles]
Particle momentum azimuthal angle [radians].
G4double getCurrentTime() const
Nucleus(G4int mass, G4int charge, Config const *const conf, const G4double universeRadius=-1.)
G4double getEmissionQValueCorrection(const G4int AParent, const G4int ZParent) const
Computes correction on the emission Q-value.
void computeRecoilKinematics()
Compute the recoil momentum and spin of the nucleus.
INuclearPotential const * createPotential(const PotentialType type, const G4int theA, const G4int theZ, const G4bool pionPotential)
Create an INuclearPotential object.
Float_t firstCollisionSpectatorMomentum
Momentum of the spectator on the first collision (fm)
const ThreeVector & adjustMomentumFromEnergy()
Rescale the momentum to match the total energy.
void addToOutgoing(Particle *p)
add the particle to the outgoing particle list.
G4int getEnergyViolationInteraction() const
Float_t px[maxSizeParticles]
Particle momentum, x component [MeV/c].
Short_t Ap
Mass number of the projectile nucleus.
Short_t nCascadeParticles
Number of cascade particles.
G4bool decayOutgoingPionResonances(G4double timeThreshold)
Force the decay of outgoing PionResonances (eta/omega).
void setExcitationEnergy(const G4double e)
Set the excitation energy of the cluster.
const G4double effectiveNucleonMass
Short_t origin[maxSizeParticles]
Origin of the particle.
#define INCL_DATABLOCK(x)
void setNeutronSeparationEnergy(const G4double s)
Setter for protonSeparationEnergy.
void setSpin(const ThreeVector &j)
Set the spin of the nucleus.
ParticleList::const_iterator ParticleIter
Int_t projectileType
Projectile particle type.
virtual void setMomentum(const G4INCL::ThreeVector &momentum)
std::vector< std::string > history
History of the particle.