source: trunk/source/processes/hadronic/util/src/G4Nucleus.cc@ 1340

Last change on this file since 1340 was 1315, checked in by garnier, 15 years ago

update geant4-09-04-beta-cand-01 interfaces-V09-03-09 vis-V09-03-08

File size: 14.6 KB
Line 
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 // original by H.P. Wellisch
29 // modified by J.L. Chuma, TRIUMF, 19-Nov-1996
30 // last modified: 27-Mar-1997
31 // J.P.Wellisch: 23-Apr-97: minor simplifications
32 // modified by J.L.Chuma 24-Jul-97 to set the total momentum in Cinema and
33 // EvaporationEffects
34 // modified by J.L.Chuma 21-Oct-97 put std::abs() around the totalE^2-mass^2
35 // in calculation of total momentum in
36 // Cinema and EvaporationEffects
37 // Chr. Volcker, 10-Nov-1997: new methods and class variables.
38 // HPW added utilities for low energy neutron transport. (12.04.1998)
39 // M.G. Pia, 2 Oct 1998: modified GetFermiMomentum to avoid memory leaks
40 // G.Folger, spring 2010: add integer A/Z interface
41
42#include "G4Nucleus.hh"
43#include "G4NucleiProperties.hh"
44#include "Randomize.hh"
45#include "G4HadronicException.hh"
46
47G4Nucleus::G4Nucleus()
48{
49 pnBlackTrackEnergy = 0.0;
50 dtaBlackTrackEnergy = 0.0;
51 pnBlackTrackEnergyfromAnnihilation = 0.0;
52 dtaBlackTrackEnergyfromAnnihilation = 0.0;
53 excitationEnergy = 0.0;
54 momentum = G4ThreeVector(0.,0.,0.);
55 fermiMomentum = 1.52*hbarc/fermi;
56 theTemp = 293.16*kelvin;
57}
58
59G4Nucleus::G4Nucleus( const G4double A, const G4double Z )
60{
61 SetParameters( A, Z );
62 pnBlackTrackEnergy = 0.0;
63 dtaBlackTrackEnergy = 0.0;
64 pnBlackTrackEnergyfromAnnihilation = 0.0;
65 dtaBlackTrackEnergyfromAnnihilation = 0.0;
66 excitationEnergy = 0.0;
67 momentum = G4ThreeVector(0.,0.,0.);
68 fermiMomentum = 1.52*hbarc/fermi;
69 theTemp = 293.16*kelvin;
70}
71
72G4Nucleus::G4Nucleus( const G4int A, const G4int Z )
73{
74 SetParameters( A, Z );
75 pnBlackTrackEnergy = 0.0;
76 dtaBlackTrackEnergy = 0.0;
77 pnBlackTrackEnergyfromAnnihilation = 0.0;
78 dtaBlackTrackEnergyfromAnnihilation = 0.0;
79 excitationEnergy = 0.0;
80 momentum = G4ThreeVector(0.,0.,0.);
81 fermiMomentum = 1.52*hbarc/fermi;
82 theTemp = 293.16*kelvin;
83}
84
85G4Nucleus::G4Nucleus( const G4Material *aMaterial )
86{
87 ChooseParameters( aMaterial );
88 pnBlackTrackEnergy = 0.0;
89 dtaBlackTrackEnergy = 0.0;
90 pnBlackTrackEnergyfromAnnihilation = 0.0;
91 dtaBlackTrackEnergyfromAnnihilation = 0.0;
92 excitationEnergy = 0.0;
93 momentum = G4ThreeVector(0.,0.,0.);
94 fermiMomentum = 1.52*hbarc/fermi;
95 theTemp = aMaterial->GetTemperature();
96}
97
98G4Nucleus::~G4Nucleus() {}
99
100G4ReactionProduct G4Nucleus::
101GetBiasedThermalNucleus(G4double aMass, G4ThreeVector aVelocity, G4double temp) const
102{
103 G4double velMag = aVelocity.mag();
104 G4ReactionProduct result;
105 G4double value = 0;
106 G4double random = 1;
107 G4double norm = 3.*std::sqrt(k_Boltzmann*temp*aMass*G4Neutron::Neutron()->GetPDGMass());
108 norm /= G4Neutron::Neutron()->GetPDGMass();
109 norm *= 5.;
110 norm += velMag;
111 norm /= velMag;
112 while(value/norm<random)
113 {
114 result = GetThermalNucleus(aMass, temp);
115 G4ThreeVector targetVelocity = 1./result.GetMass()*result.GetMomentum();
116 value = (targetVelocity+aVelocity).mag()/velMag;
117 random = G4UniformRand();
118 }
119 return result;
120}
121
122G4ReactionProduct G4Nucleus::GetThermalNucleus(G4double targetMass, G4double temp) const
123 {
124 G4double currentTemp = temp;
125 if(currentTemp < 0) currentTemp = theTemp;
126 G4ReactionProduct theTarget;
127 theTarget.SetMass(targetMass*G4Neutron::Neutron()->GetPDGMass());
128 G4double px, py, pz;
129 px = GetThermalPz(theTarget.GetMass(), currentTemp);
130 py = GetThermalPz(theTarget.GetMass(), currentTemp);
131 pz = GetThermalPz(theTarget.GetMass(), currentTemp);
132 theTarget.SetMomentum(px, py, pz);
133 G4double tMom = std::sqrt(px*px+py*py+pz*pz);
134 G4double tEtot = std::sqrt((tMom+theTarget.GetMass())*
135 (tMom+theTarget.GetMass())-
136 2.*tMom*theTarget.GetMass());
137 if(1-tEtot/theTarget.GetMass()>0.001)
138 {
139 theTarget.SetTotalEnergy(tEtot);
140 }
141 else
142 {
143 theTarget.SetKineticEnergy(tMom*tMom/(2.*theTarget.GetMass()));
144 }
145 return theTarget;
146 }
147
148 void
149 G4Nucleus::ChooseParameters( const G4Material *aMaterial )
150 {
151 G4double random = G4UniformRand();
152 G4double sum = aMaterial->GetTotNbOfAtomsPerVolume();
153 const G4ElementVector *theElementVector = aMaterial->GetElementVector();
154 G4double running(0);
155 G4Element* element(0);
156 for(unsigned int i=0; i<aMaterial->GetNumberOfElements(); ++i )
157 {
158 running += aMaterial->GetVecNbOfAtomsPerVolume()[i];
159 if( running > random*sum ) {
160 element=(*theElementVector)[i];
161 break;
162 }
163 }
164 if ( element->GetNumberOfIsotopes() > 0 ) {
165 G4double randomAbundance = G4UniformRand();
166 G4double sumAbundance = element->GetRelativeAbundanceVector()[0];
167 unsigned int iso=0;
168 while ( iso < element->GetNumberOfIsotopes() &&
169 sumAbundance < randomAbundance ) {
170 ++iso;
171 sumAbundance += element->GetRelativeAbundanceVector()[iso];
172 }
173 theA=element->GetIsotope(iso)->GetN();
174 theZ=element->GetIsotope(iso)->GetZ();
175 aEff=theA;
176 zEff=theZ;
177 } else {
178 aEff = element->GetN();
179 zEff = element->GetZ();
180 theZ = G4int(zEff + 0.5);
181 theA = G4int(aEff + 0.5);
182 }
183 }
184
185 void
186 G4Nucleus::SetParameters( const G4double A, const G4double Z )
187 {
188 theZ = G4int(Z + 0.5);
189 theA = G4int(A + 0.5);
190 if( theA<1 || theZ<0 || theZ>theA )
191 {
192 throw G4HadronicException(__FILE__, __LINE__,
193 "G4Nucleus::SetParameters called with non-physical parameters");
194 }
195 aEff = A; // atomic weight
196 zEff = Z; // atomic number
197 }
198
199 void
200 G4Nucleus::SetParameters( const G4int A, const G4int Z )
201 {
202 theZ = Z;
203 theA = A;
204 if( theA<1 || theZ<0 || theZ>theA )
205 {
206 throw G4HadronicException(__FILE__, __LINE__,
207 "G4Nucleus::SetParameters called with non-physical parameters");
208 }
209 aEff = A; // atomic weight
210 zEff = Z; // atomic number
211 }
212
213 G4DynamicParticle *
214 G4Nucleus::ReturnTargetParticle() const
215 {
216 // choose a proton or a neutron as the target particle
217
218 G4DynamicParticle *targetParticle = new G4DynamicParticle;
219 if( G4UniformRand() < zEff/aEff )
220 targetParticle->SetDefinition( G4Proton::Proton() );
221 else
222 targetParticle->SetDefinition( G4Neutron::Neutron() );
223 return targetParticle;
224 }
225
226 G4double
227 G4Nucleus::AtomicMass( const G4double A, const G4double Z ) const
228 {
229 // Now returns (atomic mass - electron masses)
230 return G4NucleiProperties::GetNuclearMass(A, Z);
231 }
232
233 G4double
234 G4Nucleus::AtomicMass( const G4int A, const G4int Z ) const
235 {
236 // Now returns (atomic mass - electron masses)
237 return G4NucleiProperties::GetNuclearMass(A, Z);
238 }
239
240 G4double
241 G4Nucleus::GetThermalPz( const G4double mass, const G4double temp ) const
242 {
243 G4double result = G4RandGauss::shoot();
244 result *= std::sqrt(k_Boltzmann*temp*mass); // Das ist impuls (Pz),
245 // nichtrelativistische rechnung
246 // Maxwell verteilung angenommen
247 return result;
248 }
249
250 G4double
251 G4Nucleus::EvaporationEffects( G4double kineticEnergy )
252 {
253 // derived from original FORTRAN code EXNU by H. Fesefeldt (10-Dec-1986)
254 //
255 // Nuclear evaporation as function of atomic number
256 // and kinetic energy (MeV) of primary particle
257 //
258 // returns kinetic energy (MeV)
259 //
260 if( aEff < 1.5 )
261 {
262 pnBlackTrackEnergy = dtaBlackTrackEnergy = 0.0;
263 return 0.0;
264 }
265 G4double ek = kineticEnergy/GeV;
266 G4float ekin = std::min( 4.0, std::max( 0.1, ek ) );
267 const G4float atno = std::min( 120., aEff );
268 const G4float gfa = 2.0*((aEff-1.0)/70.)*std::exp(-(aEff-1.0)/70.);
269 //
270 // 0.35 value at 1 GeV
271 // 0.05 value at 0.1 GeV
272 //
273 G4float cfa = std::max( 0.15, 0.35 + ((0.35-0.05)/2.3)*std::log(ekin) );
274 G4float exnu = 7.716 * cfa * std::exp(-cfa)
275 * ((atno-1.0)/120.)*std::exp(-(atno-1.0)/120.);
276 G4float fpdiv = std::max( 0.5, 1.0-0.25*ekin*ekin );
277 //
278 // pnBlackTrackEnergy is the kinetic energy (in GeV) available for
279 // proton/neutron black track particles
280 // dtaBlackTrackEnergy is the kinetic energy (in GeV) available for
281 // deuteron/triton/alpha black track particles
282 //
283 pnBlackTrackEnergy = exnu*fpdiv;
284 dtaBlackTrackEnergy = exnu*(1.0-fpdiv);
285
286 if( G4int(zEff+0.1) != 82 )
287 {
288 G4double ran1 = -6.0;
289 G4double ran2 = -6.0;
290 for( G4int i=0; i<12; ++i )
291 {
292 ran1 += G4UniformRand();
293 ran2 += G4UniformRand();
294 }
295 pnBlackTrackEnergy *= 1.0 + ran1*gfa;
296 dtaBlackTrackEnergy *= 1.0 + ran2*gfa;
297 }
298 pnBlackTrackEnergy = std::max( 0.0, pnBlackTrackEnergy );
299 dtaBlackTrackEnergy = std::max( 0.0, dtaBlackTrackEnergy );
300 while( pnBlackTrackEnergy+dtaBlackTrackEnergy >= ek )
301 {
302 pnBlackTrackEnergy *= 1.0 - 0.5*G4UniformRand();
303 dtaBlackTrackEnergy *= 1.0 - 0.5*G4UniformRand();
304 }
305// G4cout << "EvaporationEffects "<<kineticEnergy<<" "
306// <<pnBlackTrackEnergy+dtaBlackTrackEnergy<<endl;
307 return (pnBlackTrackEnergy+dtaBlackTrackEnergy)*GeV;
308 }
309
310 G4double G4Nucleus::AnnihilationEvaporationEffects(G4double kineticEnergy, G4double ekOrg)
311 {
312 // Nuclear evaporation as a function of atomic number and kinetic
313 // energy (MeV) of primary particle. Modified for annihilation effects.
314 //
315 if( aEff < 1.5 || ekOrg < 0.)
316 {
317 pnBlackTrackEnergyfromAnnihilation = 0.0;
318 dtaBlackTrackEnergyfromAnnihilation = 0.0;
319 return 0.0;
320 }
321 G4double ek = kineticEnergy/GeV;
322 G4float ekin = std::min( 4.0, std::max( 0.1, ek ) );
323 const G4float atno = std::min( 120., aEff );
324 const G4float gfa = 2.0*((aEff-1.0)/70.)*std::exp(-(aEff-1.0)/70.);
325
326 G4float cfa = std::max( 0.15, 0.35 + ((0.35-0.05)/2.3)*std::log(ekin) );
327 G4float exnu = 7.716 * cfa * std::exp(-cfa)
328 * ((atno-1.0)/120.)*std::exp(-(atno-1.0)/120.);
329 G4float fpdiv = std::max( 0.5, 1.0-0.25*ekin*ekin );
330
331 pnBlackTrackEnergyfromAnnihilation = exnu*fpdiv;
332 dtaBlackTrackEnergyfromAnnihilation = exnu*(1.0-fpdiv);
333
334 G4double ran1 = -6.0;
335 G4double ran2 = -6.0;
336 for( G4int i=0; i<12; ++i ) {
337 ran1 += G4UniformRand();
338 ran2 += G4UniformRand();
339 }
340 pnBlackTrackEnergyfromAnnihilation *= 1.0 + ran1*gfa;
341 dtaBlackTrackEnergyfromAnnihilation *= 1.0 + ran2*gfa;
342
343 pnBlackTrackEnergyfromAnnihilation = std::max( 0.0, pnBlackTrackEnergyfromAnnihilation);
344 dtaBlackTrackEnergyfromAnnihilation = std::max( 0.0, dtaBlackTrackEnergyfromAnnihilation);
345 G4double blackSum = pnBlackTrackEnergyfromAnnihilation+dtaBlackTrackEnergyfromAnnihilation;
346 if (blackSum >= ekOrg/GeV) {
347 pnBlackTrackEnergyfromAnnihilation *= ekOrg/GeV/blackSum;
348 dtaBlackTrackEnergyfromAnnihilation *= ekOrg/GeV/blackSum;
349 }
350
351 return (pnBlackTrackEnergyfromAnnihilation+dtaBlackTrackEnergyfromAnnihilation)*GeV;
352 }
353
354 G4double
355 G4Nucleus::Cinema( G4double kineticEnergy )
356 {
357 // derived from original FORTRAN code CINEMA by H. Fesefeldt (14-Oct-1987)
358 //
359 // input: kineticEnergy (MeV)
360 // returns modified kinetic energy (MeV)
361 //
362 static const G4double expxu = 82.; // upper bound for arg. of exp
363 static const G4double expxl = -expxu; // lower bound for arg. of exp
364
365 G4double ek = kineticEnergy/GeV;
366 G4double ekLog = std::log( ek );
367 G4double aLog = std::log( aEff );
368 G4double em = std::min( 1.0, 0.2390 + 0.0408*aLog*aLog );
369 G4double temp1 = -ek * std::min( 0.15, 0.0019*aLog*aLog*aLog );
370 G4double temp2 = std::exp( std::max( expxl, std::min( expxu, -(ekLog-em)*(ekLog-em)*2.0 ) ) );
371 G4double result = 0.0;
372 if( std::abs( temp1 ) < 1.0 )
373 {
374 if( temp2 > 1.0e-10 )result = temp1*temp2;
375 }
376 else result = temp1*temp2;
377 if( result < -ek )result = -ek;
378 return result*GeV;
379 }
380
381 //
382 // methods for class G4Nucleus ... by Christian Volcker
383 //
384
385 G4ThreeVector G4Nucleus::GetFermiMomentum()
386 {
387 // chv: .. we assume zero temperature!
388
389 // momentum is equally distributed in each phasespace volume dpx, dpy, dpz.
390 G4double ranflat1=
391 CLHEP::RandFlat::shoot((G4double)0.,(G4double)fermiMomentum);
392 G4double ranflat2=
393 CLHEP::RandFlat::shoot((G4double)0.,(G4double)fermiMomentum);
394 G4double ranflat3=
395 CLHEP::RandFlat::shoot((G4double)0.,(G4double)fermiMomentum);
396 G4double ranmax = (ranflat1>ranflat2? ranflat1: ranflat2);
397 ranmax = (ranmax>ranflat3? ranmax : ranflat3);
398
399 // Isotropic momentum distribution
400 G4double costheta = 2.*G4UniformRand() - 1.0;
401 G4double sintheta = std::sqrt(1.0 - costheta*costheta);
402 G4double phi = 2.0*pi*G4UniformRand();
403
404 G4double pz=costheta*ranmax;
405 G4double px=sintheta*std::cos(phi)*ranmax;
406 G4double py=sintheta*std::sin(phi)*ranmax;
407 G4ThreeVector p(px,py,pz);
408 return p;
409 }
410
411 G4ReactionProductVector* G4Nucleus::Fragmentate()
412 {
413 // needs implementation!
414 return NULL;
415 }
416
417 void G4Nucleus::AddMomentum(const G4ThreeVector aMomentum)
418 {
419 momentum+=(aMomentum);
420 }
421
422 void G4Nucleus::AddExcitationEnergy( G4double anEnergy )
423 {
424 excitationEnergy+=anEnergy;
425 }
426
427 /* end of file */
428
Note: See TracBrowser for help on using the repository browser.