56{
57
58
59
60
61
62
69 G4bool veryForward =
false;
70
77 G4double centerofmassEnergy = std::sqrt(mOriginal*mOriginal +
78 targetMass*targetMass +
79 2.0*targetMass*etOriginal);
81 targetMass = targetParticle.
GetMass()/GeV;
82
83 if (currentMass == 0.0 && targetMass == 0.0) {
86 currentParticle = *vec[0];
87 targetParticle = *vec[1];
88 for (i = 0; i < (vecLen-2); ++i) *vec[i] = *vec[i+2];
89 if (vecLen < 2) {
90 for (
G4int j = 0; j < vecLen; j++)
delete vec[j];
91 vecLen = 0;
93 "G4RPGTwoCluster::ReactionStage : Negative number of particles");
94 }
95 delete vec[vecLen-1];
96 delete vec[vecLen-2];
97 vecLen -= 2;
98 currentMass = currentParticle.
GetMass()/GeV;
99 targetMass = targetParticle.
GetMass()/GeV;
100 incidentHasChanged = true;
101 targetHasChanged = true;
104 veryForward = true;
105 }
106
109
110
111
112
113
114
115 G4int forwardCount = 1;
119
120
121 G4int backwardCount = 1;
125
126
127 for (i = 0; i < vecLen; ++i) {
128 if (vec[i]->GetSide() < 0) vec[i]->SetSide(-1);
129
130
131 if (vec[i]->GetSide() == -1) {
132 ++backwardCount;
133 backwardMass += vec[i]->GetMass()/GeV;
134 } else {
135 ++forwardCount;
136 forwardMass += vec[i]->GetMass()/GeV;
137 }
138 }
139
140
141 G4double term1 = std::log(centerofmassEnergy*centerofmassEnergy);
142 if(term1 < 0) term1 = 0.0001;
143 const G4double afc = 0.312 + 0.2 * std::log(term1);
146 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2*backwardCount+vecLen+2)/2.0;
147 else
148 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2*backwardCount);
149 if( xtarg <= 0.0 )xtarg = 0.01;
151
152 if(atomicWeight<1.0001) nuclearExcitationCount = 0;
153
154
155
156 if( nuclearExcitationCount > 0 )
157 {
158 G4int momentumBin = std::min( 4,
G4int(pOriginal/3.0) );
159 const G4double nucsup[] = { 1.0, 0.8, 0.6, 0.5, 0.4 };
160
161
162
163
164 for( i=0; i<nuclearExcitationCount; ++i )
165 {
168 {
171 else
173
174
175
176 }
177 else
178 {
180 if( ran < 0.3181 )
182 else if( ran < 0.6819 )
184 else
186
187
188
189
190 }
192
195 }
196 }
197
198
199
200
201
202 G4double forwardEnergy = (centerofmassEnergy-cMass-bMass)/2.0 +cMass - forwardMass;
203 G4double backwardEnergy = (centerofmassEnergy-cMass-bMass)/2.0 +bMass - backwardMass;
204 G4double eAvailable = centerofmassEnergy - (forwardMass+backwardMass);
207
208 while( eAvailable <= 0.0 )
209 {
210 secondaryDeleted = false;
211 for( i=(vecLen-1); i>=0; --i )
212 {
213 if( vec[i]->GetSide() == 1 && vec[i]->GetMayBeKilled())
214 {
215 pMass = vec[i]->GetMass()/GeV;
216 for(
G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
217 --forwardCount;
218 forwardEnergy += pMass;
219 forwardMass -= pMass;
220 secondaryDeleted = true;
221 break;
222 }
223 else if( vec[i]->GetSide() == -1 && vec[i]->GetMayBeKilled())
224 {
225 pMass = vec[i]->GetMass()/GeV;
226 for(
G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
227 --backwardCount;
228 backwardEnergy += pMass;
229 backwardMass -= pMass;
230 secondaryDeleted = true;
231 break;
232 }
233 }
234
235 if( secondaryDeleted )
236 {
237 delete vec[vecLen-1];
238 --vecLen;
239
240 }
241 else
242 {
243 if( vecLen == 0 ) return false;
244 if( targetParticle.
GetSide() == -1 )
245 {
246 pMass = targetParticle.
GetMass()/GeV;
247 targetParticle = *vec[0];
248 for(
G4int j=0; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
249 --backwardCount;
250 backwardEnergy += pMass;
251 backwardMass -= pMass;
252 secondaryDeleted = true;
253 }
254 else if( targetParticle.
GetSide() == 1 )
255 {
256 pMass = targetParticle.
GetMass()/GeV;
257 targetParticle = *vec[0];
258 for(
G4int j=0; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
259 --forwardCount;
260 forwardEnergy += pMass;
261 forwardMass -= pMass;
262 secondaryDeleted = true;
263 }
264
265 if( secondaryDeleted )
266 {
267 delete vec[vecLen-1];
268 --vecLen;
269 }
270 else
271 {
272 if( currentParticle.
GetSide() == -1 )
273 {
274 pMass = currentParticle.
GetMass()/GeV;
275 currentParticle = *vec[0];
276 for(
G4int j=0; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
277 --backwardCount;
278 backwardEnergy += pMass;
279 backwardMass -= pMass;
280 secondaryDeleted = true;
281 }
282 else if( currentParticle.
GetSide() == 1 )
283 {
284 pMass = currentParticle.
GetMass()/GeV;
285 currentParticle = *vec[0];
286 for(
G4int j=0; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
287 --forwardCount;
288 forwardEnergy += pMass;
289 forwardMass -= pMass;
290 secondaryDeleted = true;
291 }
292 if( secondaryDeleted )
293 {
294 delete vec[vecLen-1];
295 --vecLen;
296 }
297 else break;
298
299 }
300 }
301
302 eAvailable = centerofmassEnergy - (forwardMass+backwardMass);
303 }
304
305
306
307
308
309
310
311
312
313
314 const G4double cpar[] = { 1.60, 1.35, 1.15, 1.10 };
315 const G4double gpar[] = { 2.60, 1.80, 1.30, 1.20 };
317
318 if (forwardCount < 1 || backwardCount < 1) return false;
319
321 if (forwardCount > 1) {
322 ntc = std::min(3,forwardCount-2);
323 rmc += std::pow(-std::log(1.0-
G4UniformRand()),1./cpar[ntc])/gpar[ntc];
324 }
326 if( backwardCount > 1 ) {
327 ntc = std::min(3,backwardCount-2);
328 rmd += std::pow(-std::log(1.0-
G4UniformRand()),1./cpar[ntc])/gpar[ntc];
329 }
330
331 while( rmc+rmd > centerofmassEnergy )
332 {
333 if( (rmc <= forwardMass) && (rmd <= backwardMass) )
334 {
335 G4double temp = 0.999*centerofmassEnergy/(rmc+rmd);
336 rmc *= temp;
337 rmd *= temp;
338 }
339 else
340 {
341 rmc = 0.1*forwardMass + 0.9*rmc;
342 rmd = 0.1*backwardMass + 0.9*rmd;
343 }
344 }
345
347 for( i=0; i<8; ++i )pseudoParticle[i].SetZero();
348
349 pseudoParticle[1].
SetMass( mOriginal*GeV );
351 pseudoParticle[1].
SetMomentum( 0.0, 0.0, pOriginal*GeV );
352
353 pseudoParticle[2].
SetMass( protonMass*MeV );
356
357
358
359 pseudoParticle[0] = pseudoParticle[1] + pseudoParticle[2];
360 pseudoParticle[1].
Lorentz( pseudoParticle[1], pseudoParticle[0] );
361 pseudoParticle[2].Lorentz( pseudoParticle[2], pseudoParticle[0] );
362
363
364
365
366
368 G4double pf = (centerofmassEnergy*centerofmassEnergy+rmd*rmd-rmc*rmc);
369 pf *= pf;
370 pf -= 4*centerofmassEnergy*centerofmassEnergy*rmd*rmd;
371 pf = std::sqrt( std::max(pf,pfMin) )/(2.0*centerofmassEnergy);
372
373
374
375 pseudoParticle[3].SetMass( rmc*GeV );
376 pseudoParticle[3].SetTotalEnergy( std::sqrt(pf*pf+rmc*rmc)*GeV );
377
378 pseudoParticle[4].SetMass( rmd*GeV );
379 pseudoParticle[4].SetTotalEnergy( std::sqrt(pf*pf+rmd*rmd)*GeV );
380
381
382
383
387 G4double pin = pseudoParticle[1].GetMomentum().mag()/GeV;
388 G4double dtb = 4.0*pin*pf*std::max( bMin, b1+b2*std::log(pOriginal) );
389 G4double factor = 1.0 - std::exp(-dtb);
391
392 costheta = std::max(-1.0, std::min(1.0, costheta));
393 G4double sintheta = std::sqrt((1.0-costheta)*(1.0+costheta));
395
396
397
398 pseudoParticle[3].SetMomentum( pf*sintheta*std::cos(phi)*GeV,
399 pf*sintheta*std::sin(phi)*GeV,
400 pf*costheta*GeV );
401 pseudoParticle[4].SetMomentum( -pseudoParticle[3].GetMomentum());
402
403
404
405
407 if( nuclearExcitationCount > 0 )
408 {
412 if( ekOriginal <= 5.0 )
413 {
414 ekit1 *= ekOriginal*ekOriginal/25.0;
415 ekit2 *= ekOriginal*ekOriginal/25.0;
416 }
417 G4double scale = std::pow(ekit2/ekit1, 1.0-ga) - 1.0;
418 for( i=0; i<vecLen; ++i )
419 {
420 if( vec[i]->GetSide() == -2 )
421 {
423 vec[i]->SetKineticEnergy( kineticE*GeV );
424 G4double vMass = vec[i]->GetMass()/MeV;
425 G4double totalE = kineticE*GeV + vMass;
426 pp = std::sqrt( std::abs(totalE*totalE-vMass*vMass) );
428 G4double sint = std::sqrt(1.0-cost*cost);
430 vec[i]->SetMomentum( pp*sint*std::cos(phi)*MeV,
431 pp*sint*std::sin(phi)*MeV,
432 pp*cost*MeV );
433 vec[i]->Lorentz( *vec[i], pseudoParticle[0] );
434 }
435 }
436 }
437
438
439
440
441
442 currentParticle.
SetMomentum( pseudoParticle[3].GetMomentum() );
443 currentParticle.
SetTotalEnergy( pseudoParticle[3].GetTotalEnergy() );
444
445 targetParticle.
SetMomentum( pseudoParticle[4].GetMomentum() );
446 targetParticle.
SetTotalEnergy( pseudoParticle[4].GetTotalEnergy() );
447
448 pseudoParticle[5].SetMomentum( pseudoParticle[3].GetMomentum() * (-1.0) );
449 pseudoParticle[5].SetMass( pseudoParticle[3].GetMass() );
450 pseudoParticle[5].SetTotalEnergy( pseudoParticle[3].GetTotalEnergy() );
451
452 pseudoParticle[6].SetMomentum( pseudoParticle[4].GetMomentum() * (-1.0) );
453 pseudoParticle[6].SetMass( pseudoParticle[4].GetMass() );
454 pseudoParticle[6].SetTotalEnergy( pseudoParticle[4].GetTotalEnergy() );
455
457
458 if( forwardCount > 1 )
459 {
462 G4bool constantCrossSection =
true;
464 if( currentParticle.
GetSide() == 1 )
465 tempV.
SetElement( tempLen++, ¤tParticle );
466 if( targetParticle.
GetSide() == 1 )
467 tempV.
SetElement( tempLen++, &targetParticle );
468 for( i=0; i<vecLen; ++i )
469 {
470 if( vec[i]->GetSide() == 1 )
471 {
472 if( tempLen < 18 )
474 else
475 {
476 vec[i]->SetSide( -1 );
477 continue;
478 }
479 }
480 }
481 if( tempLen >= 2 )
482 {
484 constantCrossSection, tempV, tempLen );
485 if( currentParticle.
GetSide() == 1 )
486 currentParticle.
Lorentz( currentParticle, pseudoParticle[5] );
487 if( targetParticle.
GetSide() == 1 )
488 targetParticle.
Lorentz( targetParticle, pseudoParticle[5] );
489 for( i=0; i<vecLen; ++i )
490 {
491 if( vec[i]->GetSide() == 1 )vec[i]->Lorentz( *vec[i], pseudoParticle[5] );
492 }
493 }
494 }
495
496 if( backwardCount > 1 )
497 {
500 G4bool constantCrossSection =
true;
502 if( currentParticle.
GetSide() == -1 )
503 tempV.
SetElement( tempLen++, ¤tParticle );
504 if( targetParticle.
GetSide() == -1 )
505 tempV.
SetElement( tempLen++, &targetParticle );
506 for( i=0; i<vecLen; ++i )
507 {
508 if( vec[i]->GetSide() == -1 )
509 {
510 if( tempLen < 18 )
512 else
513 {
514 vec[i]->SetSide( -2 );
515 vec[i]->SetKineticEnergy( 0.0 );
516 vec[i]->SetMomentum( 0.0, 0.0, 0.0 );
517 continue;
518 }
519 }
520 }
521 if( tempLen >= 2 )
522 {
524 constantCrossSection, tempV, tempLen );
525 if( currentParticle.
GetSide() == -1 )
526 currentParticle.
Lorentz( currentParticle, pseudoParticle[6] );
527 if( targetParticle.
GetSide() == -1 )
528 targetParticle.
Lorentz( targetParticle, pseudoParticle[6] );
529 for( i=0; i<vecLen; ++i )
530 {
531 if( vec[i]->GetSide() == -1 )vec[i]->Lorentz( *vec[i], pseudoParticle[6] );
532 }
533 }
534 }
535
536
537
538
539
540 currentParticle.
Lorentz( currentParticle, pseudoParticle[2] );
541 targetParticle.
Lorentz( targetParticle, pseudoParticle[2] );
542 for( i=0; i<vecLen; ++i ) vec[i]->Lorentz( *vec[i], pseudoParticle[2] );
543
544
545
546
547
549 if( leadFlag )
550 {
551
552
553
554
555
556
558 dum = false;
560 dum = false;
561 else
562 {
563 for( i=0; i<vecLen; ++i )
564 {
565 if( vec[i]->GetDefinition() == leadingStrangeParticle.
GetDefinition() )
566 {
567 dum = false;
568 break;
569 }
570 }
571 }
572 if( dum )
573 {
576 if( ((leadMass < protonMass) && (targetParticle.
GetMass()/MeV < protonMass)) ||
577 ((leadMass >= protonMass) && (targetParticle.
GetMass()/MeV >= protonMass)) )
578 {
584 if( pp1 < 1.0e-3 ) {
587 } else {
589 }
590 targetHasChanged = true;
591 }
592 else
593 {
599 if( pp1 < 1.0e-3 ) {
602 } else {
604 }
605 incidentHasChanged = true;
606 }
607 }
608 }
609
610
611
612
613 std::pair<G4int, G4int> finalStateNucleons =
615
616 G4int protonsInFinalState = finalStateNucleons.first;
617 G4int neutronsInFinalState = finalStateNucleons.second;
618
619 G4int numberofFinalStateNucleons =
620 protonsInFinalState + neutronsInFinalState;
621
626 numberofFinalStateNucleons++;
627
628 numberofFinalStateNucleons = std::max(1, numberofFinalStateNucleons);
629
630 G4int PinNucleus = std::max(0,
632 G4int NinNucleus = std::max(0,
634
635
636
637
638 pseudoParticle[4].SetMass( mOriginal*GeV );
639 pseudoParticle[4].SetTotalEnergy( etOriginal*GeV );
640 pseudoParticle[4].SetMomentum( 0.0, 0.0, pOriginal*GeV );
641
645 if(numberofFinalStateNucleons == 1) diff = 0;
646 pseudoParticle[5].SetMomentum( 0.0, 0.0, 0.0 );
647 pseudoParticle[5].SetMass( protonMass*(numberofFinalStateNucleons-diff)*MeV);
648 pseudoParticle[5].SetTotalEnergy( protonMass*(numberofFinalStateNucleons-diff)*MeV);
649
651 pseudoParticle[4].GetTotalEnergy()/GeV + pseudoParticle[5].GetTotalEnergy()/GeV;
652
653 pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
654 pseudoParticle[4].Lorentz( pseudoParticle[4], pseudoParticle[6] );
655 pseudoParticle[5].Lorentz( pseudoParticle[5], pseudoParticle[6] );
656
657 if( vecLen < 16 )
658 {
660 tempR[0] = currentParticle;
661 tempR[1] = targetParticle;
662 for( i=0; i<vecLen; ++i )tempR[i+2] = *vec[i];
663
666 G4bool constantCrossSection =
true;
668 for( i=0; i<vecLen+2; ++i )tempV.
SetElement( tempLen++, &tempR[i] );
669
670 if( tempLen >= 2 )
671 {
672
674 pseudoParticle[5].GetTotalEnergy()/MeV,
675 constantCrossSection, tempV, tempLen );
676 if (wgt == -1) {
678 for (i = 0; i < tempLen; i++) Qvalue += tempV[i]->GetMass();
680 constantCrossSection, tempV, tempLen );
681 }
682 theoreticalKinetic = 0.0;
683 for( i=0; i<vecLen+2; ++i )
684 {
685 pseudoParticle[7].SetMomentum( tempV[i]->GetMomentum() );
686 pseudoParticle[7].SetMass( tempV[i]->GetMass() );
687 pseudoParticle[7].SetTotalEnergy( tempV[i]->GetTotalEnergy() );
688 pseudoParticle[7].Lorentz( pseudoParticle[7], pseudoParticle[5] );
689 theoreticalKinetic += pseudoParticle[7].GetKineticEnergy()/GeV;
690 }
691 }
692
693 }
694 else
695 {
696 theoreticalKinetic -=
698 for( i=0; i<vecLen; ++i )theoreticalKinetic -= vec[i]->GetMass()/GeV;
699 }
702 for( i=0; i<vecLen; ++i )simulatedKinetic += vec[i]->GetKineticEnergy()/GeV;
703
704
705
706
707 if( simulatedKinetic != 0.0 )
708 {
709 wgt = (theoreticalKinetic)/simulatedKinetic;
713 if( pp1 < 0.001*MeV ) {
716 } else {
718 }
719
723 if( pp1 < 0.001*MeV ) {
726 } else {
728 }
729
730 for( i=0; i<vecLen; ++i )
731 {
732 vec[i]->SetKineticEnergy( wgt*vec[i]->GetKineticEnergy() );
733 pp = vec[i]->GetTotalMomentum()/MeV;
734 pp1 = vec[i]->GetMomentum().mag()/MeV;
735 if( pp1 < 0.001 ) {
737 vec[i]->SetMomentum( iso.
x(), iso.
y(), iso.
z() );
738 } else {
739 vec[i]->SetMomentum( vec[i]->GetMomentum() * (pp/pp1) );
740 }
741 }
742 }
743
744
745 Rotate( numberofFinalStateNucleons, pseudoParticle[4].GetMomentum(),
746 modifiedOriginal, originalIncident, targetNucleus,
747 currentParticle, targetParticle, vec, vecLen );
748
749
750
751
752
753 if( atomicWeight >= 1.5 )
754 {
755
756
757
758
759
760
761
764
766 if (veryForward) {
769 } else {
772 }
773
776
777
778
779
780
781
782
783
784 if( epnb >= pnCutOff )
785 {
786 npnb =
G4Poisson((1.5+1.25*numberofFinalStateNucleons)*epnb/(epnb+edta));
787 if( numberofFinalStateNucleons + npnb > atomicWeight )
788 npnb =
G4int(atomicWeight - numberofFinalStateNucleons);
789 npnb = std::min( npnb, 127-vecLen );
790 }
791 if( edta >= dtaCutOff )
792 {
793 ndta =
G4Poisson( (1.5+1.25*numberofFinalStateNucleons)*edta/(epnb+edta) );
794 ndta = std::min( ndta, 127-vecLen );
795 }
796 if (npnb == 0 && ndta == 0) npnb = 1;
797
798
799
801 PinNucleus, NinNucleus, targetNucleus,
802 vec, vecLen );
803
804 }
805
806
807
808
809
810
811 if( (atomicWeight >= 1.5) && (atomicWeight <= 230.0) && (ekOriginal <= 0.2) )
813 else
814 currentParticle.
SetTOF( 1.0 );
815
816 return true;
817}
G4long G4Poisson(G4double mean)
void SetElement(G4int anIndex, Type *anElement)
void Initialize(G4int items)
const G4ParticleDefinition * GetDefinition() const
static G4Lambda * Lambda()
static G4Neutron * Neutron()
G4double GetAnnihilationPNBlackTrackEnergy() const
G4double GetPNBlackTrackEnergy() const
G4double GetAnnihilationDTABlackTrackEnergy() const
G4double GetDTABlackTrackEnergy() const
G4double GetPDGMass() const
G4int GetBaryonNumber() const
static G4PionMinus * PionMinus()
static G4PionPlus * PionPlus()
static G4PionZero * PionZero()
static G4Proton * Proton()
void Rotate(const G4double numberofFinalStateNucleons, const G4ThreeVector &temp, const G4ReactionProduct &modifiedOriginal, const G4HadProjectile *originalIncident, const G4Nucleus &targetNucleus, G4ReactionProduct ¤tParticle, G4ReactionProduct &targetParticle, G4FastVector< G4ReactionProduct, 256 > &vec, G4int &vecLen)
std::pair< G4int, G4int > GetFinalStateNucleons(const G4DynamicParticle *originalTarget, const G4FastVector< G4ReactionProduct, 256 > &vec, const G4int &vecLen)
void AddBlackTrackParticles(const G4double, const G4int, const G4double, const G4int, const G4ReactionProduct &, G4int, G4int, const G4Nucleus &, G4FastVector< G4ReactionProduct, 256 > &, G4int &)
G4double GenerateNBodyEvent(const G4double totalEnergy, const G4bool constantCrossSection, G4FastVector< G4ReactionProduct, 256 > &vec, G4int &vecLen)
G4ThreeVector Isotropic(const G4double &)
void SetMomentum(const G4double x, const G4double y, const G4double z)
void SetTotalEnergy(const G4double en)
G4double GetTotalMomentum() const
G4double GetKineticEnergy() const
G4double GetTotalEnergy() const
void SetNewlyAdded(const G4bool f)
G4ThreeVector GetMomentum() const
void SetSide(const G4int sid)
void Lorentz(const G4ReactionProduct &p1, const G4ReactionProduct &p2)
void SetKineticEnergy(const G4double en)
G4ParticleDefinition * GetDefinition() const
void SetTOF(const G4double t)
void SetDefinition(G4ParticleDefinition *aParticleDefinition)
void SetMass(const G4double mas)