Geant4  10.02.p03
G4INCLSurfaceAvatar.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 
38 /*
39  * G4INCLReflectionAvatar.cc
40  *
41  * \date Jun 8, 2009
42  * \author Pekka Kaitaniemi
43  */
44 
45 #include "G4INCLSurfaceAvatar.hh"
46 #include "G4INCLRandom.hh"
49 #include "G4INCLClustering.hh"
50 #include <sstream>
51 #include <string>
52 
53 namespace G4INCL {
54 
55  SurfaceAvatar::SurfaceAvatar(G4INCL::Particle *aParticle, G4double time, G4INCL::Nucleus *n)
56  :IAvatar(time), theParticle(aParticle), theNucleus(n),
57  particlePIn(0.),
58  particlePOut(0.),
59  particleTOut(0.),
60  TMinusV(0.),
61  TMinusV2(0.),
62  particleMass(0.),
63  sinIncidentAngle(0.),
64  cosIncidentAngle(0.),
65  sinRefractionAngle(0.),
66  cosRefractionAngle(0.),
67  refractionIndexRatio(0.),
68  internalReflection(false)
69  {
70  setType(SurfaceAvatarType);
71  }
72 
73  SurfaceAvatar::~SurfaceAvatar() {
74 
75  }
76 
77  G4INCL::IChannel* SurfaceAvatar::getChannel() {
78  if(theParticle->isTargetSpectator()) {
79  INCL_DEBUG("Particle " << theParticle->getID() << " is a spectator, reflection" << '\n');
80  return new ReflectionChannel(theNucleus, theParticle);
81  }
82 
83  // We forbid transmission of resonances below the Fermi energy. Emitting a
84  // delta particle below Tf can lead to negative excitation energies, since
85  // CDPP assumes that particles stay in the Fermi sea.
86  if(theParticle->isResonance()) {
87  const G4double theFermiEnergy = theNucleus->getPotential()->getFermiEnergy(theParticle);
88  if(theParticle->getKineticEnergy()<theFermiEnergy) {
89  INCL_DEBUG("Particle " << theParticle->getID() << " is a resonance below Tf, reflection" << '\n'
90  << " Tf=" << theFermiEnergy << ", EKin=" << theParticle->getKineticEnergy() << '\n');
91  return new ReflectionChannel(theNucleus, theParticle);
92  }
93  }
94 
95  // Don't try to make a cluster if the leading particle is too slow
96  const G4double transmissionProbability = getTransmissionProbability(theParticle);
97  const G4double TOut = TMinusV;
98  const G4double kOut = particlePOut;
99  const G4double cosR = cosRefractionAngle;
100 
101  INCL_DEBUG("Transmission probability for particle " << theParticle->getID() << " = " << transmissionProbability << '\n');
102  /* Don't attempt to construct clusters when a projectile spectator is
103  * trying to escape during a nucleus-nucleus collision. The idea behind
104  * this is that projectile spectators will later be collected in the
105  * projectile remnant, and trying to clusterise them somewhat feels like
106  * G4double counting. Moreover, applying the clustering algorithm on escaping
107  * projectile spectators makes the code *really* slow if the projectile is
108  * large.
109  */
110  if(theParticle->isNucleon()
111  && (!theParticle->isProjectileSpectator() || !theNucleus->isNucleusNucleusCollision())
112  && transmissionProbability>1.E-4) {
113  Cluster *candidateCluster = 0;
114 
115  candidateCluster = Clustering::getCluster(theNucleus, theParticle);
116  if(candidateCluster != 0 &&
117  Clustering::clusterCanEscape(theNucleus, candidateCluster)) {
118 
119  INCL_DEBUG("Cluster algorithm succeded. Candidate cluster:" << '\n' << candidateCluster->print() << '\n');
120 
121  // Check if the cluster can penetrate the Coulomb barrier
122  const G4double clusterTransmissionProbability = getTransmissionProbability(candidateCluster);
123  const G4double x = Random::shoot();
124 
125  INCL_DEBUG("Transmission probability for cluster " << candidateCluster->getID() << " = " << clusterTransmissionProbability << '\n');
126 
127  if (x <= clusterTransmissionProbability) {
128  theNucleus->getStore()->getBook().incrementEmittedClusters();
129  INCL_DEBUG("Cluster " << candidateCluster->getID() << " passes the Coulomb barrier, transmitting." << '\n');
130  return new TransmissionChannel(theNucleus, candidateCluster);
131  } else {
132  INCL_DEBUG("Cluster " << candidateCluster->getID() << " does not pass the Coulomb barrier. Falling back to transmission of the leading particle." << '\n');
133  delete candidateCluster;
134  }
135  } else {
136  delete candidateCluster;
137  }
138  }
139 
140  // If we haven't transmitted a cluster (maybe cluster feature was
141  // disabled or maybe we just can't produce an acceptable cluster):
142 
143  // Always transmit projectile spectators if no cluster was formed and if
144  // transmission is energetically allowed
145  if(theParticle->isProjectileSpectator() && transmissionProbability>0.) {
146  INCL_DEBUG("Particle " << theParticle->getID() << " is a projectile spectator, transmission" << '\n');
147  return new TransmissionChannel(theNucleus, theParticle, TOut);
148  }
149 
150  // Transmit or reflect depending on the transmission probability
151  const G4double x = Random::shoot();
152 
153  if(x <= transmissionProbability) { // Transmission
154  INCL_DEBUG("Particle " << theParticle->getID() << " passes the Coulomb barrier, transmitting." << '\n');
155  if(theNucleus->getStore()->getConfig()->getRefraction()) {
156  return new TransmissionChannel(theNucleus, theParticle, kOut, cosR);
157  } else {
158  return new TransmissionChannel(theNucleus, theParticle, TOut);
159  }
160  } else { // Reflection
161  INCL_DEBUG("Particle " << theParticle->getID() << " does not pass the Coulomb barrier, reflection." << '\n');
162  return new ReflectionChannel(theNucleus, theParticle);
163  }
164  }
165 
166  void SurfaceAvatar::fillFinalState(FinalState *fs) {
167  getChannel()->fillFinalState(fs);
168  }
169 
170  void SurfaceAvatar::preInteraction() {}
171 
172  void SurfaceAvatar::postInteraction(FinalState *fs) {
173  ParticleList const &outgoing = fs->getOutgoingParticles();
174  if(!outgoing.empty()) { // Transmission
175 // assert(outgoing.size()==1);
176  Particle *out = outgoing.front();
177  out->rpCorrelate();
178  if(out->isCluster()) {
179  Cluster *clusterOut = dynamic_cast<Cluster*>(out);
180  ParticleList const &components = clusterOut->getParticles();
181  for(ParticleIter i=components.begin(), e=components.end(); i!=e; ++i) {
182  if(!(*i)->isTargetSpectator())
183  theNucleus->getStore()->getBook().decrementCascading();
184  }
185  } else if(!theParticle->isTargetSpectator()) {
186 // assert(out==theParticle);
187  theNucleus->getStore()->getBook().decrementCascading();
188  }
189  }
190  }
191 
192  std::string SurfaceAvatar::dump() const {
193  std::stringstream ss;
194  ss << "(avatar " << theTime << " 'reflection" << '\n'
195  << "(list " << '\n'
196  << theParticle->dump()
197  << "))" << '\n';
198  return ss.str();
199  }
200 
201  G4double SurfaceAvatar::getTransmissionProbability(Particle const * const particle) {
202 
203  particleMass = particle->getMass();
204  const G4double V = particle->getPotentialEnergy();
205 
206  // Correction to the particle kinetic energy if using real masses
207  const G4int theA = theNucleus->getA();
208  const G4int theZ = theNucleus->getZ();
209  const G4double correction = particle->getEmissionQValueCorrection(theA, theZ);
210  particleTOut = particle->getKineticEnergy() + correction;
211 
212  if (particleTOut <= V) // No transmission if total energy < 0
213  return 0.0;
214 
215  TMinusV = particleTOut-V;
216  TMinusV2 = TMinusV*TMinusV;
217 
218  // Momenta in and out
219  const G4double particlePIn2 = particle->getMomentum().mag2();
220  const G4double particlePOut2 = 2.*particleMass*TMinusV+TMinusV2;
221  particlePIn = std::sqrt(particlePIn2);
222  particlePOut = std::sqrt(particlePOut2);
223 
224  // Compute the transmission probability
225  G4double theTransmissionProbability;
226  if(theNucleus->getStore()->getConfig()->getRefraction()) {
227  // Use the formula with refraction
228  initializeRefractionVariables(particle);
229 
230  if(internalReflection)
231  return 0.; // total internal reflection
232 
233  // Intermediate variables for calculation
234  const G4double x = refractionIndexRatio*cosIncidentAngle;
235  const G4double y = (x - cosRefractionAngle) / (x + cosRefractionAngle);
236 
237  theTransmissionProbability = 1. - y*y;
238  } else {
239  // Use the formula without refraction
240 
241  // Intermediate variable for calculation
242  const G4double y = particlePIn+particlePOut;
243 
244  // The transmission probability for a potential step
245  theTransmissionProbability = 4.*particlePIn*particlePOut/(y*y);
246  }
247 
248  // For neutral and negative particles, no Coulomb transmission
249  // Also, no Coulomb if the particle takes away all of the nuclear charge
250  const G4int particleZ = particle->getZ();
251  if (particleZ <= 0 || particleZ >= theZ)
252  return theTransmissionProbability;
253 
254  // Nominal Coulomb barrier
255  const G4double theTransmissionBarrier = theNucleus->getTransmissionBarrier(particle);
256  if (TMinusV >= theTransmissionBarrier) // Above the Coulomb barrier
257  return theTransmissionProbability;
258 
259  // Coulomb-penetration factor
260  const G4double px = std::sqrt(TMinusV/theTransmissionBarrier);
261  const G4double logCoulombTransmission =
262  particleZ*(theZ-particleZ)/137.03*std::sqrt(2.*particleMass/TMinusV/(1.+TMinusV/2./particleMass))
263  *(Math::arcCos(px)-px*std::sqrt(1.-px*px));
264  INCL_DEBUG("Coulomb barrier, logCoulombTransmission=" << logCoulombTransmission << '\n');
265  if (logCoulombTransmission > 35.) // Transmission is forbidden by Coulomb
266  return 0.;
267  theTransmissionProbability *= std::exp(-2.*logCoulombTransmission);
268 
269  return theTransmissionProbability;
270  }
271 
272  void SurfaceAvatar::initializeRefractionVariables(Particle const * const particle) {
273  cosIncidentAngle = particle->getCosRPAngle();
274  if(cosIncidentAngle>1.)
275  cosIncidentAngle=1.;
276  sinIncidentAngle = std::sqrt(1. - cosIncidentAngle*cosIncidentAngle);
277  refractionIndexRatio = particlePIn/particlePOut;
278  const G4double sinCandidate = refractionIndexRatio*sinIncidentAngle;
279  internalReflection = (std::fabs(sinCandidate)>1.);
280  if(internalReflection) {
281  sinRefractionAngle = 1.;
282  cosRefractionAngle = 0.;
283  } else {
284  sinRefractionAngle = sinCandidate;
285  cosRefractionAngle = std::sqrt(1. - sinRefractionAngle*sinRefractionAngle);
286  }
287  INCL_DEBUG("Refraction parameters initialised as follows:\n"
288  << " cosIncidentAngle=" << cosIncidentAngle << '\n'
289  << " sinIncidentAngle=" << sinIncidentAngle << '\n'
290  << " cosRefractionAngle=" << cosRefractionAngle << '\n'
291  << " sinRefractionAngle=" << sinRefractionAngle << '\n'
292  << " refractionIndexRatio=" << refractionIndexRatio << '\n'
293  << " internalReflection=" << internalReflection << '\n');
294  }
295 }
G4double arcCos(const G4double x)
Calculates arccos with some tolerance on illegal arguments.
int G4int
Definition: G4Types.hh:78
G4bool clusterCanEscape(Nucleus const *const n, Cluster const *const c)
Determine whether the cluster can escape or not.
Double_t y
Char_t n[5]
Cluster * getCluster(Nucleus *n, Particle *p)
Call the clustering algorithm.
Static class for cluster formation.
G4double shoot()
Definition: G4INCLRandom.cc:93
double G4double
Definition: G4Types.hh:76
#define INCL_DEBUG(x)
ParticleList::const_iterator ParticleIter