Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4EvaporationChannel.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// $Id$
27//
28//J.M. Quesada (August2008). Based on:
29//
30// Hadronic Process: Nuclear De-excitations
31// by V. Lara (Oct 1998)
32//
33// Modified:
34// 03-09-2008 J.M. Quesada for external choice of inverse cross section option
35// 06-09-2008 J.M. Quesada Also external choices have been added for superimposed
36// Coulomb barrier (if useSICB is set true, by default is false)
37// 17-11-2010 V.Ivanchenko in constructor replace G4VEmissionProbability by
38// G4EvaporationProbability and do not new and delete probability
39// object at each call; use G4Pow
40
43#include "G4NucleiProperties.hh"
44#include "G4Pow.hh"
47#include "G4SystemOfUnits.hh"
48#include "Randomize.hh"
49#include "G4Alpha.hh"
50
52 const G4String & aName,
53 G4EvaporationProbability* aEmissionStrategy,
54 G4VCoulombBarrier* aCoulombBarrier):
56 theA(anA),
57 theZ(aZ),
58 theEvaporationProbabilityPtr(aEmissionStrategy),
59 theCoulombBarrierPtr(aCoulombBarrier),
60 EmissionProbability(0.0),
61 MaximalKineticEnergy(-1000.0)
62{
63 ResidualA = 0;
64 ResidualZ = 0;
65 ResidualMass = CoulombBarrier=0.0;
66 EvaporatedMass = G4NucleiProperties::GetNuclearMass(theA, theZ);
67 theLevelDensityPtr = new G4EvaporationLevelDensityParameter;
68}
69
72 theA(0),
73 theZ(0),
74 theEvaporationProbabilityPtr(0),
75 theCoulombBarrierPtr(0),
76 EmissionProbability(0.0),
77 MaximalKineticEnergy(-1000.0)
78{
79 ResidualA = 0;
80 ResidualZ = 0;
81 EvaporatedMass = ResidualMass = CoulombBarrier = 0.0;
82 theLevelDensityPtr = new G4EvaporationLevelDensityParameter;
83}
84
86{
87 delete theLevelDensityPtr;
88}
89
90//void G4EvaporationChannel::Initialize(const G4Fragment &)
91//{}
92
94{
95 //for inverse cross section choice
96 theEvaporationProbabilityPtr->SetOPTxs(OPTxs);
97 // for superimposed Coulomb Barrier for inverse cross sections
98 theEvaporationProbabilityPtr->UseSICB(useSICB);
99
100 G4int FragmentA = fragment->GetA_asInt();
101 G4int FragmentZ = fragment->GetZ_asInt();
102 ResidualA = FragmentA - theA;
103 ResidualZ = FragmentZ - theZ;
104 //G4cout << "G4EvaporationChannel::Initialize Z= " << theZ << " A= " << theA
105 // << " FragZ= " << FragmentZ << " FragA= " << FragmentA << G4endl;
106
107 //Effective excitation energy
108 G4double ExEnergy = fragment->GetExcitationEnergy() -
110
111 // Only channels which are physically allowed are taken into account
112 if (ResidualA <= 0 || ResidualZ <= 0 || ResidualA < ResidualZ ||
113 (ResidualA == ResidualZ && ResidualA > 1) || ExEnergy <= 0.0) {
114 CoulombBarrier = ResidualMass = 0.0;
115 MaximalKineticEnergy = -1000.0*MeV;
116 EmissionProbability = 0.0;
117 } else {
118 ResidualMass = G4NucleiProperties::GetNuclearMass(ResidualA, ResidualZ);
119 G4double FragmentMass = fragment->GetGroundStateMass();
120 CoulombBarrier = theCoulombBarrierPtr->GetCoulombBarrier(ResidualA,ResidualZ,ExEnergy);
121 // Maximal Kinetic Energy
122 MaximalKineticEnergy = CalcMaximalKineticEnergy(FragmentMass + ExEnergy);
123 //MaximalKineticEnergy = ExEnergy + fragment.GetGroundStateMass()
124 // - EvaporatedMass - ResidualMass;
125
126 // Emission probability
127 // Protection for the case Tmax<V. If not set in this way we could end up in an
128 // infinite loop in the method GetKineticEnergy if OPTxs!=0 && useSICB=true.
129 // Of course for OPTxs=0 we have the Coulomb barrier
130
131 G4double limit;
132 if (OPTxs==0 || (OPTxs!=0 && useSICB))
133 limit= CoulombBarrier;
134 else limit=0.;
135 limit = std::max(limit, FragmentMass - ResidualMass - EvaporatedMass);
136
137 // The threshold for charged particle emission must be set to 0 if Coulomb
138 //cutoff is included in the cross sections
139 if (MaximalKineticEnergy <= limit) EmissionProbability = 0.0;
140 else {
141 // Total emission probability for this channel
142 EmissionProbability = theEvaporationProbabilityPtr->
143 EmissionProbability(*fragment, MaximalKineticEnergy);
144 }
145 }
146 //G4cout << "G4EvaporationChannel:: probability= " << EmissionProbability << G4endl;
147
148 return EmissionProbability;
149}
150
152{
153 /*
154 G4double Ecm = GetKineticEnergy(theNucleus) + ResidualMass + EvaporatedMass;
155
156 G4double EvaporatedEnergy =
157 ((Ecm-ResidualMass)*(Ecm+ResidualMass) + EvaporatedMass*EvaporatedMass)/(2*Ecm);
158 */
159 G4double EvaporatedEnergy = GetKineticEnergy(theNucleus) + EvaporatedMass;
160
161 G4ThreeVector momentum(IsotropicVector
162 (std::sqrt((EvaporatedEnergy - EvaporatedMass)*
163 (EvaporatedEnergy + EvaporatedMass))));
164
165 G4LorentzVector EvaporatedMomentum(momentum,EvaporatedEnergy);
166 G4LorentzVector ResidualMomentum = theNucleus.GetMomentum();
167 EvaporatedMomentum.boost(ResidualMomentum.boostVector());
168
169 G4Fragment * EvaporatedFragment = new G4Fragment(theA,theZ,EvaporatedMomentum);
170 ResidualMomentum -= EvaporatedMomentum;
171
172 G4Fragment * ResidualFragment = new G4Fragment(ResidualA, ResidualZ, ResidualMomentum);
173
174 G4FragmentVector * theResult = new G4FragmentVector;
175
176#ifdef debug
177 G4double Efinal = ResidualMomentum.e() + EvaporatedMomentum.e();
178 G4ThreeVector Pfinal = ResidualMomentum.vect() + EvaporatedMomentum.vect();
179 if (std::abs(Efinal-theNucleus.GetMomentum().e()) > 1.0*keV) {
180 G4cout << "@@@@@@@@@@@@@@@@@@@@@ G4Evaporation Chanel: ENERGY @@@@@@@@@@@@@@@@" << G4endl;
181 G4cout << "Initial : " << theNucleus.GetMomentum().e()/MeV << " MeV Final :"
182 <<Efinal/MeV << " MeV Delta: " << (Efinal-theNucleus.GetMomentum().e())/MeV
183 << " MeV" << G4endl;
184 }
185 if (std::abs(Pfinal.x()-theNucleus.GetMomentum().x()) > 1.0*keV ||
186 std::abs(Pfinal.y()-theNucleus.GetMomentum().y()) > 1.0*keV ||
187 std::abs(Pfinal.z()-theNucleus.GetMomentum().z()) > 1.0*keV ) {
188 G4cout << "@@@@@@@@@@@@@@@@@@@@@ G4Evaporation Chanel: MOMENTUM @@@@@@@@@@@@@@@@" << G4endl;
189 G4cout << "Initial : " << theNucleus.GetMomentum().vect() << " MeV Final :"
190 <<Pfinal/MeV << " MeV Delta: " << Pfinal-theNucleus.GetMomentum().vect()
191 << " MeV" << G4endl;
192
193 }
194#endif
195 theResult->push_back(EvaporatedFragment);
196 theResult->push_back(ResidualFragment);
197 return theResult;
198}
199
200/////////////////////////////////////////
201// Calculates the maximal kinetic energy that can be carried by fragment.
202G4double G4EvaporationChannel::CalcMaximalKineticEnergy(G4double NucleusTotalE)
203{
204 // This is the "true" assimptotic kinetic energy (from energy conservation)
205 G4double Tmax =
206 ((NucleusTotalE-ResidualMass)*(NucleusTotalE+ResidualMass) + EvaporatedMass*EvaporatedMass)
207 /(2.0*NucleusTotalE) - EvaporatedMass;
208
209 //JMQ (13-09-08) bug fixed: in the original version the Tmax is calculated
210 //at the Coulomb barrier
211 //IMPORTANT: meaning of Tmax differs in OPTxs=0 and OPTxs!=0
212 //When OPTxs!=0 Tmax is the TRUE (assimptotic) maximal kinetic energy
213
214 if(OPTxs==0)
215 Tmax=Tmax- CoulombBarrier;
216
217 return Tmax;
218}
219
220///////////////////////////////////////////
221//JMQ: New method for MC sampling of kinetic energy. Substitutes old CalcKineticEnergy
222G4double G4EvaporationChannel::GetKineticEnergy(const G4Fragment & aFragment)
223{
224
225 if (OPTxs==0) {
226 // It uses Dostrovsky's approximation for the inverse reaction cross
227 // in the probability for fragment emission
228 // MaximalKineticEnergy energy in the original version (V.Lara) was calculated at
229 //the Coulomb barrier.
230
231
232 if (MaximalKineticEnergy < 0.0) {
233 throw G4HadronicException(__FILE__, __LINE__,
234 "G4EvaporationChannel::CalcKineticEnergy: maximal kinetic at the Coulomb barrier is less than 0");
235 }
236 G4double Rb = 4.0*theLevelDensityPtr->
237 LevelDensityParameter(ResidualA+theA,ResidualZ+theZ,MaximalKineticEnergy)*
238 MaximalKineticEnergy;
239 G4double RbSqrt = std::sqrt(Rb);
240 G4double PEX1 = 0.0;
241 if (RbSqrt < 160.0) PEX1 = std::exp(-RbSqrt);
242 G4double Rk = 0.0;
243 G4double FRk = 0.0;
244 do {
245 G4double RandNumber = G4UniformRand();
246 Rk = 1.0 + (1./RbSqrt)*std::log(RandNumber + (1.0-RandNumber)*PEX1);
247 G4double Q1 = 1.0;
248 G4double Q2 = 1.0;
249 if (theZ == 0) { // for emitted neutron
250 G4double Beta = (2.12/G4Pow::GetInstance()->Z23(ResidualA) - 0.05)*MeV/
251 (0.76 + 2.2/G4Pow::GetInstance()->Z13(ResidualA));
252 Q1 = 1.0 + Beta/(MaximalKineticEnergy);
253 Q2 = Q1*std::sqrt(Q1);
254 }
255
256 FRk = (3.0*std::sqrt(3.0)/2.0)/Q2 * Rk * (Q1 - Rk*Rk);
257
258 } while (FRk < G4UniformRand());
259
260 G4double result = MaximalKineticEnergy * (1.0-Rk*Rk) + CoulombBarrier;
261 return result;
262 } else if (OPTxs==1 || OPTxs==2 || OPTxs==3 || OPTxs==4) {
263
264 // Coulomb barrier is just included in the cross sections
265 G4double V = 0;
266 if(useSICB) { V= CoulombBarrier; }
267
268 V = std::max(V, aFragment.GetGroundStateMass()-EvaporatedMass-ResidualMass);
269
270 G4double Tmax=MaximalKineticEnergy;
271 G4double T(0.0);
272 G4double NormalizedProbability(1.0);
273
274 // VI: This is very ineffective - create new objects at each call to the method
275 /*
276 // A pointer is created in order to access the distribution function.
277 G4EvaporationProbability * G4EPtemp = 0;
278
279 if (theA==1 && theZ==0) G4EPtemp=new G4NeutronEvaporationProbability();
280 else if (theA==1 && theZ==1) G4EPtemp=new G4ProtonEvaporationProbability();
281 else if (theA==2 && theZ==1 ) G4EPtemp=new G4DeuteronEvaporationProbability();
282 else if (theA==3 && theZ==1 ) G4EPtemp=new G4TritonEvaporationProbability();
283 else if (theA==3 && theZ==2 ) G4EPtemp=new G4He3EvaporationProbability();
284 else if (theA==4 && theZ==2) G4EPtemp=new G4AlphaEvaporationProbability();
285 else {
286 std::ostringstream errOs;
287 errOs << "ejected particle out of range in G4EvaporationChannel" << G4endl;
288 throw G4HadronicException(__FILE__, __LINE__, errOs.str());
289 }
290
291 //for cross section selection and superimposed Coulom Barrier for xs
292 G4EPtemp->SetOPTxs(OPTxs);
293 G4EPtemp->UseSICB(useSICB);
294 */
295
296 // use local pointer and not create a new one
297 do
298 {
299 T=V+G4UniformRand()*(Tmax-V);
300 NormalizedProbability =
301 theEvaporationProbabilityPtr->ProbabilityDistributionFunction(aFragment,T)/
302 GetEmissionProbability(const_cast<G4Fragment*>(&aFragment));
303
304 }
305 while (G4UniformRand() > NormalizedProbability);
306 // delete G4EPtemp;
307 return T;
308 } else{
309 std::ostringstream errOs;
310 errOs << "Bad option for energy sampling in evaporation" <<G4endl;
311 throw G4HadronicException(__FILE__, __LINE__, errOs.str());
312 }
313}
314
315G4ThreeVector G4EvaporationChannel::IsotropicVector(G4double Magnitude)
316 // Samples a isotropic random vectorwith a magnitud given by Magnitude.
317 // By default Magnitude = 1.0
318{
319 G4double CosTheta = 1.0 - 2.0*G4UniformRand();
320 G4double SinTheta = std::sqrt(1.0 - CosTheta*CosTheta);
321 G4double Phi = twopi*G4UniformRand();
322 G4ThreeVector Vector(Magnitude*std::cos(Phi)*SinTheta,
323 Magnitude*std::sin(Phi)*SinTheta,
324 Magnitude*CosTheta);
325 return Vector;
326}
327
328
329
330
331
332
333
334
335
336
std::vector< G4Fragment * > G4FragmentVector
Definition: G4Fragment.hh:65
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
double z() const
double x() const
double y() const
Hep3Vector boostVector() const
HepLorentzVector & boost(double, double, double)
Hep3Vector vect() const
G4FragmentVector * BreakUp(const G4Fragment &theNucleus)
virtual G4double GetEmissionProbability(G4Fragment *fragment)
G4double ProbabilityDistributionFunction(const G4Fragment &aFragment, G4double K)
G4double GetGroundStateMass() const
Definition: G4Fragment.hh:240
G4double GetExcitationEnergy() const
Definition: G4Fragment.hh:235
const G4LorentzVector & GetMomentum() const
Definition: G4Fragment.hh:251
G4int GetZ_asInt() const
Definition: G4Fragment.hh:223
G4int GetA_asInt() const
Definition: G4Fragment.hh:218
static G4double GetNuclearMass(const G4double A, const G4double Z)
static G4PairingCorrection * GetInstance()
G4double GetPairingCorrection(G4int A, G4int Z) const
static G4Pow * GetInstance()
Definition: G4Pow.cc:50
G4double Z23(G4int Z)
Definition: G4Pow.hh:134
G4double Z13(G4int Z)
Definition: G4Pow.hh:110
virtual G4double GetCoulombBarrier(G4int ARes, G4int ZRes, G4double U) const =0