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
G4LEAntiXiZeroInelastic.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// Hadronic Process: AntiXiZero Inelastic Process
29// J.L. Chuma, TRIUMF, 20-Feb-1997
30// Modified by J.L.Chuma 30-Apr-97: added originalTarget for CalculateMomenta
31//
32// NOTE: The FORTRAN version of the cascade, CASAXO, simply called the
33// routine for the XiZero particle. Hence, the ApplyYourself function
34// below is just a copy of the ApplyYourself from the XiZero particle.
35
38#include "G4SystemOfUnits.hh"
39#include "Randomize.hh"
40
41void G4LEAntiXiZeroInelastic::ModelDescription(std::ostream& outFile) const
42{
43 outFile << "G4LEAntiXiZeroInelastic is one of the Low Energy Parameterized\n"
44 << "(LEP) models used to implement inelastic antiXi0 scattering\n"
45 << "from nuclei. It is a re-engineered version of the GHEISHA\n"
46 << "code of H. Fesefeldt. It divides the initial collision\n"
47 << "products into backward- and forward-going clusters which are\n"
48 << "then decayed into final state hadrons. The model does not\n"
49 << "conserve energy on an event-by-event basis. It may be\n"
50 << "applied to antiXi0 with initial energies between 0 and 25\n"
51 << "GeV.\n";
52}
53
56 G4Nucleus& targetNucleus)
57{
58 const G4HadProjectile *originalIncident = &aTrack;
59
60 // create the target particle
61 G4DynamicParticle* originalTarget = targetNucleus.ReturnTargetParticle();
62
63 if (verboseLevel > 1) {
64 const G4Material *targetMaterial = aTrack.GetMaterial();
65 G4cout << "G4LEAntiXiZeroInelastic::ApplyYourself called" << G4endl;
66 G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
67 G4cout << "target material = " << targetMaterial->GetName() << ", ";
68 G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
69 << G4endl;
70 }
71
72 // Fermi motion and evaporation
73 // As of Geant3, the Fermi energy calculation had not been Done
74 G4double ek = originalIncident->GetKineticEnergy()/MeV;
75 G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
76 G4ReactionProduct modifiedOriginal;
77 modifiedOriginal = *originalIncident;
78
79 G4double tkin = targetNucleus.Cinema( ek );
80 ek += tkin;
81 modifiedOriginal.SetKineticEnergy( ek*MeV );
82 G4double et = ek + amas;
83 G4double p = std::sqrt( std::abs((et-amas)*(et+amas)) );
84 G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
85 if (pp > 0.0) {
86 G4ThreeVector momentum = modifiedOriginal.GetMomentum();
87 modifiedOriginal.SetMomentum( momentum * (p/pp) );
88 }
89
90 // calculate black track energies
91 tkin = targetNucleus.EvaporationEffects( ek );
92 ek -= tkin;
93 modifiedOriginal.SetKineticEnergy( ek*MeV );
94 et = ek + amas;
95 p = std::sqrt( std::abs((et-amas)*(et+amas)) );
96 pp = modifiedOriginal.GetMomentum().mag()/MeV;
97 if (pp > 0.0) {
98 G4ThreeVector momentum = modifiedOriginal.GetMomentum();
99 modifiedOriginal.SetMomentum( momentum * (p/pp) );
100 }
101 G4ReactionProduct currentParticle = modifiedOriginal;
102 G4ReactionProduct targetParticle;
103 targetParticle = *originalTarget;
104 currentParticle.SetSide(1); // incident always goes in forward hemisphere
105 targetParticle.SetSide(-1); // target always goes in backward hemisphere
106 G4bool incidentHasChanged = false;
107 G4bool targetHasChanged = false;
108 G4bool quasiElastic = false;
109 G4FastVector<G4ReactionProduct,GHADLISTSIZE> vec; // vec will contain the secondary particles
110 G4int vecLen = 0;
111 vec.Initialize(0);
112
113 const G4double cutOff = 0.1;
114 const G4double anni = std::min( 1.3*currentParticle.GetTotalMomentum()/GeV, 0.4 );
115 if ((currentParticle.GetKineticEnergy()/MeV > cutOff) ||
116 (G4UniformRand() > anni) )
117 Cascade(vec, vecLen, originalIncident, currentParticle, targetParticle,
118 incidentHasChanged, targetHasChanged, quasiElastic);
119
120 CalculateMomenta(vec, vecLen, originalIncident, originalTarget,
121 modifiedOriginal, targetNucleus, currentParticle,
122 targetParticle, incidentHasChanged, targetHasChanged,
123 quasiElastic);
124
125 SetUpChange(vec, vecLen, currentParticle, targetParticle, incidentHasChanged);
126
127 if (isotopeProduction) DoIsotopeCounting(originalIncident, targetNucleus);
128
129 delete originalTarget;
130 return &theParticleChange;
131}
132
133
134void G4LEAntiXiZeroInelastic::Cascade(
136 G4int& vecLen,
137 const G4HadProjectile *originalIncident,
138 G4ReactionProduct &currentParticle,
139 G4ReactionProduct &targetParticle,
140 G4bool &incidentHasChanged,
141 G4bool &targetHasChanged,
142 G4bool &quasiElastic)
143{
144 // derived from original FORTRAN code CASAX0 by H. Fesefeldt (20-Jan-1989)
145 // which is just a copy of CASX0 (cascade for Xi0)
146 //
147 // AntiXiZero undergoes interaction with nucleon within a nucleus. Check if it is
148 // energetically possible to produce pions/kaons. In not, assume nuclear excitation
149 // occurs and input particle is degraded in energy. No other particles are produced.
150 // If reaction is possible, find the correct number of pions/protons/neutrons
151 // produced using an interpolation to multiplicity data. Replace some pions or
152 // protons/neutrons by kaons or strange baryons according to the average
153 // multiplicity per inelastic reaction.
154 //
155 const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
156 const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
157 const G4double targetMass = targetParticle.GetMass()/MeV;
158 G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
159 targetMass*targetMass +
160 2.0*targetMass*etOriginal );
161 G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
162 if( availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV )
163 {
164 quasiElastic = true;
165 return;
166 }
167 static G4bool first = true;
168 const G4int numMul = 1200;
169 const G4int numSec = 60;
170 static G4double protmul[numMul], protnorm[numSec]; // proton constants
171 static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
172 // npos = number of pi+, nneg = number of pi-, nzero = number of pi0
173 G4int counter, nt=0, npos=0, nneg=0, nzero=0;
174 G4double test;
175 const G4double c = 1.25;
176 const G4double b[] = { 0.7, 0.7 };
177 if( first ) // compute normalization constants, this will only be Done once
178 {
179 first = false;
180 G4int i;
181 for( i=0; i<numMul; ++i )protmul[i] = 0.0;
182 for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
183 counter = -1;
184 for( npos=0; npos<(numSec/3); ++npos )
185 {
186 for( nneg=std::max(0,npos-2); nneg<=(npos+1); ++nneg )
187 {
188 for( nzero=0; nzero<numSec/3; ++nzero )
189 {
190 if( ++counter < numMul )
191 {
192 nt = npos+nneg+nzero;
193 if( nt>0 && nt<=numSec )
194 {
195 protmul[counter] = Pmltpc(npos,nneg,nzero,nt,b[0],c);
196 protnorm[nt-1] += protmul[counter];
197 }
198 }
199 }
200 }
201 }
202 for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
203 for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
204 counter = -1;
205 for( npos=0; npos<numSec/3; ++npos )
206 {
207 for( nneg=std::max(0,npos-1); nneg<=(npos+2); ++nneg )
208 {
209 for( nzero=0; nzero<numSec/3; ++nzero )
210 {
211 if( ++counter < numMul )
212 {
213 nt = npos+nneg+nzero;
214 if( nt>0 && nt<=numSec )
215 {
216 neutmul[counter] = Pmltpc(npos,nneg,nzero,nt,b[1],c);
217 neutnorm[nt-1] += neutmul[counter];
218 }
219 }
220 }
221 }
222 }
223 for( i=0; i<numSec; ++i )
224 {
225 if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
226 if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
227 }
228 } // end of initialization
229
230 const G4double expxu = 82.; // upper bound for arg. of exp
231 const G4double expxl = -expxu; // lower bound for arg. of exp
237 //
238 // energetically possible to produce pion(s) --> inelastic scattering
239 //
240 G4double n, anpn;
241 GetNormalizationConstant( availableEnergy, n, anpn );
242 G4double ran = G4UniformRand();
243 G4double dum, excs = 0.0;
244 if( targetParticle.GetDefinition() == aProton )
245 {
246 counter = -1;
247 for( npos=0; npos<numSec/3 && ran>=excs; ++npos )
248 {
249 for( nneg=std::max(0,npos-2); nneg<=(npos+1) && ran>=excs; ++nneg )
250 {
251 for( nzero=0; nzero<numSec/3 && ran>=excs; ++nzero )
252 {
253 if( ++counter < numMul )
254 {
255 nt = npos+nneg+nzero;
256 if( nt>0 && nt<=numSec )
257 {
258 test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
259 dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
260 if( std::fabs(dum) < 1.0 )
261 {
262 if( test >= 1.0e-10 )excs += dum*test;
263 }
264 else
265 excs += dum*test;
266 }
267 }
268 }
269 }
270 }
271 if( ran >= excs ) // 3 previous loops continued to the end
272 {
273 quasiElastic = true;
274 return;
275 }
276 npos--; nneg--; nzero--;
277 //
278 // number of secondary mesons determined by kno distribution
279 // check for total charge of final state mesons to determine
280 // the kind of baryons to be produced, taking into account
281 // charge and strangeness conservation
282 //
283 if( npos < nneg+1 )
284 {
285 if( npos != nneg ) // charge mismatch
286 {
287 currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
288 incidentHasChanged = true;
289 //
290 // correct the strangeness by replacing a pi- by a kaon-
291 //
292 vec.Initialize( 1 );
294 p->SetDefinition( aKaonMinus );
295 (G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
296 vec.SetElement( vecLen++, p );
297 --nneg;
298 }
299 }
300 else if( npos == nneg+1 )
301 {
302 if( G4UniformRand() < 0.5 )
303 {
304 targetParticle.SetDefinitionAndUpdateE( aNeutron );
305 targetHasChanged = true;
306 }
307 else
308 {
309 currentParticle.SetDefinitionAndUpdateE( aXiMinus );
310 incidentHasChanged = true;
311 }
312 }
313 else
314 {
315 currentParticle.SetDefinitionAndUpdateE( aXiMinus );
316 incidentHasChanged = true;
317 targetParticle.SetDefinitionAndUpdateE( aNeutron );
318 targetHasChanged = true;
319 }
320 }
321 else // target must be a neutron
322 {
323 counter = -1;
324 for( npos=0; npos<numSec/3 && ran>=excs; ++npos )
325 {
326 for( nneg=std::max(0,npos-1); nneg<=(npos+2) && ran>=excs; ++nneg )
327 {
328 for( nzero=0; nzero<numSec/3 && ran>=excs; ++nzero )
329 {
330 if( ++counter < numMul )
331 {
332 nt = npos+nneg+nzero;
333 if( nt>0 && nt<=numSec )
334 {
335 test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
336 dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
337 if( std::fabs(dum) < 1.0 )
338 {
339 if( test >= 1.0e-10 )excs += dum*test;
340 }
341 else
342 excs += dum*test;
343 }
344 }
345 }
346 }
347 }
348 if( ran >= excs ) // 3 previous loops continued to the end
349 {
350 quasiElastic = true;
351 return;
352 }
353 npos--; nneg--; nzero--;
354 if( npos < nneg )
355 {
356 if( npos+1 == nneg )
357 {
358 targetParticle.SetDefinitionAndUpdateE( aProton );
359 targetHasChanged = true;
360 }
361 else // charge mismatch
362 {
363 currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
364 incidentHasChanged = true;
365 targetParticle.SetDefinitionAndUpdateE( aProton );
366 targetHasChanged = true;
367 //
368 // correct the strangeness by replacing a pi- by a kaon-
369 //
370 vec.Initialize( 1 );
372 p->SetDefinition( aKaonMinus );
373 (G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
374 vec.SetElement( vecLen++, p );
375 --nneg;
376 }
377 }
378 else if( npos == nneg )
379 {
380 if( G4UniformRand() >= 0.5 )
381 {
382 currentParticle.SetDefinitionAndUpdateE( aXiMinus );
383 incidentHasChanged = true;
384 targetParticle.SetDefinitionAndUpdateE( aProton );
385 targetHasChanged = true;
386 }
387 }
388 else
389 {
390 currentParticle.SetDefinitionAndUpdateE( aXiMinus );
391 incidentHasChanged = true;
392 }
393 }
394 SetUpPions( npos, nneg, nzero, vec, vecLen );
395 return;
396}
397
398 /* end of file */
399
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
double mag() const
G4ParticleDefinition * GetDefinition() const
void SetElement(G4int anIndex, Type *anElement)
Definition: G4FastVector.hh:76
void Initialize(G4int items)
Definition: G4FastVector.hh:63
const G4Material * GetMaterial() const
const G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
G4double GetTotalEnergy() const
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)
static G4KaonMinus * KaonMinus()
Definition: G4KaonMinus.cc:113
virtual void ModelDescription(std::ostream &outFile) const
G4HadFinalState * ApplyYourself(const G4HadProjectile &aTrack, G4Nucleus &targetNucleus)
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 G4PionPlus * PionPlus()
Definition: G4PionPlus.cc:98
static G4Proton * Proton()
Definition: G4Proton.cc:93
void SetMomentum(const G4double x, const G4double y, const G4double z)
G4double GetTotalMomentum() const
G4double GetKineticEnergy() const
G4ThreeVector GetMomentum() const
void SetSide(const G4int sid)
void SetDefinitionAndUpdateE(G4ParticleDefinition *aParticleDefinition)
void SetKineticEnergy(const G4double en)
G4ParticleDefinition * GetDefinition() const
void SetDefinition(G4ParticleDefinition *aParticleDefinition)
G4double GetMass() const
static G4SigmaPlus * SigmaPlus()
Definition: G4SigmaPlus.cc:108
static G4XiMinus * XiMinus()
Definition: G4XiMinus.cc:106
const G4double pi