Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4PreCompoundEmission.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//
27// -------------------------------------------------------------------
28//
29// GEANT4 Class file
30//
31//
32// File name: G4PreCompoundEmission
33//
34// Author: V.Lara
35//
36// Modified:
37// 15.01.2010 J.M.Quesada added protection against unphysical values of parameter an
38// 19.01.2010 V.Ivanchenko simplified computation of parameter an, sample cosTheta
39// instead of theta; protect all calls to sqrt
40// 20.08.2010 V.Ivanchenko added G4Pow and G4PreCompoundParameters pointers
41// use int Z and A and cleanup
42//
43
46#include "G4SystemOfUnits.hh"
47#include "G4Pow.hh"
48#include "G4Exp.hh"
49#include "G4Log.hh"
50#include "Randomize.hh"
51#include "G4RandomDirection.hh"
55#include "G4NuclearLevelData.hh"
58
59
61{
62 theFragmentsFactory = new G4PreCompoundEmissionFactory();
63 theFragmentsVector =
64 new G4PreCompoundFragmentVector(theFragmentsFactory->GetFragmentVector());
65 g4calc = G4Pow::GetInstance();
67 G4DeexPrecoParameters* param = fNuclData->GetParameters();
68 fFermiEnergy = param->GetFermiEnergy();
69 fUseAngularGenerator = param->UseAngularGen();
70 fModelID = G4PhysicsModelCatalog::GetModelID("model_PRECO");
71}
72
74{
75 delete theFragmentsFactory;
76 delete theFragmentsVector;
77}
78
80{
81 if (theFragmentsFactory) { delete theFragmentsFactory; }
82 theFragmentsFactory = new G4PreCompoundEmissionFactory();
83 if (theFragmentsVector) {
84 theFragmentsVector->SetVector(theFragmentsFactory->GetFragmentVector());
85 } else {
86 theFragmentsVector =
87 new G4PreCompoundFragmentVector(theFragmentsFactory->GetFragmentVector());
88 }
89}
90
92{
93 if (theFragmentsFactory) delete theFragmentsFactory;
94 theFragmentsFactory = new G4HETCEmissionFactory();
95 if (theFragmentsVector) {
96 theFragmentsVector->SetVector(theFragmentsFactory->GetFragmentVector());
97 } else {
98 theFragmentsVector =
99 new G4PreCompoundFragmentVector(theFragmentsFactory->GetFragmentVector());
100 }
101}
102
105{
106 // Choose a Fragment for emission
107 G4VPreCompoundFragment * thePreFragment =
108 theFragmentsVector->ChooseFragment();
109 if (thePreFragment == nullptr)
110 {
111 G4cout << "G4PreCompoundEmission::PerformEmission : "
112 << "I couldn't choose a fragment\n"
113 << "while trying to de-excite\n"
114 << aFragment << G4endl;
115 throw G4HadronicException(__FILE__, __LINE__, "");
116 }
117
118 //G4cout << "Chosen fragment: " << G4endl;
119 //G4cout << *thePreFragment << G4endl;
120
121 // Kinetic Energy of emitted fragment
122 G4double kinEnergy = thePreFragment->SampleKineticEnergy(aFragment);
123 kinEnergy = std::max(kinEnergy, 0.0);
124
125 // Calculate the fragment momentum (three vector)
126 if(fUseAngularGenerator) {
127 AngularDistribution(thePreFragment,aFragment,kinEnergy);
128 } else {
129 G4double pmag =
130 std::sqrt(kinEnergy*(kinEnergy + 2.0*thePreFragment->GetNuclearMass()));
131 theFinalMomentum = pmag*G4RandomDirection();
132 }
133
134 // Mass of emittef fragment
135 G4double EmittedMass = thePreFragment->GetNuclearMass();
136 // Now we can calculate the four momentum
137 // both options are valid and give the same result but 2nd one is faster
138 G4LorentzVector Emitted4Momentum(theFinalMomentum,EmittedMass + kinEnergy);
139
140 // Perform Lorentz boost
141 G4LorentzVector Rest4Momentum = aFragment.GetMomentum();
142 Emitted4Momentum.boost(Rest4Momentum.boostVector());
143
144 // Set emitted fragment momentum
145 thePreFragment->SetMomentum(Emitted4Momentum);
146
147 // NOW THE RESIDUAL NUCLEUS
148 // ------------------------
149
150 Rest4Momentum -= Emitted4Momentum;
151
152 // Update nucleus parameters:
153 // --------------------------
154
155 // Z and A
156 aFragment.SetZandA_asInt(thePreFragment->GetRestZ(),
157 thePreFragment->GetRestA());
158
159 // Number of excitons
160 aFragment.SetNumberOfParticles(aFragment.GetNumberOfParticles()-
161 thePreFragment->GetA());
162 // Number of charges
163 aFragment.SetNumberOfCharged(aFragment.GetNumberOfCharged()-
164 thePreFragment->GetZ());
165
166 // Update nucleus momentum
167 // A check on consistence of Z, A, and mass will be performed
168 aFragment.SetMomentum(Rest4Momentum);
169
170 // Create a G4ReactionProduct
171 G4ReactionProduct * MyRP = thePreFragment->GetReactionProduct();
172
173 // Set the creator model ID
174 aFragment.SetCreatorModelID(fModelID);
175 if (MyRP != nullptr) MyRP->SetCreatorModelID(fModelID);
176
177 return MyRP;
178}
179
180void G4PreCompoundEmission::AngularDistribution(
181 G4VPreCompoundFragment* thePreFragment,
182 const G4Fragment& aFragment,
183 G4double ekin)
184{
185 G4int p = aFragment.GetNumberOfParticles();
186 G4int h = aFragment.GetNumberOfHoles();
187 G4double U = aFragment.GetExcitationEnergy();
188
189 // Emission particle separation energy
190 G4double Bemission = thePreFragment->GetBindingEnergy();
191
192 G4double gg = (6.0/pi2)*fNuclData->GetLevelDensity(aFragment.GetZ_asInt(),
193 aFragment.GetA_asInt(),U);
194
195 // Average exciton energy relative to bottom of nuclear well
196 G4double Eav = 2*p*(p+1)/((p+h)*gg);
197
198 // Excitation energy relative to the Fermi Level
199 G4double Uf = std::max(U - (p - h)*fFermiEnergy , 0.0);
200 // G4double Uf = U - KineticEnergyOfEmittedFragment - Bemission;
201
202 G4double w_num = rho(p+1, h, gg, Uf, fFermiEnergy);
203 G4double w_den = rho(p, h, gg, Uf, fFermiEnergy);
204 if (w_num > 0.0 && w_den > 0.0)
205 {
206 Eav *= (w_num/w_den);
207 Eav += - Uf/(p+h) + fFermiEnergy;
208 }
209 else
210 {
211 Eav = fFermiEnergy;
212 }
213
214 // VI + JMQ 19/01/2010 update computation of the parameter an
215 //
216 G4double an = 0.0;
217 G4double Eeff = ekin + Bemission + fFermiEnergy;
218 if(ekin > DBL_MIN && Eeff > DBL_MIN) {
219
220 G4double zeta = std::max(1.0,9.3/std::sqrt(ekin/CLHEP::MeV));
221
222 // This should be the projectile energy. If I would know which is
223 // the projectile (proton, neutron) I could remove the binding energy.
224 // But, what happens if INC precedes precompound? This approximation
225 // seems to work well enough
226 G4double ProjEnergy = aFragment.GetExcitationEnergy();
227
228 an = 3*std::sqrt((ProjEnergy+fFermiEnergy)*Eeff)/(zeta*Eav);
229
230 G4int ne = aFragment.GetNumberOfExcitons() - 1;
231 if ( ne > 1 ) { an /= static_cast<G4double>(ne); }
232
233 // protection of exponent
234 if ( an > 10. ) { an = 10.; }
235 }
236
237 // sample cosine of theta and not theta as in old versions
238 G4double random = G4UniformRand();
239 G4double cost;
240
241 if(an < 0.1) { cost = 1. - 2*random; }
242 else {
243 G4double exp2an = G4Exp(-2*an);
244 cost = 1. + G4Log(1-random*(1-exp2an))/an;
245 if(cost > 1.) { cost = 1.; }
246 else if(cost < -1.) {cost = -1.; }
247 }
248
249 G4double phi = CLHEP::twopi*G4UniformRand();
250
251 // Calculate the momentum magnitude of emitted fragment
252 G4double pmag =
253 std::sqrt(ekin*(ekin + 2.0*thePreFragment->GetNuclearMass()));
254
255 G4double sint = std::sqrt((1.0-cost)*(1.0+cost));
256
257 theFinalMomentum.set(pmag*std::cos(phi)*sint,pmag*std::sin(phi)*sint,
258 pmag*cost);
259
260 // theta is the angle wrt the incident direction
261 G4ThreeVector theIncidentDirection = aFragment.GetMomentum().vect().unit();
262 theFinalMomentum.rotateUz(theIncidentDirection);
263}
264
265G4double G4PreCompoundEmission::rho(G4int p, G4int h, G4double gg,
266 G4double E, G4double Ef) const
267{
268 // 25.02.2010 V.Ivanchenko added more protections
269 G4double Aph = (p*p + h*h + p - 3.0*h)/(4.0*gg);
270
271 if ( E - Aph < 0.0) { return 0.0; }
272
273 G4double logConst = (p+h)*G4Log(gg)
274 - g4calc->logfactorial(p+h-1) - g4calc->logfactorial(p)
275 - g4calc->logfactorial(h);
276
277 // initialise values using j=0
278
279 G4double t1=1;
280 G4double t2=1;
281 G4double logt3 = (p+h-1) * G4Log(E-Aph) + logConst;
282 const G4double logmax = 200.;
283 if(logt3 > logmax) { logt3 = logmax; }
284 G4double tot = G4Exp( logt3 );
285
286 // and now sum rest of terms
287 // 25.02.2010 V.Ivanchenko change while to for loop and cleanup
288 G4double Eeff = E - Aph;
289 for(G4int j=1; j<=h; ++j)
290 {
291 Eeff -= Ef;
292 if(Eeff < 0.0) { break; }
293 t1 *= -1.;
294 t2 *= static_cast<G4double>(h+1-j)/static_cast<G4double>(j);
295 logt3 = (p+h-1) * G4Log( Eeff) + logConst;
296 if(logt3 > logmax) { logt3 = logmax; }
297 tot += t1*t2*G4Exp(logt3);
298 }
299
300 return tot;
301}
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:180
G4double G4Log(G4double x)
Definition: G4Log.hh:227
G4ThreeVector G4RandomDirection()
double G4double
Definition: G4Types.hh:83
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
Hep3Vector unit() const
void set(double x, double y, double z)
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:33
Hep3Vector boostVector() const
HepLorentzVector & boost(double, double, double)
Hep3Vector vect() const
G4int GetNumberOfParticles() const
Definition: G4Fragment.hh:366
G4int GetNumberOfHoles() const
Definition: G4Fragment.hh:386
void SetZandA_asInt(G4int Znew, G4int Anew, G4int Lnew=0)
Definition: G4Fragment.hh:295
void SetNumberOfCharged(G4int value)
Definition: G4Fragment.hh:410
G4double GetExcitationEnergy() const
Definition: G4Fragment.hh:312
const G4LorentzVector & GetMomentum() const
Definition: G4Fragment.hh:322
void SetCreatorModelID(G4int value)
Definition: G4Fragment.hh:433
G4int GetZ_asInt() const
Definition: G4Fragment.hh:289
G4int GetNumberOfExcitons() const
Definition: G4Fragment.hh:361
void SetMomentum(const G4LorentzVector &value)
Definition: G4Fragment.hh:327
void SetNumberOfParticles(G4int value)
Definition: G4Fragment.hh:405
G4int GetNumberOfCharged() const
Definition: G4Fragment.hh:371
G4int GetA_asInt() const
Definition: G4Fragment.hh:284
G4double GetLevelDensity(G4int Z, G4int A, G4double U)
G4DeexPrecoParameters * GetParameters()
static G4NuclearLevelData * GetInstance()
static G4int GetModelID(const G4int modelIndex)
static G4Pow * GetInstance()
Definition: G4Pow.cc:41
G4double logfactorial(G4int Z) const
Definition: G4Pow.hh:237
G4ReactionProduct * PerformEmission(G4Fragment &aFragment)
G4VPreCompoundFragment * ChooseFragment()
void SetCreatorModelID(const G4int mod)
std::vector< G4VPreCompoundFragment * > * GetFragmentVector()
virtual G4double SampleKineticEnergy(const G4Fragment &aFragment)=0
G4double GetNuclearMass() const
G4double GetBindingEnergy() const
G4int GetRestZ() const
G4ReactionProduct * GetReactionProduct() const
void SetMomentum(const G4LorentzVector &value)
G4int GetRestA() const
#define DBL_MIN
Definition: templates.hh:54