Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4INCLInteractionAvatar.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// Pekka Kaitaniemi, CEA and Helsinki Institute of Physics
28// Davide Mancusi, CEA
29// Alain Boudard, CEA
30// Sylvie Leray, CEA
31// Joseph Cugnon, University of Liege
32//
33// INCL++ revision: v5.1.8
34//
35#define INCLXX_IN_GEANT4_MODE 1
36
37#include "globals.hh"
38
39/* \file G4INCLInteractionAvatar.cc
40 * \brief Virtual class for interaction avatars.
41 *
42 * This class is inherited by decay and collision avatars. The goal is to
43 * provide a uniform treatment of common physics, such as Pauli blocking,
44 * enforcement of energy conservation, etc.
45 *
46 * \date Mar 1st, 2011
47 * \author Davide Mancusi
48 */
49
54#include "G4INCLRootFinder.hh"
55#include "G4INCLLogger.hh"
56#include "G4INCLConfigEnums.hh"
57// #include <cassert>
58
59namespace G4INCL {
60
63
65 : IAvatar(time), theNucleus(n),
66 particle1(p1), particle2(NULL), isPiN(false)
67 {
68 }
69
72 : IAvatar(time), theNucleus(n),
73 particle1(p1), particle2(p2),
74 isPiN((p1->isPion() && p2->isNucleon()) || (p2->isPion() && p1->isNucleon()))
75 {
76 }
77
79 }
80
89
90 if(particle2) {
101 } else {
103 }
104 }
105
107 if(!theNucleus || p->isPion()) return; // Local energy does not make any sense without a nucleus
108
111 }
112
115
117
118 if(particle2) {
120 if(!isPiN) {
123 }
124 } else {
126 }
127 if(!isPiN)
129 }
130
132 ThreeVector pos = p->getPosition();
133 G4double pos2 = pos.mag2();
135 short iterations=0;
136 const short maxIterations=50;
137
138 if(pos2 < r*r) return true;
139
140 while( pos2 >= r*r && iterations<maxIterations )
141 {
142 pos *= std::sqrt(r*r*0.99/pos2);
143 pos2 = pos.mag2();
144 iterations++;
145 }
146 if( iterations < maxIterations)
147 {
148 DEBUG("Particle position vector length was : " << p->getPosition().mag() << ", rescaled to: " << pos.mag() << std::endl);
149 p->setPosition(pos);
150 return true;
151 }
152 else
153 return false;
154 }
155
157 ParticleList modified = fs->getModifiedParticles();
158 ParticleList modifiedAndCreated = modified;
159 ParticleList created = fs->getCreatedParticles();
160 modifiedAndCreated.insert(modifiedAndCreated.end(), created.begin(), created.end());
161
162 if(!isPiN) {
163 // Boost back to lab
164 for( ParticleIter i = modifiedAndCreated.begin(); i != modifiedAndCreated.end(); ++i )
165 (*i)->boost(-boostVector);
166 }
167
168 // If there is no Nucleus, just return
169 if(!theNucleus) return fs;
170
171 // Mark pions that have been created outside their well (we will force them
172 // to be emitted later).
173 for( ParticleIter i = created.begin(); i != created.end(); ++i )
174 if((*i)->isPion() && (*i)->getPosition().mag() > theNucleus->getSurfaceRadius(*i)) {
175 (*i)->makeParticipant();
176 (*i)->setOutOfWell();
177 fs->addOutgoingParticle(*i);
178 DEBUG("Pion was created outside its potential well." << std::endl
179 << (*i)->print());
180 }
181
182 // Try to enforce energy conservation
184 G4bool success = true;
186 success = enforceEnergyConservation(fs);
187 if(!success) {
188 DEBUG("Enforcing energy conservation: failed!" << std::endl);
189
190 // Restore the state of the initial particles
192
193 // Delete newly created particles
194 for( ParticleIter i = created.begin(); i != created.end(); ++i )
195 delete *i;
196
197 FinalState *fsBlocked = new FinalState;
198 delete fs;
199 fsBlocked->makeNoEnergyConservation();
200 fsBlocked->setTotalEnergyBeforeInteraction(0.0);
201
202 return fsBlocked; // Interaction is blocked. Return an empty final state.
203 }
204 DEBUG("Enforcing energy conservation: success!" << std::endl);
205
206 // Check that outgoing delta resonances can decay to pi-N
207 for( ParticleIter i = modified.begin(); i != modified.end(); ++i )
208 if((*i)->isDelta() &&
210 DEBUG("Mass of the produced delta below decay threshold; forbidding collision. deltaMass=" <<
211 (*i)->getMass() << std::endl);
212
213 // Restore the state of the initial particles
215
216 // Delete newly created particles
217 for( ParticleIter j = created.begin(); j != created.end(); ++j )
218 delete *j;
219
220 FinalState *fsBlocked = new FinalState;
221 delete fs;
222 fsBlocked->makeNoEnergyConservation();
223 fsBlocked->setTotalEnergyBeforeInteraction(0.0);
224
225 return fsBlocked; // Interaction is blocked. Return an empty final state.
226 }
227
228 // Test Pauli blocking
229 G4bool isBlocked = Pauli::isBlocked(modifiedAndCreated, theNucleus);
230
231 if(isBlocked) {
232 DEBUG("Pauli: Blocked!" << std::endl);
233
234 // Restore the state of the initial particles
236
237 // Delete newly created particles
238 for( ParticleIter i = created.begin(); i != created.end(); ++i )
239 delete *i;
240
241 FinalState *fsBlocked = new FinalState;
242 delete fs;
243 fsBlocked->makePauliBlocked();
244 fsBlocked->setTotalEnergyBeforeInteraction(0.0);
245
246 return fsBlocked; // Interaction is blocked. Return an empty final state.
247 }
248 DEBUG("Pauli: Allowed!" << std::endl);
249
250 // Test CDPP blocking
251 G4bool isCDPPBlocked = Pauli::isCDPPBlocked(created, theNucleus);
252
253 if(isCDPPBlocked) {
254 DEBUG("CDPP: Blocked!" << std::endl);
255
256 // Restore the state of the initial particles
258
259 // Delete newly created particles
260 for( ParticleIter i = created.begin(); i != created.end(); ++i )
261 delete *i;
262
263 FinalState *fsBlocked = new FinalState;
264 delete fs;
265 fsBlocked->makePauliBlocked();
266 fsBlocked->setTotalEnergyBeforeInteraction(0.0);
267
268 return fsBlocked; // Interaction is blocked. Return an empty final state.
269 }
270 DEBUG("CDPP: Allowed!" << std::endl);
271
272 // If all went well, try to bring particles inside the nucleus...
273 for( ParticleIter i = modifiedAndCreated.begin(); i != modifiedAndCreated.end(); ++i )
274 {
275 // ...except for pions beyond their surface radius.
276 if((*i)->isOutOfWell()) continue;
277
278 const G4bool successBringParticlesInside = bringParticleInside(*i);
279 if( !successBringParticlesInside ) {
280 ERROR("Failed to bring particle inside the nucleus!" << std::endl);
281 }
282 }
283
284 // Collision accepted!
285 for( ParticleIter i = modifiedAndCreated.begin(); i != modifiedAndCreated.end(); ++i ) {
286 if(!(*i)->isOutOfWell()) {
287 // Decide if the particle should be made into a spectator
288 // (Back to spectator)
289 G4bool goesBackToSpectator = false;
290 if((*i)->isNucleon() && theNucleus->getStore()->getConfig()->getBackToSpectator()) {
291 G4double threshold = (*i)->getPotentialEnergy();
292 if((*i)->getType()==Proton)
294 if((*i)->getKineticEnergy() < threshold)
295 goesBackToSpectator = true;
296 }
297
298 // Thaw the particle propagation
299 (*i)->thawPropagation();
300
301 // Increment or decrement the participant counters
302 if(goesBackToSpectator) {
303 DEBUG("The following particle goes back to spectator:" << std::endl
304 << (*i)->print() << std::endl);
305 if(!(*i)->isTargetSpectator()) {
307 }
308 (*i)->makeTargetSpectator();
309 } else {
310 if((*i)->isTargetSpectator()) {
312 }
313 (*i)->makeParticipant();
314 }
315 }
316 }
317 ParticleList destroyed = fs->getDestroyedParticles();
318 for( ParticleIter i = destroyed.begin(); i != destroyed.end(); ++i )
319 if(!(*i)->isTargetSpectator())
321
322 return fs;
323 }
324
333
334 if(particle2) {
342 }
343 }
344
346 // Set up the violationE calculation
347 ParticleList modified = fs->getModifiedParticles();
348 const G4bool manyBodyFinalState = (modified.size() + fs->getCreatedParticles().size() > 1);
349 if(manyBodyFinalState)
350 violationEFunctor = new ViolationEMomentumFunctor(theNucleus, fs, &boostVector, shouldUseLocalEnergy());
351 else {
352 Particle const * const p = modified.front();
353 // The following condition is necessary for the functor to work
354 // correctly. A similar condition exists in INCL4.6.
356 return false;
357 violationEFunctor = new ViolationEEnergyFunctor(theNucleus, fs);
358 }
359
360 // Apply the root-finding algorithm
361 const G4bool success = RootFinder::solve(violationEFunctor, 1.0);
362 if(success) { // Apply the solution
363 std::pair<G4double,G4double> theSolution = RootFinder::getSolution();
364 (*violationEFunctor)(theSolution.first);
365 } else {
366 WARN("Couldn't enforce energy conservation after an interaction, root-finding algorithm failed." << std::endl);
367 }
368 delete violationEFunctor;
369 return success;
370 }
371
372 /* *** ***
373 * *** InteractionAvatar::ViolationEMomentumFunctor methods ***
374 * *** ***/
375
376 InteractionAvatar::ViolationEMomentumFunctor::ViolationEMomentumFunctor(Nucleus * const nucleus, FinalState const * const finalState, ThreeVector const * const boost, const G4bool localE) :
377 RootFunctor(0., 1E6),
378 initialEnergy(finalState->getTotalEnergyBeforeInteraction()),
379 theNucleus(nucleus),
380 boostVector(boost),
381 shouldUseLocalEnergy(localE)
382 {
383 // Set up the finalParticles list
384 finalParticles = finalState->getModifiedParticles();
385 ParticleList created = finalState->getCreatedParticles();
386 finalParticles.splice(finalParticles.end(), created);
387
388 // Store the particle momenta (necessary for the calls to
389 // scaleParticleMomenta() to work)
390 particleMomenta.clear();
391 for(ParticleIter i=finalParticles.begin(); i!=finalParticles.end(); ++i) {
392 (*i)->boost(*boostVector);
393 particleMomenta.push_back((*i)->getMomentum());
394 }
395 }
396
397 G4double InteractionAvatar::ViolationEMomentumFunctor::operator()(const G4double alpha) const {
398 scaleParticleMomenta(alpha);
399
400 G4double deltaE = 0.0;
401 for(ParticleIter i=finalParticles.begin(); i!=finalParticles.end(); ++i)
402 deltaE += (*i)->getEnergy() - (*i)->getPotentialEnergy();
403 deltaE -= initialEnergy;
404 return deltaE;
405 }
406
407 void InteractionAvatar::ViolationEMomentumFunctor::scaleParticleMomenta(const G4double alpha) const {
408
409 std::list<ThreeVector>::const_iterator iP = particleMomenta.begin();
410 for(ParticleIter i=finalParticles.begin(); i!=finalParticles.end(); ++i, ++iP) {
411 (*i)->setMomentum((*iP)*alpha);
412 (*i)->adjustEnergyFromMomentum();
413 (*i)->boost(-(*boostVector));
414 if(theNucleus)
415 theNucleus->updatePotentialEnergy(*i);
416 else
417 (*i)->setPotentialEnergy(0.);
418
419 if(shouldUseLocalEnergy && !(*i)->isPion()) { // This translates AECSVT's loops 1, 3 and 4
420// assert(theNucleus); // Local energy without a nucleus doesn't make sense
421 const G4double energy = (*i)->getEnergy(); // Store the energy of the particle
422 G4double locE = KinematicsUtils::getLocalEnergy(theNucleus, *i); // Initial value of local energy
423 G4double locEOld;
425 for(G4int iterLocE=0;
427 ++iterLocE) {
428 locEOld = locE;
429 (*i)->setEnergy(energy + locE); // Update the energy of the particle...
430 (*i)->adjustMomentumFromEnergy();
431 theNucleus->updatePotentialEnergy(*i); // ...update its potential energy...
432 locE = KinematicsUtils::getLocalEnergy(theNucleus, *i); // ...and recompute locE.
433 deltaLocE = std::abs(locE-locEOld);
434 }
435 }
436 }
437 }
438
439 void InteractionAvatar::ViolationEMomentumFunctor::cleanUp(const G4bool success) const {
440 if(!success)
441 scaleParticleMomenta(1.);
442 }
443
444 /* *** ***
445 * *** InteractionAvatar::ViolationEEnergyFunctor methods ***
446 * *** ***/
447
448 InteractionAvatar::ViolationEEnergyFunctor::ViolationEEnergyFunctor(Nucleus * const nucleus, FinalState const * const finalState) :
449 RootFunctor(0., 1E6),
450 initialEnergy(finalState->getTotalEnergyBeforeInteraction()),
451 theNucleus(nucleus),
452 theParticle(finalState->getModifiedParticles().front()),
453 theEnergy(theParticle->getEnergy()),
454 theMomentum(theParticle->getMomentum()),
455 energyThreshold(KinematicsUtils::energy(theMomentum,ParticleTable::effectiveDeltaDecayThreshold))
456 {
457// assert(theNucleus);
458// assert(finalState->getModifiedParticles().size()==1);
459// assert(theParticle->isDelta());
460 }
461
462 G4double InteractionAvatar::ViolationEEnergyFunctor::operator()(const G4double alpha) const {
463 setParticleEnergy(alpha);
464 return theParticle->getEnergy() - theParticle->getPotentialEnergy() - initialEnergy;
465 }
466
467 void InteractionAvatar::ViolationEEnergyFunctor::setParticleEnergy(const G4double alpha) const {
468
469 G4double locE = KinematicsUtils::getLocalEnergy(theNucleus, theParticle); // Initial value of local energy
470 G4double locEOld;
472 for(G4int iterLocE=0;
474 ++iterLocE) {
475 locEOld = locE;
476 const G4double particleEnergy = energyThreshold + alpha*(theEnergy-energyThreshold);
477 const G4double theMass = std::sqrt(std::pow(particleEnergy,2.)-theMomentum.mag2());
478 theParticle->setMass(theMass);
479 theParticle->setEnergy(particleEnergy + locE); // Update the energy of the particle...
480 theParticle->adjustMomentumFromEnergy();
481 theNucleus->updatePotentialEnergy(theParticle); // ...update its potential energy...
482 locE = KinematicsUtils::getLocalEnergy(theNucleus, theParticle); // ...and recompute locE.
483 deltaLocE = std::abs(locE-locEOld);
484 }
485
486 }
487
488 void InteractionAvatar::ViolationEEnergyFunctor::cleanUp(const G4bool success) const {
489 if(!success)
490 setParticleEnergy(1.);
491 }
492
493}
#define WARN(x)
#define DEBUG(x)
#define ERROR(x)
Static root-finder algorithm.
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
void decrementCascading()
Definition: G4INCLBook.hh:74
void incrementCascading()
Definition: G4INCLBook.hh:73
G4bool getBackToSpectator() const
Get back-to-spectator.
static G4double total(Particle const *const p1, Particle const *const p2)
ParticleList const & getModifiedParticles() const
void setTotalEnergyBeforeInteraction(G4double E)
void addOutgoingParticle(Particle *p)
ParticleList const & getDestroyedParticles() const
ParticleList const & getCreatedParticles() const
static const G4int maxIterLocE
Max number of iterations for the determination of the local-energy Q-value.
FinalState * postInteraction(FinalState *)
void restoreParticles() const
Restore the state of both particles.
G4bool enforceEnergyConservation(FinalState *const fs)
Enforce energy conservation.
void preInteractionBlocking()
Store the state of the particles before the interaction.
static const G4double locEAccuracy
Target accuracy in the determination of the local-energy Q-value.
InteractionAvatar(G4double, G4INCL::Nucleus *, G4INCL::Particle *)
G4bool shouldUseLocalEnergy() const
true if the given avatar should use local energy
G4bool bringParticleInside(Particle *const p)
void preInteractionLocalEnergy(Particle *const p)
Apply local-energy transformation, if appropriate.
static ThreeVector makeBoostVector(Particle const *const p1, Particle const *const p2)
static void transformToLocalEnergyFrame(Nucleus const *const n, Particle *const p)
static G4double getLocalEnergy(Nucleus const *const n, Particle *const p)
Store * getStore() const
G4double getSurfaceRadius(Particle const *const particle) const
Get the maximum allowed radius for a given particle.
G4double getTransmissionBarrier(Particle const *const p)
Get the transmission barrier.
static const G4double effectiveDeltaDecayThreshold
void setPotentialEnergy(G4double v)
Set the particle potential energy.
G4double getEnergy() const
G4double getPotentialEnergy() const
Get the particle potential energy.
G4double getHelicity()
void setMass(G4double mass)
void setHelicity(G4double h)
const G4INCL::ThreeVector & getPosition() const
G4bool isPion() const
Is this a pion?
const G4INCL::ThreeVector & getMomentum() const
virtual void setMomentum(const G4INCL::ThreeVector &momentum)
G4INCL::ParticleType getType() const
void setEnergy(G4double energy)
void setType(ParticleType t)
G4double getMass() const
Get the cached particle mass.
void boost(const ThreeVector &aBoostVector)
virtual void setPosition(const G4INCL::ThreeVector &position)
static G4bool isBlocked(ParticleList const p, Nucleus const *const n)
Check Pauli blocking.
static G4bool isCDPPBlocked(ParticleList const p, Nucleus const *const n)
Check CDPP blocking.
static std::pair< G4double, G4double > const & getSolution()
Get the solution of the last call to solve().
static G4bool solve(RootFunctor const *const f, const G4double x0)
Numerically solve a one-dimensional equation.
Book * getBook()
Definition: G4INCLStore.hh:243
Config const * getConfig()
Definition: G4INCLStore.hh:257
G4double mag() const
G4double mag2() const
const G4double twoThirds
std::list< G4INCL::Particle * > ParticleList
std::list< G4INCL::Particle * >::const_iterator ParticleIter