118 {
119
120
121
122
123
124
125
126
127
128
129
130
131
132 if(vecLen == 0) return false;
133
139
141 G4bool veryForward =
false;
142
148 G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
149 targetMass*targetMass +
150 2.0*targetMass*etOriginal );
152 targetMass = targetParticle.
GetMass()/GeV;
153
154
155
156
157 for( i=0; i<vecLen; ++i )
158 {
161 *vec[itemp] = *vec[i];
162 *vec[i] = pTemp;
163
164 }
165
166 if( currentMass == 0.0 && targetMass == 0.0 )
167 {
168
169
170
173 currentParticle = *vec[0];
174 targetParticle = *vec[1];
175 for( i=0; i<(vecLen-2); ++i )*vec[i] = *vec[i+2];
177 delete temp;
178 temp = vec[vecLen-2];
179 delete temp;
180 vecLen -= 2;
181 currentMass = currentParticle.
GetMass()/GeV;
182 targetMass = targetParticle.
GetMass()/GeV;
183 incidentHasChanged = true;
184 targetHasChanged = true;
187 veryForward = true;
188 }
192
196 currentParticle = targetParticle;
197 targetParticle = temp;
198 incidentHasChanged = true;
199 targetHasChanged = true;
200 currentMass = currentParticle.
GetMass()/GeV;
201 targetMass = targetParticle.
GetMass()/GeV;
202 }
203 const G4double afc = std::min( 0.75,
204 0.312+0.200*std::log(std::log(centerofmassEnergy*centerofmassEnergy))+
205 std::pow(centerofmassEnergy*centerofmassEnergy,1.5)/6000.0 );
206
207 G4double freeEnergy = centerofmassEnergy-currentMass-targetMass;
208 G4double forwardEnergy = freeEnergy/2.;
209 G4int forwardCount = 1;
210
211 G4double backwardEnergy = freeEnergy/2.;
212 G4int backwardCount = 1;
213
214 if(veryForward)
215 {
216 if(currentParticle.
GetSide()==-1)
217 {
218 forwardEnergy += currentMass;
219 forwardCount --;
220 backwardEnergy -= currentMass;
221 backwardCount ++;
222 }
223 if(targetParticle.
GetSide()!=-1)
224 {
225 backwardEnergy += targetMass;
226 backwardCount --;
227 forwardEnergy -= targetMass;
228 forwardCount ++;
229 }
230 }
231
232 for( i=0; i<vecLen; ++i )
233 {
234 if( vec[i]->GetSide() == -1 )
235 {
236 ++backwardCount;
237 backwardEnergy -= vec[i]->GetMass()/GeV;
238 } else {
239 ++forwardCount;
240 forwardEnergy -= vec[i]->GetMass()/GeV;
241 }
242 }
243
244
245
246
247
250 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount+vecLen+2)/2.0;
251 else
252 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount);
253 if( xtarg <= 0.0 )xtarg = 0.01;
254 G4int nuclearExcitationCount = Poisson( xtarg );
255 if(atomicWeight<1.0001) nuclearExcitationCount = 0;
256 G4int extraNucleonCount = 0;
258 if( nuclearExcitationCount > 0 )
259 {
260 const G4double nucsup[] = { 1.00, 0.7, 0.5, 0.4, 0.35, 0.3 };
261 const G4double psup[] = { 3., 6., 20., 50., 100., 1000. };
262 G4int momentumBin = 0;
263 while( (momentumBin < 6) &&
265 ++momentumBin;
266 momentumBin = std::min( 5, momentumBin );
267
268
269
270
271
272 for( i=0; i<nuclearExcitationCount; ++i )
273 {
276 {
279 else
282 ++extraNucleonCount;
283 backwardEnergy += pVec->
GetMass()/GeV;
284 extraNucleonMass += pVec->
GetMass()/GeV;
285 }
286 else
287 {
289 if( ran < 0.3181 )
291 else if( ran < 0.6819 )
293 else
296 }
299
300 backwardEnergy -= pVec->
GetMass()/GeV;
301 ++backwardCount;
302 }
303 }
304
305
306
308 while( forwardEnergy <= 0.0 )
309 {
310
312 is = 0;
313 G4int forwardParticlesLeft = 0;
314 for( i=(vecLen-1); i>=0; --i )
315 {
316 if( vec[i]->GetSide() == 1 && vec[i]->GetMayBeKilled())
317 {
318 forwardParticlesLeft = 1;
319 if( ++is == iskip )
320 {
321 forwardEnergy += vec[i]->GetMass()/GeV;
322 for(
G4int j=i; j<(vecLen-1); j++ )*vec[j] = *vec[j+1];
323 --forwardCount;
324 delete vec[vecLen-1];
325 if( --vecLen == 0 )return false;
326 break;
327 }
328 }
329 }
330
331 if( forwardParticlesLeft == 0 )
332 {
334 for (i = 0; i < vecLen; i++) {
335 if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
336 iremove = i;
337 break;
338 }
339 }
340 if (iremove == -1) {
341 for (i = 0; i < vecLen; i++) {
342 if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon") {
343 iremove = i;
344 break;
345 }
346 }
347 }
348 if (iremove == -1) iremove = 0;
349
350 forwardEnergy += vec[iremove]->GetMass()/GeV;
351 if (vec[iremove]->GetSide() > 0) --forwardCount;
352
353 for (i = iremove; i < vecLen-1; i++) *vec[i] = *vec[i+1];
354 delete vec[vecLen-1];
355 vecLen--;
356 if (vecLen == 0) return false;
357 break;
358 }
359 }
360
361
362 while( backwardEnergy <= 0.0 )
363 {
364
366 is = 0;
367 G4int backwardParticlesLeft = 0;
368 for( i=(vecLen-1); i>=0; --i )
369 {
370 if( vec[i]->GetSide() < 0 && vec[i]->GetMayBeKilled())
371 {
372 backwardParticlesLeft = 1;
373 if( ++is == iskip )
374 {
375 if( vec[i]->GetSide() == -2 )
376 {
377 --extraNucleonCount;
378 extraNucleonMass -= vec[i]->GetMass()/GeV;
379 backwardEnergy -= vec[i]->GetTotalEnergy()/GeV;
380 }
381 backwardEnergy += vec[i]->GetTotalEnergy()/GeV;
382 for(
G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
383 --backwardCount;
384 delete vec[vecLen-1];
385 if( --vecLen == 0 )return false;
386 break;
387 }
388 }
389 }
390
391 if( backwardParticlesLeft == 0 )
392 {
394 for (i = 0; i < vecLen; i++) {
395 if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
396 iremove = i;
397 break;
398 }
399 }
400 if (iremove == -1) {
401 for (i = 0; i < vecLen; i++) {
402 if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon") {
403 iremove = i;
404 break;
405 }
406 }
407 }
408 if (iremove == -1) iremove = 0;
409
410 backwardEnergy += vec[iremove]->GetMass()/GeV;
411 if (vec[iremove]->GetSide() > 0) --backwardCount;
412
413 for (i = iremove; i < vecLen-1; i++) *vec[i] = *vec[i+1];
414 delete vec[vecLen-1];
415 vecLen--;
416 if (vecLen == 0) return false;
417 break;
418 }
419 }
420
421
422
423
424
425
427 for( i=0; i<10; ++i )pseudoParticle[i].SetZero();
428
429 pseudoParticle[0].
SetMass( mOriginal*GeV );
430 pseudoParticle[0].
SetMomentum( 0.0, 0.0, pOriginal*GeV );
432 std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
433
434 pseudoParticle[1].
SetMass( protonMass*MeV );
436
437 pseudoParticle[3].
SetMass( protonMass*(1+extraNucleonCount)*MeV );
438 pseudoParticle[3].
SetTotalEnergy( protonMass*(1+extraNucleonCount)*MeV );
439
440 pseudoParticle[8].
SetMomentum( 1.0*GeV, 0.0, 0.0 );
441
442 pseudoParticle[2] = pseudoParticle[0] + pseudoParticle[1];
443 pseudoParticle[3] = pseudoParticle[3] + pseudoParticle[0];
444
445 pseudoParticle[0].
Lorentz( pseudoParticle[0], pseudoParticle[2] );
446 pseudoParticle[1].Lorentz( pseudoParticle[1], pseudoParticle[2] );
447
449
450
451
452
454 G4int innerCounter, outerCounter;
455 G4bool eliminateThisParticle, resetEnergies, constantCrossSection;
456
457 G4double forwardKinetic = 0.0, backwardKinetic = 0.0;
458
459
460
461
462
463 G4double binl[20] = {0.,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0,1.11,1.25,
464 1.43,1.67,2.0,2.5,3.33,5.00,10.00};
465 G4int backwardNucleonCount = 0;
466 G4double totalEnergy, kineticEnergy, vecMass;
467
468 for( i=(vecLen-1); i>=0; --i )
469 {
471 if( vec[i]->GetNewlyAdded() )
472 {
473 if( vec[i]->GetSide() == -2 )
474 {
475 if( backwardNucleonCount < 18 )
476 {
477 if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
478 for(
G4int j=0; j<vecLen; j++)
delete vec[j];
479 vecLen = 0;
481 "G4ReactionDynamics::GenerateXandPt : a pion has been counted as a backward nucleon");
482 }
483 vec[i]->SetSide( -3 );
484 ++backwardNucleonCount;
485 continue;
486 }
487 }
488 }
489
490
491
492
493 vecMass = vec[i]->GetMass()/GeV;
495 if( vec[i]->GetSide() == -2 )
496 {
497 if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon" ||
498 vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
499 aspar = 0.75;
500 pt = std::sqrt( std::pow( ran, 1.7 ) );
501 } else {
502 aspar = 0.20;
503 pt = std::sqrt( std::pow( ran, 1.2 ) );
504 }
505
506 } else {
507
508 if (vec[i]->GetDefinition()->GetParticleSubType() == "pi") {
509 aspar = 0.75;
510 pt = std::sqrt( std::pow( ran, 1.7 ) );
511 } else if (vec[i]->GetDefinition()->GetParticleSubType() == "kaon") {
512 aspar = 0.70;
513 pt = std::sqrt( std::pow( ran, 1.7 ) );
514 } else {
515 aspar = 0.65;
516 pt = std::sqrt( std::pow( ran, 1.5 ) );
517 }
518 }
519 pt = std::max( 0.001, pt );
520 vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
521 for(
G4int j=0; j<20; ++j )binl[j] = j/(19.*pt);
522 if( vec[i]->GetSide() > 0 )
523 et = pseudoParticle[0].GetTotalEnergy()/GeV;
524 else
525 et = pseudoParticle[1].GetTotalEnergy()/GeV;
526 dndl[0] = 0.0;
527
528
529
530 outerCounter = 0;
531 eliminateThisParticle = true;
532 resetEnergies = true;
533 while( ++outerCounter < 3 )
534 {
535 for( l=1; l<20; ++l )
536 {
537 x = (binl[l]+binl[l-1])/2.;
538 pt = std::max( 0.001, pt );
539 if( x > 1.0/pt )
540 dndl[l] += dndl[l-1];
541 else
542 dndl[l] = et * aspar/std::sqrt( std::pow((1.+aspar*x*aspar*x),3) )
543 * (binl[l]-binl[l-1]) / std::sqrt( pt*x*et*pt*x*et + pt*pt + vecMass*vecMass )
544 + dndl[l-1];
545 }
546 innerCounter = 0;
547 vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
548
549
550
551 while( ++innerCounter < 7 )
552 {
554 l = 1;
555 while( ( ran >= dndl[l] ) && ( l < 20 ) )l++;
556 l = std::min( 19, l );
557 x = std::min( 1.0, pt*(binl[l-1] +
G4UniformRand()*(binl[l]-binl[l-1]) ) );
558 if( vec[i]->GetSide() < 0 )x *= -1.;
559 vec[i]->SetMomentum( x*et*GeV );
560 totalEnergy = std::sqrt( x*et*x*et + pt*pt + vecMass*vecMass );
561 vec[i]->SetTotalEnergy( totalEnergy*GeV );
562 kineticEnergy = vec[i]->GetKineticEnergy()/GeV;
563 if( vec[i]->GetSide() > 0 )
564 {
565 if( (forwardKinetic+kineticEnergy) < 0.95*forwardEnergy )
566 {
567 pseudoParticle[4] = pseudoParticle[4] + (*vec[i]);
568 forwardKinetic += kineticEnergy;
569 pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
570 pseudoParticle[6].SetMomentum( 0.0 );
571 phi = pseudoParticle[6].Angle( pseudoParticle[8] );
572 if( pseudoParticle[6].GetMomentum().y()/MeV < 0.0 )phi = twopi - phi;
573 phi +=
pi + normal()*
pi/12.0;
574 if( phi > twopi )phi -= twopi;
575 if( phi < 0.0 )phi = twopi - phi;
576 outerCounter = 2;
577 eliminateThisParticle = false;
578 resetEnergies = false;
579 break;
580 }
581 if( innerCounter > 5 )break;
582 if( backwardEnergy >= vecMass )
583 {
584 vec[i]->SetSide( -1 );
585 forwardEnergy += vecMass;
586 backwardEnergy -= vecMass;
587 ++backwardCount;
588 }
589 } else {
590 if( extraNucleonCount > 19 )
591 x = 0.999;
592 G4double xxx = 0.95+0.05*extraNucleonCount/20.0;
593 if( (backwardKinetic+kineticEnergy) < xxx*backwardEnergy )
594 {
595 pseudoParticle[5] = pseudoParticle[5] + (*vec[i]);
596 backwardKinetic += kineticEnergy;
597 pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
598 pseudoParticle[6].SetMomentum( 0.0 );
599 phi = pseudoParticle[6].Angle( pseudoParticle[8] );
600 if( pseudoParticle[6].GetMomentum().y()/MeV < 0.0 )phi = twopi - phi;
601 phi +=
pi + normal() *
pi / 12.0;
602 if( phi > twopi )phi -= twopi;
603 if( phi < 0.0 )phi = twopi - phi;
604 outerCounter = 2;
605 eliminateThisParticle = false;
606 resetEnergies = false;
607 break;
608 }
609 if( innerCounter > 5 )break;
610 if( forwardEnergy >= vecMass )
611 {
612 vec[i]->SetSide( 1 );
613 forwardEnergy -= vecMass;
614 backwardEnergy += vecMass;
615 backwardCount--;
616 }
617 }
619 vec[i]->SetMomentum( momentum.
x() * 0.9, momentum.
y() * 0.9 );
620 pt *= 0.9;
621 dndl[19] *= 0.9;
622 }
623 if( resetEnergies )
624 {
625
626
627
628
629
630 forwardKinetic = 0.0;
631 backwardKinetic = 0.0;
632 pseudoParticle[4].SetZero();
633 pseudoParticle[5].SetZero();
634 for( l=i+1; l<vecLen; ++l )
635 {
636 if (vec[l]->GetSide() > 0 ||
637 vec[l]->GetDefinition()->GetParticleSubType() == "kaon" ||
638 vec[l]->GetDefinition()->GetParticleSubType() == "pi") {
639
640 G4double tempMass = vec[l]->GetMass()/MeV;
641 totalEnergy = 0.95*vec[l]->GetTotalEnergy()/MeV + 0.05*tempMass;
642 totalEnergy = std::max( tempMass, totalEnergy );
643 vec[l]->SetTotalEnergy( totalEnergy*MeV );
644 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - tempMass*tempMass ) );
645 pp1 = vec[l]->GetMomentum().mag()/MeV;
646 if( pp1 < 1.0e-6*GeV )
647 {
649 G4double sintheta = std::sqrt(1. - costheta*costheta);
651 vec[l]->SetMomentum( pp*sintheta*std::cos(phi2)*MeV,
652 pp*sintheta*std::sin(phi2)*MeV,
653 pp*costheta*MeV ) ;
654 } else {
655 vec[l]->SetMomentum( vec[l]->GetMomentum() * (pp/pp1) );
656 }
657 G4double px = vec[l]->GetMomentum().x()/MeV;
658 G4double py = vec[l]->GetMomentum().y()/MeV;
659 pt = std::max( 1.0, std::sqrt( px*px + py*py ) )/GeV;
660 if( vec[l]->GetSide() > 0 )
661 {
662 forwardKinetic += vec[l]->GetKineticEnergy()/GeV;
663 pseudoParticle[4] = pseudoParticle[4] + (*vec[l]);
664 } else {
665 backwardKinetic += vec[l]->GetKineticEnergy()/GeV;
666 pseudoParticle[5] = pseudoParticle[5] + (*vec[l]);
667 }
668 }
669 }
670 }
671 }
672
673 if( eliminateThisParticle && vec[i]->GetMayBeKilled())
674 {
675 if( vec[i]->GetSide() > 0 )
676 {
677 --forwardCount;
678 forwardEnergy += vecMass;
679 } else {
680 if( vec[i]->GetSide() == -2 )
681 {
682 --extraNucleonCount;
683 extraNucleonMass -= vecMass;
684 backwardEnergy -= vecMass;
685 }
686 --backwardCount;
687 backwardEnergy += vecMass;
688 }
689 for(
G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
691 delete temp;
692
693 if( --vecLen == 0 )return false;
694 pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
696 phi = pseudoParticle[6].Angle( pseudoParticle[8] );
697 if( pseudoParticle[6].GetMomentum().y()/MeV < 0.0 )phi = twopi - phi;
698 phi +=
pi + normal() *
pi / 12.0;
699 if( phi > twopi )phi -= twopi;
700 if( phi < 0.0 )phi = twopi - phi;
701 }
702 }
703
704
705
706
707
708
712 aspar = 0.60;
713 pt = std::sqrt( std::pow( ran/6.0, 1.7 ) );
715 aspar = 0.50;
716 pt = std::sqrt( std::pow( ran/5.0, 1.4 ) );
717 } else {
718 aspar = 0.40;
719 pt = std::sqrt( std::pow( ran/4.0, 1.2 ) );
720 }
721
722 for(
G4int j=0; j<20; ++j )binl[j] = j/(19.*pt);
723 currentParticle.
SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
724 et = pseudoParticle[0].GetTotalEnergy()/GeV;
725 dndl[0] = 0.0;
726 vecMass = currentParticle.
GetMass()/GeV;
727 for( l=1; l<20; ++l )
728 {
729 x = (binl[l]+binl[l-1])/2.;
730 if( x > 1.0/pt )
731 dndl[l] += dndl[l-1];
732 else
733 dndl[l] = aspar/std::sqrt( std::pow((1.+
sqr(aspar*x)),3) ) *
734 (binl[l]-binl[l-1]) * et / std::sqrt( pt*x*et*pt*x*et + pt*pt + vecMass*vecMass ) +
735 dndl[l-1];
736 }
738 l = 1;
739 while( (ran>dndl[l]) && (l<20) )l++;
740 l = std::min( 19, l );
741 x = std::min( 1.0, pt*(binl[l-1] +
G4UniformRand()*(binl[l]-binl[l-1]) ) );
743 if( forwardEnergy < forwardKinetic )
744 totalEnergy = vecMass + 0.04*std::fabs(normal());
745 else
746 totalEnergy = vecMass + forwardEnergy - forwardKinetic;
748 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
750 if( pp1 < 1.0e-6*GeV )
751 {
753 G4double sintheta = std::sqrt(1. - costheta*costheta);
755 currentParticle.
SetMomentum( pp*sintheta*std::cos(phi2)*MeV,
756 pp*sintheta*std::sin(phi2)*MeV,
757 pp*costheta*MeV ) ;
758 } else {
760 }
761 pseudoParticle[4] = pseudoParticle[4] + currentParticle;
762
763
764
765
766
767
768
769 if( backwardNucleonCount < 18 )
770 {
772 ++backwardNucleonCount;
773 }
774 else
775 {
776
777
778
779 vecMass = targetParticle.
GetMass()/GeV;
781 aspar = 0.40;
782 pt = std::max( 0.001, std::sqrt( std::pow( ran/4.0, 1.2 ) ) );
783 targetParticle.
SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
784 for(
G4int j=0; j<20; ++j )binl[j] = (j-1.)/(19.*pt);
785 et = pseudoParticle[1].GetTotalEnergy()/GeV;
786 dndl[0] = 0.0;
787 outerCounter = 0;
788 eliminateThisParticle = true;
789 resetEnergies = true;
790 while( ++outerCounter < 3 )
791 {
792 for( l=1; l<20; ++l )
793 {
794 x = (binl[l]+binl[l-1])/2.;
795 if( x > 1.0/pt )
796 dndl[l] += dndl[l-1];
797 else
798 dndl[l] = aspar/std::sqrt( std::pow((1.+aspar*x*aspar*x),3) ) *
799 (binl[l]-binl[l-1])*et / std::sqrt( pt*x*et*pt*x*et+pt*pt+vecMass*vecMass ) +
800 dndl[l-1];
801 }
802 innerCounter = 0;
803 while( ++innerCounter < 7 )
804 {
805 l = 1;
807 while( ( ran >= dndl[l] ) && ( l < 20 ) )l++;
808 l = std::min( 19, l );
809 x = std::min( 1.0, pt*(binl[l-1] +
G4UniformRand()*(binl[l]-binl[l-1]) ) );
810 if( targetParticle.
GetSide() < 0 )x *= -1.;
812 totalEnergy = std::sqrt( x*et*x*et + pt*pt + vecMass*vecMass );
814 if( targetParticle.
GetSide() < 0 )
815 {
816 if( extraNucleonCount > 19 )x=0.999;
817 G4double xxx = 0.95+0.05*extraNucleonCount/20.0;
818 if( (backwardKinetic+totalEnergy-vecMass) < xxx*backwardEnergy )
819 {
820 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
821 backwardKinetic += totalEnergy - vecMass;
822 pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
824 phi = pseudoParticle[6].Angle( pseudoParticle[8] );
825 if( pseudoParticle[6].GetMomentum().y()/MeV < 0.0 )phi = twopi - phi;
826 phi +=
pi + normal() *
pi / 12.0;
827 if( phi > twopi )phi -= twopi;
828 if( phi < 0.0 )phi = twopi - phi;
829 outerCounter = 2;
830 eliminateThisParticle = false;
831 resetEnergies = false;
832 break;
833 }
834 if( innerCounter > 5 )break;
835 if( forwardEnergy >= vecMass )
836 {
837 targetParticle.SetSide( 1 );
838 forwardEnergy -= vecMass;
839 backwardEnergy += vecMass;
840 --backwardCount;
841 }
843 targetParticle.SetMomentum( momentum.
x() * 0.9, momentum.
y() * 0.9 );
844 pt *= 0.9;
845 dndl[19] *= 0.9;
846 }
847 else
848 {
849 if( forwardEnergy < forwardKinetic )
850 totalEnergy = vecMass + 0.04*std::fabs(normal());
851 else
852 totalEnergy = vecMass + forwardEnergy - forwardKinetic;
853 targetParticle.SetTotalEnergy( totalEnergy*GeV );
854 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
855 pp1 = targetParticle.GetMomentum().mag()/MeV;
856 if( pp1 < 1.0e-6*GeV )
857 {
859 G4double sintheta = std::sqrt(1. - costheta*costheta);
861 targetParticle.SetMomentum( pp*sintheta*std::cos(phi2)*MeV,
862 pp*sintheta*std::sin(phi2)*MeV,
863 pp*costheta*MeV ) ;
864 }
865 else
866 targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
867
868 pseudoParticle[4] = pseudoParticle[4] + targetParticle;
869 outerCounter = 2;
870 eliminateThisParticle = false;
871 resetEnergies = false;
872 break;
873 }
874 }
875 if( resetEnergies )
876 {
877
878
879
880
881
882 forwardKinetic = backwardKinetic = 0.0;
883 pseudoParticle[4].SetZero();
884 pseudoParticle[5].SetZero();
885 for( l=0; l<vecLen; ++l )
886 {
887 if (vec[l]->GetSide() > 0 ||
888 vec[l]->GetDefinition()->GetParticleSubType() == "kaon" ||
889 vec[l]->GetDefinition()->GetParticleSubType() == "pi") {
890 G4double tempMass = vec[l]->GetMass()/GeV;
891 totalEnergy =
892 std::max( tempMass, 0.95*vec[l]->GetTotalEnergy()/GeV + 0.05*tempMass );
893 vec[l]->SetTotalEnergy( totalEnergy*GeV );
894 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - tempMass*tempMass ) )*GeV;
895 pp1 = vec[l]->GetMomentum().mag()/MeV;
896 if( pp1 < 1.0e-6*GeV )
897 {
899 G4double sintheta = std::sqrt(1. - costheta*costheta);
901 vec[l]->SetMomentum( pp*sintheta*std::cos(phi2)*MeV,
902 pp*sintheta*std::sin(phi2)*MeV,
903 pp*costheta*MeV ) ;
904 }
905 else
906 vec[l]->SetMomentum( vec[l]->GetMomentum() * (pp/pp1) );
907
908 pt = std::max( 0.001*GeV, std::sqrt(
sqr(vec[l]->GetMomentum().x()/MeV) +
909 sqr(vec[l]->GetMomentum().y()/MeV) ) )/GeV;
910 if( vec[l]->GetSide() > 0)
911 {
912 forwardKinetic += vec[l]->GetKineticEnergy()/GeV;
913 pseudoParticle[4] = pseudoParticle[4] + (*vec[l]);
914 } else {
915 backwardKinetic += vec[l]->GetKineticEnergy()/GeV;
916 pseudoParticle[5] = pseudoParticle[5] + (*vec[l]);
917 }
918 }
919 }
920 }
921 }
922 }
923
924
925
926
927
928
929 pseudoParticle[6].Lorentz( pseudoParticle[3], pseudoParticle[2] );
930 pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[4];
931 pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[5];
932 if( backwardNucleonCount == 1 )
933 {
935 std::min( backwardEnergy-backwardKinetic, centerofmassEnergy/2.0-protonMass/GeV );
936
937 if( ekin < 0.04 )ekin = 0.04 * std::fabs( normal() );
938 vecMass = targetParticle.GetMass()/GeV;
939 totalEnergy = ekin+vecMass;
940 targetParticle.SetTotalEnergy( totalEnergy*GeV );
941 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
942 pp1 = pseudoParticle[6].GetMomentum().mag()/MeV;
943 if( pp1 < 1.0e-6*GeV )
944 {
946 G4double sintheta = std::sqrt(1. - costheta*costheta);
948 targetParticle.SetMomentum( pp*sintheta*std::cos(phi2)*MeV,
949 pp*sintheta*std::sin(phi2)*MeV,
950 pp*costheta*MeV ) ;
951 } else {
952 targetParticle.SetMomentum( pseudoParticle[6].GetMomentum() * (pp/pp1) );
953 }
954 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
955 }
956 else
957 {
958 const G4double cpar[] = { 0.6, 0.6, 0.35, 0.15, 0.10 };
959 const G4double gpar[] = { 2.6, 2.6, 1.80, 1.30, 1.20 };
960
961
963 if (backwardNucleonCount < 5)
964 {
965 tempCount = backwardNucleonCount;
966 }
967 else
968 {
969 tempCount = 5;
970 }
971 tempCount--;
972
973
975 if( targetParticle.GetSide() == -3 )
976 rmb0 += targetParticle.GetMass()/GeV;
977 for( i=0; i<vecLen; ++i )
978 {
979 if( vec[i]->GetSide() == -3 )rmb0 += vec[i]->GetMass()/GeV;
980 }
981 rmb = rmb0 + std::pow(-std::log(1.0-
G4UniformRand()),cpar[tempCount]) / gpar[tempCount];
982 totalEnergy = pseudoParticle[6].GetTotalEnergy()/GeV;
983 vecMass = std::min( rmb, totalEnergy );
984 pseudoParticle[6].SetMass( vecMass*GeV );
985 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
986 pp1 = pseudoParticle[6].GetMomentum().mag()/MeV;
987 if( pp1 < 1.0e-6*GeV )
988 {
990 G4double sintheta = std::sqrt(1. - costheta*costheta);
992 pseudoParticle[6].SetMomentum( -pp*sintheta*std::cos(phi2)*MeV,
993 -pp*sintheta*std::sin(phi2)*MeV,
994 -pp*costheta*MeV ) ;
995 }
996 else
997 pseudoParticle[6].SetMomentum( pseudoParticle[6].GetMomentum() * (-pp/pp1) );
998
1002 if( targetParticle.GetSide() == -3 )tempV.
SetElement( tempLen++, &targetParticle );
1003 for( i=0; i<vecLen; ++i )
1004 {
1005 if( vec[i]->GetSide() == -3 )tempV.
SetElement( tempLen++, vec[i] );
1006 }
1007 if( tempLen != backwardNucleonCount )
1008 {
1009 G4cerr <<
"tempLen is not the same as backwardNucleonCount" <<
G4endl;
1010 G4cerr <<
"tempLen = " << tempLen;
1011 G4cerr <<
", backwardNucleonCount = " << backwardNucleonCount <<
G4endl;
1012 G4cerr <<
"targetParticle side = " << targetParticle.GetSide() <<
G4endl;
1013 G4cerr <<
"currentParticle side = " << currentParticle.GetSide() <<
G4endl;
1014 for( i=0; i<vecLen; ++i )
1015 G4cerr <<
"particle #" << i <<
" side = " << vec[i]->GetSide() <<
G4endl;
1016 G4Exception(
"G4ReactionDynamics::GenerateXandPt",
"601",
1018 }
1019 constantCrossSection = true;
1020
1021 if( tempLen >= 2 )
1022 {
1024 pseudoParticle[6].GetMass(), constantCrossSection, tempV, tempLen );
1025
1026 if( targetParticle.GetSide() == -3 )
1027 {
1028 targetParticle.Lorentz( targetParticle, pseudoParticle[6] );
1029
1030 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
1031 }
1032 for( i=0; i<vecLen; ++i )
1033 {
1034 if( vec[i]->GetSide() == -3 )
1035 {
1036 vec[i]->Lorentz( *vec[i], pseudoParticle[6] );
1037 pseudoParticle[5] = pseudoParticle[5] + (*vec[i]);
1038 }
1039 }
1040
1041 }
1042 }
1043
1044
1045
1046 if( vecLen == 0 )return false;
1047
1048
1049 currentParticle.Lorentz( currentParticle, pseudoParticle[1] );
1050 targetParticle.Lorentz( targetParticle, pseudoParticle[1] );
1051 for( i=0; i<vecLen; ++i ) vec[i]->Lorentz( *vec[i], pseudoParticle[1] );
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063 G4bool leadingStrangeParticleHasChanged =
true;
1064 if( leadFlag )
1065 {
1066 if( currentParticle.GetDefinition() == leadingStrangeParticle.
GetDefinition() )
1067 leadingStrangeParticleHasChanged = false;
1068 if( leadingStrangeParticleHasChanged &&
1069 ( targetParticle.GetDefinition() == leadingStrangeParticle.
GetDefinition() ) )
1070 leadingStrangeParticleHasChanged = false;
1071 if( leadingStrangeParticleHasChanged )
1072 {
1073 for( i=0; i<vecLen; i++ )
1074 {
1075 if( vec[i]->GetDefinition() == leadingStrangeParticle.
GetDefinition() )
1076 {
1077 leadingStrangeParticleHasChanged = false;
1078 break;
1079 }
1080 }
1081 }
1082 if( leadingStrangeParticleHasChanged )
1083 {
1088 (targetParticle.GetDefinition()->GetParticleSubType() == "kaon" ||
1089 targetParticle.GetDefinition()->GetParticleSubType() == "pi");
1090
1091
1092
1093 if( (leadTest&&targetTest) || !(leadTest||targetTest) )
1094 {
1095 targetParticle.SetDefinitionAndUpdateE( leadingStrangeParticle.
GetDefinition() );
1096 targetHasChanged = true;
1097
1098 }
1099 else
1100 {
1101 currentParticle.SetDefinitionAndUpdateE( leadingStrangeParticle.
GetDefinition() );
1102 incidentHasChanged = false;
1103
1104 }
1105 }
1106 }
1107
1108
1109
1110
1111 std::pair<G4int, G4int> finalStateNucleons =
1112 GetFinalStateNucleons(originalTarget, vec, vecLen);
1113
1114 G4int protonsInFinalState = finalStateNucleons.first;
1115 G4int neutronsInFinalState = finalStateNucleons.second;
1116
1117 G4int numberofFinalStateNucleons =
1118 protonsInFinalState + neutronsInFinalState;
1119
1120 if (currentParticle.GetDefinition()->GetBaryonNumber() == 1 &&
1121 targetParticle.GetDefinition()->GetBaryonNumber() == 1 &&
1124 numberofFinalStateNucleons++;
1125
1126 numberofFinalStateNucleons = std::max(1, numberofFinalStateNucleons);
1127
1128 G4int PinNucleus = std::max(0,
1129 targetNucleus.
GetZ_asInt() - protonsInFinalState);
1130 G4int NinNucleus = std::max(0,
1131 targetNucleus.
GetN_asInt() - neutronsInFinalState);
1132
1133 pseudoParticle[3].SetMomentum( 0.0, 0.0, pOriginal*GeV );
1134 pseudoParticle[3].SetMass( mOriginal*GeV );
1135 pseudoParticle[3].SetTotalEnergy(
1136 std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
1137
1141 if(numberofFinalStateNucleons == 1) diff = 0;
1142 pseudoParticle[4].SetMomentum( 0.0, 0.0, 0.0 );
1143 pseudoParticle[4].SetMass( protonMass*(numberofFinalStateNucleons-diff)*MeV );
1144 pseudoParticle[4].SetTotalEnergy( protonMass*(numberofFinalStateNucleons-diff)*MeV );
1145
1147 pseudoParticle[3].GetTotalEnergy()/MeV +
1148 pseudoParticle[4].GetTotalEnergy()/MeV -
1149 currentParticle.GetMass()/MeV -
1150 targetParticle.GetMass()/MeV;
1151
1153 currentParticle.GetKineticEnergy()/MeV + targetParticle.GetKineticEnergy()/MeV;
1154
1155 pseudoParticle[5] = pseudoParticle[3] + pseudoParticle[4];
1156 pseudoParticle[3].Lorentz( pseudoParticle[3], pseudoParticle[5] );
1157 pseudoParticle[4].Lorentz( pseudoParticle[4], pseudoParticle[5] );
1158
1159 pseudoParticle[7].SetZero();
1160 pseudoParticle[7] = pseudoParticle[7] + currentParticle;
1161 pseudoParticle[7] = pseudoParticle[7] + targetParticle;
1162
1163 for( i=0; i<vecLen; ++i )
1164 {
1165 pseudoParticle[7] = pseudoParticle[7] + *vec[i];
1166 simulatedKinetic += vec[i]->GetKineticEnergy()/MeV;
1167 theoreticalKinetic -= vec[i]->GetMass()/MeV;
1168 }
1169
1170 if( vecLen <= 16 && vecLen > 0 )
1171 {
1172
1173
1174
1176 tempR[0] = currentParticle;
1177 tempR[1] = targetParticle;
1178 for( i=0; i<vecLen; ++i )tempR[i+2] = *vec[i];
1182 for( i=0; i<vecLen+2; ++i )tempV.
SetElement( tempLen++, &tempR[i] );
1183 constantCrossSection = true;
1184
1186 pseudoParticle[4].GetTotalEnergy()/MeV,
1187 constantCrossSection, tempV, tempLen );
1188 if (wgt == -1) {
1190 for (i = 0; i < tempLen; i++) Qvalue += tempV[i]->GetMass();
1192 constantCrossSection, tempV, tempLen );
1193 }
1194 if(wgt>-.5)
1195 {
1196 theoreticalKinetic = 0.0;
1197 for( i=0; i<tempLen; ++i )
1198 {
1199 pseudoParticle[6].Lorentz( *tempV[i], pseudoParticle[4] );
1200 theoreticalKinetic += pseudoParticle[6].GetKineticEnergy()/MeV;
1201 }
1202 }
1203
1204 }
1205
1206
1207
1208 if( simulatedKinetic != 0.0 )
1209 {
1210 wgt = (theoreticalKinetic)/simulatedKinetic;
1211 theoreticalKinetic = currentParticle.GetKineticEnergy()/MeV * wgt;
1212 simulatedKinetic = theoreticalKinetic;
1213 currentParticle.SetKineticEnergy( theoreticalKinetic*MeV );
1214 pp = currentParticle.GetTotalMomentum()/MeV;
1215 pp1 = currentParticle.GetMomentum().mag()/MeV;
1216 if( pp1 < 1.0e-6*GeV )
1217 {
1219 G4double sintheta = std::sqrt(1. - costheta*costheta);
1221 currentParticle.SetMomentum( pp*sintheta*std::cos(phi2)*MeV,
1222 pp*sintheta*std::sin(phi2)*MeV,
1223 pp*costheta*MeV ) ;
1224 }
1225 else
1226 {
1227 currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
1228 }
1229 theoreticalKinetic = targetParticle.GetKineticEnergy()/MeV * wgt;
1230 targetParticle.SetKineticEnergy( theoreticalKinetic*MeV );
1231 simulatedKinetic += theoreticalKinetic;
1232 pp = targetParticle.GetTotalMomentum()/MeV;
1233 pp1 = targetParticle.GetMomentum().mag()/MeV;
1234
1235 if( pp1 < 1.0e-6*GeV )
1236 {
1238 G4double sintheta = std::sqrt(1. - costheta*costheta);
1240 targetParticle.SetMomentum( pp*sintheta*std::cos(phi2)*MeV,
1241 pp*sintheta*std::sin(phi2)*MeV,
1242 pp*costheta*MeV ) ;
1243 } else {
1244 targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
1245 }
1246 for( i=0; i<vecLen; ++i )
1247 {
1248 theoreticalKinetic = vec[i]->GetKineticEnergy()/MeV * wgt;
1249 simulatedKinetic += theoreticalKinetic;
1250 vec[i]->SetKineticEnergy( theoreticalKinetic*MeV );
1251 pp = vec[i]->GetTotalMomentum()/MeV;
1252 pp1 = vec[i]->GetMomentum().mag()/MeV;
1253 if( pp1 < 1.0e-6*GeV )
1254 {
1256 G4double sintheta = std::sqrt(1. - costheta*costheta);
1258 vec[i]->SetMomentum( pp*sintheta*std::cos(phi2)*MeV,
1259 pp*sintheta*std::sin(phi2)*MeV,
1260 pp*costheta*MeV ) ;
1261 }
1262 else
1263 vec[i]->SetMomentum( vec[i]->GetMomentum() * (pp/pp1) );
1264 }
1265 }
1266
1267
1268 Rotate( numberofFinalStateNucleons, pseudoParticle[3].GetMomentum(),
1269 modifiedOriginal, originalIncident, targetNucleus,
1270 currentParticle, targetParticle, vec, vecLen );
1271
1272
1273
1274
1275
1276
1277 if( atomicWeight >= 1.5 )
1278 {
1279
1280
1281
1282
1283
1286
1288 if (veryForward) {
1291 } else {
1294 }
1295
1298 const G4double kineticMinimum = 1.e-6;
1299 const G4double kineticFactor = -0.010;
1302 if( ekIncident >= 5.0 )sprob = std::min( 1.0, 0.6*std::log(ekIncident-4.0) );
1303 if( epnb >= pnCutOff )
1304 {
1305 npnb = Poisson((1.5+1.25*numberofFinalStateNucleons)*epnb/(epnb+edta));
1306 if( numberofFinalStateNucleons + npnb > atomicWeight )
1307 npnb =
G4int(atomicWeight+0.00001 - numberofFinalStateNucleons);
1308 npnb = std::min( npnb, 127-vecLen );
1309 }
1310 if( edta >= dtaCutOff )
1311 {
1312 ndta = Poisson( (1.5+1.25*numberofFinalStateNucleons)*edta/(epnb+edta) );
1313 ndta = std::min( ndta, 127-vecLen );
1314 }
1315 if (npnb == 0 && ndta == 0) npnb = 1;
1316
1317
1318
1319 AddBlackTrackParticles(epnb, npnb, edta, ndta, sprob, kineticMinimum,
1320 kineticFactor, modifiedOriginal,
1321 PinNucleus, NinNucleus, targetNucleus,
1322 vec, vecLen);
1323
1324
1325 }
1326
1327
1328
1329
1330
1331 if( (atomicWeight >= 1.5) && (atomicWeight <= 230.0) && (ekOriginal <= 0.2) )
1332 currentParticle.SetTOF( 1.0-500.0*std::exp(-ekOriginal/0.04)*std::log(
G4UniformRand()) );
1333 else
1334 currentParticle.SetTOF( 1.0 );
1335 return true;
1336
1337 }
void SetElement(G4int anIndex, Type *anElement)
void Initialize(G4int items)
const G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
static G4Lambda * Lambda()
static G4Neutron * Neutron()
G4double GetAnnihilationPNBlackTrackEnergy() const
G4double GetPNBlackTrackEnergy() const
G4double GetAnnihilationDTABlackTrackEnergy() const
G4double GetDTABlackTrackEnergy() const
G4double GetPDGMass() const
const G4String & GetParticleSubType() const
static G4PionMinus * PionMinus()
static G4PionPlus * PionPlus()
static G4PionZero * PionZero()
static G4Proton * Proton()
G4double GenerateNBodyEvent(const G4double totalEnergy, const G4bool constantCrossSection, G4FastVector< G4ReactionProduct, GHADLISTSIZE > &vec, G4int &vecLen)
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 SetDefinition(G4ParticleDefinition *aParticleDefinition)
void SetMass(const G4double mas)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)