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
G4RPGOmegaMinusInelastic.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
31#include "G4SystemOfUnits.hh"
32#include "Randomize.hh"
33
36 G4Nucleus &targetNucleus )
37{
38 const G4HadProjectile *originalIncident = &aTrack;
39 if (originalIncident->GetKineticEnergy()<= 0.1*MeV)
40 {
44 return &theParticleChange;
45 }
46
47 // create the target particle
48
49 G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
50// G4double targetMass = originalTarget->GetDefinition()->GetPDGMass();
51 G4ReactionProduct targetParticle( originalTarget->GetDefinition() );
52
53 if( verboseLevel > 1 )
54 {
55 const G4Material *targetMaterial = aTrack.GetMaterial();
56 G4cout << "G4RPGOmegaMinusInelastic::ApplyYourself called" << G4endl;
57 G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy() << "MeV, ";
58 G4cout << "target material = " << targetMaterial->GetName() << ", ";
59 G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
60 << G4endl;
61 }
62 G4ReactionProduct currentParticle( const_cast<G4ParticleDefinition *>(originalIncident->GetDefinition() ));
63 currentParticle.SetMomentum( originalIncident->Get4Momentum().vect() );
64 currentParticle.SetKineticEnergy( originalIncident->GetKineticEnergy() );
65
66 // Fermi motion and evaporation
67 // As of Geant3, the Fermi energy calculation had not been Done
68
69 G4double ek = originalIncident->GetKineticEnergy();
70 G4double amas = originalIncident->GetDefinition()->GetPDGMass();
71
72 G4double tkin = targetNucleus.Cinema( ek );
73 ek += tkin;
74 currentParticle.SetKineticEnergy( ek );
75 G4double et = ek + amas;
76 G4double p = std::sqrt( std::abs((et-amas)*(et+amas)) );
77 G4double pp = currentParticle.GetMomentum().mag();
78 if( pp > 0.0 )
79 {
80 G4ThreeVector momentum = currentParticle.GetMomentum();
81 currentParticle.SetMomentum( momentum * (p/pp) );
82 }
83
84 // calculate black track energies
85
86 tkin = targetNucleus.EvaporationEffects( ek );
87 ek -= tkin;
88 currentParticle.SetKineticEnergy( ek );
89 et = ek + amas;
90 p = std::sqrt( std::abs((et-amas)*(et+amas)) );
91 pp = currentParticle.GetMomentum().mag();
92 if( pp > 0.0 )
93 {
94 G4ThreeVector momentum = currentParticle.GetMomentum();
95 currentParticle.SetMomentum( momentum * (p/pp) );
96 }
97
98 G4ReactionProduct modifiedOriginal = currentParticle;
99
100 currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
101 targetParticle.SetSide( -1 ); // target always goes in backward hemisphere
102 G4bool incidentHasChanged = false;
103 G4bool targetHasChanged = false;
104 G4bool quasiElastic = false;
105 G4FastVector<G4ReactionProduct,GHADLISTSIZE> vec; // vec will contain the secondary particles
106 G4int vecLen = 0;
107 vec.Initialize( 0 );
108
109 const G4double cutOff = 0.1*MeV;
110 if( currentParticle.GetKineticEnergy() > cutOff )
111 Cascade( vec, vecLen,
112 originalIncident, currentParticle, targetParticle,
113 incidentHasChanged, targetHasChanged, quasiElastic );
114
115 CalculateMomenta( vec, vecLen,
116 originalIncident, originalTarget, modifiedOriginal,
117 targetNucleus, currentParticle, targetParticle,
118 incidentHasChanged, targetHasChanged, quasiElastic );
119
120 SetUpChange( vec, vecLen,
121 currentParticle, targetParticle,
122 incidentHasChanged );
123
124 delete originalTarget;
125 return &theParticleChange;
126}
127
128
129void G4RPGOmegaMinusInelastic::Cascade(
131 G4int& vecLen,
132 const G4HadProjectile *originalIncident,
133 G4ReactionProduct &currentParticle,
134 G4ReactionProduct &targetParticle,
135 G4bool &incidentHasChanged,
136 G4bool &targetHasChanged,
137 G4bool &quasiElastic )
138{
139 // Derived from H. Fesefeldt's original FORTRAN code CASOM
140 // OmegaMinus undergoes interaction with nucleon within a nucleus. Check if it is
141 // energetically possible to produce pions/kaons. In not, assume nuclear excitation
142 // occurs and input particle is degraded in energy. No other particles are produced.
143 // If reaction is possible, find the correct number of pions/protons/neutrons
144 // produced using an interpolation to multiplicity data. Replace some pions or
145 // protons/neutrons by kaons or strange baryons according to the average
146 // multiplicity per Inelastic reaction.
147
148 const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass();
149 const G4double etOriginal = originalIncident->GetTotalEnergy();
150// const G4double pOriginal = originalIncident->GetTotalMomentum();
151 const G4double targetMass = targetParticle.GetMass();
152 G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
153 targetMass*targetMass +
154 2.0*targetMass*etOriginal );
155 G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
156 if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass() )
157 {
158 quasiElastic = true;
159 return;
160 }
161 static G4bool first = true;
162 const G4int numMul = 1200;
163 const G4int numSec = 60;
164 static G4double protmul[numMul], protnorm[numSec]; // proton constants
165 static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
166 // np = number of pi+, nneg = number of pi-, nz = number of pi0
167 G4int counter, nt=0, np=0, nneg=0, nz=0;
168 G4double test;
169 const G4double c = 1.25;
170 const G4double b[] = { 0.70, 0.70 };
171 if( first ) // compute normalization constants, this will only be Done once
172 {
173 first = false;
174 G4int i;
175 for( i=0; i<numMul; ++i )protmul[i] = 0.0;
176 for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
177 counter = -1;
178 for( np=0; np<(numSec/3); ++np )
179 {
180 for( nneg=std::max(0,np-1); nneg<=(np+1); ++nneg )
181 {
182 for( nz=0; nz<numSec/3; ++nz )
183 {
184 if( ++counter < numMul )
185 {
186 nt = np+nneg+nz;
187 if( nt > 0 )
188 {
189 protmul[counter] = Pmltpc(np,nneg,nz,nt,b[0],c);
190 protnorm[nt-1] += protmul[counter];
191 }
192 }
193 }
194 }
195 }
196 for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
197 for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
198 counter = -1;
199 for( np=0; np<numSec/3; ++np )
200 {
201 for( nneg=np; nneg<=(np+2); ++nneg )
202 {
203 for( nz=0; nz<numSec/3; ++nz )
204 {
205 if( ++counter < numMul )
206 {
207 nt = np+nneg+nz;
208 if( (nt>0) && (nt<=numSec) )
209 {
210 neutmul[counter] = Pmltpc(np,nneg,nz,nt,b[1],c);
211 neutnorm[nt-1] += neutmul[counter];
212 }
213 }
214 }
215 }
216 }
217 for( i=0; i<numSec; ++i )
218 {
219 if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
220 if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
221 }
222 } // end of initialization
223
224 const G4double expxu = 82.; // upper bound for arg. of exp
225 const G4double expxl = -expxu; // lower bound for arg. of exp
232
233 // energetically possible to produce pion(s) --> inelastic scattering
234
235 G4double n, anpn;
236 GetNormalizationConstant( availableEnergy, n, anpn );
237 G4double ran = G4UniformRand();
238 G4double dum, excs = 0.0;
239 if( targetParticle.GetDefinition() == aProton )
240 {
241 counter = -1;
242 for( np=0; np<numSec/3 && ran>=excs; ++np )
243 {
244 for( nneg=std::max(0,np-1); nneg<=(np+1) && ran>=excs; ++nneg )
245 {
246 for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
247 {
248 if( ++counter < numMul )
249 {
250 nt = np+nneg+nz;
251 if( nt > 0 )
252 {
253 test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
254 dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
255 if( std::fabs(dum) < 1.0 )
256 {
257 if( test >= 1.0e-10 )excs += dum*test;
258 }
259 else
260 excs += dum*test;
261 }
262 }
263 }
264 }
265 }
266 if( ran >= excs ) // 3 previous loops continued to the end
267 {
268 quasiElastic = true;
269 return;
270 }
271 np--; nneg--; nz--;
272 }
273 else // target must be a neutron
274 {
275 counter = -1;
276 for( np=0; np<numSec/3 && ran>=excs; ++np )
277 {
278 for( nneg=np; nneg<=(np+2) && ran>=excs; ++nneg )
279 {
280 for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
281 {
282 if( ++counter < numMul )
283 {
284 nt = np+nneg+nz;
285 if( (nt>=1) && (nt<=numSec) )
286 {
287 test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
288 dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
289 if( std::fabs(dum) < 1.0 )
290 {
291 if( test >= 1.0e-10 )excs += dum*test;
292 }
293 else
294 excs += dum*test;
295 }
296 }
297 }
298 }
299 }
300 if( ran >= excs ) // 3 previous loops continued to the end
301 {
302 quasiElastic = true;
303 return;
304 }
305 np--; nneg--; nz--;
306 }
307 // number of secondary mesons determined by kno distribution
308 // check for total charge of final state mesons to determine
309 // the kind of baryons to be produced, taking into account
310 // charge and strangeness conservation
311 //
312 G4int nvefix = 0;
313 if( targetParticle.GetDefinition() == aProton )
314 {
315 if( nneg > np )
316 {
317 if( nneg == np+1 )
318 {
319 currentParticle.SetDefinitionAndUpdateE( aXiZero );
320 nvefix = 1;
321 }
322 else
323 {
324 currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
325 nvefix = 2;
326 }
327 incidentHasChanged = true;
328 }
329 else if( nneg < np )
330 {
331 targetParticle.SetDefinitionAndUpdateE( aNeutron );
332 targetHasChanged = true;
333 }
334 }
335 else // target is a neutron
336 {
337 if( np+1 < nneg )
338 {
339 if( nneg == np+2 )
340 {
341 currentParticle.SetDefinitionAndUpdateE( aXiZero );
342 incidentHasChanged = true;
343 nvefix = 1;
344 }
345 else // charge mismatch
346 {
347 currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
348 incidentHasChanged = true;
349 nvefix = 2;
350 }
351 targetParticle.SetDefinitionAndUpdateE( aProton );
352 targetHasChanged = true;
353 }
354 else if( nneg == np+1 )
355 {
356 targetParticle.SetDefinitionAndUpdateE( aProton );
357 targetHasChanged = true;
358 }
359 }
360
361 SetUpPions(np, nneg, nz, vec, vecLen);
362 for (G4int i = 0; i < vecLen && nvefix > 0; ++i) {
363 if (vec[i]->GetDefinition() == aPiMinus) {
364 if( nvefix >= 1 )vec[i]->SetDefinitionAndUpdateE(aKaonMinus);
365 --nvefix;
366 }
367 }
368
369 return;
370}
371
372 /* end of file */
373
@ 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
const G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4LorentzVector & Get4Momentum() const
G4double GetTotalEnergy() const
static G4KaonMinus * KaonMinus()
Definition: G4KaonMinus.cc:113
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 G4PionPlus * PionPlus()
Definition: G4PionPlus.cc:98
static G4Proton * Proton()
Definition: G4Proton.cc:93
void SetUpPions(const G4int np, const G4int nm, const G4int nz, G4FastVector< G4ReactionProduct, 256 > &vec, G4int &vecLen)
void GetNormalizationConstant(const G4double availableEnergy, G4double &n, G4double &anpn)
void CalculateMomenta(G4FastVector< G4ReactionProduct, 256 > &vec, G4int &vecLen, const G4HadProjectile *originalIncident, const G4DynamicParticle *originalTarget, G4ReactionProduct &modifiedOriginal, G4Nucleus &targetNucleus, G4ReactionProduct &currentParticle, G4ReactionProduct &targetParticle, G4bool &incidentHasChanged, G4bool &targetHasChanged, G4bool quasiElastic)
void SetUpChange(G4FastVector< G4ReactionProduct, 256 > &vec, G4int &vecLen, G4ReactionProduct &currentParticle, G4ReactionProduct &targetParticle, G4bool &incidentHasChanged)
G4double Pmltpc(G4int np, G4int nm, G4int nz, G4int n, G4double b, G4double c)
G4HadFinalState * ApplyYourself(const G4HadProjectile &aTrack, G4Nucleus &targetNucleus)
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
static G4SigmaPlus * SigmaPlus()
Definition: G4SigmaPlus.cc:108
static G4XiZero * XiZero()
Definition: G4XiZero.cc:106
const G4double pi