Geant4 9.6.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
G4LEPionMinusInelastic.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// Hadronic Process: PionMinus Inelastic Process
27// J.L. Chuma, TRIUMF, 19-Nov-1996
28// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
29
30#include <iostream>
31
34#include "G4SystemOfUnits.hh"
35#include "Randomize.hh"
36
39{
40 SetMinEnergy(0.0);
41 SetMaxEnergy(55.*GeV);
42 G4cout << "WARNING: model G4LEPionMinusInelastic is being deprecated and will\n"
43 << "disappear in Geant4 version 10.0" << G4endl;
44}
45
46
47void G4LEPionMinusInelastic::ModelDescription(std::ostream& outFile) const
48{
49 outFile << "G4LEPionMinusInelastic is one of the Low Energy Parameterized\n"
50 << "(LEP) models used to implement inelastic pi- scattering\n"
51 << "from nuclei. It is a re-engineered version of the GHEISHA\n"
52 << "code of H. Fesefeldt. It divides the initial collision\n"
53 << "products into backward- and forward-going clusters which are\n"
54 << "then decayed into final state hadrons. The model does not\n"
55 << "conserve energy on an event-by-event basis. It may be\n"
56 << "applied to pions with initial energies between 0 and 25\n"
57 << "GeV.\n";
58}
59
60
63 G4Nucleus& targetNucleus)
64{
65 const G4HadProjectile *originalIncident = &aTrack;
66 if (originalIncident->GetKineticEnergy()<= 0.1*MeV) {
70 return &theParticleChange;
71 }
72
73 // create the target particle
74 G4DynamicParticle* originalTarget = targetNucleus.ReturnTargetParticle();
75 G4ReactionProduct targetParticle( originalTarget->GetDefinition() );
76
77 if (verboseLevel > 1) {
78 const G4Material* targetMaterial = aTrack.GetMaterial();
79 G4cout << "G4PionMinusInelastic::ApplyYourself called" << G4endl;
80 G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy() << "MeV, ";
81 G4cout << "target material = " << targetMaterial->GetName() << ", ";
82 G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
83 << G4endl;
84 }
85 G4ReactionProduct currentParticle(
86 const_cast<G4ParticleDefinition *>(originalIncident->GetDefinition() ) );
87 currentParticle.SetMomentum( originalIncident->Get4Momentum().vect() );
88 currentParticle.SetKineticEnergy( originalIncident->GetKineticEnergy() );
89
90 // Fermi motion and evaporation
91 // As of Geant3, the Fermi energy calculation had not been Done
92 G4double ek = originalIncident->GetKineticEnergy();
93 G4double amas = originalIncident->GetDefinition()->GetPDGMass();
94
95 G4double tkin = targetNucleus.Cinema(ek);
96 ek += tkin;
97 currentParticle.SetKineticEnergy(ek);
98 G4double et = ek + amas;
99 G4double p = std::sqrt( std::abs((et-amas)*(et+amas)) );
100 G4double pp = currentParticle.GetMomentum().mag();
101 if (pp > 0.0) {
102 G4ThreeVector momentum = currentParticle.GetMomentum();
103 currentParticle.SetMomentum(momentum * (p/pp) );
104 }
105
106 // calculate black track energies
107 tkin = targetNucleus.EvaporationEffects(ek);
108 ek -= tkin;
109 currentParticle.SetKineticEnergy(ek);
110 et = ek + amas;
111 p = std::sqrt( std::abs((et-amas)*(et+amas)) );
112 pp = currentParticle.GetMomentum().mag();
113 if (pp > 0.0) {
114 G4ThreeVector momentum = currentParticle.GetMomentum();
115 currentParticle.SetMomentum( momentum * (p/pp) );
116 }
117
118 G4ReactionProduct modifiedOriginal = currentParticle;
119
120 currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
121 targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
122 G4bool incidentHasChanged = false;
123 G4bool targetHasChanged = false;
124 G4bool quasiElastic = false;
125 G4FastVector<G4ReactionProduct,GHADLISTSIZE> vec; // vec will contain the secondary particles
126 G4int vecLen = 0;
127 vec.Initialize(0);
128
129 const G4double cutOff = 0.1*MeV;
130 if (currentParticle.GetKineticEnergy() > cutOff)
131 Cascade(vec, vecLen, originalIncident, currentParticle, targetParticle,
132 incidentHasChanged, targetHasChanged, quasiElastic);
133
134 CalculateMomenta(vec, vecLen, originalIncident, originalTarget,
135 modifiedOriginal, targetNucleus, currentParticle,
136 targetParticle, incidentHasChanged, targetHasChanged,
137 quasiElastic);
138
139 SetUpChange(vec, vecLen, currentParticle, targetParticle, incidentHasChanged);
140
141 if (isotopeProduction) DoIsotopeCounting(originalIncident, targetNucleus);
142
143 delete originalTarget;
144 return &theParticleChange;
145}
146
147
148void
149G4LEPionMinusInelastic::Cascade(
151 G4int& vecLen,
152 const G4HadProjectile* originalIncident,
153 G4ReactionProduct& currentParticle,
154 G4ReactionProduct& targetParticle,
155 G4bool& incidentHasChanged,
156 G4bool& targetHasChanged,
157 G4bool& quasiElastic)
158{
159 // derived from original FORTRAN code CASPIM by H. Fesefeldt (13-Sep-1987)
160 //
161 // pi- undergoes interaction with nucleon within nucleus.
162 // Check if energetically possible to produce pions/kaons.
163 // If not assume nuclear excitation occurs and input particle
164 // is degraded in energy. No other particles produced.
165 // If reaction is possible find correct number of pions/protons/neutrons
166 // produced using an interpolation to multiplicity data.
167 // Replace some pions or protons/neutrons by kaons or strange baryons
168 // according to average multiplicity per inelastic reactions.
169
170 const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass();
171 const G4double etOriginal = originalIncident->GetTotalEnergy();
172 const G4double pOriginal = originalIncident->GetTotalMomentum();
173 const G4double targetMass = targetParticle.GetMass();
174 G4double centerofmassEnergy = std::sqrt(mOriginal*mOriginal +
175 targetMass*targetMass +
176 2.0*targetMass*etOriginal);
177 G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
178 static G4bool first = true;
179 const G4int numMul = 1200;
180 const G4int numSec = 60;
181 static G4double protmul[numMul], protnorm[numSec]; // proton constants
182 static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
183
184 // npos = number of pi+, nneg = number of pi-, nzero = number of pi0
185 G4int counter, nt=0, npos=0, nneg=0, nzero=0;
186 const G4double c = 1.25;
187 const G4double b[] = { 0.70, 0.70 };
188 if( first ) // compute normalization constants, this will only be Done once
189 {
190 first = false;
191 G4int i;
192 for( i=0; i<numMul; ++i )protmul[i] = 0.0;
193 for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
194 counter = -1;
195 for( npos=0; npos<(numSec/3); ++npos )
196 {
197 for( nneg=std::max(0,npos-1); nneg<=(npos+1); ++nneg )
198 {
199 for( nzero=0; nzero<numSec/3; ++nzero )
200 {
201 if( ++counter < numMul )
202 {
203 nt = npos+nneg+nzero;
204 if( nt > 0 )
205 {
206 protmul[counter] = Pmltpc(npos,nneg,nzero,nt,b[0],c);
207 protnorm[nt-1] += protmul[counter];
208 }
209 }
210 }
211 }
212 }
213 for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
214 for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
215 counter = -1;
216 for( npos=0; npos<numSec/3; ++npos )
217 {
218 for( nneg=npos; nneg<=(npos+2); ++nneg )
219 {
220 for( nzero=0; nzero<numSec/3; ++nzero )
221 {
222 if( ++counter < numMul )
223 {
224 nt = npos+nneg+nzero;
225 if( (nt>0) && (nt<=numSec) )
226 {
227 neutmul[counter] = Pmltpc(npos,nneg,nzero,nt,b[1],c);
228 neutnorm[nt-1] += neutmul[counter];
229 }
230 }
231 }
232 }
233 }
234 for( i=0; i<numSec; ++i )
235 {
236 if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
237 if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
238 }
239 } // end of initialization
240
241 const G4double expxu = 82.; // upper bound for arg. of exp
242 const G4double expxl = -expxu; // lower bound for arg. of exp
246 G4int ieab = G4int(availableEnergy*5.0/GeV);
247 const G4double supp[] = {0.,0.4,0.55,0.65,0.75,0.82,0.86,0.90,0.94,0.98};
248 G4double test, w0, wp, wt, wm;
249 if( (availableEnergy<2.0*GeV) && (G4UniformRand()>=supp[ieab]) )
250 {
251 // suppress high multiplicity events at low momentum
252 // only one pion will be produced
253
254 // charge exchange reaction is included in inelastic cross section
255
256 const G4double cech[] = {1.,0.95,0.79,0.32,0.19,0.16,0.14,0.12,0.10,0.08};
257 G4int iplab = G4int(std::min( 9.0, pOriginal/GeV*5.0 ));
258 if( G4UniformRand() <= cech[iplab] )
259 {
260 if( targetParticle.GetDefinition() == aProton )
261 {
262 currentParticle.SetDefinitionAndUpdateE( aPiZero ); // charge exchange
263 targetParticle.SetDefinitionAndUpdateE( aNeutron );
264 incidentHasChanged = true;
265 targetHasChanged = true;
266 }
267 }
268
269 if( availableEnergy <= G4PionMinus::PionMinus()->GetPDGMass() )
270 {
271 quasiElastic = true;
272 return;
273 }
274
275 nneg = npos = nzero = 0;
276 if( targetParticle.GetDefinition() == aProton )
277 {
278 test = std::exp( std::min( expxu, std::max( expxl, -(1.0+b[0])*(1.0+b[0])/(2.0*c*c) ) ) );
279 w0 = test;
280 wp = 10.0*test;
281 test = std::exp( std::min( expxu, std::max( expxl, -(-1.0+b[0])*(-1.0+b[0])/(2.0*c*c) ) ) );
282 wm = test;
283 wt = w0+wp+wm;
284 wp += w0;
285 G4double ran = G4UniformRand();
286 if( ran < w0/wt )
287 nzero = 1;
288 else if( ran < wp/wt )
289 npos = 1;
290 else
291 nneg = 1;
292 }
293 else // target is a neutron
294 {
295 test = std::exp( std::min( expxu, std::max( expxl, -(1.0+b[1])*(1.0+b[1])/(2.0*c*c) ) ) );
296 w0 = test;
297 test = std::exp( std::min( expxu, std::max( expxl, -(-1.0+b[1])*(-1.0+b[1])/(2.0*c*c) ) ) );
298 wm = test;
299 G4double ran = G4UniformRand();
300 if( ran < w0/(w0+wm) )
301 nzero = 1;
302 else
303 nneg = 1;
304 }
305 }
306 else
307 {
308 if( availableEnergy <= G4PionMinus::PionMinus()->GetPDGMass() )
309 {
310 quasiElastic = true;
311 return;
312 }
313 G4double n, anpn;
314 GetNormalizationConstant( availableEnergy, n, anpn );
315 G4double ran = G4UniformRand();
316 G4double dum, excs = 0.0;
317 if( targetParticle.GetDefinition() == aProton )
318 {
319 counter = -1;
320 for( npos=0; (npos<numSec/3) && (ran>=excs); ++npos )
321 {
322 for( nneg=std::max(0,npos-1); (nneg<=(npos+1)) && (ran>=excs); ++nneg )
323 {
324 for( nzero=0; (nzero<numSec/3) && (ran>=excs); ++nzero )
325 {
326 if( ++counter < numMul )
327 {
328 nt = npos+nneg+nzero;
329 if( nt > 0 )
330 {
331 test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
332 dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
333 if( std::fabs(dum) < 1.0 )
334 {
335 if( test >= 1.0e-10 )excs += dum*test;
336 }
337 else
338 excs += dum*test;
339 }
340 }
341 }
342 }
343 }
344 if( ran >= excs ) // 3 previous loops continued to the end
345 {
346 quasiElastic = true;
347 return;
348 }
349 npos--; nneg--; nzero--;
350 }
351 else // target must be a neutron
352 {
353 counter = -1;
354 for( npos=0; (npos<numSec/3) && (ran>=excs); ++npos )
355 {
356 for( nneg=npos; (nneg<=(npos+2)) && (ran>=excs); ++nneg )
357 {
358 for( nzero=0; (nzero<numSec/3) && (ran>=excs); ++nzero )
359 {
360 if( ++counter < numMul )
361 {
362 nt = npos+nneg+nzero;
363 if( (nt>=1) && (nt<=numSec) )
364 {
365 test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
366 dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
367 if( std::fabs(dum) < 1.0 )
368 {
369 if( test >= 1.0e-10 )excs += dum*test;
370 }
371 else
372 excs += dum*test;
373 }
374 }
375 }
376 }
377 }
378 if( ran >= excs ) // 3 previous loops continued to the end
379 {
380 quasiElastic = true;
381 return;
382 }
383 npos--; nneg--; nzero--;
384 }
385 }
386 if( targetParticle.GetDefinition() == aProton )
387 {
388 switch( npos-nneg )
389 {
390 case 0:
391 if( G4UniformRand() >= 0.75 )
392 {
393 currentParticle.SetDefinitionAndUpdateE( aPiZero );
394 targetParticle.SetDefinitionAndUpdateE( aNeutron );
395 incidentHasChanged = true;
396 targetHasChanged = true;
397 }
398 break;
399 case 1:
400 targetParticle.SetDefinitionAndUpdateE( aNeutron );
401 targetHasChanged = true;
402 break;
403 default:
404 currentParticle.SetDefinitionAndUpdateE( aPiZero );
405 incidentHasChanged = true;
406 break;
407 }
408 }
409 else
410 {
411 switch( npos-nneg )
412 {
413 case -1:
414 if( G4UniformRand() < 0.5 )
415 {
416 targetParticle.SetDefinitionAndUpdateE( aProton );
417 targetHasChanged = true;
418 } else {
419 currentParticle.SetDefinitionAndUpdateE( aPiZero );
420 incidentHasChanged = true;
421 }
422 break;
423 case 0:
424 break;
425 default:
426 currentParticle.SetDefinitionAndUpdateE( aPiZero );
427 incidentHasChanged = true;
428 break;
429 }
430 }
431 SetUpPions( npos, nneg, nzero, vec, vecLen );
432 return;
433 }
434
435 /* end of file */
436
@ isAlive
double G4double
Definition: G4Types.hh:64
int G4int
Definition: G4Types.hh:66
bool G4bool
Definition: G4Types.hh:67
#define G4endl
Definition: G4ios.hh:52
G4DLLIMPORT std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:53
Hep3Vector unit() const
double mag() const
Hep3Vector vect() const
G4ParticleDefinition * GetDefinition() const
void Initialize(G4int items)
Definition: G4FastVector.hh:63
void SetStatusChange(G4HadFinalStateStatus aS)
void SetEnergyChange(G4double anEnergy)
void SetMomentumChange(const G4ThreeVector &aV)
const G4Material * GetMaterial() const
G4double GetTotalMomentum() const
const G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4LorentzVector & Get4Momentum() const
G4double GetTotalEnergy() const
void SetMinEnergy(G4double anEnergy)
void SetMaxEnergy(const G4double anEnergy)
G4double Pmltpc(G4int np, G4int nm, G4int nz, G4int n, G4double b, G4double c)
void GetNormalizationConstant(const G4double availableEnergy, G4double &n, G4double &anpn)
void SetUpPions(const G4int np, const G4int nm, const G4int nz, G4FastVector< G4ReactionProduct, GHADLISTSIZE > &vec, G4int &vecLen)
void CalculateMomenta(G4FastVector< G4ReactionProduct, GHADLISTSIZE > &vec, G4int &vecLen, const G4HadProjectile *originalIncident, const G4DynamicParticle *originalTarget, G4ReactionProduct &modifiedOriginal, G4Nucleus &targetNucleus, G4ReactionProduct &currentParticle, G4ReactionProduct &targetParticle, G4bool &incidentHasChanged, G4bool &targetHasChanged, G4bool quasiElastic)
void DoIsotopeCounting(const G4HadProjectile *theProjectile, const G4Nucleus &aNucleus)
void SetUpChange(G4FastVector< G4ReactionProduct, GHADLISTSIZE > &vec, G4int &vecLen, G4ReactionProduct &currentParticle, G4ReactionProduct &targetParticle, G4bool &incidentHasChanged)
G4HadFinalState * ApplyYourself(const G4HadProjectile &aTrack, G4Nucleus &targetNucleus)
virtual void ModelDescription(std::ostream &outFile) const
G4LEPionMinusInelastic(const G4String &name="G4LEPionMinusInelastic")
const G4String & GetName() const
Definition: G4Material.hh:177
static G4Neutron * Neutron()
Definition: G4Neutron.cc:104
G4double EvaporationEffects(G4double kineticEnergy)
Definition: G4Nucleus.cc:264
G4double Cinema(G4double kineticEnergy)
Definition: G4Nucleus.cc:368
G4DynamicParticle * ReturnTargetParticle() const
Definition: G4Nucleus.cc:227
const G4String & GetParticleName() const
static G4PionMinus * PionMinus()
Definition: G4PionMinus.cc:98
static G4PionZero * PionZero()
Definition: G4PionZero.cc:104
static G4Proton * Proton()
Definition: G4Proton.cc:93
void SetMomentum(const G4double x, const G4double y, const G4double z)
G4double GetKineticEnergy() const
G4ThreeVector GetMomentum() const
void SetSide(const G4int sid)
void SetDefinitionAndUpdateE(G4ParticleDefinition *aParticleDefinition)
void SetKineticEnergy(const G4double en)
G4ParticleDefinition * GetDefinition() const
G4double GetMass() const
const G4double pi