Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4INCLParticleEntryChannel.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// INCL++ intra-nuclear cascade model
27// Alain Boudard, CEA-Saclay, France
28// Joseph Cugnon, University of Liege, Belgium
29// Jean-Christophe David, CEA-Saclay, France
30// Pekka Kaitaniemi, CEA-Saclay, France, and Helsinki Institute of Physics, Finland
31// Sylvie Leray, CEA-Saclay, France
32// Davide Mancusi, CEA-Saclay, France
33//
34#define INCLXX_IN_GEANT4_MODE 1
35
36#include "globals.hh"
37
39#include "G4INCLRootFinder.hh"
40#include "G4INCLIntersection.hh"
41#include <algorithm>
45
46namespace G4INCL {
47
49 :theNucleus(n), theParticle(p)
50 {}
51
54
56 // Behaves slightly differency if a third body (the projectile) is present
57 G4bool isNN = theNucleus->isNucleusNucleusCollision();
58
59 /* Corrections to the energy of the entering particle
60 *
61 * In particle-nucleus reactions, the goal of this correction is to satisfy
62 * energy conservation in particle-nucleus reactions using real particle
63 * and nuclear masses.
64 *
65 * In nucleus-nucleus reactions, in addition to the above, the correction
66 * is determined by a model for the excitation energy of the
67 * quasi-projectile (QP). The energy of the entering nucleon is such that
68 * the QP excitation energy, as determined by conservation, is what given
69 * by our model.
70 *
71 * Possible choices for the correction (or, equivalently, for the QP
72 * excitation energy):
73 *
74 * 1. the correction is 0. (same as in particle-nucleus);
75 * 2. the correction is the separation energy of the entering nucleon in
76 * the current QP;
77 * 3. the QP excitation energy is given by A. Boudard's algorithm, as
78 * implemented in INCL4.2-HI/Geant4.
79 * 4. the QP excitation energy vanishes.
80 *
81 * Ideally, the QP excitation energy should always be >=0. Algorithms 1.
82 * and 2. do not guarantee this, although violations to the rule seem to be
83 * more severe for 1. than for 2.. Algorithms 3. and 4., by construction,
84 * yields non-negative QP excitation energies.
85 */
86 G4double theCorrection;
87 if(isNN) {
88// assert(theParticle->isNucleonorLambda() || theParticle->isAntiNucleon()); // Possible hypernucleus projectile of inverse kinematic
89 ProjectileRemnant * const projectileRemnant = theNucleus->getProjectileRemnant();
90// assert(projectileRemnant);
91
92 // No correction (model 1. above)
93 /*
94 theCorrection = theParticle->getEmissionQValueCorrection(
95 theNucleus->getA() + theParticle->getA(),
96 theNucleus->getZ() + theParticle->getZ())
97 + theParticle->getTableMass() - theParticle->getINCLMass();
98 const G4double theProjectileCorrection = 0.;
99 */
100
101 // Correct the energy of the entering particle for the Q-value of the
102 // emission from the projectile (model 2. above)
103 /*
104 theCorrection = theParticle->getTransferQValueCorrection(
105 projectileRemnant->getA(), projectileRemnant->getZ(),
106 theNucleus->getA(), theNucleus->getZ());
107 G4double theProjectileCorrection;
108 if(projectileRemnant->getA()>theParticle->getA()) { // if there are any particles left
109 // Compute the projectile Q-value (to be used as a correction to the
110 // other components of the projectile remnant)
111 theProjectileCorrection = ParticleTable::getTableQValue(
112 projectileRemnant->getA() - theParticle->getA(),
113 projectileRemnant->getZ() - theParticle->getZ(),
114 theParticle->getA(),
115 theParticle->getZ());
116 } else
117 theProjectileCorrection = 0.;
118 */
119
120 // Fix the correction in such a way that the quasi-projectile excitation
121 // energy is given by A. Boudard's INCL4.2-HI model (model 3. above).
122 G4double theProjectileExcitationEnergy = 0;
123 G4double theProjectileEffectiveMass =0;
124 if (theParticle->isNucleonorLambda()){
125 theProjectileExcitationEnergy = (projectileRemnant->getA()-theParticle->getA()>1) ? (projectileRemnant->computeExcitationEnergyExcept(theParticle->getID())) : 0.;
126 theProjectileEffectiveMass =
127 ParticleTable::getTableMass(projectileRemnant->getA() - theParticle->getA(), projectileRemnant->getZ() - theParticle->getZ(), projectileRemnant->getS() - theParticle->getS())
128 + theProjectileExcitationEnergy;
129 }
130 else if (theParticle->isAntiNucleon()){
131 theProjectileExcitationEnergy = (projectileRemnant->getA() -theParticle->getA()<-1) ? (projectileRemnant->computeExcitationEnergyExcept(theParticle->getID())) : 0;
132 theProjectileEffectiveMass =
133 ParticleTable::getTableMass(-(projectileRemnant->getA() - theParticle->getA()), -(projectileRemnant->getZ() - theParticle->getZ()), projectileRemnant->getS() - theParticle->getS())
134 + theProjectileExcitationEnergy;
135 }
136 // Set the projectile excitation energy to zero (cold quasi-projectile,
137 // model 4. above).
138 // const G4double theProjectileExcitationEnergy = 0.;
139 // The part that follows is common to model 3. and 4.
140 const ThreeVector &theProjectileMomentum = projectileRemnant->getMomentum() - theParticle->getMomentum();
141 const G4double theProjectileEnergy = std::sqrt(theProjectileMomentum.mag2() + theProjectileEffectiveMass*theProjectileEffectiveMass);
142 const G4double theProjectileCorrection = theProjectileEnergy - (projectileRemnant->getEnergy() - theParticle->getEnergy());
143 /*if(theParticle->isAntiNucleon()){
144 bool Pvictim=0; //Proton or Neutron is the Victim ?
145 if(((theNucleus->getZ() - theParticle->getZ())- theNucleus->getZ()) == 1)
146 Pvictim = 1;
147 else
148 Pvictim = 0;
149 double theCorrection1 = theParticle->getEmissionPbarQvalueCorrection(theNucleus->getA(), theNucleus->getZ(), Pvictim);
150 double theCorrection2 = theParticle->getEmissionPbarQvalueCorrection(theNucleus->getA(), theNucleus->getZ(), !Pvictim);
151 theCorrection = theParticle->getEmissionPbarQvalueCorrection(theNucleus->getA() - theParticle->getA(), theNucleus->getZ() - theParticle->getZ(),Pvictim)
152 + theParticle->getTableMass() - theParticle->getINCLMass() + theProjectileCorrection;
153 if(Pvictim == 1 && theParticle->getType() == antiNeutron)
154 theCorrection += theCorrection2 - theCorrection1;
155 else if(Pvictim == 0 && theParticle->getType()==antiProton)
156 theCorrection += theCorrection2 - theCorrection1;
157 theCorrection = theParticle->getEmissionQValueCorrection(
158 theNucleus->getA() + theParticle->getA(),
159 theNucleus->getZ() + theParticle->getZ(),
160 theNucleus->getS() + theParticle->getS())
161 + theParticle->getTableMass() - theParticle->getINCLMass()
162 + theProjectileCorrection << std::endl;
163 }*/
164 //else
165 theCorrection = theParticle->getEmissionQValueCorrection(
166 theNucleus->getA() + theParticle->getA(),
167 theNucleus->getZ() + theParticle->getZ(),
168 theNucleus->getS() + theParticle->getS())
169 + theParticle->getTableMass() - theParticle->getINCLMass()
170 + theProjectileCorrection;
171 // end of part common to model 3. and 4.
172
173
174 projectileRemnant->removeParticle(theParticle, theProjectileCorrection);
175 } else {
176 const G4int ACN = theNucleus->getA() + theParticle->getA();
177 const G4int ZCN = theNucleus->getZ() + theParticle->getZ();
178 const G4int SCN = theNucleus->getS() + theParticle->getS();
179 // Correction to the Q-value of the entering particle
180 theCorrection = theParticle->getEmissionQValueCorrection(ACN,ZCN,SCN);
181 INCL_DEBUG("The following Particle enters with correction " << theCorrection << '\n'
182 << theParticle->print() << '\n');
183 }
184
185 const G4double energyBefore = theParticle->getEnergy() - theCorrection;
186 G4bool success;
187 if(isNN && theParticle->isAntiNucleon() && (theParticle->getEnergy() - theCorrection <=theParticle->getINCLMass()) ){
188 success =true;
189 G4double energyInside = theParticle->getEnergy() + theNucleus->getPotential()->computePotentialEnergy(theParticle) - theCorrection;
190 theParticle->setEnergy(energyInside);
191 theParticle->setPotentialEnergy(theNucleus->getPotential()->computePotentialEnergy(theParticle));
192 theParticle->setMomentum(theParticle->getMomentum());
193 theParticle->adjustMomentumFromEnergy();
194 }
195 else{
196 success = particleEnters(theCorrection);
197 }
198 fs->addEnteringParticle(theParticle);
199
200 if(!success) {
202 } else if(theParticle->isNucleonorLambda() &&
203 theParticle->getKineticEnergy()<theNucleus->getPotential()->getFermiEnergy(theParticle)) {
204 // If the participant is a nucleon entering below its Fermi energy, force a
205 // compound nucleus
207 } else if(theParticle->isKaon()) theNucleus->setNumberOfKaon(theNucleus->getNumberOfKaon()+1);
208
209 fs->setTotalEnergyBeforeInteraction(energyBefore);
210 }
211
212 G4bool ParticleEntryChannel::particleEnters(const G4double theQValueCorrection) {
213
214 // \todo{this is the place to add refraction}
215
216 theParticle->setINCLMass(); // Will automatically put the particle on shell
217
218 // Add the nuclear potential to the kinetic energy when entering the
219 // nucleus
220
221 class IncomingEFunctor : public RootFunctor {
222 public:
223 IncomingEFunctor(Particle * const p, Nucleus const * const n, const G4double correction) :
224 RootFunctor(0., 1E6),
225 theParticle(p),
226 thePotential(n->getPotential()),
227 theEnergy(theParticle->getEnergy()),
228 theMass(theParticle->getMass()),
229 theQValueCorrection(correction),
230 refraction(n->getStore()->getConfig()->getRefraction()),
231 theMomentumDirection(theParticle->getMomentum())
232 {
233 if(refraction) {
234 const ThreeVector &position = theParticle->getPosition();
235 const G4double r2 = position.mag2();
236 if(r2>0.)
237 normal = - position / std::sqrt(r2);
238 G4double cosIncidenceAngle = theParticle->getCosRPAngle();
239 if(cosIncidenceAngle < -1.)
240 sinIncidenceAnglePOut = 0.;
241 else
242 sinIncidenceAnglePOut = theMomentumDirection.mag()*std::sqrt(1.-cosIncidenceAngle*cosIncidenceAngle);
243 } else {
244 sinIncidenceAnglePOut = 0.;
245 }
246 }
247 ~IncomingEFunctor() {}
248 G4double operator()(const G4double v) const {
249 G4double energyInside = std::max(theMass, theEnergy + v - theQValueCorrection);
250 theParticle->setEnergy(energyInside);
251 theParticle->setPotentialEnergy(v);
252 if(refraction) {
253 // Compute the new direction of the particle momentum
254 const G4double pIn = std::sqrt(energyInside*energyInside-theMass*theMass);
255 const G4double sinRefractionAngle = sinIncidenceAnglePOut/pIn;
256 const G4double cosRefractionAngle = (sinRefractionAngle>1.) ? 0. : std::sqrt(1.-sinRefractionAngle*sinRefractionAngle);
257 const ThreeVector momentumInside = theMomentumDirection - normal * normal.dot(theMomentumDirection) + normal * (pIn * cosRefractionAngle);
258 theParticle->setMomentum(momentumInside);
259 } else {
260 theParticle->setMomentum(theMomentumDirection); // keep the same direction
261 }
262 // Scale the particle momentum
263 theParticle->adjustMomentumFromEnergy();
264 return v - thePotential->computePotentialEnergy(theParticle);
265 }
266 void cleanUp(const G4bool /*success*/) const {}
267 private:
268 Particle *theParticle;
269 NuclearPotential::INuclearPotential const *thePotential;
270 const G4double theEnergy;
271 const G4double theMass;
272 const G4double theQValueCorrection;
273 const G4bool refraction;
274 const ThreeVector theMomentumDirection;
275 ThreeVector normal;
276 G4double sinIncidenceAnglePOut;
277 } theIncomingEFunctor(theParticle,theNucleus,theQValueCorrection);
278
279 G4double v = theNucleus->getPotential()->computePotentialEnergy(theParticle);
280 if(theParticle->getKineticEnergy()+v-theQValueCorrection<0.) { // Particle entering below 0. Die gracefully
281 INCL_DEBUG("Particle " << theParticle->getID() << " is trying to enter below 0" << '\n');
282 return false;
283 }
284 const RootFinder::Solution theSolution = RootFinder::solve(&theIncomingEFunctor, v);
285 if(theSolution.success) { // Apply the solution
286 theIncomingEFunctor(theSolution.x);
287 INCL_DEBUG("Particle successfully entered:\n" << theParticle->print() << '\n');
288 } else {
289 INCL_WARN("Couldn't compute the potential for incoming particle, root-finding algorithm failed." << '\n');
290 }
291 return theSolution.success;
292 }
293
294}
295
Simple class for computing intersections between a straight line and a sphere.
#define INCL_WARN(x)
#define INCL_DEBUG(x)
Static root-finder algorithm.
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
void addEnteringParticle(Particle *p)
void setTotalEnergyBeforeInteraction(G4double E)
ParticleEntryChannel(Nucleus *n, Particle *p)
G4int getS() const
Returns the strangeness number.
G4double getEnergy() const
G4int getZ() const
Returns the charge number.
void setINCLMass()
Set the mass of the Particle to its table mass.
const G4INCL::ThreeVector & getMomentum() const
G4int getA() const
Returns the baryon number.
void removeParticle(Particle *const p, const G4double theProjectileCorrection)
Remove a nucleon from the projectile remnant.
G4double computeExcitationEnergyExcept(const long exceptID) const
Compute the excitation energy when a nucleon is removed.
G4double mag2() const
G4ThreadLocal NuclearMassFn getTableMass
Static pointer to the mass function for nuclei.
Solution solve(RootFunctor const *const f, const G4double x0)
Numerically solve a one-dimensional equation.