source: trunk/source/processes/hadronic/models/rpg/src/G4RPGFragmentation.cc@ 819

Last change on this file since 819 was 819, checked in by garnier, 17 years ago

import all except CVS

File size: 46.5 KB
RevLine 
[819]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: G4RPGFragmentation.cc,v 1.3 2007/12/06 01:13:14 dennis Exp $
27// GEANT4 tag $Name: geant4-09-01-patch-02 $
28//
29
30#include "G4RPGFragmentation.hh"
31#include "G4AntiProton.hh"
32#include "G4AntiNeutron.hh"
33#include "Randomize.hh"
34#include "G4Poisson.hh"
35#include <iostream>
36#include "G4HadReentrentException.hh"
37#include <signal.h>
38
39
40G4RPGFragmentation::G4RPGFragmentation()
41 : G4RPGReaction() {}
42
43
44void G4RPGFragmentation::
45FragmentationIntegral(G4double pt, G4double et, G4double parMass, G4double secMass)
46{
47 pt = std::max( 0.001, pt );
48 G4double dx = 1./(19.*pt);
49 G4double x;
50 G4double term1;
51 G4double term2;
52
53 for (G4int i = 1; i < 20; i++) {
54 x = (G4double(i) - 0.5)*dx;
55 term1 = 1. + parMass*parMass*x*x;
56 term2 = pt*x*et*pt*x*et + pt*pt + secMass*secMass;
57 dndl[i] = dx / std::sqrt( term1*term1*term1*term2 )
58 + dndl[i-1];
59 }
60}
61
62
63G4bool G4RPGFragmentation::
64ReactionStage(const G4HadProjectile* originalIncident,
65 G4ReactionProduct& modifiedOriginal,
66 G4bool& incidentHasChanged,
67 const G4DynamicParticle* originalTarget,
68 G4ReactionProduct& targetParticle,
69 G4bool& targetHasChanged,
70 const G4Nucleus& targetNucleus,
71 G4ReactionProduct& currentParticle,
72 G4FastVector<G4ReactionProduct,256>& vec,
73 G4int& vecLen,
74 G4bool leadFlag,
75 G4ReactionProduct& leadingStrangeParticle)
76{
77 //
78 // Derived from H. Fesefeldt's original FORTRAN code GENXPT
79 //
80 // Generation of x- and pT- values for incident, target, and all secondary
81 // particles using a simple single variable description E D3S/DP3= F(Q)
82 // with Q^2 = (M*X)^2 + PT^2. Final state kinematics are produced by an
83 // FF-type iterative cascade method
84 //
85 // Internal units are GeV
86 //
87
88 // Protection in case no secondary has been created. In that case use
89 // two-body scattering
90 //
91 if(vecLen == 0) return false;
92
93 G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
94 G4ParticleDefinition *aProton = G4Proton::Proton();
95 G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
96 G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
97 G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
98
99 G4int i, l;
100 G4bool veryForward = false;
101
102 const G4double ekOriginal = modifiedOriginal.GetKineticEnergy()/GeV;
103 const G4double etOriginal = modifiedOriginal.GetTotalEnergy()/GeV;
104 const G4double mOriginal = modifiedOriginal.GetMass()/GeV;
105 const G4double pOriginal = modifiedOriginal.GetMomentum().mag()/GeV;
106 G4double targetMass = targetParticle.GetDefinition()->GetPDGMass()/GeV;
107 G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
108 targetMass*targetMass +
109 2.0*targetMass*etOriginal ); // GeV
110 G4double currentMass = currentParticle.GetMass()/GeV;
111 targetMass = targetParticle.GetMass()/GeV;
112 //
113 // randomize the order of the secondary particles
114 // note that the current and target particles are not affected
115 //
116 for( i=0; i<vecLen; ++i )
117 {
118 G4int itemp = G4int( G4UniformRand()*vecLen );
119 G4ReactionProduct pTemp = *vec[itemp];
120 *vec[itemp] = *vec[i];
121 *vec[i] = pTemp;
122 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
123 }
124
125 if( currentMass == 0.0 && targetMass == 0.0 )
126 {
127 // Target and projectile have annihilated. Replace them with the first
128 // two secondaries in the list. Current particle KE is maintained.
129
130 G4double ek = currentParticle.GetKineticEnergy();
131 G4ThreeVector m = currentParticle.GetMomentum();
132 currentParticle = *vec[0];
133 targetParticle = *vec[1];
134 for( i=0; i<(vecLen-2); ++i )*vec[i] = *vec[i+2];
135 G4ReactionProduct *temp = vec[vecLen-1];
136 delete temp;
137 temp = vec[vecLen-2];
138 delete temp;
139 vecLen -= 2;
140 currentMass = currentParticle.GetMass()/GeV;
141 targetMass = targetParticle.GetMass()/GeV;
142 incidentHasChanged = true;
143 targetHasChanged = true;
144 currentParticle.SetKineticEnergy( ek );
145 currentParticle.SetMomentum( m );
146 veryForward = true;
147 }
148 const G4double atomicWeight = targetNucleus.GetN();
149 const G4double atomicNumber = targetNucleus.GetZ();
150 const G4double protonMass = aProton->GetPDGMass()/MeV;
151
152 if (originalIncident->GetDefinition()->GetParticleSubType() == "kaon"
153 && G4UniformRand() >= 0.7) {
154 G4ReactionProduct temp = currentParticle;
155 currentParticle = targetParticle;
156 targetParticle = temp;
157 incidentHasChanged = true;
158 targetHasChanged = true;
159 currentMass = currentParticle.GetMass()/GeV;
160 targetMass = targetParticle.GetMass()/GeV;
161 }
162 const G4double afc = std::min( 0.75,
163 0.312+0.200*std::log(std::log(centerofmassEnergy*centerofmassEnergy))+
164 std::pow(centerofmassEnergy*centerofmassEnergy,1.5)/6000.0 );
165
166 G4double freeEnergy = centerofmassEnergy-currentMass-targetMass;
167 G4double forwardEnergy = freeEnergy/2.;
168 G4int forwardCount = 1; // number of particles in forward hemisphere
169
170 G4double backwardEnergy = freeEnergy/2.;
171 G4int backwardCount = 1; // number of particles in backward hemisphere
172
173 if(veryForward)
174 {
175 if(currentParticle.GetSide()==-1)
176 {
177 forwardEnergy += currentMass;
178 forwardCount --;
179 backwardEnergy -= currentMass;
180 backwardCount ++;
181 }
182 if(targetParticle.GetSide()!=-1)
183 {
184 backwardEnergy += targetMass;
185 backwardCount --;
186 forwardEnergy -= targetMass;
187 forwardCount ++;
188 }
189 }
190
191 for( i=0; i<vecLen; ++i )
192 {
193 if( vec[i]->GetSide() == -1 )
194 {
195 ++backwardCount;
196 backwardEnergy -= vec[i]->GetMass()/GeV;
197 } else {
198 ++forwardCount;
199 forwardEnergy -= vec[i]->GetMass()/GeV;
200 }
201 }
202 //
203 // Add particles from intranuclear cascade.
204 // nuclearExcitationCount = number of new secondaries produced by nuclear excitation
205 // extraCount = number of nucleons within these new secondaries
206 //
207 G4double xtarg;
208 if( centerofmassEnergy < (2.0+G4UniformRand()) )
209 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount+vecLen+2)/2.0;
210 else
211 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount);
212 if( xtarg <= 0.0 )xtarg = 0.01;
213 G4int nuclearExcitationCount = G4Poisson( xtarg );
214 if(atomicWeight<1.0001) nuclearExcitationCount = 0;
215 G4int extraNucleonCount = 0;
216 G4double extraNucleonMass = 0.0;
217 if( nuclearExcitationCount > 0 )
218 {
219 const G4double nucsup[] = { 1.00, 0.7, 0.5, 0.4, 0.35, 0.3 };
220 const G4double psup[] = { 3., 6., 20., 50., 100., 1000. };
221 G4int momentumBin = 0;
222 while( (momentumBin < 6) &&
223 (modifiedOriginal.GetTotalMomentum()/GeV > psup[momentumBin]) )
224 ++momentumBin;
225 momentumBin = std::min( 5, momentumBin );
226 //
227 // NOTE: in GENXPT, these new particles were given negative codes
228 // here I use NewlyAdded = true instead
229 //
230
231 for( i=0; i<nuclearExcitationCount; ++i )
232 {
233 G4ReactionProduct * pVec = new G4ReactionProduct();
234 if( G4UniformRand() < nucsup[momentumBin] )
235 {
236 if( G4UniformRand() > 1.0-atomicNumber/atomicWeight )
237 pVec->SetDefinition( aProton );
238 else
239 pVec->SetDefinition( aNeutron );
240 pVec->SetSide( -2 ); // -2 means backside nucleon
241 ++extraNucleonCount;
242 backwardEnergy += pVec->GetMass()/GeV;
243 extraNucleonMass += pVec->GetMass()/GeV;
244 }
245 else
246 {
247 G4double ran = G4UniformRand();
248 if( ran < 0.3181 )
249 pVec->SetDefinition( aPiPlus );
250 else if( ran < 0.6819 )
251 pVec->SetDefinition( aPiZero );
252 else
253 pVec->SetDefinition( aPiMinus );
254 pVec->SetSide( -1 ); // backside particle, but not a nucleon
255 }
256 pVec->SetNewlyAdded( true ); // true is the same as IPA(i)<0
257 vec.SetElement( vecLen++, pVec );
258 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
259 backwardEnergy -= pVec->GetMass()/GeV;
260 ++backwardCount;
261 }
262 }
263 //
264 // assume conservation of kinetic energy in forward & backward hemispheres
265 //
266 G4int is, iskip;
267 while( forwardEnergy <= 0.0 ) // must eliminate a particle from the forward side
268 {
269 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
270 iskip = G4int(G4UniformRand()*forwardCount) + 1; // 1 <= iskip <= forwardCount
271 is = 0;
272 G4int forwardParticlesLeft = 0;
273 for( i=(vecLen-1); i>=0; --i )
274 {
275 if( vec[i]->GetSide() == 1 && vec[i]->GetMayBeKilled())
276 {
277 forwardParticlesLeft = 1;
278 if( ++is == iskip )
279 {
280 forwardEnergy += vec[i]->GetMass()/GeV;
281 for( G4int j=i; j<(vecLen-1); j++ )*vec[j] = *vec[j+1]; // shift up
282 --forwardCount;
283 delete vec[vecLen-1];
284 if( --vecLen == 0 )return false; // all the secondaries have been eliminated
285 break; // --+
286 } // |
287 } // |
288 } // break goes down to here
289 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
290 if( forwardParticlesLeft == 0 )
291 {
292 G4int iremove = -1;
293 for (G4int i = 0; i < vecLen; i++) {
294 if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
295 iremove = i;
296 break;
297 }
298 }
299 if (iremove == -1) {
300 for (G4int i = 0; i < vecLen; i++) {
301 if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon") {
302 iremove = i;
303 break;
304 }
305 }
306 }
307 if (iremove == -1) iremove = 0;
308
309 forwardEnergy += vec[iremove]->GetMass()/GeV;
310 if (vec[iremove]->GetSide() > 0) --forwardCount;
311
312 for (G4int i = iremove; i < vecLen-1; i++) *vec[i] = *vec[i+1];
313 delete vec[vecLen-1];
314 vecLen--;
315 if (vecLen == 0) return false; // all secondaries have been eliminated
316 break;
317 }
318 } // while
319
320 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
321 while( backwardEnergy <= 0.0 ) // must eliminate a particle from the backward side
322 {
323 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
324 iskip = G4int(G4UniformRand()*backwardCount) + 1; // 1 <= iskip <= backwardCount
325 is = 0;
326 G4int backwardParticlesLeft = 0;
327 for( i=(vecLen-1); i>=0; --i )
328 {
329 if( vec[i]->GetSide() < 0 && vec[i]->GetMayBeKilled())
330 {
331 backwardParticlesLeft = 1;
332 if( ++is == iskip ) // eliminate the i'th particle
333 {
334 if( vec[i]->GetSide() == -2 )
335 {
336 --extraNucleonCount;
337 extraNucleonMass -= vec[i]->GetMass()/GeV;
338 backwardEnergy -= vec[i]->GetTotalEnergy()/GeV;
339 }
340 backwardEnergy += vec[i]->GetTotalEnergy()/GeV;
341 for( G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1]; // shift up
342 --backwardCount;
343 delete vec[vecLen-1];
344 if( --vecLen == 0 )return false; // all the secondaries have been eliminated
345 break;
346 }
347 }
348 }
349 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
350 if( backwardParticlesLeft == 0 )
351 {
352 G4int iremove = -1;
353 for (G4int i = 0; i < vecLen; i++) {
354 if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
355 iremove = i;
356 break;
357 }
358 }
359 if (iremove == -1) {
360 for (G4int i = 0; i < vecLen; i++) {
361 if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon") {
362 iremove = i;
363 break;
364 }
365 }
366 }
367 if (iremove == -1) iremove = 0;
368
369 backwardEnergy += vec[iremove]->GetMass()/GeV;
370 if (vec[iremove]->GetSide() > 0) --backwardCount;
371
372 for (G4int i = iremove; i < vecLen-1; i++) *vec[i] = *vec[i+1];
373 delete vec[vecLen-1];
374 vecLen--;
375 if (vecLen == 0) return false; // all secondaries have been eliminated
376 break;
377 }
378 } // while
379
380 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
381 //
382 // define initial state vectors for Lorentz transformations
383 // the pseudoParticles have non-standard masses, hence the "pseudo"
384 //
385 G4ReactionProduct pseudoParticle[8];
386 for( i=0; i<8; ++i )pseudoParticle[i].SetZero();
387
388 pseudoParticle[0].SetMass( mOriginal*GeV );
389 pseudoParticle[0].SetMomentum( 0.0, 0.0, pOriginal*GeV );
390 pseudoParticle[0].SetTotalEnergy(
391 std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
392
393 pseudoParticle[1].SetMass( protonMass*MeV ); // this could be targetMass
394 pseudoParticle[1].SetTotalEnergy( protonMass*MeV );
395
396 pseudoParticle[3].SetMass( protonMass*(1+extraNucleonCount)*MeV );
397 pseudoParticle[3].SetTotalEnergy( protonMass*(1+extraNucleonCount)*MeV );
398
399 pseudoParticle[2] = pseudoParticle[0] + pseudoParticle[1];
400 pseudoParticle[3] = pseudoParticle[3] + pseudoParticle[0];
401
402 pseudoParticle[0].Lorentz( pseudoParticle[0], pseudoParticle[2] );
403 pseudoParticle[1].Lorentz( pseudoParticle[1], pseudoParticle[2] );
404
405 //
406 // main loop for 4-momentum generation
407 // see Pitha-report (Aachen) for a detailed description of the method
408 //
409 G4double aspar, pt, et, x, pp, pp1, wgt;
410 G4int innerCounter, outerCounter;
411 G4bool eliminateThisParticle, resetEnergies, constantCrossSection;
412
413 G4double forwardKinetic = 0.0, backwardKinetic = 0.0;
414 //
415 // process the secondary particles in reverse order
416 // the incident particle is Done after the secondaries
417 // nucleons, including the target, in the backward hemisphere are also Done later
418 //
419 G4int backwardNucleonCount = 0; // number of nucleons in backward hemisphere
420 G4double totalEnergy, kineticEnergy, vecMass;
421
422 for( i=(vecLen-1); i>=0; --i )
423 {
424 G4double phi = G4UniformRand()*twopi;
425 if( vec[i]->GetNewlyAdded() ) // added from intranuclear cascade
426 {
427 if( vec[i]->GetSide() == -2 ) // is a nucleon
428 {
429 if( backwardNucleonCount < 18 )
430 {
431 if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
432 for(G4int i=0; i<vecLen; i++) delete vec[i];
433 vecLen = 0;
434 throw G4HadReentrentException(__FILE__, __LINE__,
435 "G4RPGFragmentation::ReactionStage : a pion has been counted as a backward nucleon");
436 }
437 vec[i]->SetSide( -3 );
438 ++backwardNucleonCount;
439 continue;
440 }
441 }
442 }
443 //
444 // set pt and phi values, they are changed somewhat in the iteration loop
445 // set mass parameter for lambda fragmentation model
446 //
447 vecMass = vec[i]->GetMass()/GeV;
448 G4double ran = -std::log(1.0-G4UniformRand())/3.5;
449 if( vec[i]->GetSide() == -2 ) // backward nucleon
450 {
451 if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon" ||
452 vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
453 aspar = 0.75;
454 pt = std::sqrt( std::pow( ran, 1.7 ) );
455 } else { // vec[i] must be a proton, neutron,
456 aspar = 0.20; // lambda, sigma, xsi, or ion
457 pt = std::sqrt( std::pow( ran, 1.2 ) );
458 }
459
460 } else { // not a backward nucleon
461
462 if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
463 aspar = 0.75;
464 pt = std::sqrt( std::pow( ran, 1.7 ) );
465 } else if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon") {
466 aspar = 0.70;
467 pt = std::sqrt( std::pow( ran, 1.7 ) );
468 } else { // vec[i] must be a proton, neutron,
469 aspar = 0.65; // lambda, sigma, xsi, or ion
470 pt = std::sqrt( std::pow( ran, 1.5 ) );
471 }
472 }
473 pt = std::max( 0.001, pt );
474 vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
475 if( vec[i]->GetSide() > 0 )
476 et = pseudoParticle[0].GetTotalEnergy()/GeV;
477 else
478 et = pseudoParticle[1].GetTotalEnergy()/GeV;
479
480 //
481 // start of outer iteration loop
482 //
483 outerCounter = 0;
484 eliminateThisParticle = true;
485 resetEnergies = true;
486 dndl[0] = 0.0;
487
488 while( ++outerCounter < 3 )
489 {
490 FragmentationIntegral(pt, et, aspar, vecMass);
491
492 innerCounter = 0;
493 vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
494 //
495 // start of inner iteration loop
496 //
497 while( ++innerCounter < 7 )
498 {
499 ran = G4UniformRand()*dndl[19];
500 l = 1;
501 while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
502 x = (G4double(l-1) + G4UniformRand())/19.;
503 if( vec[i]->GetSide() < 0 )x *= -1.;
504 vec[i]->SetMomentum( x*et*GeV ); // set the z-momentum
505 totalEnergy = std::sqrt( x*et*x*et + pt*pt + vecMass*vecMass );
506 vec[i]->SetTotalEnergy( totalEnergy*GeV );
507 kineticEnergy = vec[i]->GetKineticEnergy()/GeV;
508 if( vec[i]->GetSide() > 0 ) // forward side
509 {
510 if( (forwardKinetic+kineticEnergy) < 0.95*forwardEnergy )
511 {
512 pseudoParticle[4] = pseudoParticle[4] + (*vec[i]);
513 forwardKinetic += kineticEnergy;
514 outerCounter = 2; // leave outer loop
515 eliminateThisParticle = false; // don't eliminate this particle
516 resetEnergies = false;
517 break; // leave inner loop
518 }
519 if( innerCounter > 5 )break; // leave inner loop
520 if( backwardEnergy >= vecMass ) // switch sides
521 {
522 vec[i]->SetSide( -1 );
523 forwardEnergy += vecMass;
524 backwardEnergy -= vecMass;
525 ++backwardCount;
526 }
527 } else { // backward side
528 if( extraNucleonCount > 19 ) // commented out to duplicate ?bug? in GENXPT
529 x = 0.999;
530 G4double xxx = 0.95+0.05*extraNucleonCount/20.0;
531 if( (backwardKinetic+kineticEnergy) < xxx*backwardEnergy )
532 {
533 pseudoParticle[5] = pseudoParticle[5] + (*vec[i]);
534 backwardKinetic += kineticEnergy;
535 outerCounter = 2; // leave outer loop
536 eliminateThisParticle = false; // don't eliminate this particle
537 resetEnergies = false;
538 break; // leave inner loop
539 }
540 if( innerCounter > 5 )break; // leave inner loop
541 if( forwardEnergy >= vecMass ) // switch sides
542 {
543 vec[i]->SetSide( 1 );
544 forwardEnergy -= vecMass;
545 backwardEnergy += vecMass;
546 backwardCount--;
547 }
548 }
549 G4ThreeVector momentum = vec[i]->GetMomentum();
550 vec[i]->SetMomentum( momentum.x() * 0.9, momentum.y() * 0.9 );
551 pt *= 0.9;
552 dndl[19] *= 0.9;
553 } // closes inner loop
554 if( resetEnergies ) {
555 // If we get to here, the inner loop has been done 6 times.
556 // Reset the kinetic energies of previously done particles, if
557 // they are lighter than protons and in the forward hemisphere,
558 // then continue with outer loop.
559 //
560 forwardKinetic = 0.0;
561 backwardKinetic = 0.0;
562 pseudoParticle[4].SetZero();
563 pseudoParticle[5].SetZero();
564 for( l=i+1; l<vecLen; ++l ) {
565 if (vec[l]->GetSide() > 0 ||
566 vec[l]->GetDefinition()->GetParticleSubType() == "kaon" ||
567 vec[l]->GetDefinition()->GetParticleSubType() == "pi") {
568
569 G4double tempMass = vec[l]->GetMass()/MeV;
570 totalEnergy = 0.95*vec[l]->GetTotalEnergy()/MeV + 0.05*tempMass;
571 totalEnergy = std::max( tempMass, totalEnergy );
572 vec[l]->SetTotalEnergy( totalEnergy*MeV );
573 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - tempMass*tempMass ) );
574 pp1 = vec[l]->GetMomentum().mag()/MeV;
575 if( pp1 < 1.0e-6*GeV ) {
576 G4ThreeVector iso = Isotropic(pp);
577 vec[l]->SetMomentum( iso.x(), iso.y(), iso.z() );
578 } else {
579 vec[l]->SetMomentum( vec[l]->GetMomentum() * (pp/pp1) );
580 }
581 G4double px = vec[l]->GetMomentum().x()/MeV;
582 G4double py = vec[l]->GetMomentum().y()/MeV;
583 pt = std::max( 1.0, std::sqrt( px*px + py*py ) )/GeV;
584 if( vec[l]->GetSide() > 0 )
585 {
586 forwardKinetic += vec[l]->GetKineticEnergy()/GeV;
587 pseudoParticle[4] = pseudoParticle[4] + (*vec[l]);
588 } else {
589 backwardKinetic += vec[l]->GetKineticEnergy()/GeV;
590 pseudoParticle[5] = pseudoParticle[5] + (*vec[l]);
591 }
592 } // if pi, K or forward
593 } // for l
594 } // if resetEnergies
595 } // closes outer loop
596
597 if( eliminateThisParticle && vec[i]->GetMayBeKilled()) // not enough energy, eliminate this particle
598 {
599 if( vec[i]->GetSide() > 0 )
600 {
601 --forwardCount;
602 forwardEnergy += vecMass;
603 } else {
604 if( vec[i]->GetSide() == -2 )
605 {
606 --extraNucleonCount;
607 extraNucleonMass -= vecMass;
608 backwardEnergy -= vecMass;
609 }
610 --backwardCount;
611 backwardEnergy += vecMass;
612 }
613 for( G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1]; // shift up
614 G4ReactionProduct *temp = vec[vecLen-1];
615 delete temp;
616 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
617 if( --vecLen == 0 )return false; // all the secondaries have been eliminated
618 }
619 } // closes main for loop
620
621 //
622 // for the incident particle: it was placed in the forward hemisphere
623 // set pt and phi values, they are changed somewhat in the iteration loop
624 // set mass parameter for lambda fragmentation model
625 //
626 G4double phi = G4UniformRand()*twopi;
627 G4double ran = -std::log(1.0-G4UniformRand());
628 if (currentParticle.GetDefinition()->GetParticleSubType() == "pi") {
629 aspar = 0.60;
630 pt = std::sqrt( std::pow( ran/6.0, 1.7 ) );
631 } else if (currentParticle.GetDefinition()->GetParticleSubType() == "kaon") {
632 aspar = 0.50;
633 pt = std::sqrt( std::pow( ran/5.0, 1.4 ) );
634 } else {
635 aspar = 0.40;
636 pt = std::sqrt( std::pow( ran/4.0, 1.2 ) );
637 }
638
639 currentParticle.SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
640 et = pseudoParticle[0].GetTotalEnergy()/GeV;
641 dndl[0] = 0.0;
642 vecMass = currentParticle.GetMass()/GeV;
643
644 FragmentationIntegral(pt, et, aspar, vecMass);
645
646 ran = G4UniformRand()*dndl[19];
647 l = 1;
648 while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
649 x = (G4double(l-1) + G4UniformRand())/19.;
650 currentParticle.SetMomentum( x*et*GeV ); // set the z-momentum
651 if( forwardEnergy < forwardKinetic )
652 totalEnergy = vecMass + 0.04*std::fabs(normal());
653 else
654 totalEnergy = vecMass + forwardEnergy - forwardKinetic;
655 currentParticle.SetTotalEnergy( totalEnergy*GeV );
656 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
657 pp1 = currentParticle.GetMomentum().mag()/MeV;
658
659 if( pp1 < 1.0e-6*GeV ) {
660 G4ThreeVector iso = Isotropic(pp);
661 currentParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
662 } else {
663 currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
664 }
665 pseudoParticle[4] = pseudoParticle[4] + currentParticle;
666
667 //
668 // Current particle now finished
669 //
670 // Begin target particle
671 //
672
673 if( backwardNucleonCount < 18 )
674 {
675 targetParticle.SetSide( -3 );
676 ++backwardNucleonCount;
677 }
678 else
679 {
680 // set pt and phi values, they are changed somewhat in the iteration loop
681 // set mass parameter for lambda fragmentation model
682 //
683 vecMass = targetParticle.GetMass()/GeV;
684 ran = -std::log(1.0-G4UniformRand());
685 aspar = 0.40;
686 pt = std::max( 0.001, std::sqrt( std::pow( ran/4.0, 1.2 ) ) );
687 targetParticle.SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
688 et = pseudoParticle[1].GetTotalEnergy()/GeV;
689 outerCounter = 0;
690 eliminateThisParticle = true; // should never eliminate the target particle
691 resetEnergies = true;
692 dndl[0] = 0.0;
693
694 while( ++outerCounter < 3 ) // start of outer iteration loop
695 {
696 FragmentationIntegral(pt, et, aspar, vecMass);
697
698 innerCounter = 0;
699 while( ++innerCounter < 7 ) // start of inner iteration loop
700 {
701 ran = G4UniformRand()*dndl[19];
702 l = 1;
703 while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
704 x = (G4double(l-1) + G4UniformRand())/19.;
705 if( targetParticle.GetSide() < 0 )x *= -1.;
706 targetParticle.SetMomentum( x*et*GeV ); // set the z-momentum
707 totalEnergy = std::sqrt( x*et*x*et + pt*pt + vecMass*vecMass );
708 targetParticle.SetTotalEnergy( totalEnergy*GeV );
709 if( targetParticle.GetSide() < 0 )
710 {
711 if( extraNucleonCount > 19 )x=0.999;
712 G4double xxx = 0.95+0.05*extraNucleonCount/20.0;
713 if( (backwardKinetic+totalEnergy-vecMass) < xxx*backwardEnergy )
714 {
715 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
716 backwardKinetic += totalEnergy - vecMass;
717 // pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
718 // pseudoParticle[6].SetMomentum( 0.0 ); // set z-momentum
719 outerCounter = 2; // leave outer loop
720 eliminateThisParticle = false; // don't eliminate this particle
721 resetEnergies = false;
722 break; // leave inner loop
723 }
724 if( innerCounter > 5 )break; // leave inner loop
725 if( forwardEnergy >= vecMass ) // switch sides
726 {
727 targetParticle.SetSide( 1 );
728 forwardEnergy -= vecMass;
729 backwardEnergy += vecMass;
730 --backwardCount;
731 }
732 G4ThreeVector momentum = targetParticle.GetMomentum();
733 targetParticle.SetMomentum( momentum.x() * 0.9, momentum.y() * 0.9 );
734 pt *= 0.9;
735 dndl[19] *= 0.9;
736 }
737 else // target has gone to forward side
738 {
739 if( forwardEnergy < forwardKinetic )
740 totalEnergy = vecMass + 0.04*std::fabs(normal());
741 else
742 totalEnergy = vecMass + forwardEnergy - forwardKinetic;
743 targetParticle.SetTotalEnergy( totalEnergy*GeV );
744 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
745 pp1 = targetParticle.GetMomentum().mag()/MeV;
746 if( pp1 < 1.0e-6*GeV ) {
747 G4ThreeVector iso = Isotropic(pp);
748 targetParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
749 } else {
750 targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
751 }
752
753 pseudoParticle[4] = pseudoParticle[4] + targetParticle;
754 outerCounter = 2; // leave outer loop
755 eliminateThisParticle = false; // don't eliminate this particle
756 resetEnergies = false;
757 break; // leave inner loop
758 }
759 } // closes inner loop
760
761 if( resetEnergies ) {
762 // If we get to here, the inner loop has been done 6 times.
763 // Reset the kinetic energies of previously done particles,
764 // if they are lighter than protons and in the forward hemisphere,
765 // then continue with outer loop.
766
767 forwardKinetic = backwardKinetic = 0.0;
768 pseudoParticle[4].SetZero();
769 pseudoParticle[5].SetZero();
770 for( l=0; l<vecLen; ++l ) {
771 if (vec[l]->GetSide() > 0 ||
772 vec[l]->GetDefinition()->GetParticleSubType() == "kaon" ||
773 vec[l]->GetDefinition()->GetParticleSubType() == "pi") {
774 G4double tempMass = vec[l]->GetMass()/GeV;
775 totalEnergy =
776 std::max( tempMass, 0.95*vec[l]->GetTotalEnergy()/GeV + 0.05*tempMass );
777 vec[l]->SetTotalEnergy( totalEnergy*GeV );
778 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - tempMass*tempMass ) )*GeV;
779 pp1 = vec[l]->GetMomentum().mag()/MeV;
780 if( pp1 < 1.0e-6*GeV ) {
781 G4ThreeVector iso = Isotropic(pp);
782 vec[l]->SetMomentum( iso.x(), iso.y(), iso.z() );
783 } else {
784 vec[l]->SetMomentum( vec[l]->GetMomentum() * (pp/pp1) );
785 }
786 pt = std::max( 0.001*GeV, std::sqrt( sqr(vec[l]->GetMomentum().x()/MeV) +
787 sqr(vec[l]->GetMomentum().y()/MeV) ) )/GeV;
788 if( vec[l]->GetSide() > 0)
789 {
790 forwardKinetic += vec[l]->GetKineticEnergy()/GeV;
791 pseudoParticle[4] = pseudoParticle[4] + (*vec[l]);
792 } else {
793 backwardKinetic += vec[l]->GetKineticEnergy()/GeV;
794 pseudoParticle[5] = pseudoParticle[5] + (*vec[l]);
795 }
796 } // if pi, K or forward
797 } // for l
798 } // if (resetEnergies)
799 } // closes outer loop
800
801// if( eliminateThisParticle ) // not enough energy, eliminate target
802// {
803// G4cerr << "Warning: eliminating target particle" << G4endl;
804// exit( EXIT_FAILURE );
805// }
806 }
807 //
808 // Target particle finished.
809 //
810 // Now produce backward nucleons with a cluster model
811 //
812 pseudoParticle[6].Lorentz( pseudoParticle[3], pseudoParticle[2] );
813 pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[4];
814 pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[5];
815 if( backwardNucleonCount == 1 ) // target particle is the only backward nucleon
816 {
817 G4double ekin =
818 std::min( backwardEnergy-backwardKinetic, centerofmassEnergy/2.0-protonMass/GeV );
819
820 if( ekin < 0.04 )ekin = 0.04 * std::fabs( normal() );
821 vecMass = targetParticle.GetMass()/GeV;
822 totalEnergy = ekin+vecMass;
823 targetParticle.SetTotalEnergy( totalEnergy*GeV );
824 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
825 pp1 = pseudoParticle[6].GetMomentum().mag()/MeV;
826 if( pp1 < 1.0e-6*GeV ) {
827 G4ThreeVector iso = Isotropic(pp);
828 targetParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
829 } else {
830 targetParticle.SetMomentum( pseudoParticle[6].GetMomentum() * (pp/pp1) );
831 }
832 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
833 }
834 else if (backwardNucleonCount > 1)
835 {
836 const G4double cpar[] = { 1.60, 1.35, 1.15, 1.10 };
837 const G4double gpar[] = { 2.60, 1.80, 1.30, 1.20 };
838
839 G4int tempCount = 5;
840 if (backwardNucleonCount < 5) tempCount = backwardNucleonCount;
841 tempCount -= 2;
842
843 G4double rmb = 0.;
844 if( targetParticle.GetSide() == -3 ) rmb += targetParticle.GetMass()/GeV;
845 for( i=0; i<vecLen; ++i )
846 {
847 if( vec[i]->GetSide() == -3 ) rmb += vec[i]->GetMass()/GeV;
848 }
849 rmb += std::pow(-std::log(1.0-G4UniformRand()),1./cpar[tempCount]) / gpar[tempCount];
850 totalEnergy = pseudoParticle[6].GetTotalEnergy()/GeV;
851 vecMass = std::min( rmb, totalEnergy );
852 pseudoParticle[6].SetMass( vecMass*GeV );
853 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
854 pp1 = pseudoParticle[6].GetMomentum().mag()/MeV;
855 if( pp1 < 1.0e-6*GeV ) {
856 G4ThreeVector iso = Isotropic(pp);
857 pseudoParticle[6].SetMomentum( iso.x(), iso.y(), iso.z() );
858 } else {
859 pseudoParticle[6].SetMomentum( pseudoParticle[6].GetMomentum() * (-pp/pp1) );
860 }
861 G4FastVector<G4ReactionProduct,256> tempV; // tempV contains the backward nucleons
862 tempV.Initialize( backwardNucleonCount );
863 G4int tempLen = 0;
864 if( targetParticle.GetSide() == -3 )tempV.SetElement( tempLen++, &targetParticle );
865 for( i=0; i<vecLen; ++i )
866 {
867 if( vec[i]->GetSide() == -3 )tempV.SetElement( tempLen++, vec[i] );
868 }
869 if( tempLen != backwardNucleonCount )
870 {
871 G4cerr << "tempLen is not the same as backwardNucleonCount" << G4endl;
872 G4cerr << "tempLen = " << tempLen;
873 G4cerr << ", backwardNucleonCount = " << backwardNucleonCount << G4endl;
874 G4cerr << "targetParticle side = " << targetParticle.GetSide() << G4endl;
875 G4cerr << "currentParticle side = " << currentParticle.GetSide() << G4endl;
876 for( i=0; i<vecLen; ++i )
877 G4cerr << "particle #" << i << " side = " << vec[i]->GetSide() << G4endl;
878 exit( EXIT_FAILURE );
879 }
880 constantCrossSection = true;
881 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
882 if( tempLen >= 2 )
883 {
884 wgt = GenerateNBodyEvent(
885 pseudoParticle[6].GetMass(), constantCrossSection, tempV, tempLen );
886 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
887 if( targetParticle.GetSide() == -3 )
888 {
889 targetParticle.Lorentz( targetParticle, pseudoParticle[6] );
890 // tempV contains the real stuff
891 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
892 }
893 for( i=0; i<vecLen; ++i )
894 {
895 if( vec[i]->GetSide() == -3 )
896 {
897 vec[i]->Lorentz( *vec[i], pseudoParticle[6] );
898 pseudoParticle[5] = pseudoParticle[5] + (*vec[i]);
899 }
900 }
901 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
902 }
903 }
904 else return false;
905
906 //
907 // Lorentz transformation in lab system
908 //
909 if( vecLen == 0 )return false; // all the secondaries have been eliminated
910 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
911
912 currentParticle.Lorentz( currentParticle, pseudoParticle[1] );
913 targetParticle.Lorentz( targetParticle, pseudoParticle[1] );
914 for( i=0; i<vecLen; ++i ) vec[i]->Lorentz( *vec[i], pseudoParticle[1] );
915
916 // leadFlag will be true if original particle and incident particle are
917 // both strange, in which case the incident particle becomes the leading
918 // particle.
919 // leadFlag will also be true if the target particle is strange, but the
920 // incident particle is not, in which case the target particle becomes the
921 // leading particle.
922
923 G4bool leadingStrangeParticleHasChanged = true;
924 if( leadFlag )
925 {
926 if( currentParticle.GetDefinition() == leadingStrangeParticle.GetDefinition() )
927 leadingStrangeParticleHasChanged = false;
928 if( leadingStrangeParticleHasChanged &&
929 ( targetParticle.GetDefinition() == leadingStrangeParticle.GetDefinition() ) )
930 leadingStrangeParticleHasChanged = false;
931 if( leadingStrangeParticleHasChanged )
932 {
933 for( i=0; i<vecLen; i++ )
934 {
935 if( vec[i]->GetDefinition() == leadingStrangeParticle.GetDefinition() )
936 {
937 leadingStrangeParticleHasChanged = false;
938 break;
939 }
940 }
941 }
942 if( leadingStrangeParticleHasChanged )
943 {
944 G4bool leadTest =
945 (leadingStrangeParticle.GetDefinition()->GetParticleSubType() == "kaon" ||
946 leadingStrangeParticle.GetDefinition()->GetParticleSubType() == "pi");
947 G4bool targetTest =
948 (targetParticle.GetDefinition()->GetParticleSubType() == "kaon" ||
949 targetParticle.GetDefinition()->GetParticleSubType() == "pi");
950
951 // following modified by JLC 22-Oct-97
952
953 if( (leadTest&&targetTest) || !(leadTest||targetTest) ) // both true or both false
954 {
955 targetParticle.SetDefinitionAndUpdateE( leadingStrangeParticle.GetDefinition() );
956 targetHasChanged = true;
957 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
958 }
959 else
960 {
961 currentParticle.SetDefinitionAndUpdateE( leadingStrangeParticle.GetDefinition() );
962 incidentHasChanged = false;
963 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
964 }
965 }
966 } // end of if( leadFlag )
967
968 // Get number of final state nucleons and nucleons remaining in
969 // target nucleus
970
971 std::pair<G4int, G4int> finalStateNucleons =
972 GetFinalStateNucleons(originalTarget, vec, vecLen);
973
974 G4int protonsInFinalState = finalStateNucleons.first;
975 G4int neutronsInFinalState = finalStateNucleons.second;
976
977 G4int numberofFinalStateNucleons =
978 protonsInFinalState + neutronsInFinalState;
979
980 if (currentParticle.GetDefinition()->GetBaryonNumber() == 1 &&
981 targetParticle.GetDefinition()->GetBaryonNumber() == 1 &&
982 originalIncident->GetDefinition()->GetPDGMass() <
983 G4Lambda::Lambda()->GetPDGMass())
984 numberofFinalStateNucleons++;
985
986 numberofFinalStateNucleons = std::max(1, numberofFinalStateNucleons);
987
988 G4int PinNucleus = std::max(0,
989 G4int(targetNucleus.GetZ()) - protonsInFinalState);
990 G4int NinNucleus = std::max(0,
991 G4int(targetNucleus.GetN()-targetNucleus.GetZ()) - neutronsInFinalState);
992
993 pseudoParticle[3].SetMomentum( 0.0, 0.0, pOriginal*GeV );
994 pseudoParticle[3].SetMass( mOriginal*GeV );
995 pseudoParticle[3].SetTotalEnergy(
996 std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
997
998 G4ParticleDefinition * aOrgDef = modifiedOriginal.GetDefinition();
999 G4int diff = 0;
1000 if(aOrgDef == G4Proton::Proton() || aOrgDef == G4Neutron::Neutron() ) diff = 1;
1001 if(numberofFinalStateNucleons == 1) diff = 0;
1002 pseudoParticle[4].SetMomentum( 0.0, 0.0, 0.0 );
1003 pseudoParticle[4].SetMass( protonMass*(numberofFinalStateNucleons-diff)*MeV );
1004 pseudoParticle[4].SetTotalEnergy( protonMass*(numberofFinalStateNucleons-diff)*MeV );
1005
1006 G4double theoreticalKinetic =
1007 pseudoParticle[3].GetTotalEnergy()/MeV +
1008 pseudoParticle[4].GetTotalEnergy()/MeV -
1009 currentParticle.GetMass()/MeV -
1010 targetParticle.GetMass()/MeV;
1011
1012 G4double simulatedKinetic =
1013 currentParticle.GetKineticEnergy()/MeV + targetParticle.GetKineticEnergy()/MeV;
1014
1015 pseudoParticle[5] = pseudoParticle[3] + pseudoParticle[4];
1016 pseudoParticle[3].Lorentz( pseudoParticle[3], pseudoParticle[5] );
1017 pseudoParticle[4].Lorentz( pseudoParticle[4], pseudoParticle[5] );
1018
1019 pseudoParticle[7].SetZero();
1020 pseudoParticle[7] = pseudoParticle[7] + currentParticle;
1021 pseudoParticle[7] = pseudoParticle[7] + targetParticle;
1022
1023 for( i=0; i<vecLen; ++i )
1024 {
1025 pseudoParticle[7] = pseudoParticle[7] + *vec[i];
1026 simulatedKinetic += vec[i]->GetKineticEnergy()/MeV;
1027 theoreticalKinetic -= vec[i]->GetMass()/MeV;
1028 }
1029
1030 if( vecLen <= 16 && vecLen > 0 )
1031 {
1032 // must create a new set of ReactionProducts here because GenerateNBody will
1033 // modify the momenta for the particles, and we don't want to do this
1034 //
1035 G4ReactionProduct tempR[130];
1036 tempR[0] = currentParticle;
1037 tempR[1] = targetParticle;
1038 for( i=0; i<vecLen; ++i )tempR[i+2] = *vec[i];
1039 G4FastVector<G4ReactionProduct,256> tempV;
1040 tempV.Initialize( vecLen+2 );
1041 G4int tempLen = 0;
1042 for( i=0; i<vecLen+2; ++i )tempV.SetElement( tempLen++, &tempR[i] );
1043 constantCrossSection = true;
1044
1045 wgt = GenerateNBodyEvent( pseudoParticle[3].GetTotalEnergy()/MeV+
1046 pseudoParticle[4].GetTotalEnergy()/MeV,
1047 constantCrossSection, tempV, tempLen );
1048 if (wgt == -1) {
1049 G4double Qvalue = 0;
1050 for (i = 0; i < tempLen; i++) Qvalue += tempV[i]->GetMass();
1051 wgt = GenerateNBodyEvent( Qvalue/MeV,
1052 constantCrossSection, tempV, tempLen );
1053 }
1054 if(wgt>-.5)
1055 {
1056 theoreticalKinetic = 0.0;
1057 for( i=0; i<tempLen; ++i )
1058 {
1059 pseudoParticle[6].Lorentz( *tempV[i], pseudoParticle[4] );
1060 theoreticalKinetic += pseudoParticle[6].GetKineticEnergy()/MeV;
1061 }
1062 }
1063 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
1064 }
1065 //
1066 // Make sure, that the kinetic energies are correct
1067 //
1068 if( simulatedKinetic != 0.0 )
1069 {
1070 wgt = (theoreticalKinetic)/simulatedKinetic;
1071 theoreticalKinetic = currentParticle.GetKineticEnergy()/MeV * wgt;
1072 simulatedKinetic = theoreticalKinetic;
1073 currentParticle.SetKineticEnergy( theoreticalKinetic*MeV );
1074 pp = currentParticle.GetTotalMomentum()/MeV;
1075 pp1 = currentParticle.GetMomentum().mag()/MeV;
1076 if( pp1 < 1.0e-6*GeV ) {
1077 G4ThreeVector iso = Isotropic(pp);
1078 currentParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
1079 } else {
1080 currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
1081 }
1082 theoreticalKinetic = targetParticle.GetKineticEnergy()/MeV * wgt;
1083 targetParticle.SetKineticEnergy( theoreticalKinetic*MeV );
1084 simulatedKinetic += theoreticalKinetic;
1085 pp = targetParticle.GetTotalMomentum()/MeV;
1086 pp1 = targetParticle.GetMomentum().mag()/MeV;
1087 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
1088 if( pp1 < 1.0e-6*GeV ) {
1089 G4ThreeVector iso = Isotropic(pp);
1090 targetParticle.SetMomentum( iso.x(), iso.y(), iso.z() );
1091 } else {
1092 targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
1093 }
1094
1095 for( i=0; i<vecLen; ++i ) {
1096 theoreticalKinetic = vec[i]->GetKineticEnergy()/MeV * wgt;
1097 simulatedKinetic += theoreticalKinetic;
1098 vec[i]->SetKineticEnergy( theoreticalKinetic*MeV );
1099 pp = vec[i]->GetTotalMomentum()/MeV;
1100 pp1 = vec[i]->GetMomentum().mag()/MeV;
1101 if( pp1 < 1.0e-6*GeV ) {
1102 G4ThreeVector iso = Isotropic(pp);
1103 vec[i]->SetMomentum( iso.x(), iso.y(), iso.z() );
1104 } else {
1105 vec[i]->SetMomentum( vec[i]->GetMomentum() * (pp/pp1) );
1106 }
1107 }
1108 }
1109 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
1110
1111 Rotate( numberofFinalStateNucleons, pseudoParticle[3].GetMomentum(),
1112 modifiedOriginal, originalIncident, targetNucleus,
1113 currentParticle, targetParticle, vec, vecLen );
1114 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
1115 //
1116 // add black track particles
1117 // the total number of particles produced is restricted to 198
1118 // this may have influence on very high energies
1119 //
1120 if( atomicWeight >= 1.5 )
1121 {
1122 // npnb is number of proton/neutron black track particles
1123 // ndta is the number of deuterons, tritons, and alphas produced
1124 // epnb is the kinetic energy available for proton/neutron black track particles
1125 // edta is the kinetic energy available for deuteron/triton/alpha particles
1126 //
1127 G4int npnb = 0;
1128 G4int ndta = 0;
1129
1130 G4double epnb, edta;
1131 if (veryForward) {
1132 epnb = targetNucleus.GetAnnihilationPNBlackTrackEnergy();
1133 edta = targetNucleus.GetAnnihilationDTABlackTrackEnergy();
1134 } else {
1135 epnb = targetNucleus.GetPNBlackTrackEnergy();
1136 edta = targetNucleus.GetDTABlackTrackEnergy();
1137 }
1138
1139 const G4double pnCutOff = 0.001;
1140 const G4double dtaCutOff = 0.001;
1141 const G4double kineticMinimum = 1.e-6;
1142 const G4double kineticFactor = -0.010;
1143 G4double sprob = 0.0; // sprob = probability of self-absorption in heavy molecules
1144 const G4double ekIncident = originalIncident->GetKineticEnergy()/GeV;
1145 if( ekIncident >= 5.0 )sprob = std::min( 1.0, 0.6*std::log(ekIncident-4.0) );
1146 if( epnb >= pnCutOff )
1147 {
1148 npnb = G4Poisson((1.5+1.25*numberofFinalStateNucleons)*epnb/(epnb+edta));
1149 if( numberofFinalStateNucleons + npnb > atomicWeight )
1150 npnb = G4int(atomicWeight+0.00001 - numberofFinalStateNucleons);
1151 npnb = std::min( npnb, 127-vecLen );
1152 }
1153 if( edta >= dtaCutOff )
1154 {
1155 ndta = G4Poisson( (1.5+1.25*numberofFinalStateNucleons)*edta/(epnb+edta) );
1156 ndta = std::min( ndta, 127-vecLen );
1157 }
1158 if (npnb == 0 && ndta == 0) npnb = 1;
1159
1160 // DEBUGGING --> DumpFrames::DumpFrame(vec, vecLen);
1161
1162 AddBlackTrackParticles(epnb, npnb, edta, ndta, sprob, kineticMinimum,
1163 kineticFactor, modifiedOriginal,
1164 PinNucleus, NinNucleus, targetNucleus,
1165 vec, vecLen);
1166 }
1167 // if( centerofmassEnergy <= (4.0+G4UniformRand()) )
1168 // MomentumCheck( modifiedOriginal, currentParticle, targetParticle,
1169 // vec, vecLen );
1170 //
1171 // calculate time delay for nuclear reactions
1172 //
1173 if( (atomicWeight >= 1.5) && (atomicWeight <= 230.0) && (ekOriginal <= 0.2) )
1174 currentParticle.SetTOF(
1175 1.0-500.0*std::exp(-ekOriginal/0.04)*std::log(G4UniformRand()) );
1176 else
1177 currentParticle.SetTOF( 1.0 );
1178 return true;
1179
1180}
1181
1182 /* end of file */
Note: See TracBrowser for help on using the repository browser.