35#define INCLXX_IN_GEANT4_MODE 1
46#ifndef G4INCLNucleus_hh
47#define G4INCLNucleus_hh 1
72 theInitialZ(charge), theInitialA(mass),
73 theNpInitial(0), theNnInitial(0),
74 initialInternalEnergy(0.),
75 incomingAngularMomentum(0.,0.,0.), incomingMomentum(0.,0.,0.),
76 initialCenterOfMass(0.,0.,0.),
81 forceTransparent(false),
84 theUniverseRadius(universeRadius),
85 isNucleusNucleus(false),
86 theProjectileRemnant(NULL),
100 switch(potentialType) {
114 FATAL(
"Unrecognized potential type at Nucleus creation." << std::endl);
115 std::exit(EXIT_FAILURE);
127 if(theUniverseRadius<0)
129 theStore =
new Store(conf);
142 delete theProjectileRemnant;
143 theProjectileRemnant = NULL;
156 std::stringstream ss;
157 ss <<
"(list ;; List of participants " << std::endl;
159 for(
ParticleIter i = participants.begin(); i != participants.end(); ++i) {
160 ss <<
"(make-particle-avatar-map " << std::endl
162 <<
"(list ;; List of avatars in this particle" << std::endl
163 <<
")) ;; Close the list of avatars and the particle-avatar-map" << std::endl;
165 ss <<
")" << std::endl;
179 for(
ParticleIter iter = created.begin(); iter != created.end(); ++iter) {
180 theStore->
add((*iter));
181 if(!(*iter)->isOutOfWell()) {
182 totalEnergy += (*iter)->getEnergy() - (*iter)->getPotentialEnergy();
183 justCreated.push_back((*iter));
193 for(
ParticleIter iter = modified.begin(); iter != modified.end(); ++iter) {
195 totalEnergy += (*iter)->getEnergy() - (*iter)->getPotentialEnergy();
196 toBeUpdated.push_back((*iter));
200 for(
ParticleIter iter = out.begin(); iter != out.end(); ++iter) {
201 if((*iter)->isCluster()) {
204 for(
ParticleIter in = components.begin(); in != components.end(); ++in)
209 totalEnergy += (*iter)->getEnergy();
210 theA -= (*iter)->getA();
211 theZ -= (*iter)->getZ();
217 for(
ParticleIter iter = entering.begin(); iter != entering.end(); ++iter) {
219 totalEnergy += (*iter)->getEnergy() - (*iter)->getPotentialEnergy();
220 toBeUpdated.push_back((*iter));
225 DEBUG(
"A Particle is entering below the Fermi sea:" << std::endl << finalstate->
print() << std::endl);
228 for(
ParticleIter iter = entering.begin(); iter != entering.end(); ++iter) {
232 DEBUG(
"A Particle is entering below zero energy:" << std::endl << finalstate->
print() << std::endl);
233 forceTransparent =
true;
235 for(
ParticleIter iter = entering.begin(); iter != entering.end(); ++iter) {
242 ERROR(
"Energy nonconservation! Energy at the beginning of the event = "
244 <<
" and after interaction = "
245 << totalEnergy << std::endl
246 << finalstate->
print());
251 WARN(
"Useless Nucleus::propagateParticles -method called." << std::endl);
257 for(
ParticleIter p=inside.begin(); p!=inside.end(); ++p) {
258 if((*p)->isNucleon())
259 totalEnergy += (*p)->getKineticEnergy() - (*p)->getPotentialEnergy();
260 else if((*p)->isResonance())
263 totalEnergy += (*p)->getEnergy() - (*p)->getPotentialEnergy();
273 computeOneNucleonRecoilKinematics();
280 theSpin = incomingAngularMomentum;
283 for(
ParticleIter p=outgoing.begin(); p!=outgoing.end(); ++p)
286 theSpin -= (*p)->getAngularMomentum();
302 for(
ParticleIter p=inside.begin(); p!=inside.end(); ++p) {
303 const G4double mass = (*p)->getMass();
304 cm += (*p)->getPosition() * mass;
315 return totalEnergy - initialInternalEnergy - separationEnergies;
320 std::stringstream ss;
321 ss <<
"Particles in the nucleus:" << std::endl
322 <<
"Participants:" << std::endl;
325 for(
ParticleIter p = participants.begin(); p != participants.end(); ++p) {
326 ss <<
"index = " << counter << std::endl
330 ss <<
"Spectators:" << std::endl;
332 for(
ParticleIter p = spectators.begin(); p != spectators.end(); ++p)
334 ss <<
"Outgoing:" << std::endl;
336 for(
ParticleIter p = outgoing.begin(); p != outgoing.end(); ++p)
345 for(
ParticleIter i = out.begin(); i != out.end(); ++i) {
346 if((*i)->isDelta()) deltas.push_back((*i));
348 if(deltas.empty())
return false;
350 for(
ParticleIter i = deltas.begin(); i != deltas.end(); ++i) {
351 DEBUG(
"Decay outgoing delta particle:" << std::endl
352 << (*i)->print() << std::endl);
354 const G4double deltaMass = (*i)->getMass();
359 (*i)->setEnergy((*i)->getMass());
372 newMomentum *= decayMomentum / newMomentum.
mag();
384 nucleon->
boost(beta);
403 const G4bool unphysicalRemnant = (theZ<0 || theZ>
theA);
410 for(
ParticleIter i = inside.begin(); i != inside.end(); ++i)
411 if((*i)->isDelta()) deltas.push_back((*i));
414 for(
ParticleIter i = deltas.begin(); i != deltas.end(); ++i) {
415 DEBUG(
"Decay inside delta particle:" << std::endl
416 << (*i)->print() << std::endl);
422 if(unphysicalRemnant)
440 if(unphysicalRemnant) {
441 DEBUG(
"Remnant is unphysical: Z=" <<
theZ <<
", A=" <<
theA << std::endl);
451 for(
ParticleIter i = out.begin(); i != out.end(); ++i) {
452 if((*i)->isCluster()) clusters.push_back((*i));
454 if(clusters.empty())
return false;
456 for(
ParticleIter i = clusters.begin(); i != clusters.end(); ++i) {
460 for(
ParticleIter j = decayProducts.begin(); j!=decayProducts.end(); ++j)
472 for(
ParticleIter j = decayProducts.begin(); j!=decayProducts.end(); ++j)
483 WARN(
"Forcing emissions of all pions in the nucleus." << std::endl);
486 const G4double tinyPionEnergy = 0.1;
490 for(
ParticleIter i = inside.begin(); i != inside.end(); ++i) {
494 const G4double theQValueCorrection = (*i)->getEmissionQValueCorrection(
theA,
theZ);
495 const G4double kineticEnergyOutside = (*i)->getKineticEnergy() - (*i)->getPotentialEnergy() + theQValueCorrection;
496 (*i)->setTableMass();
497 if(kineticEnergyOutside > 0.0)
498 (*i)->setEnergy((*i)->getMass()+kineticEnergyOutside);
500 (*i)->setEnergy((*i)->getMass()+tinyPionEnergy);
501 (*i)->adjustMomentumFromEnergy();
502 (*i)->setPotentialEnergy(0.);
503 theZ -= (*i)->getZ();
517 G4int outZ = 0, outA = 0;
522 if( (*p)->getNumberOfCollisions() != 0 )
return false;
523 if( (*p)->getNumberOfDecays() != 0 )
return false;
524 outZ += (*p)->getZ();
525 outA += (*p)->getA();
529 if(theProjectileRemnant) {
530 outZ += theProjectileRemnant->
getZ();
531 outA += theProjectileRemnant->
getA();
534 if(outZ!=projectileZ || outA!=projectileA)
return false;
540 void Nucleus::computeOneNucleonRecoilKinematics() {
544 ERROR(
"Computing one-nucleon recoil kinematics. We should never be here nowadays, cascade should stop earlier than this." << std::endl);
563 for(
ParticleIter j = created.begin(); j != created.end(); ++j)
571 if(outgoing.size() == 2) {
573 DEBUG(
"Two particles in the outgoing channel, applying exact two-body kinematics" << std::endl);
577 Particle *p1 = outgoing.front(), *p2 = outgoing.back();
578 const ThreeVector aBoostVector = incomingMomentum / initialEnergy;
580 p1->boost(aBoostVector);
581 const G4double sqrts = std::sqrt(initialEnergy*initialEnergy - incomingMomentum.
mag2());
583 const G4double scale = pcm/(p1->getMomentum().mag());
585 p1->setMomentum(p1->getMomentum()*scale);
586 p2->setMomentum(-p1->getMomentum());
587 p1->adjustEnergyFromMomentum();
588 p2->adjustEnergyFromMomentum();
590 p1->boost(-aBoostVector);
591 p2->boost(-aBoostVector);
595 DEBUG(
"Trying to adjust final-state momenta to achieve energy and momentum conservation" << std::endl);
597 const G4int maxIterations=8;
599 G4double val=1.E+100, oldVal=1.E+100, oldOldVal=1.E+100, oldOldOldVal;
600 ThreeVector totalMomentum, deltaP;
601 std::vector<ThreeVector> minMomenta;
604 minMomenta.reserve(outgoing.size());
607 totalMomentum.setX(0.0);
608 totalMomentum.setY(0.0);
609 totalMomentum.setZ(0.0);
610 for(
ParticleIter i=outgoing.begin(); i!=outgoing.end(); ++i)
611 totalMomentum += (*i)->getMomentum();
615 for(
ParticleIter i=outgoing.begin(); i!=outgoing.end(); ++i)
616 totalEnergy += (*i)->getEnergy();
619 for(
G4int iterations=0; iterations < maxIterations; ++iterations) {
622 oldOldOldVal = oldOldVal;
626 if(iterations%2 == 0) {
627 DEBUG(
"Momentum step" << std::endl);
629 deltaP = incomingMomentum - totalMomentum;
631 for(
ParticleIter i=outgoing.begin(); i!=outgoing.end(); ++i)
632 pOldTot += (*i)->getMomentum().
mag();
633 for(
ParticleIter i=outgoing.begin(); i!=outgoing.end(); ++i) {
634 const ThreeVector mom = (*i)->getMomentum();
635 (*i)->setMomentum(mom + deltaP*mom.mag()/pOldTot);
636 (*i)->adjustEnergyFromMomentum();
639 DEBUG(
"Energy step" << std::endl);
641 energyScale = initialEnergy/totalEnergy;
642 for(
ParticleIter i=outgoing.begin(); i!=outgoing.end(); ++i) {
643 const ThreeVector mom = (*i)->getMomentum();
644 G4double pScale = ((*i)->getEnergy()*energyScale - std::pow((*i)->getMass(),2))/mom.mag2();
646 (*i)->setEnergy((*i)->getEnergy()*energyScale);
647 (*i)->adjustMomentumFromEnergy();
653 totalMomentum.setX(0.0);
654 totalMomentum.setY(0.0);
655 totalMomentum.setZ(0.0);
657 for(
ParticleIter i=outgoing.begin(); i!=outgoing.end(); ++i) {
658 totalMomentum += (*i)->getMomentum();
659 totalEnergy += (*i)->getEnergy();
663 val = std::pow(totalEnergy - initialEnergy,2) +
664 0.25*(totalMomentum - incomingMomentum).mag2();
665 DEBUG(
"Merit function: val=" << val <<
", oldVal=" << oldVal <<
", oldOldVal=" << oldOldVal <<
", oldOldOldVal=" << oldOldOldVal << std::endl);
669 DEBUG(
"New minimum found, storing the particle momenta" << std::endl);
671 for(
ParticleIter i=outgoing.begin(); i!=outgoing.end(); ++i)
672 minMomenta.push_back((*i)->getMomentum());
676 if(val > oldOldVal && oldVal > oldOldOldVal) {
677 DEBUG(
"Search is diverging, breaking out of the iteration loop: val=" << val <<
", oldVal=" << oldVal <<
", oldOldVal=" << oldOldVal <<
", oldOldOldVal=" << oldOldOldVal << std::endl);
686 DEBUG(
"Applying the solution" << std::endl);
687 std::vector<ThreeVector>::const_iterator v = minMomenta.begin();
688 for(
ParticleIter i=outgoing.begin(); i!=outgoing.end(); ++i, ++v) {
689 (*i)->setMomentum(*v);
690 (*i)->adjustEnergyFromMomentum();
700 G4bool isNucleonAbsorption =
false;
702 G4bool isPionAbsorption =
false;
708 isPionAbsorption =
true;
719 if(outgoingParticles.size() == 0 &&
722 isNucleonAbsorption =
true;
729 for(
ParticleIter i = outgoingParticles.begin(); i != outgoingParticles.end(); ++i ) {
731 if((*i)->isCluster()) {
734#ifdef INCLXX_IN_GEANT4_MODE
739 if(std::abs(eStar)>1E-10) {
741 WARN(
"Negative excitation energy in outgoing cluster! EStar = " << eStar << std::endl);
753 remnantSpin *= remnantSpinMag/remnantSpin.
mag();
772 if(isPionAbsorption) {
774 isPionAbsorption =
false;
777 eventInfo->
A[eventInfo->
nParticles] = (*i)->getA();
778 eventInfo->
Z[eventInfo->
nParticles] = (*i)->getZ();
780 eventInfo->
EKin[eventInfo->
nParticles] = (*i)->getKineticEnergy();
788 eventInfo->
history.push_back(
"");
801 WARN(
"Negative excitation energy! EStarRem = " << eventInfo->
EStarRem[eventInfo->
nRemnants] << std::endl);
833 theBalance.
Z = theEventInfo.
Zp + theEventInfo.
Zt;
834 theBalance.
A = theEventInfo.
Ap + theEventInfo.
At;
841 for(
ParticleIter i = outgoingParticles.begin(); i != outgoingParticles.end(); ++i ) {
842 theBalance.
Z -= (*i)->getZ();
843 theBalance.
A -= (*i)->getA();
846 theBalance.
energy -= (*i)->getEnergy();
847 theBalance.
momentum -= (*i)->getMomentum();
852 theBalance.
Z -=
getZ();
853 theBalance.
A -=
getA();
867 setSpin(incomingAngularMomentum);
874 if(theProjectileRemnant->
getA()>1) {
877 theProjectileRemnant->
setMass(aMass);
880 const G4double anExcitationEnergy = aMass
896 theProjectileRemnant = NULL;
897 }
else if(theProjectileRemnant->
getA()==1) {
Static class for carrying out cluster decays.
Simple class implementing De Jong's spin model for nucleus-nucleus collisions.
Isospin- and energy-independent nuclear potential.
Isospin- and energy-dependent nuclear potential.
Isospin- and energy-dependent nuclear potential.
Isospin-dependent nuclear potential.
G4int getAcceptedDecays() const
G4double getFirstCollisionTime()
G4int getAvatars(AvatarType type) const
G4int getAcceptedCollisions() const
G4int getBlockedCollisions() const
G4double getCurrentTime()
G4double getFirstCollisionXSec()
G4int getBlockedDecays() const
static ParticleList decay(Cluster *const c)
Carries out a cluster decay.
ThreeVector const & getSpin() const
Get the spin of the nucleus.
ParticleList const & getParticles() const
void setExcitationEnergy(const G4double e)
Set the excitation energy of the cluster.
void setSpin(const ThreeVector &j)
Set the spin of the nucleus.
virtual void initializeParticles()
Initialise the NuclearDensity pointer and sample the particles.
ParticleSampler * theParticleSampler
G4double getExcitationEnergy() const
Get the excitation energy of the cluster.
virtual G4double getTableMass() const
Get the real particle mass.
G4double theExcitationEnergy
G4bool getPionPotential() const
Do we want the pion potential?
PotentialType getPotentialType() const
Get the type of the potential for nucleons.
static ThreeVector shoot(const G4int Ap, const G4int Af)
ParticleList const & getOutgoingParticles() const
ParticleList const & getEnteringParticles() const
std::string print() const
ParticleList const & getModifiedParticles() const
FinalStateValidity getValidity() const
Particle * getBlockedDelta()
ParticleList const & getDestroyedParticles() const
G4double getTotalEnergyBeforeInteraction() const
ParticleList const & getCreatedParticles() const
G4INCL::FinalState * getFinalState()
static G4double momentumInCM(Particle const *const p1, Particle const *const p2)
gives the momentum in the CM frame of two particles.
static NuclearDensity * createDensity(const G4int A, const G4int Z)
G4double getMaximumRadius() const
G4double getSeparationEnergy(const Particle *const p) const
Return the separation energy for a particle.
G4bool hasPionPotential()
Do we have a pion potential?
G4double computeSeparationEnergyBalance() const
Outgoing - incoming separation energies.
void fillEventInfo(EventInfo *eventInfo)
G4bool decayMe()
Force the phase-space decay of the Nucleus.
G4double computeTotalEnergy() const
Compute the current total energy.
G4bool decayInsideDeltas()
Force the decay of deltas inside the nucleus.
void computeRecoilKinematics()
Compute the recoil momentum and spin of the nucleus.
void finalizeProjectileRemnant(const G4double emissionTime)
Finalise the projectile remnant.
G4bool isEventTransparent() const
Is the event transparent?
void applyFinalState(FinalState *)
void insertParticle(Particle *p)
Insert a new particle (e.g. a projectile) in the nucleus.
void deleteProjectileRemnant()
Delete the projectile remnant.
void useFusionKinematics()
Adjust the kinematics for complete-fusion events.
void updatePotentialEnergy(Particle *p)
Update the particle potential energy.
const ThreeVector & getIncomingMomentum() const
Get the incoming momentum vector.
void emitInsidePions()
Force emission of all pions inside the nucleus.
G4double getInitialEnergy() const
Get the initial energy.
ThreeVector computeCenterOfMass() const
Compute the current center-of-mass position.
G4bool decayOutgoingClusters()
Force the decay of unstable outgoing clusters.
G4double getExcitationEnergy() const
Get the excitation energy of the nucleus.
void propagateParticles(G4double step)
ConservationBalance getConservationBalance(EventInfo const &theEventInfo, const G4bool afterRecoil) const
Compute charge, mass, energy and momentum balance.
void initializeParticles()
G4bool hasRemnant() const
Does the nucleus give a cascade remnant?
G4double computeExcitationEnergy() const
Compute the current excitation energy.
Nucleus(G4int mass, G4int charge, Config const *const conf, const G4double universeRadius=-1.)
G4bool decayOutgoingDeltas()
Force the decay of outgoing deltas.
void setPotential(NuclearPotential::INuclearPotential const *const p)
Setter for thePotential.
void setDensity(NuclearDensity const *const d)
Setter for theDensity.
static NuclearMassFn getTableMass
Static pointer to the mass function for nuclei.
static void setNeutronSeparationEnergy(const G4double s)
Setter for protonSeparationEnergy.
static void setProtonSeparationEnergy(const G4double s)
Setter for protonSeparationEnergy.
static const G4double effectiveNucleonMass
G4INCL::ThreeVector theMomentum
void setMass(G4double mass)
G4int getZ() const
Returns the charge number.
G4double getKineticEnergy() const
Get the particle kinetic energy.
void setEmissionTime(G4double t)
G4double adjustEnergyFromMomentum()
Recompute the energy to match the momentum.
const G4INCL::ThreeVector & getMomentum() const
virtual void setMomentum(const G4INCL::ThreeVector &momentum)
virtual G4double getTableMass() const
Get the tabulated particle mass.
G4double getInvariantMass() const
Get the the particle invariant mass.
void setEnergy(G4double energy)
void boost(const ThreeVector &aBoostVector)
void setTableMass()
Set the mass of the Particle to its table mass.
G4bool isDelta() const
Is it a Delta?
G4int getA() const
Returns the baryon number.
G4INCL::ThreeVector thePosition
G4int getNumberStoredComponents() const
Get the number of the stored components.
void particleHasBeenDestroyed(long)
void particleHasBeenEjected(long)
ParticleList const & getOutgoingParticles() const
void particleHasBeenUpdated(long)
void addToOutgoing(Particle *p)
add the particle to the outgoing particle list.
ParticleList const & getParticles() const
ParticleList getSpectators()
ParticleList getParticipants()
G4double toDegrees(G4double radians)
const G4double hc
[MeV*fm]
std::list< G4INCL::Particle * > ParticleList
@ IsospinEnergySmoothPotential
std::list< G4INCL::Particle * >::const_iterator ParticleIter
Bool_t pionAbsorption
True if the event is absorption.
Int_t nCollisionAvatars
Number of collision avatars.
Short_t origin[maxSizeParticles]
Origin of the particle.
Short_t At
Mass number of the target nucleus.
Short_t Zp
Charge number of the projectile nucleus.
Int_t nDecays
Number of accepted Delta decays.
Short_t nCascadeParticles
Number of cascade particles.
Float_t theta[maxSizeParticles]
Particle momentum polar angle [radians].
Short_t A[maxSizeParticles]
Particle mass number.
Float_t EKinRem[maxSizeRemnants]
Remnant kinetic energy [MeV].
Float_t jzRem[maxSizeRemnants]
Remnant angular momentum, z component [hbar].
Bool_t nucleonAbsorption
True if the event is absorption.
Float_t emissionTime[maxSizeParticles]
Emission time [fm/c].
Float_t EStarRem[maxSizeRemnants]
Remnant excitation energy [MeV].
Float_t phi[maxSizeParticles]
Particle momentum azimuthal angle [radians].
Short_t Ap
Mass number of the projectile nucleus.
Short_t Z[maxSizeParticles]
Particle charge number.
Bool_t forcedCompoundNucleus
True if the event is a forced CN.
Float_t JRem[maxSizeRemnants]
Remnant spin [ ].
Float_t thetaRem[maxSizeRemnants]
Remnant momentum polar angle [radians].
std::vector< std::string > history
History of the particle.
Float_t EKin[maxSizeParticles]
Particle kinetic energy [MeV].
Float_t jxRem[maxSizeRemnants]
Remnant angular momentum, x component [hbar].
Int_t nBlockedDecays
Number of decays blocked by Pauli or CDPP.
Float_t px[maxSizeParticles]
Particle momentum, x component [MeV/c].
Float_t pxRem[maxSizeRemnants]
Remnant momentum, x component [MeV/c].
Float_t pyRem[maxSizeRemnants]
Remnant momentum, y component [MeV/c].
Float_t firstCollisionTime
Time of the first collision [fm/c].
Short_t Zt
Charge number of the target nucleus.
Int_t nParticles
Total number of emitted particles.
Float_t phiRem[maxSizeRemnants]
Remnant momentum azimuthal angle [radians].
ParticleType projectileType
Protjectile particle type.
Float_t pzRem[maxSizeRemnants]
Remnant momentum, z component [MeV/c].
Float_t pz[maxSizeParticles]
Particle momentum, z component [MeV/c].
Int_t nCollisions
Number of accepted two-body collisions.
Int_t nRemnants
Number of remnants.
Int_t nBlockedCollisions
Number of two-body collisions blocked by Pauli or CDPP.
Float_t jyRem[maxSizeRemnants]
Remnant angular momentum, y component [hbar].
Float_t py[maxSizeParticles]
Particle momentum, y component [MeV/c].
Short_t ARem[maxSizeRemnants]
Remnant mass number.
Short_t ZRem[maxSizeRemnants]
Remnant charge number.
Float_t firstCollisionXSec
Cross section of the first collision (mb)
Int_t nDecayAvatars
Number of decay avatars.
Struct for conservation laws.