44 for (
G4int i = 0; i < 20; i++) dndl[i] = 0.0;
51 pt = std::max( 0.001, pt );
57 for (
G4int i = 1; i < 20; i++) {
59 term1 = 1. + parMass*parMass*x*
x;
60 term2 = pt*x*et*pt*x*et + pt*pt + secMass*secMass;
61 dndl[i] = dx / std::sqrt( term1*term1*term1*term2 )
70 G4bool& incidentHasChanged,
95 if (vecLen == 0)
return false;
104 G4bool veryForward =
false;
111 G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
112 targetMass*targetMass +
113 2.0*targetMass*etOriginal );
120 for (i=0; i<vecLen; ++i) {
123 *vec[itemp] = *vec[i];
127 if (currentMass == 0.0 && targetMass == 0.0) {
133 currentParticle = *vec[0];
135 targetParticle = *vec[1];
137 for( i=0; i<(vecLen-2); ++i )*vec[i] = *vec[i+2];
140 temp = vec[vecLen-2];
145 incidentHasChanged =
true;
146 targetHasChanged =
true;
158 currentParticle = targetParticle;
159 targetParticle = temp;
160 incidentHasChanged =
true;
161 targetHasChanged =
true;
165 const G4double afc = std::min( 0.75,
166 0.312+0.200*std::log(std::log(centerofmassEnergy*centerofmassEnergy))+
167 std::pow(centerofmassEnergy*centerofmassEnergy,1.5)/6000.0 );
169 G4double freeEnergy = centerofmassEnergy-currentMass-targetMass;
170 G4double forwardEnergy = freeEnergy/2.;
171 G4int forwardCount = 1;
173 G4double backwardEnergy = freeEnergy/2.;
174 G4int backwardCount = 1;
177 if(currentParticle.
GetSide()==-1)
179 forwardEnergy += currentMass;
181 backwardEnergy -= currentMass;
184 if(targetParticle.
GetSide()!=-1)
186 backwardEnergy += targetMass;
188 forwardEnergy -= targetMass;
193 for (i=0; i<vecLen; ++i) {
194 if( vec[i]->GetSide() == -1 )
197 backwardEnergy -= vec[i]->GetMass()/
GeV;
200 forwardEnergy -= vec[i]->GetMass()/
GeV;
208 if (backwardEnergy < 0.0) {
209 for (i = 0; i < vecLen; ++i) {
210 if (vec[i]->GetSide() == -1) {
211 backwardEnergy += vec[i]->GetMass()/
GeV;
214 forwardEnergy -= vec[i]->GetMass()/
GeV;
216 if (backwardEnergy > 0.0)
break;
221 if (forwardEnergy < 0.0) {
222 for (i = 0; i < vecLen; ++i) {
223 if (vec[i]->GetSide() == 1) {
224 forwardEnergy += vec[i]->GetMass()/
GeV;
227 backwardEnergy -= vec[i]->GetMass()/
GeV;
229 if (forwardEnergy > 0.0)
break;
237 if (forwardEnergy > 0.0 && backwardEnergy < 0.0) {
238 forwardEnergy += backwardEnergy;
243 if (forwardEnergy + backwardEnergy < 0.0)
return false;
260 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount+vecLen+2)/2.0;
262 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount);
263 if( xtarg <= 0.0 )xtarg = 0.01;
267 if(atomicWeight<1.0001) nuclearExcitationCount = 0;
268 G4int extraNucleonCount = 0;
271 if (nuclearExcitationCount > 0) {
272 const G4double nucsup[] = { 1.00, 0.7, 0.5, 0.4, 0.35, 0.3 };
273 const G4double psup[] = { 3., 6., 20., 50., 100., 1000. };
274 G4int momentumBin = 0;
275 while( (momentumBin < 6) &&
278 momentumBin = std::min( 5, momentumBin );
284 for (i = 0; i < nuclearExcitationCount; ++i) {
308 else if( ran < 0.6819 )
331 for (i = 0; i < 8; ++i) pseudoParticle[i].SetZero();
334 pseudoParticle[0].
SetMomentum( 0.0, 0.0, pOriginal*GeV );
336 std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
338 pseudoParticle[1].
SetMass(protonMass);
341 pseudoParticle[3].
SetMass(protonMass*(1+extraNucleonCount) );
342 pseudoParticle[3].
SetTotalEnergy(protonMass*(1+extraNucleonCount) );
344 pseudoParticle[2] = pseudoParticle[0] + pseudoParticle[1];
345 pseudoParticle[3] = pseudoParticle[3] + pseudoParticle[0];
347 pseudoParticle[0].
Lorentz( pseudoParticle[0], pseudoParticle[2] );
348 pseudoParticle[1].Lorentz( pseudoParticle[1], pseudoParticle[2] );
354 G4int innerCounter, outerCounter;
355 G4bool eliminateThisParticle, resetEnergies, constantCrossSection;
365 G4int backwardNucleonCount = 0;
366 G4double totalEnergy, kineticEnergy, vecMass;
369 for (i = vecLen-1; i >= 0; --i) {
371 if (vec[i]->GetNewlyAdded()) {
372 if (vec[i]->GetSide() == -2) {
373 if (backwardNucleonCount < 18) {
374 if (vec[i]->GetDefinition()->GetParticleSubType() ==
"pi") {
375 for (
G4int j = 0; j < vecLen; j++)
delete vec[j];
378 "G4RPGFragmentation::ReactionStage : a pion has been counted as a backward nucleon");
381 ++backwardNucleonCount;
392 vecMass = vec[i]->GetMass()/
GeV;
395 if (vec[i]->GetSide() == -2) {
397 pt = std::sqrt( std::pow( ran, 1.2 ) );
400 if (vec[i]->GetDefinition()->GetParticleSubType() ==
"pi") {
402 pt = std::sqrt( std::pow( ran, 1.7 ) );
403 }
else if (vec[i]->GetDefinition()->GetParticleSubType() ==
"kaon") {
405 pt = std::sqrt( std::pow( ran, 1.7 ) );
408 pt = std::sqrt( std::pow( ran, 1.5 ) );
412 pt = std::max( 0.001, pt );
414 vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
415 if (vec[i]->GetSide() > 0)
416 et = pseudoParticle[0].GetTotalEnergy()/
GeV;
418 et = pseudoParticle[1].GetTotalEnergy()/
GeV;
424 eliminateThisParticle =
true;
425 resetEnergies =
true;
428 while (++outerCounter < 3) {
432 vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
436 while (++innerCounter < 7) {
440 while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
442 if (vec[i]->GetSide() < 0) x *= -1.;
443 vec[i]->SetMomentum( x*et*GeV );
444 totalEnergy = std::sqrt( x*et*x*et + pt*pt + vecMass*vecMass );
445 vec[i]->SetTotalEnergy( totalEnergy*GeV );
446 kineticEnergy = vec[i]->GetKineticEnergy()/
GeV;
448 if (vec[i]->GetSide() > 0) {
449 if( (forwardKinetic+kineticEnergy) < 0.95*forwardEnergy ) {
452 pseudoParticle[4] = pseudoParticle[4] + (*vec[i]);
453 forwardKinetic += kineticEnergy;
455 eliminateThisParticle =
false;
456 resetEnergies =
false;
459 if( innerCounter > 5 )
break;
460 if( backwardEnergy >= vecMass )
463 forwardEnergy += vecMass;
464 backwardEnergy -= vecMass;
472 if (extraNucleonCount < 20) xxx = 0.95+0.05*extraNucleonCount/20.0;
474 if ((backwardKinetic+kineticEnergy) < xxx*backwardEnergy) {
475 pseudoParticle[5] = pseudoParticle[5] + (*vec[i]);
476 backwardKinetic += kineticEnergy;
478 eliminateThisParticle =
false;
479 resetEnergies =
false;
482 if (innerCounter > 5)
break;
483 if (forwardEnergy >= vecMass) {
485 forwardEnergy -= vecMass;
486 backwardEnergy += vecMass;
491 vec[i]->SetMomentum( momentum.
x() * 0.9, momentum.
y() * 0.9 );
502 ReduceEnergiesOfSecondaries(i+1, forwardKinetic, backwardKinetic,
504 pseudoParticle[4], pseudoParticle[5],
509 if (eliminateThisParticle && vec[i]->GetMayBeKilled()) {
512 if (vec[i]->GetSide() > 0) {
514 forwardEnergy += vecMass;
517 if (vec[i]->GetSide() == -2) {
519 extraNucleonMass -= vecMass;
521 backwardEnergy += vecMass;
525 for(
G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
531 G4cout <<
" FALSE RETURN DUE TO ENERGY BALANCE " <<
G4endl;
539 G4double forwardKEDiff = forwardEnergy - forwardKinetic;
540 G4double backwardKEDiff = backwardEnergy - backwardKinetic;
542 if (forwardKEDiff < 0.0 || backwardKEDiff < 0.0) {
543 ReduceEnergiesOfSecondaries(0, forwardKinetic, backwardKinetic,
545 pseudoParticle[4], pseudoParticle[5],
548 forwardKEDiff = forwardEnergy - forwardKinetic;
549 backwardKEDiff = backwardEnergy - backwardKinetic;
550 if (backwardKEDiff < 0.0) {
551 if (forwardKEDiff + backwardKEDiff > 0.0) {
552 backwardEnergy = backwardKinetic;
553 forwardEnergy += backwardKEDiff;
554 forwardKEDiff = forwardEnergy - forwardKinetic;
555 backwardKEDiff = 0.0;
557 G4cout <<
" False return due to insufficient backward energy " <<
G4endl;
562 if (forwardKEDiff < 0.0) {
563 if (forwardKEDiff + backwardKEDiff > 0.0) {
564 forwardEnergy = forwardKinetic;
565 backwardEnergy += forwardKEDiff;
566 backwardKEDiff = backwardEnergy - backwardKinetic;
569 G4cout <<
" False return due to insufficient forward energy " <<
G4endl;
583 pt = std::sqrt( std::pow( ran/6.0, 1.7 ) );
586 pt = std::sqrt( std::pow( ran/5.0, 1.4 ) );
589 pt = std::sqrt( std::pow( ran/4.0, 1.2 ) );
593 currentParticle.
SetMomentum(pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV);
594 et = pseudoParticle[0].GetTotalEnergy()/
GeV;
602 while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
606 if (forwardEnergy < forwardKinetic) {
607 totalEnergy = vecMass + 0.04*std::fabs(
normal());
608 G4cout <<
" Not enough forward energy: forwardEnergy = "
609 << forwardEnergy <<
" forwardKinetic = "
610 << forwardKinetic <<
" total energy left = "
611 << backwardKEDiff + forwardKEDiff <<
G4endl;
613 totalEnergy = vecMass + forwardEnergy - forwardKinetic;
614 forwardKinetic = forwardEnergy;
617 pp = std::sqrt(std::abs( totalEnergy*totalEnergy - vecMass*vecMass) )*
GeV;
620 if (pp1 < 1.0
e-6*GeV) {
626 pseudoParticle[4] = pseudoParticle[4] + currentParticle;
632 if (backwardNucleonCount < 18) {
634 ++backwardNucleonCount;
643 pt = std::max( 0.001, std::sqrt( std::pow( ran/4.0, 1.2 ) ) );
645 targetParticle.
SetMomentum(pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV);
646 et = pseudoParticle[1].GetTotalEnergy()/
GeV;
649 G4bool marginalEnergy =
true;
652 if( extraNucleonCount < 20 ) xxx = 0.95+0.05*extraNucleonCount/20.0;
655 while (++outerCounter < 4) {
658 for (innerCounter = 0; innerCounter < 6; innerCounter++) {
661 while( ( ran > dndl[l] ) && ( l < 19 ) ) l++;
664 totalEnergy = std::sqrt(x*et*x*et + pt*pt + vecMass*vecMass);
667 if ((backwardKinetic+totalEnergy-vecMass) < xxx*backwardEnergy) {
668 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
669 backwardKinetic += totalEnergy - vecMass;
671 marginalEnergy =
false;
675 targetParticle.
SetMomentum(momentum.
x() * 0.9, momentum.
y() * 0.9);
681 if (marginalEnergy) {
682 G4cout <<
" Extra backward kinetic energy = "
683 << 0.999*backwardEnergy - backwardKinetic <<
G4endl;
684 totalEnergy = vecMass + 0.999*backwardEnergy - backwardKinetic;
686 pp = std::sqrt(std::abs(totalEnergy*totalEnergy - vecMass*vecMass) )*
GeV;
687 targetParticle.
SetMomentum(momentum.
x()/0.9, momentum.
y()/0.9);
690 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
691 backwardKinetic = 0.999*backwardEnergy;
696 if (backwardEnergy < backwardKinetic)
697 G4cout <<
" Backward Edif = " << backwardEnergy - backwardKinetic <<
G4endl;
698 if (forwardEnergy != forwardKinetic)
699 G4cout <<
" Forward Edif = " << forwardEnergy - forwardKinetic <<
G4endl;
709 pseudoParticle[6].Lorentz( pseudoParticle[3], pseudoParticle[2] );
710 pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[4];
711 pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[5];
713 if (backwardNucleonCount == 1) {
718 std::min(backwardEnergy-backwardKinetic, centerofmassEnergy/2.0-protonMass/GeV);
720 if( ekin < 0.04 )ekin = 0.04 * std::fabs(
normal() );
722 totalEnergy = ekin + vecMass;
724 pp = std::sqrt(std::abs(totalEnergy*totalEnergy - vecMass*vecMass) )*
GeV;
725 pp1 = pseudoParticle[6].GetMomentum().mag();
726 if (pp1 < 1.0
e-6*GeV) {
730 targetParticle.
SetMomentum( pseudoParticle[6].GetMomentum() * (pp/pp1));
732 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
734 }
else if (backwardNucleonCount > 1) {
738 if (backwardNucleonCount < 5) tempCount = backwardNucleonCount;
742 if (targetParticle.
GetSide() == -3)
744 for (i = 0; i < vecLen; ++i)
745 if (vec[i]->GetSide() == -3) clusterMass += vec[i]->GetMass()/
GeV;
746 clusterMass += backwardEnergy - backwardKinetic;
748 totalEnergy = pseudoParticle[6].GetTotalEnergy()/
GeV;
749 pseudoParticle[6].SetMass(clusterMass*GeV);
751 pp = std::sqrt(std::abs(totalEnergy*totalEnergy -
752 clusterMass*clusterMass) )*
GeV;
753 pp1 = pseudoParticle[6].GetMomentum().mag();
754 if (pp1 < 1.0
e-6*GeV) {
756 pseudoParticle[6].SetMomentum(iso.
x(), iso.
y(), iso.
z());
758 pseudoParticle[6].SetMomentum(pseudoParticle[6].GetMomentum() * (-pp/pp1));
761 std::vector<G4ReactionProduct*> tempList;
762 if (targetParticle.
GetSide() == -3) tempList.push_back(&targetParticle);
763 for (i = 0; i < vecLen; ++i)
764 if (vec[i]->GetSide() == -3) tempList.push_back(vec[i]);
766 constantCrossSection =
true;
768 if (tempList.size() > 1) {
771 constantCrossSection, tempList);
773 if (targetParticle.
GetSide() == -3) {
774 targetParticle = *tempList[0];
775 targetParticle.
Lorentz(targetParticle, pseudoParticle[6]);
779 for (i = 0; i < vecLen; ++i) {
780 if (vec[i]->GetSide() == -3) {
781 *vec[i] = *tempList[n_entry];
782 vec[i]->Lorentz(*vec[i], pseudoParticle[6]);
789 if (vecLen == 0)
return false;
793 currentParticle.Lorentz( currentParticle, pseudoParticle[1] );
794 targetParticle.
Lorentz( targetParticle, pseudoParticle[1] );
795 for (i = 0; i < vecLen; ++i) vec[i]->Lorentz(*vec[i], pseudoParticle[1]);
805 G4bool leadingStrangeParticleHasChanged =
true;
808 if (currentParticle.GetDefinition() == leadingStrangeParticle.
GetDefinition())
809 leadingStrangeParticleHasChanged =
false;
810 if (leadingStrangeParticleHasChanged &&
812 leadingStrangeParticleHasChanged =
false;
813 if( leadingStrangeParticleHasChanged )
815 for( i=0; i<vecLen; i++ )
817 if( vec[i]->GetDefinition() == leadingStrangeParticle.
GetDefinition() )
819 leadingStrangeParticleHasChanged =
false;
824 if( leadingStrangeParticleHasChanged )
835 if( (leadTest&&targetTest) || !(leadTest||targetTest) )
838 targetHasChanged =
true;
842 currentParticle.SetDefinitionAndUpdateE( leadingStrangeParticle.
GetDefinition() );
843 incidentHasChanged =
false;
851 std::pair<G4int, G4int> finalStateNucleons =
854 G4int protonsInFinalState = finalStateNucleons.first;
855 G4int neutronsInFinalState = finalStateNucleons.second;
857 G4int numberofFinalStateNucleons =
858 protonsInFinalState + neutronsInFinalState;
860 if (currentParticle.GetDefinition()->GetBaryonNumber() == 1 &&
864 numberofFinalStateNucleons++;
866 numberofFinalStateNucleons = std::max(1, numberofFinalStateNucleons);
868 G4int PinNucleus = std::max(0,
870 G4int NinNucleus = std::max(0,
873 pseudoParticle[3].SetMomentum( 0.0, 0.0, pOriginal*GeV );
874 pseudoParticle[3].SetMass( mOriginal*GeV );
875 pseudoParticle[3].SetTotalEnergy(
876 std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
881 if(numberofFinalStateNucleons == 1) diff = 0;
882 pseudoParticle[4].SetMomentum( 0.0, 0.0, 0.0 );
883 pseudoParticle[4].SetMass( protonMass*(numberofFinalStateNucleons-diff) );
884 pseudoParticle[4].SetTotalEnergy( protonMass*(numberofFinalStateNucleons-diff) );
887 pseudoParticle[3].GetTotalEnergy() + pseudoParticle[4].GetTotalEnergy() -
888 currentParticle.GetMass() - targetParticle.
GetMass();
889 for (i = 0; i < vecLen; ++i) theoreticalKinetic -= vec[i]->GetMass();
893 for (i = 0; i < vecLen; ++i)
894 simulatedKinetic += vec[i]->GetKineticEnergy();
896 pseudoParticle[5] = pseudoParticle[3] + pseudoParticle[4];
897 pseudoParticle[3].Lorentz( pseudoParticle[3], pseudoParticle[5] );
898 pseudoParticle[4].Lorentz( pseudoParticle[4], pseudoParticle[5] );
900 pseudoParticle[7].SetZero();
901 pseudoParticle[7] = pseudoParticle[7] + currentParticle;
902 pseudoParticle[7] = pseudoParticle[7] + targetParticle;
903 for (i = 0; i < vecLen; ++i)
904 pseudoParticle[7] = pseudoParticle[7] + *vec[i];
949 if (simulatedKinetic != 0.0) {
950 wgt = theoreticalKinetic/simulatedKinetic;
951 theoreticalKinetic = currentParticle.GetKineticEnergy() * wgt;
952 simulatedKinetic = theoreticalKinetic;
953 currentParticle.SetKineticEnergy(theoreticalKinetic);
954 pp = currentParticle.GetTotalMomentum();
955 pp1 = currentParticle.GetMomentum().mag();
956 if (pp1 < 1.0
e-6*GeV) {
958 currentParticle.SetMomentum( iso.
x(), iso.
y(), iso.
z() );
960 currentParticle.SetMomentum(currentParticle.GetMomentum() * (pp/pp1));
963 theoreticalKinetic = targetParticle.GetKineticEnergy() * wgt;
964 targetParticle.SetKineticEnergy(theoreticalKinetic);
965 simulatedKinetic += theoreticalKinetic;
966 pp = targetParticle.GetTotalMomentum();
967 pp1 = targetParticle.GetMomentum().mag();
969 if (pp1 < 1.0
e-6*GeV) {
971 targetParticle.SetMomentum(iso.
x(), iso.
y(), iso.
z() );
973 targetParticle.SetMomentum(targetParticle.GetMomentum() * (pp/pp1) );
976 for (i = 0; i < vecLen; ++i ) {
977 theoreticalKinetic = vec[i]->GetKineticEnergy() * wgt;
978 simulatedKinetic += theoreticalKinetic;
979 vec[i]->SetKineticEnergy(theoreticalKinetic);
980 pp = vec[i]->GetTotalMomentum();
981 pp1 = vec[i]->GetMomentum().mag();
982 if( pp1 < 1.0
e-6*GeV ) {
984 vec[i]->SetMomentum(iso.
x(), iso.
y(), iso.
z() );
986 vec[i]->SetMomentum(vec[i]->GetMomentum() * (pp/pp1) );
999 if( atomicWeight >= 1.5 )
1039 if (epnb > pnCutOff)
1041 npnb =
G4Poisson((1.5+1.25*numberofFinalStateNucleons)*epnb/(epnb+edta));
1042 if (numberofFinalStateNucleons + npnb > atomicWeight)
1043 npnb =
G4int(atomicWeight+0.00001 - numberofFinalStateNucleons);
1044 npnb = std::min( npnb, 127-vecLen );
1046 if( edta >= dtaCutOff )
1048 ndta =
G4Poisson((1.5+1.25*numberofFinalStateNucleons)*edta/(epnb+edta));
1049 ndta = std::min( ndta, 127-vecLen );
1051 if (npnb == 0 && ndta == 0) npnb = 1;
1054 PinNucleus, NinNucleus, targetNucleus,
1065 if( (atomicWeight >= 1.5) && (atomicWeight <= 230.0) && (ekOriginal <= 0.2) )
1066 currentParticle.SetTOF(
1067 1.0-500.0*std::exp(-ekOriginal/0.04)*std::log(
G4UniformRand()) );
1069 currentParticle.SetTOF( 1.0 );
1075 void G4RPGFragmentation::
1076 ReduceEnergiesOfSecondaries(
G4int startingIndex,
1097 forwardKinetic = 0.0;
1098 backwardKinetic = 0.0;
1099 forwardPseudoParticle.
SetZero();
1100 backwardPseudoParticle.
SetZero();
1102 for (i = startingIndex; i < vecLen; i++) {
1108 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - mass*mass ) );
1110 if (pp1 < 1.0
e-6*
GeV) {
1119 pt = std::max(1.0, std::sqrt( px*px + py*py ) )/
GeV;
1122 forwardPseudoParticle = forwardPseudoParticle + (*pVec);
1125 backwardPseudoParticle = backwardPseudoParticle + (*pVec);