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