00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include "SimG4Core/CustomPhysics/interface/FullModelReactionDynamics.hh"
00052 #include "G4AntiProton.hh"
00053 #include "G4AntiNeutron.hh"
00054 #include "Randomize.hh"
00055 #include <iostream>
00056 #include "G4HadReentrentException.hh"
00057 #include <signal.h>
00058 #include "G4ParticleTable.hh"
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 G4bool FullModelReactionDynamics::GenerateXandPt(
00101 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> &vec,
00102 G4int &vecLen,
00103 G4ReactionProduct &modifiedOriginal,
00104 const G4HadProjectile *originalIncident,
00105 G4ReactionProduct ¤tParticle,
00106 G4ReactionProduct &targetParticle,
00107 const G4Nucleus &targetNucleus,
00108 G4bool &incidentHasChanged,
00109 G4bool &targetHasChanged,
00110 G4bool leadFlag,
00111 G4ReactionProduct &leadingStrangeParticle )
00112 {
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 if(vecLen == 0) return false;
00127
00128 G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
00129
00130
00131 G4ParticleDefinition *aProton = G4Proton::Proton();
00132 G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
00133 G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
00134 G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
00135 G4ParticleDefinition *aKaonPlus = G4KaonPlus::KaonPlus();
00136 G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
00137 G4ParticleDefinition *aKaonZeroS = G4KaonZeroShort::KaonZeroShort();
00138 G4ParticleDefinition *aKaonZeroL = G4KaonZeroLong::KaonZeroLong();
00139
00140 G4int i, l;
00141 G4double forVeryForward = 0.;
00142 G4bool veryForward = false;
00143
00144 const G4double ekOriginal = modifiedOriginal.GetKineticEnergy()/GeV;
00145 const G4double etOriginal = modifiedOriginal.GetTotalEnergy()/GeV;
00146 const G4double mOriginal = modifiedOriginal.GetMass()/GeV;
00147 const G4double pOriginal = modifiedOriginal.GetMomentum().mag()/GeV;
00148 G4double targetMass = targetParticle.GetDefinition()->GetPDGMass()/GeV;
00149 G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
00150 targetMass*targetMass +
00151 2.0*targetMass*etOriginal );
00152 G4double currentMass = currentParticle.GetMass()/GeV;
00153 targetMass = targetParticle.GetMass()/GeV;
00154
00155
00156
00157
00158 for( i=0; i<vecLen; ++i )
00159 {
00160 G4int itemp = G4int( G4UniformRand()*vecLen );
00161 G4ReactionProduct pTemp = *vec[itemp];
00162 *vec[itemp] = *vec[i];
00163 *vec[i] = pTemp;
00164
00165 }
00166
00167 if( currentMass == 0.0 && targetMass == 0.0 )
00168 {
00169
00170 G4double ek = currentParticle.GetKineticEnergy();
00171 G4ThreeVector m = currentParticle.GetMomentum();
00172 currentParticle = *vec[0];
00173 targetParticle = *vec[1];
00174 for( i=0; i<(vecLen-2); ++i )*vec[i] = *vec[i+2];
00175 G4ReactionProduct *temp = vec[vecLen-1];
00176 delete temp;
00177 temp = vec[vecLen-2];
00178 delete temp;
00179 vecLen -= 2;
00180 currentMass = currentParticle.GetMass()/GeV;
00181 targetMass = targetParticle.GetMass()/GeV;
00182 incidentHasChanged = true;
00183 targetHasChanged = true;
00184 currentParticle.SetKineticEnergy( ek );
00185 currentParticle.SetMomentum( m );
00186 forVeryForward = aProton->GetPDGMass();
00187 veryForward = true;
00188 }
00189 const G4double atomicWeight = targetNucleus.GetN();
00190
00191 const G4double atomicNumber = targetNucleus.GetZ();
00192 const G4double protonMass = aProton->GetPDGMass()/MeV;
00193 if( (originalIncident->GetDefinition() == aKaonMinus ||
00194 originalIncident->GetDefinition() == aKaonZeroL ||
00195 originalIncident->GetDefinition() == aKaonZeroS ||
00196 originalIncident->GetDefinition() == aKaonPlus) &&
00197 G4UniformRand() >= 0.7 )
00198 {
00199 G4ReactionProduct temp = currentParticle;
00200 currentParticle = targetParticle;
00201 targetParticle = temp;
00202 incidentHasChanged = true;
00203 targetHasChanged = true;
00204 currentMass = currentParticle.GetMass()/GeV;
00205 targetMass = targetParticle.GetMass()/GeV;
00206 }
00207 const G4double afc = std::min( 0.75,
00208 0.312+0.200*std::log(std::log(centerofmassEnergy*centerofmassEnergy))+
00209 std::pow(centerofmassEnergy*centerofmassEnergy,1.5)/6000.0 );
00210
00211
00212
00213 G4double freeEnergy = centerofmassEnergy-currentMass-targetMass;
00214
00215 if(freeEnergy<0)
00216 {
00217 G4cout<<"Free energy < 0!"<<G4endl;
00218 G4cout<<"E_CMS = "<<centerofmassEnergy<<" GeV"<<G4endl;
00219 G4cout<<"m_curr = "<<currentMass<<" GeV"<<G4endl;
00220 G4cout<<"m_orig = "<<mOriginal<<" GeV"<<G4endl;
00221 G4cout<<"m_targ = "<<targetMass<<" GeV"<<G4endl;
00222 G4cout<<"E_free = "<<freeEnergy<<" GeV"<<G4endl;
00223 }
00224
00225 G4double forwardEnergy = freeEnergy/2.;
00226 G4int forwardCount = 1;
00227
00228 G4double backwardEnergy = freeEnergy/2.;
00229 G4int backwardCount = 1;
00230 if(veryForward)
00231 {
00232 if(currentParticle.GetSide()==-1)
00233 {
00234 forwardEnergy += currentMass;
00235 forwardCount --;
00236 backwardEnergy -= currentMass;
00237 backwardCount ++;
00238 }
00239 if(targetParticle.GetSide()!=-1)
00240 {
00241 backwardEnergy += targetMass;
00242 backwardCount --;
00243 forwardEnergy -= targetMass;
00244 forwardCount ++;
00245 }
00246 }
00247 for( i=0; i<vecLen; ++i )
00248 {
00249 if( vec[i]->GetSide() == -1 )
00250 {
00251 ++backwardCount;
00252 backwardEnergy -= vec[i]->GetMass()/GeV;
00253 } else {
00254 ++forwardCount;
00255 forwardEnergy -= vec[i]->GetMass()/GeV;
00256 }
00257 }
00258
00259
00260
00261
00262
00263 G4double xtarg;
00264 if( centerofmassEnergy < (2.0+G4UniformRand()) )
00265 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount+vecLen+2)/2.0;
00266 else
00267 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2.0*backwardCount);
00268 if( xtarg <= 0.0 )xtarg = 0.01;
00269 G4int nuclearExcitationCount = Poisson( xtarg );
00270 if(atomicWeight<1.0001) nuclearExcitationCount = 0;
00271 G4int extraNucleonCount = 0;
00272 G4double extraNucleonMass = 0.0;
00273 if( nuclearExcitationCount > 0 )
00274 {
00275 const G4double nucsup[] = { 1.00, 0.7, 0.5, 0.4, 0.35, 0.3 };
00276 const G4double psup[] = { 3., 6., 20., 50., 100., 1000. };
00277 G4int momentumBin = 0;
00278 while( (momentumBin < 6) &&
00279 (modifiedOriginal.GetTotalMomentum()/GeV > psup[momentumBin]) )
00280 ++momentumBin;
00281 momentumBin = std::min( 5, momentumBin );
00282
00283
00284
00285
00286
00287 for( i=0; i<nuclearExcitationCount; ++i )
00288 {
00289 G4ReactionProduct * pVec = new G4ReactionProduct();
00290 if( G4UniformRand() < nucsup[momentumBin] )
00291 {
00292 if( G4UniformRand() > 1.0-atomicNumber/atomicWeight )
00293 pVec->SetDefinition( aProton );
00294 else
00295 pVec->SetDefinition( aNeutron );
00296 pVec->SetSide( -2 );
00297 ++extraNucleonCount;
00298 backwardEnergy += pVec->GetMass()/GeV;
00299 extraNucleonMass += pVec->GetMass()/GeV;
00300 }
00301 else
00302 {
00303 G4double ran = G4UniformRand();
00304 if( ran < 0.3181 )
00305 pVec->SetDefinition( aPiPlus );
00306 else if( ran < 0.6819 )
00307 pVec->SetDefinition( aPiZero );
00308 else
00309 pVec->SetDefinition( aPiMinus );
00310 pVec->SetSide( -1 );
00311 }
00312 pVec->SetNewlyAdded( true );
00313 vec.SetElement( vecLen++, pVec );
00314
00315 backwardEnergy -= pVec->GetMass()/GeV;
00316 ++backwardCount;
00317 }
00318 }
00319
00320
00321
00322 G4int is, iskip;
00323 while( forwardEnergy <= 0.0 )
00324 {
00325
00326 iskip = G4int(G4UniformRand()*forwardCount) + 1;
00327 is = 0;
00328 G4int forwardParticlesLeft = 0;
00329 for( i=(vecLen-1); i>=0; --i )
00330 {
00331 if( vec[i]->GetSide() == 1 && vec[i]->GetMayBeKilled())
00332 {
00333 forwardParticlesLeft = 1;
00334 if( ++is == iskip )
00335 {
00336 forwardEnergy += vec[i]->GetMass()/GeV;
00337 for( G4int j=i; j<(vecLen-1); j++ )*vec[j] = *vec[j+1];
00338 --forwardCount;
00339 G4ReactionProduct *temp = vec[vecLen-1];
00340 delete temp;
00341 if( --vecLen == 0 )return false;
00342 break;
00343 }
00344 }
00345 }
00346
00347 if( forwardParticlesLeft == 0 )
00348 {
00349 forwardEnergy += currentParticle.GetMass()/GeV;
00350 currentParticle.SetDefinitionAndUpdateE( targetParticle.GetDefinition() );
00351 targetParticle.SetDefinitionAndUpdateE( vec[0]->GetDefinition() );
00352
00353 --forwardCount;
00354 for( G4int j=0; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
00355 G4ReactionProduct *temp = vec[vecLen-1];
00356 delete temp;
00357 if( --vecLen == 0 )return false;
00358 break;
00359 }
00360 }
00361
00362 while( backwardEnergy <= 0.0 )
00363 {
00364
00365 iskip = G4int(G4UniformRand()*backwardCount) + 1;
00366 is = 0;
00367 G4int backwardParticlesLeft = 0;
00368 for( i=(vecLen-1); i>=0; --i )
00369 {
00370 if( vec[i]->GetSide() < 0 && vec[i]->GetMayBeKilled())
00371 {
00372 backwardParticlesLeft = 1;
00373 if( ++is == iskip )
00374 {
00375 if( vec[i]->GetSide() == -2 )
00376 {
00377 --extraNucleonCount;
00378 extraNucleonMass -= vec[i]->GetMass()/GeV;
00379 backwardEnergy -= vec[i]->GetTotalEnergy()/GeV;
00380 }
00381 backwardEnergy += vec[i]->GetTotalEnergy()/GeV;
00382 for( G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
00383 --backwardCount;
00384 G4ReactionProduct *temp = vec[vecLen-1];
00385 delete temp;
00386 if( --vecLen == 0 )return false;
00387 break;
00388 }
00389 }
00390 }
00391
00392 if( backwardParticlesLeft == 0 )
00393 {
00394 backwardEnergy += targetParticle.GetMass()/GeV;
00395 targetParticle = *vec[0];
00396 --backwardCount;
00397 for( G4int j=0; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
00398 G4ReactionProduct *temp = vec[vecLen-1];
00399 delete temp;
00400 if( --vecLen == 0 )return false;
00401 break;
00402 }
00403 }
00404
00405
00406
00407
00408
00409 G4ReactionProduct pseudoParticle[10];
00410 for( i=0; i<10; ++i )pseudoParticle[i].SetZero();
00411
00412 pseudoParticle[0].SetMass( mOriginal*GeV );
00413 pseudoParticle[0].SetMomentum( 0.0, 0.0, pOriginal*GeV );
00414 pseudoParticle[0].SetTotalEnergy(
00415 std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
00416
00417 pseudoParticle[1].SetMass( protonMass*MeV );
00418 pseudoParticle[1].SetTotalEnergy( protonMass*MeV );
00419
00420 pseudoParticle[3].SetMass( protonMass*(1+extraNucleonCount)*MeV );
00421 pseudoParticle[3].SetTotalEnergy( protonMass*(1+extraNucleonCount)*MeV );
00422
00423 pseudoParticle[8].SetMomentum( 1.0*GeV, 0.0, 0.0 );
00424
00425 pseudoParticle[2] = pseudoParticle[0] + pseudoParticle[1];
00426 pseudoParticle[3] = pseudoParticle[3] + pseudoParticle[0];
00427
00428 pseudoParticle[0].Lorentz( pseudoParticle[0], pseudoParticle[2] );
00429 pseudoParticle[1].Lorentz( pseudoParticle[1], pseudoParticle[2] );
00430
00431 G4double dndl[20];
00432
00433
00434
00435
00436 G4double aspar, pt, et, x, pp, pp1, rthnve, phinve, rmb, wgt;
00437 G4int innerCounter, outerCounter;
00438 G4bool eliminateThisParticle, resetEnergies, constantCrossSection;
00439
00440 G4double forwardKinetic = 0.0, backwardKinetic = 0.0;
00441
00442
00443
00444
00445
00446 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,
00447 1.43,1.67,2.0,2.5,3.33,5.00,10.00};
00448 G4int backwardNucleonCount = 0;
00449 G4double totalEnergy, kineticEnergy, vecMass;
00450
00451 for( i=(vecLen-1); i>=0; --i )
00452 {
00453 G4double phi = G4UniformRand()*twopi;
00454 if( vec[i]->GetNewlyAdded() )
00455 {
00456 if( vec[i]->GetSide() == -2 )
00457 {
00458 if( backwardNucleonCount < 18 )
00459 {
00460 if( vec[i]->GetDefinition() == G4PionMinus::PionMinus() ||
00461 vec[i]->GetDefinition() == G4PionPlus::PionPlus() ||
00462 vec[i]->GetDefinition() == G4PionZero::PionZero() )
00463 {
00464 for(G4int i=0; i<vecLen; i++) delete vec[i];
00465 vecLen = 0;
00466 throw G4HadReentrentException(__FILE__, __LINE__,
00467 "FullModelReactionDynamics::GenerateXandPt : a pion has been counted as a backward nucleon");
00468 }
00469 vec[i]->SetSide( -3 );
00470 ++backwardNucleonCount;
00471 continue;
00472 }
00473 }
00474 }
00475
00476
00477
00478
00479 vecMass = vec[i]->GetMass()/GeV;
00480 G4double ran = -std::log(1.0-G4UniformRand())/3.5;
00481 if( vec[i]->GetSide() == -2 )
00482 {
00483 if( vec[i]->GetDefinition() == aKaonMinus ||
00484 vec[i]->GetDefinition() == aKaonZeroL ||
00485 vec[i]->GetDefinition() == aKaonZeroS ||
00486 vec[i]->GetDefinition() == aKaonPlus ||
00487 vec[i]->GetDefinition() == aPiMinus ||
00488 vec[i]->GetDefinition() == aPiZero ||
00489 vec[i]->GetDefinition() == aPiPlus )
00490 {
00491 aspar = 0.75;
00492 pt = std::sqrt( std::pow( ran, 1.7 ) );
00493 } else {
00494 aspar = 0.20;
00495 pt = std::sqrt( std::pow( ran, 1.2 ) );
00496 }
00497 } else {
00498 if( vec[i]->GetDefinition() == aPiMinus ||
00499 vec[i]->GetDefinition() == aPiZero ||
00500 vec[i]->GetDefinition() == aPiPlus )
00501 {
00502 aspar = 0.75;
00503 pt = std::sqrt( std::pow( ran, 1.7 ) );
00504 } else if( vec[i]->GetDefinition() == aKaonMinus ||
00505 vec[i]->GetDefinition() == aKaonZeroL ||
00506 vec[i]->GetDefinition() == aKaonZeroS ||
00507 vec[i]->GetDefinition() == aKaonPlus )
00508 {
00509 aspar = 0.70;
00510 pt = std::sqrt( std::pow( ran, 1.7 ) );
00511 } else {
00512 aspar = 0.65;
00513 pt = std::sqrt( std::pow( ran, 1.5 ) );
00514 }
00515 }
00516 pt = std::max( 0.001, pt );
00517 vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
00518 for( G4int j=0; j<20; ++j )binl[j] = j/(19.*pt);
00519 if( vec[i]->GetSide() > 0 )
00520 et = pseudoParticle[0].GetTotalEnergy()/GeV;
00521 else
00522 et = pseudoParticle[1].GetTotalEnergy()/GeV;
00523 dndl[0] = 0.0;
00524
00525
00526
00527 outerCounter = 0;
00528 eliminateThisParticle = true;
00529 resetEnergies = true;
00530 while( ++outerCounter < 3 )
00531 {
00532 for( l=1; l<20; ++l )
00533 {
00534 x = (binl[l]+binl[l-1])/2.;
00535 pt = std::max( 0.001, pt );
00536 if( x > 1.0/pt )
00537 dndl[l] += dndl[l-1];
00538 else
00539 dndl[l] = et * aspar/std::sqrt( std::pow((1.+aspar*x*aspar*x),3) )
00540 * (binl[l]-binl[l-1]) / std::sqrt( pt*x*et*pt*x*et + pt*pt + vecMass*vecMass )
00541 + dndl[l-1];
00542 }
00543 innerCounter = 0;
00544 vec[i]->SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
00545
00546
00547
00548 while( ++innerCounter < 7 )
00549 {
00550 ran = G4UniformRand()*dndl[19];
00551 l = 1;
00552 while( ( ran >= dndl[l] ) && ( l < 20 ) )l++;
00553 l = std::min( 19, l );
00554 x = std::min( 1.0, pt*(binl[l-1] + G4UniformRand()*(binl[l]-binl[l-1])/2.) );
00555 if( vec[i]->GetSide() < 0 )x *= -1.;
00556 vec[i]->SetMomentum( x*et*GeV );
00557 totalEnergy = std::sqrt( x*et*x*et + pt*pt + vecMass*vecMass );
00558 vec[i]->SetTotalEnergy( totalEnergy*GeV );
00559 kineticEnergy = vec[i]->GetKineticEnergy()/GeV;
00560 if( vec[i]->GetSide() > 0 )
00561 {
00562 if( (forwardKinetic+kineticEnergy) < 0.95*forwardEnergy )
00563 {
00564 pseudoParticle[4] = pseudoParticle[4] + (*vec[i]);
00565 forwardKinetic += kineticEnergy;
00566 pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
00567 pseudoParticle[6].SetMomentum( 0.0 );
00568 phi = pseudoParticle[6].Angle( pseudoParticle[8] );
00569 if( pseudoParticle[6].GetMomentum().y()/MeV < 0.0 )phi = twopi - phi;
00570 phi += pi + normal()*pi/12.0;
00571 if( phi > twopi )phi -= twopi;
00572 if( phi < 0.0 )phi = twopi - phi;
00573 outerCounter = 2;
00574 eliminateThisParticle = false;
00575 resetEnergies = false;
00576 break;
00577 }
00578 if( innerCounter > 5 )break;
00579 if( backwardEnergy >= vecMass )
00580 {
00581 vec[i]->SetSide( -1 );
00582 forwardEnergy += vecMass;
00583 backwardEnergy -= vecMass;
00584 ++backwardCount;
00585 }
00586 } else {
00587 if( extraNucleonCount > 19 )
00588 x = 0.999;
00589 G4double xxx = 0.95+0.05*extraNucleonCount/20.0;
00590 if( (backwardKinetic+kineticEnergy) < xxx*backwardEnergy )
00591 {
00592 pseudoParticle[5] = pseudoParticle[5] + (*vec[i]);
00593 backwardKinetic += kineticEnergy;
00594 pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
00595 pseudoParticle[6].SetMomentum( 0.0 );
00596 phi = pseudoParticle[6].Angle( pseudoParticle[8] );
00597 if( pseudoParticle[6].GetMomentum().y()/MeV < 0.0 )phi = twopi - phi;
00598 phi += pi + normal() * pi / 12.0;
00599 if( phi > twopi )phi -= twopi;
00600 if( phi < 0.0 )phi = twopi - phi;
00601 outerCounter = 2;
00602 eliminateThisParticle = false;
00603 resetEnergies = false;
00604 break;
00605 }
00606 if( innerCounter > 5 )break;
00607 if( forwardEnergy >= vecMass )
00608 {
00609 vec[i]->SetSide( 1 );
00610 forwardEnergy -= vecMass;
00611 backwardEnergy += vecMass;
00612 backwardCount--;
00613 }
00614 }
00615 G4ThreeVector momentum = vec[i]->GetMomentum();
00616 vec[i]->SetMomentum( momentum.x() * 0.9, momentum.y() * 0.9 );
00617 pt *= 0.9;
00618 dndl[19] *= 0.9;
00619 }
00620 if( resetEnergies )
00621 {
00622
00623
00624
00625
00626
00627 forwardKinetic = 0.0;
00628 backwardKinetic = 0.0;
00629 pseudoParticle[4].SetZero();
00630 pseudoParticle[5].SetZero();
00631 for( l=i+1; l<vecLen; ++l )
00632 {
00633 if( vec[l]->GetSide() > 0 ||
00634 vec[l]->GetDefinition() == aKaonMinus ||
00635 vec[l]->GetDefinition() == aKaonZeroL ||
00636 vec[l]->GetDefinition() == aKaonZeroS ||
00637 vec[l]->GetDefinition() == aKaonPlus ||
00638 vec[l]->GetDefinition() == aPiMinus ||
00639 vec[l]->GetDefinition() == aPiZero ||
00640 vec[l]->GetDefinition() == aPiPlus )
00641 {
00642 G4double tempMass = vec[l]->GetMass()/MeV;
00643 totalEnergy = 0.95*vec[l]->GetTotalEnergy()/MeV + 0.05*tempMass;
00644 totalEnergy = std::max( tempMass, totalEnergy );
00645 vec[l]->SetTotalEnergy( totalEnergy*MeV );
00646 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - tempMass*tempMass ) );
00647 pp1 = vec[l]->GetMomentum().mag()/MeV;
00648 if( pp1 < 1.0e-6*GeV )
00649 {
00650 G4double rthnve = pi*G4UniformRand();
00651 G4double phinve = twopi*G4UniformRand();
00652 G4double srth = std::sin(rthnve);
00653 vec[l]->SetMomentum( pp*srth*std::cos(phinve)*MeV,
00654 pp*srth*std::sin(phinve)*MeV,
00655 pp*std::cos(rthnve)*MeV ) ;
00656 } else {
00657 vec[l]->SetMomentum( vec[l]->GetMomentum() * (pp/pp1) );
00658 }
00659 G4double px = vec[l]->GetMomentum().x()/MeV;
00660 G4double py = vec[l]->GetMomentum().y()/MeV;
00661 pt = std::max( 1.0, std::sqrt( px*px + py*py ) )/GeV;
00662 if( vec[l]->GetSide() > 0 )
00663 {
00664 forwardKinetic += vec[l]->GetKineticEnergy()/GeV;
00665 pseudoParticle[4] = pseudoParticle[4] + (*vec[l]);
00666 } else {
00667 backwardKinetic += vec[l]->GetKineticEnergy()/GeV;
00668 pseudoParticle[5] = pseudoParticle[5] + (*vec[l]);
00669 }
00670 }
00671 }
00672 }
00673 }
00674
00675 if( eliminateThisParticle && vec[i]->GetMayBeKilled())
00676 {
00677 if( vec[i]->GetSide() > 0 )
00678 {
00679 --forwardCount;
00680 forwardEnergy += vecMass;
00681 } else {
00682 if( vec[i]->GetSide() == -2 )
00683 {
00684 --extraNucleonCount;
00685 extraNucleonMass -= vecMass;
00686 backwardEnergy -= vecMass;
00687 }
00688 --backwardCount;
00689 backwardEnergy += vecMass;
00690 }
00691 for( G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
00692 G4ReactionProduct *temp = vec[vecLen-1];
00693 delete temp;
00694
00695 if( --vecLen == 0 )return false;
00696 pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
00697 pseudoParticle[6].SetMomentum( 0.0 );
00698 phi = pseudoParticle[6].Angle( pseudoParticle[8] );
00699 if( pseudoParticle[6].GetMomentum().y()/MeV < 0.0 )phi = twopi - phi;
00700 phi += pi + normal() * pi / 12.0;
00701 if( phi > twopi )phi -= twopi;
00702 if( phi < 0.0 )phi = twopi - phi;
00703 }
00704 }
00705
00706
00707
00708
00709
00710
00711 G4double phi = G4UniformRand()*twopi;
00712 G4double ran = -std::log(1.0-G4UniformRand());
00713 if( currentParticle.GetDefinition() == aPiMinus ||
00714 currentParticle.GetDefinition() == aPiZero ||
00715 currentParticle.GetDefinition() == aPiPlus )
00716 {
00717 aspar = 0.60;
00718 pt = std::sqrt( std::pow( ran/6.0, 1.7 ) );
00719 } else if( currentParticle.GetDefinition() == aKaonMinus ||
00720 currentParticle.GetDefinition() == aKaonZeroL ||
00721 currentParticle.GetDefinition() == aKaonZeroS ||
00722 currentParticle.GetDefinition() == aKaonPlus )
00723 {
00724 aspar = 0.50;
00725 pt = std::sqrt( std::pow( ran/5.0, 1.4 ) );
00726 } else {
00727 aspar = 0.40;
00728 pt = std::sqrt( std::pow( ran/4.0, 1.2 ) );
00729 }
00730 for( G4int j=0; j<20; ++j )binl[j] = j/(19.*pt);
00731 currentParticle.SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
00732 et = pseudoParticle[0].GetTotalEnergy()/GeV;
00733 dndl[0] = 0.0;
00734 vecMass = currentParticle.GetMass()/GeV;
00735 for( l=1; l<20; ++l )
00736 {
00737 x = (binl[l]+binl[l-1])/2.;
00738 if( x > 1.0/pt )
00739 dndl[l] += dndl[l-1];
00740 else
00741 dndl[l] = aspar/std::sqrt( std::pow((1.+sqr(aspar*x)),3) ) *
00742 (binl[l]-binl[l-1]) * et / std::sqrt( pt*x*et*pt*x*et + pt*pt + vecMass*vecMass ) +
00743 dndl[l-1];
00744 }
00745 ran = G4UniformRand()*dndl[19];
00746 l = 1;
00747 while( (ran>dndl[l]) && (l<20) )l++;
00748 l = std::min( 19, l );
00749 x = std::min( 1.0, pt*(binl[l-1] + G4UniformRand()*(binl[l]-binl[l-1])/2.) );
00750 currentParticle.SetMomentum( x*et*GeV );
00751 if( forwardEnergy < forwardKinetic )
00752 totalEnergy = vecMass + 0.04*std::fabs(normal());
00753 else
00754 totalEnergy = vecMass + forwardEnergy - forwardKinetic;
00755 currentParticle.SetTotalEnergy( totalEnergy*GeV );
00756 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
00757 pp1 = currentParticle.GetMomentum().mag()/MeV;
00758 if( pp1 < 1.0e-6*GeV )
00759 {
00760 G4double rthnve = pi*G4UniformRand();
00761 G4double phinve = twopi*G4UniformRand();
00762 G4double srth = std::sin(rthnve);
00763 currentParticle.SetMomentum( pp*srth*std::cos(phinve)*MeV,
00764 pp*srth*std::sin(phinve)*MeV,
00765 pp*std::cos(rthnve)*MeV );
00766 } else {
00767 currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
00768 }
00769 pseudoParticle[4] = pseudoParticle[4] + currentParticle;
00770
00771
00772
00773
00774 if( backwardNucleonCount < 18 )
00775 {
00776 targetParticle.SetSide( -3 );
00777 ++backwardNucleonCount;
00778 }
00779 else
00780 {
00781
00782
00783
00784 vecMass = targetParticle.GetMass()/GeV;
00785 ran = -std::log(1.0-G4UniformRand());
00786 aspar = 0.40;
00787 pt = std::max( 0.001, std::sqrt( std::pow( ran/4.0, 1.2 ) ) );
00788 targetParticle.SetMomentum( pt*std::cos(phi)*GeV, pt*std::sin(phi)*GeV );
00789 for( G4int j=0; j<20; ++j )binl[j] = (j-1.)/(19.*pt);
00790 et = pseudoParticle[1].GetTotalEnergy()/GeV;
00791 dndl[0] = 0.0;
00792 outerCounter = 0;
00793 eliminateThisParticle = true;
00794 resetEnergies = true;
00795 while( ++outerCounter < 3 )
00796 {
00797 for( l=1; l<20; ++l )
00798 {
00799 x = (binl[l]+binl[l-1])/2.;
00800 if( x > 1.0/pt )
00801 dndl[l] += dndl[l-1];
00802 else
00803 dndl[l] = aspar/std::sqrt( std::pow((1.+aspar*x*aspar*x),3) ) *
00804 (binl[l]-binl[l-1])*et / std::sqrt( pt*x*et*pt*x*et+pt*pt+vecMass*vecMass ) +
00805 dndl[l-1];
00806 }
00807 innerCounter = 0;
00808 while( ++innerCounter < 7 )
00809 {
00810 l = 1;
00811 ran = G4UniformRand()*dndl[19];
00812 while( ( ran >= dndl[l] ) && ( l < 20 ) )l++;
00813 l = std::min( 19, l );
00814 x = std::min( 1.0, pt*(binl[l-1] + G4UniformRand()*(binl[l]-binl[l-1])/2.) );
00815 if( targetParticle.GetSide() < 0 )x *= -1.;
00816 targetParticle.SetMomentum( x*et*GeV );
00817 totalEnergy = std::sqrt( x*et*x*et + pt*pt + vecMass*vecMass );
00818 targetParticle.SetTotalEnergy( totalEnergy*GeV );
00819 if( targetParticle.GetSide() < 0 )
00820 {
00821 if( extraNucleonCount > 19 )x=0.999;
00822 G4double xxx = 0.95+0.05*extraNucleonCount/20.0;
00823 if( (backwardKinetic+totalEnergy-vecMass) < xxx*backwardEnergy )
00824 {
00825 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
00826 backwardKinetic += totalEnergy - vecMass;
00827 pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
00828 pseudoParticle[6].SetMomentum( 0.0 );
00829 phi = pseudoParticle[6].Angle( pseudoParticle[8] );
00830 if( pseudoParticle[6].GetMomentum().y()/MeV < 0.0 )phi = twopi - phi;
00831 phi += pi + normal() * pi / 12.0;
00832 if( phi > twopi )phi -= twopi;
00833 if( phi < 0.0 )phi = twopi - phi;
00834 outerCounter = 2;
00835 eliminateThisParticle = false;
00836 resetEnergies = false;
00837 break;
00838 }
00839 if( innerCounter > 5 )break;
00840 if( forwardEnergy >= vecMass )
00841 {
00842 targetParticle.SetSide( 1 );
00843 forwardEnergy -= vecMass;
00844 backwardEnergy += vecMass;
00845 --backwardCount;
00846 }
00847 G4ThreeVector momentum = targetParticle.GetMomentum();
00848 targetParticle.SetMomentum( momentum.x() * 0.9, momentum.y() * 0.9 );
00849 pt *= 0.9;
00850 dndl[19] *= 0.9;
00851 }
00852 else
00853 {
00854 if( forwardEnergy < forwardKinetic )
00855 totalEnergy = vecMass + 0.04*std::fabs(normal());
00856 else
00857 totalEnergy = vecMass + forwardEnergy - forwardKinetic;
00858 targetParticle.SetTotalEnergy( totalEnergy*GeV );
00859 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
00860 pp1 = targetParticle.GetMomentum().mag()/MeV;
00861 if( pp1 < 1.0e-6*GeV )
00862 {
00863 G4double rthnve = pi*G4UniformRand();
00864 G4double phinve = twopi*G4UniformRand();
00865 G4double srth = std::sin(rthnve);
00866 targetParticle.SetMomentum( pp*srth*std::cos(phinve)*MeV,
00867 pp*srth*std::sin(phinve)*MeV,
00868 pp*std::cos(rthnve)*MeV );
00869 }
00870 else
00871 targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
00872
00873 pseudoParticle[4] = pseudoParticle[4] + targetParticle;
00874 outerCounter = 2;
00875 eliminateThisParticle = false;
00876 resetEnergies = false;
00877 break;
00878 }
00879 }
00880 if( resetEnergies )
00881 {
00882
00883
00884
00885
00886
00887 forwardKinetic = backwardKinetic = 0.0;
00888 pseudoParticle[4].SetZero();
00889 pseudoParticle[5].SetZero();
00890 for( l=0; l<vecLen; ++l )
00891 {
00892 if( vec[l]->GetSide() > 0 ||
00893 vec[l]->GetDefinition() == aKaonMinus ||
00894 vec[l]->GetDefinition() == aKaonZeroL ||
00895 vec[l]->GetDefinition() == aKaonZeroS ||
00896 vec[l]->GetDefinition() == aKaonPlus ||
00897 vec[l]->GetDefinition() == aPiMinus ||
00898 vec[l]->GetDefinition() == aPiZero ||
00899 vec[l]->GetDefinition() == aPiPlus )
00900 {
00901 G4double tempMass = vec[l]->GetMass()/GeV;
00902 totalEnergy =
00903 std::max( tempMass, 0.95*vec[l]->GetTotalEnergy()/GeV + 0.05*tempMass );
00904 vec[l]->SetTotalEnergy( totalEnergy*GeV );
00905 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - tempMass*tempMass ) )*GeV;
00906 pp1 = vec[l]->GetMomentum().mag()/MeV;
00907 if( pp1 < 1.0e-6*GeV )
00908 {
00909 G4double rthnve = pi*G4UniformRand();
00910 G4double phinve = twopi*G4UniformRand();
00911 G4double srth = std::sin(rthnve);
00912 vec[l]->SetMomentum( pp*srth*std::cos(phinve)*MeV,
00913 pp*srth*std::sin(phinve)*MeV,
00914 pp*std::cos(rthnve)*MeV );
00915 }
00916 else
00917 vec[l]->SetMomentum( vec[l]->GetMomentum() * (pp/pp1) );
00918
00919 pt = std::max( 0.001*GeV, std::sqrt( sqr(vec[l]->GetMomentum().x()/MeV) +
00920 sqr(vec[l]->GetMomentum().y()/MeV) ) )/GeV;
00921 if( vec[l]->GetSide() > 0)
00922 {
00923 forwardKinetic += vec[l]->GetKineticEnergy()/GeV;
00924 pseudoParticle[4] = pseudoParticle[4] + (*vec[l]);
00925 } else {
00926 backwardKinetic += vec[l]->GetKineticEnergy()/GeV;
00927 pseudoParticle[5] = pseudoParticle[5] + (*vec[l]);
00928 }
00929 }
00930 }
00931 }
00932 }
00933
00934
00935
00936
00937
00938 }
00939
00940
00941
00942
00943 pseudoParticle[6].Lorentz( pseudoParticle[3], pseudoParticle[2] );
00944 pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[4];
00945 pseudoParticle[6] = pseudoParticle[6] - pseudoParticle[5];
00946 if( backwardNucleonCount == 1 )
00947 {
00948 G4double ekin =
00949 std::min( backwardEnergy-backwardKinetic, centerofmassEnergy/2.0-protonMass/GeV );
00950 if( ekin < 0.04 )ekin = 0.04 * std::fabs( normal() );
00951 vecMass = targetParticle.GetMass()/GeV;
00952 totalEnergy = ekin+vecMass;
00953 targetParticle.SetTotalEnergy( totalEnergy*GeV );
00954 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
00955 pp1 = pseudoParticle[6].GetMomentum().mag()/MeV;
00956 if( pp1 < 1.0e-6*GeV )
00957 {
00958 rthnve = pi*G4UniformRand();
00959 phinve = twopi*G4UniformRand();
00960 G4double srth = std::sin(rthnve);
00961 targetParticle.SetMomentum( pp*srth*std::cos(phinve)*MeV,
00962 pp*srth*std::sin(phinve)*MeV,
00963 pp*std::cos(rthnve)*MeV );
00964 } else {
00965 targetParticle.SetMomentum( pseudoParticle[6].GetMomentum() * (pp/pp1) );
00966 }
00967 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
00968 }
00969 else
00970 {
00971 const G4double cpar[] = { 0.6, 0.6, 0.35, 0.15, 0.10 };
00972 const G4double gpar[] = { 2.6, 2.6, 1.80, 1.30, 1.20 };
00973
00974
00975 G4int tempCount;
00976 if (backwardNucleonCount < 5)
00977 {
00978 tempCount = backwardNucleonCount;
00979 }
00980 else
00981 {
00982 tempCount = 5;
00983 }
00984 tempCount--;
00985
00986
00987 G4double rmb0 = 0.0;
00988 if( targetParticle.GetSide() == -3 )
00989 rmb0 += targetParticle.GetMass()/GeV;
00990 for( i=0; i<vecLen; ++i )
00991 {
00992 if( vec[i]->GetSide() == -3 )rmb0 += vec[i]->GetMass()/GeV;
00993 }
00994 rmb = rmb0 + std::pow(-std::log(1.0-G4UniformRand()),cpar[tempCount]) / gpar[tempCount];
00995 totalEnergy = pseudoParticle[6].GetTotalEnergy()/GeV;
00996 vecMass = std::min( rmb, totalEnergy );
00997 pseudoParticle[6].SetMass( vecMass*GeV );
00998 pp = std::sqrt( std::abs( totalEnergy*totalEnergy - vecMass*vecMass ) )*GeV;
00999 pp1 = pseudoParticle[6].GetMomentum().mag()/MeV;
01000 if( pp1 < 1.0e-6*GeV )
01001 {
01002 rthnve = pi * G4UniformRand();
01003 phinve = twopi * G4UniformRand();
01004 G4double srth = std::sin(rthnve);
01005 pseudoParticle[6].SetMomentum( -pp*srth*std::cos(phinve)*MeV,
01006 -pp*srth*std::sin(phinve)*MeV,
01007 -pp*std::cos(rthnve)*MeV );
01008 }
01009 else
01010 pseudoParticle[6].SetMomentum( pseudoParticle[6].GetMomentum() * (-pp/pp1) );
01011
01012 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> tempV;
01013 tempV.Initialize( backwardNucleonCount );
01014 G4int tempLen = 0;
01015 if( targetParticle.GetSide() == -3 )tempV.SetElement( tempLen++, &targetParticle );
01016 for( i=0; i<vecLen; ++i )
01017 {
01018 if( vec[i]->GetSide() == -3 )tempV.SetElement( tempLen++, vec[i] );
01019 }
01020 if( tempLen != backwardNucleonCount )
01021 {
01022 G4cerr << "tempLen is not the same as backwardNucleonCount" << G4endl;
01023 G4cerr << "tempLen = " << tempLen;
01024 G4cerr << ", backwardNucleonCount = " << backwardNucleonCount << G4endl;
01025 G4cerr << "targetParticle side = " << targetParticle.GetSide() << G4endl;
01026 G4cerr << "currentParticle side = " << currentParticle.GetSide() << G4endl;
01027 for( i=0; i<vecLen; ++i )
01028 G4cerr << "particle #" << i << " side = " << vec[i]->GetSide() << G4endl;
01029 exit( EXIT_FAILURE );
01030 }
01031 constantCrossSection = true;
01032
01033 if( tempLen >= 2 )
01034 {
01035 wgt = GenerateNBodyEvent(
01036 pseudoParticle[6].GetMass(), constantCrossSection, tempV, tempLen );
01037
01038 if( targetParticle.GetSide() == -3 )
01039 {
01040 targetParticle.Lorentz( targetParticle, pseudoParticle[6] );
01041
01042 pseudoParticle[5] = pseudoParticle[5] + targetParticle;
01043 }
01044 for( i=0; i<vecLen; ++i )
01045 {
01046 if( vec[i]->GetSide() == -3 )
01047 {
01048 vec[i]->Lorentz( *vec[i], pseudoParticle[6] );
01049 pseudoParticle[5] = pseudoParticle[5] + (*vec[i]);
01050 }
01051 }
01052
01053 }
01054 }
01055
01056
01057
01058 if( vecLen == 0 )return false;
01059
01060
01061 G4int numberofFinalStateNucleons = 0;
01062 if( currentParticle.GetDefinition() ==aProton ||
01063 currentParticle.GetDefinition() == aNeutron ||
01064 currentParticle.GetDefinition() == G4SigmaMinus::SigmaMinus()||
01065 currentParticle.GetDefinition() == G4SigmaPlus::SigmaPlus()||
01066 currentParticle.GetDefinition() == G4SigmaZero::SigmaZero()||
01067 currentParticle.GetDefinition() == G4XiZero::XiZero()||
01068 currentParticle.GetDefinition() == G4XiMinus::XiMinus()||
01069 currentParticle.GetDefinition() == G4OmegaMinus::OmegaMinus()||
01070 currentParticle.GetDefinition() == G4Lambda::Lambda()) ++numberofFinalStateNucleons;
01071 currentParticle.Lorentz( currentParticle, pseudoParticle[1] );
01072
01073 if( targetParticle.GetDefinition() ==aProton ||
01074 targetParticle.GetDefinition() == aNeutron ||
01075 targetParticle.GetDefinition() == G4Lambda::Lambda() ||
01076 targetParticle.GetDefinition() == G4XiZero::XiZero()||
01077 targetParticle.GetDefinition() == G4XiMinus::XiMinus()||
01078 targetParticle.GetDefinition() == G4OmegaMinus::OmegaMinus()||
01079 targetParticle.GetDefinition() == G4SigmaZero::SigmaZero()||
01080 targetParticle.GetDefinition() == G4SigmaPlus::SigmaPlus()||
01081 targetParticle.GetDefinition() == G4SigmaMinus::SigmaMinus()) ++numberofFinalStateNucleons;
01082 if( targetParticle.GetDefinition() ==G4AntiProton::AntiProton()) --numberofFinalStateNucleons;
01083 if( targetParticle.GetDefinition() ==G4AntiNeutron::AntiNeutron()) --numberofFinalStateNucleons;
01084 if( targetParticle.GetDefinition() ==G4AntiSigmaMinus::AntiSigmaMinus()) --numberofFinalStateNucleons;
01085 if( targetParticle.GetDefinition() ==G4AntiSigmaPlus::AntiSigmaPlus()) --numberofFinalStateNucleons;
01086 if( targetParticle.GetDefinition() ==G4AntiSigmaZero::AntiSigmaZero()) --numberofFinalStateNucleons;
01087 if( targetParticle.GetDefinition() ==G4AntiXiZero::AntiXiZero()) --numberofFinalStateNucleons;
01088 if( targetParticle.GetDefinition() ==G4AntiXiMinus::AntiXiMinus()) --numberofFinalStateNucleons;
01089 if( targetParticle.GetDefinition() ==G4AntiOmegaMinus::AntiOmegaMinus()) --numberofFinalStateNucleons;
01090 if( targetParticle.GetDefinition() ==G4AntiLambda::AntiLambda()) --numberofFinalStateNucleons;
01091 targetParticle.Lorentz( targetParticle, pseudoParticle[1] );
01092
01093 for( i=0; i<vecLen; ++i )
01094 {
01095 if( vec[i]->GetDefinition() ==aProton ||
01096 vec[i]->GetDefinition() == aNeutron ||
01097 vec[i]->GetDefinition() == G4Lambda::Lambda() ||
01098 vec[i]->GetDefinition() == G4XiZero::XiZero() ||
01099 vec[i]->GetDefinition() == G4XiMinus::XiMinus() ||
01100 vec[i]->GetDefinition() == G4OmegaMinus::OmegaMinus() ||
01101 vec[i]->GetDefinition() == G4SigmaPlus::SigmaPlus()||
01102 vec[i]->GetDefinition() == G4SigmaZero::SigmaZero()||
01103 vec[i]->GetDefinition() == G4SigmaMinus::SigmaMinus()) ++numberofFinalStateNucleons;
01104 if( vec[i]->GetDefinition() ==G4AntiProton::AntiProton()) --numberofFinalStateNucleons;
01105 if( vec[i]->GetDefinition() ==G4AntiNeutron::AntiNeutron()) --numberofFinalStateNucleons;
01106 if( vec[i]->GetDefinition() ==G4AntiSigmaMinus::AntiSigmaMinus()) --numberofFinalStateNucleons;
01107 if( vec[i]->GetDefinition() ==G4AntiSigmaPlus::AntiSigmaPlus()) --numberofFinalStateNucleons;
01108 if( vec[i]->GetDefinition() ==G4AntiSigmaZero::AntiSigmaZero()) --numberofFinalStateNucleons;
01109 if( vec[i]->GetDefinition() ==G4AntiLambda::AntiLambda()) --numberofFinalStateNucleons;
01110 if( vec[i]->GetDefinition() ==G4AntiXiZero::AntiXiZero()) --numberofFinalStateNucleons;
01111 if( vec[i]->GetDefinition() ==G4AntiXiMinus::AntiXiMinus()) --numberofFinalStateNucleons;
01112 if( vec[i]->GetDefinition() ==G4AntiOmegaMinus::AntiOmegaMinus()) --numberofFinalStateNucleons;
01113 vec[i]->Lorentz( *vec[i], pseudoParticle[1] );
01114 }
01115
01116 if(veryForward) numberofFinalStateNucleons++;
01117 numberofFinalStateNucleons = std::max( 1, numberofFinalStateNucleons );
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128 G4bool leadingStrangeParticleHasChanged = true;
01129 if( leadFlag )
01130 {
01131 if( currentParticle.GetDefinition() == leadingStrangeParticle.GetDefinition() )
01132 leadingStrangeParticleHasChanged = false;
01133 if( leadingStrangeParticleHasChanged &&
01134 ( targetParticle.GetDefinition() == leadingStrangeParticle.GetDefinition() ) )
01135 leadingStrangeParticleHasChanged = false;
01136 if( leadingStrangeParticleHasChanged )
01137 {
01138 for( i=0; i<vecLen; i++ )
01139 {
01140 if( vec[i]->GetDefinition() == leadingStrangeParticle.GetDefinition() )
01141 {
01142 leadingStrangeParticleHasChanged = false;
01143 break;
01144 }
01145 }
01146 }
01147 if( leadingStrangeParticleHasChanged )
01148 {
01149 G4bool leadTest =
01150 (leadingStrangeParticle.GetDefinition() == aKaonMinus ||
01151 leadingStrangeParticle.GetDefinition() == aKaonZeroL ||
01152 leadingStrangeParticle.GetDefinition() == aKaonZeroS ||
01153 leadingStrangeParticle.GetDefinition() == aKaonPlus ||
01154 leadingStrangeParticle.GetDefinition() == aPiMinus ||
01155 leadingStrangeParticle.GetDefinition() == aPiZero ||
01156 leadingStrangeParticle.GetDefinition() == aPiPlus);
01157 G4bool targetTest = false;
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168 if( (leadTest&&targetTest) || !(leadTest||targetTest) )
01169 {
01170 targetParticle.SetDefinitionAndUpdateE( leadingStrangeParticle.GetDefinition() );
01171 targetHasChanged = true;
01172
01173 }
01174 else
01175 {
01176 currentParticle.SetDefinitionAndUpdateE( leadingStrangeParticle.GetDefinition() );
01177 incidentHasChanged = false;
01178
01179 }
01180 }
01181 }
01182
01183 pseudoParticle[3].SetMomentum( 0.0, 0.0, pOriginal*GeV );
01184 pseudoParticle[3].SetMass( mOriginal*GeV );
01185 pseudoParticle[3].SetTotalEnergy(
01186 std::sqrt( pOriginal*pOriginal + mOriginal*mOriginal )*GeV );
01187
01188
01189
01190 G4ParticleDefinition * aOrgDef = modifiedOriginal.GetDefinition();
01191 G4int diff = 0;
01192 if(aOrgDef == G4Proton::Proton() || aOrgDef == G4Neutron::Neutron() ) diff = 1;
01193 if(numberofFinalStateNucleons == 1) diff = 0;
01194 pseudoParticle[4].SetMomentum( 0.0, 0.0, 0.0 );
01195 pseudoParticle[4].SetMass( protonMass*(numberofFinalStateNucleons-diff)*MeV );
01196 pseudoParticle[4].SetTotalEnergy( protonMass*(numberofFinalStateNucleons-diff)*MeV );
01197
01198 G4double theoreticalKinetic =
01199 pseudoParticle[3].GetTotalEnergy()/MeV +
01200 pseudoParticle[4].GetTotalEnergy()/MeV -
01201 currentParticle.GetMass()/MeV -
01202 targetParticle.GetMass()/MeV;
01203
01204 G4double simulatedKinetic =
01205 currentParticle.GetKineticEnergy()/MeV + targetParticle.GetKineticEnergy()/MeV;
01206
01207 pseudoParticle[5] = pseudoParticle[3] + pseudoParticle[4];
01208 pseudoParticle[3].Lorentz( pseudoParticle[3], pseudoParticle[5] );
01209 pseudoParticle[4].Lorentz( pseudoParticle[4], pseudoParticle[5] );
01210
01211 pseudoParticle[7].SetZero();
01212 pseudoParticle[7] = pseudoParticle[7] + currentParticle;
01213 pseudoParticle[7] = pseudoParticle[7] + targetParticle;
01214
01215 for( i=0; i<vecLen; ++i )
01216 {
01217 pseudoParticle[7] = pseudoParticle[7] + *vec[i];
01218 simulatedKinetic += vec[i]->GetKineticEnergy()/MeV;
01219 theoreticalKinetic -= vec[i]->GetMass()/MeV;
01220 }
01221 if( vecLen <= 16 && vecLen > 0 )
01222 {
01223
01224
01225
01226 G4ReactionProduct tempR[130];
01227
01228 tempR[0] = currentParticle;
01229 tempR[1] = targetParticle;
01230 for( i=0; i<vecLen; ++i )tempR[i+2] = *vec[i];
01231 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> tempV;
01232 tempV.Initialize( vecLen+2 );
01233 G4int tempLen = 0;
01234 for( i=0; i<vecLen+2; ++i )tempV.SetElement( tempLen++, &tempR[i] );
01235 constantCrossSection = true;
01236
01237 wgt = GenerateNBodyEvent( pseudoParticle[3].GetTotalEnergy()/MeV+
01238 pseudoParticle[4].GetTotalEnergy()/MeV,
01239 constantCrossSection, tempV, tempLen );
01240 if(wgt>-.5)
01241 {
01242 theoreticalKinetic = 0.0;
01243 for( i=0; i<tempLen; ++i )
01244 {
01245 pseudoParticle[6].Lorentz( *tempV[i], pseudoParticle[4] );
01246 theoreticalKinetic += pseudoParticle[6].GetKineticEnergy()/MeV;
01247 }
01248 }
01249
01250
01251 }
01252
01253
01254
01255 if( simulatedKinetic != 0.0 )
01256 {
01257 wgt = (theoreticalKinetic)/simulatedKinetic;
01258 theoreticalKinetic = currentParticle.GetKineticEnergy()/MeV * wgt;
01259 simulatedKinetic = theoreticalKinetic;
01260 currentParticle.SetKineticEnergy( theoreticalKinetic*MeV );
01261 pp = currentParticle.GetTotalMomentum()/MeV;
01262 pp1 = currentParticle.GetMomentum().mag()/MeV;
01263 if( pp1 < 1.0e-6*GeV )
01264 {
01265 rthnve = pi*G4UniformRand();
01266 phinve = twopi*G4UniformRand();
01267 currentParticle.SetMomentum( pp*std::sin(rthnve)*std::cos(phinve)*MeV,
01268 pp*std::sin(rthnve)*std::sin(phinve)*MeV,
01269 pp*std::cos(rthnve)*MeV );
01270 }
01271 else
01272 {
01273 currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
01274 }
01275 theoreticalKinetic = targetParticle.GetKineticEnergy()/MeV * wgt;
01276 targetParticle.SetKineticEnergy( theoreticalKinetic*MeV );
01277 simulatedKinetic += theoreticalKinetic;
01278 pp = targetParticle.GetTotalMomentum()/MeV;
01279 pp1 = targetParticle.GetMomentum().mag()/MeV;
01280
01281 if( pp1 < 1.0e-6*GeV )
01282 {
01283 rthnve = pi*G4UniformRand();
01284 phinve = twopi*G4UniformRand();
01285 targetParticle.SetMomentum( pp*std::sin(rthnve)*std::cos(phinve)*MeV,
01286 pp*std::sin(rthnve)*std::sin(phinve)*MeV,
01287 pp*std::cos(rthnve)*MeV );
01288 } else {
01289 targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
01290 }
01291 for( i=0; i<vecLen; ++i )
01292 {
01293 theoreticalKinetic = vec[i]->GetKineticEnergy()/MeV * wgt;
01294 simulatedKinetic += theoreticalKinetic;
01295 vec[i]->SetKineticEnergy( theoreticalKinetic*MeV );
01296 pp = vec[i]->GetTotalMomentum()/MeV;
01297 pp1 = vec[i]->GetMomentum().mag()/MeV;
01298 if( pp1 < 1.0e-6*GeV )
01299 {
01300 rthnve = pi*G4UniformRand();
01301 phinve = twopi*G4UniformRand();
01302 vec[i]->SetMomentum( pp*std::sin(rthnve)*std::cos(phinve)*MeV,
01303 pp*std::sin(rthnve)*std::sin(phinve)*MeV,
01304 pp*std::cos(rthnve)*MeV );
01305 }
01306 else
01307 vec[i]->SetMomentum( vec[i]->GetMomentum() * (pp/pp1) );
01308 }
01309 }
01310
01311 Rotate( numberofFinalStateNucleons, pseudoParticle[3].GetMomentum(),
01312 modifiedOriginal, originalIncident, targetNucleus,
01313 currentParticle, targetParticle, vec, vecLen );
01314
01315
01316
01317
01318
01319
01320 if( atomicWeight >= 1.5 )
01321 {
01322
01323
01324
01325
01326
01327 G4double epnb, edta;
01328 G4int npnb = 0;
01329 G4int ndta = 0;
01330
01331 epnb = targetNucleus.GetPNBlackTrackEnergy();
01332 edta = targetNucleus.GetDTABlackTrackEnergy();
01333 const G4double pnCutOff = 0.001;
01334 const G4double dtaCutOff = 0.001;
01335 const G4double kineticMinimum = 1.e-6;
01336 const G4double kineticFactor = -0.010;
01337 G4double sprob = 0.0;
01338 const G4double ekIncident = originalIncident->GetKineticEnergy()/GeV;
01339 if( ekIncident >= 5.0 )sprob = std::min( 1.0, 0.6*std::log(ekIncident-4.0) );
01340 if( epnb >= pnCutOff )
01341 {
01342 npnb = Poisson((1.5+1.25*numberofFinalStateNucleons)*epnb/(epnb+edta));
01343 if( numberofFinalStateNucleons + npnb > atomicWeight )
01344 npnb = G4int(atomicWeight+0.00001 - numberofFinalStateNucleons);
01345 npnb = std::min( npnb, 127-vecLen );
01346 }
01347 if( edta >= dtaCutOff )
01348 {
01349 ndta = Poisson( (1.5+1.25*numberofFinalStateNucleons)*edta/(epnb+edta) );
01350 ndta = std::min( ndta, 127-vecLen );
01351 }
01352 G4double spall = numberofFinalStateNucleons;
01353
01354
01355 AddBlackTrackParticles( epnb, npnb, edta, ndta, sprob, kineticMinimum, kineticFactor,
01356 modifiedOriginal, spall, targetNucleus,
01357 vec, vecLen );
01358
01359
01360
01361
01362
01363
01364
01365 }
01366
01367
01368
01369
01370
01371 if( (atomicWeight >= 1.5) && (atomicWeight <= 230.0) && (ekOriginal <= 0.2) )
01372 currentParticle.SetTOF( 1.0-500.0*std::exp(-ekOriginal/0.04)*std::log(G4UniformRand()) );
01373 else
01374 currentParticle.SetTOF( 1.0 );
01375 return true;
01376
01377 }
01378
01379 void FullModelReactionDynamics::SuppressChargedPions(
01380 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> &vec,
01381 G4int &vecLen,
01382 const G4ReactionProduct &modifiedOriginal,
01383 G4ReactionProduct ¤tParticle,
01384 G4ReactionProduct &targetParticle,
01385 const G4Nucleus &targetNucleus,
01386 G4bool &incidentHasChanged,
01387 G4bool &targetHasChanged )
01388 {
01389
01390
01391
01392
01393 const G4double atomicWeight = targetNucleus.GetN();
01394 const G4double atomicNumber = targetNucleus.GetZ();
01395 const G4double pOriginal = modifiedOriginal.GetTotalMomentum()/GeV;
01396
01397
01398 G4ParticleDefinition *aProton = G4Proton::Proton();
01399 G4ParticleDefinition *anAntiProton = G4AntiProton::AntiProton();
01400 G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
01401 G4ParticleDefinition *anAntiNeutron = G4AntiNeutron::AntiNeutron();
01402 G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
01403 G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
01404
01405 const G4bool antiTest =
01406 modifiedOriginal.GetDefinition() != anAntiProton &&
01407 modifiedOriginal.GetDefinition() != anAntiNeutron;
01408 if( antiTest && (
01409
01410 currentParticle.GetDefinition() == aPiPlus ||
01411 currentParticle.GetDefinition() == aPiMinus ) &&
01412 ( G4UniformRand() <= (10.0-pOriginal)/6.0 ) &&
01413 ( G4UniformRand() <= atomicWeight/300.0 ) )
01414 {
01415 if( G4UniformRand() > atomicNumber/atomicWeight )
01416 currentParticle.SetDefinitionAndUpdateE( aNeutron );
01417 else
01418 currentParticle.SetDefinitionAndUpdateE( aProton );
01419 incidentHasChanged = true;
01420 }
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435 for( G4int i=0; i<vecLen; ++i )
01436 {
01437 if( antiTest && (
01438
01439 vec[i]->GetDefinition() == aPiPlus ||
01440 vec[i]->GetDefinition() == aPiMinus ) &&
01441 ( G4UniformRand() <= (10.0-pOriginal)/6.0 ) &&
01442 ( G4UniformRand() <= atomicWeight/300.0 ) )
01443 {
01444 if( G4UniformRand() > atomicNumber/atomicWeight )
01445 vec[i]->SetDefinitionAndUpdateE( aNeutron );
01446 else
01447 vec[i]->SetDefinitionAndUpdateE( aProton );
01448
01449 }
01450 }
01451
01452 }
01453
01454 G4bool FullModelReactionDynamics::TwoCluster(
01455 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> &vec,
01456 G4int &vecLen,
01457 G4ReactionProduct &modifiedOriginal,
01458 const G4HadProjectile *originalIncident,
01459 G4ReactionProduct ¤tParticle,
01460 G4ReactionProduct &targetParticle,
01461 const G4Nucleus &targetNucleus,
01462 G4bool &incidentHasChanged,
01463 G4bool &targetHasChanged,
01464 G4bool leadFlag,
01465 G4ReactionProduct &leadingStrangeParticle )
01466 {
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480 G4int i;
01481 G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
01482 G4ParticleDefinition *aProton = G4Proton::Proton();
01483 G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
01484 G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
01485 G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
01486 G4ParticleDefinition *aSigmaMinus = G4SigmaMinus::SigmaMinus();
01487 const G4double protonMass = aProton->GetPDGMass()/MeV;
01488 const G4double ekOriginal = modifiedOriginal.GetKineticEnergy()/GeV;
01489 const G4double etOriginal = modifiedOriginal.GetTotalEnergy()/GeV;
01490 const G4double mOriginal = modifiedOriginal.GetMass()/GeV;
01491 const G4double pOriginal = modifiedOriginal.GetMomentum().mag()/GeV;
01492 G4double targetMass = targetParticle.GetDefinition()->GetPDGMass()/GeV;
01493 G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
01494 targetMass*targetMass +
01495 2.0*targetMass*etOriginal );
01496 G4double currentMass = currentParticle.GetMass()/GeV;
01497 targetMass = targetParticle.GetMass()/GeV;
01498
01499 if( currentMass == 0.0 && targetMass == 0.0 )
01500 {
01501 G4double ek = currentParticle.GetKineticEnergy();
01502 G4ThreeVector m = currentParticle.GetMomentum();
01503 currentParticle = *vec[0];
01504 targetParticle = *vec[1];
01505 for( i=0; i<(vecLen-2); ++i )*vec[i] = *vec[i+2];
01506 if(vecLen<2)
01507 {
01508 for(G4int i=0; i<vecLen; i++) delete vec[i];
01509 vecLen = 0;
01510 throw G4HadReentrentException(__FILE__, __LINE__,
01511 "FullModelReactionDynamics::TwoCluster: Negative number of particles");
01512 }
01513 delete vec[vecLen-1];
01514 delete vec[vecLen-2];
01515 vecLen -= 2;
01516 currentMass = currentParticle.GetMass()/GeV;
01517 targetMass = targetParticle.GetMass()/GeV;
01518 incidentHasChanged = true;
01519 targetHasChanged = true;
01520 currentParticle.SetKineticEnergy( ek );
01521 currentParticle.SetMomentum( m );
01522 }
01523 const G4double atomicWeight = targetNucleus.GetN();
01524 const G4double atomicNumber = targetNucleus.GetZ();
01525
01526
01527
01528
01529
01530 G4int forwardCount = 1;
01531 currentParticle.SetSide( 1 );
01532 G4double forwardMass = currentParticle.GetMass()/GeV;
01533 G4double cMass = forwardMass;
01534
01535
01536 G4int backwardCount = 1;
01537 G4int backwardNucleonCount = 1;
01538 targetParticle.SetSide( -1 );
01539 G4double backwardMass = targetParticle.GetMass()/GeV;
01540 G4double bMass = backwardMass;
01541
01542 for( i=0; i<vecLen; ++i )
01543 {
01544 if( vec[i]->GetSide() < 0 )vec[i]->SetSide( -1 );
01545
01546
01547 if( vec[i]->GetSide() == -1 )
01548 {
01549 ++backwardCount;
01550 backwardMass += vec[i]->GetMass()/GeV;
01551 }
01552 else
01553 {
01554 ++forwardCount;
01555 forwardMass += vec[i]->GetMass()/GeV;
01556 }
01557 }
01558
01559
01560
01561 G4double term1 = std::log(centerofmassEnergy*centerofmassEnergy);
01562 if(term1 < 0) term1 = 0.0001;
01563 const G4double afc = 0.312 + 0.2 * std::log(term1);
01564 G4double xtarg;
01565 if( centerofmassEnergy < 2.0+G4UniformRand() )
01566 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2*backwardCount+vecLen+2)/2.0;
01567 else
01568 xtarg = afc * (std::pow(atomicWeight,0.33)-1.0) * (2*backwardCount);
01569 if( xtarg <= 0.0 )xtarg = 0.01;
01570 G4int nuclearExcitationCount = Poisson( xtarg );
01571 if(atomicWeight<1.0001) nuclearExcitationCount = 0;
01572 G4int extraNucleonCount = 0;
01573 G4double extraMass = 0.0;
01574 G4double extraNucleonMass = 0.0;
01575 if( nuclearExcitationCount > 0 )
01576 {
01577 G4int momentumBin = std::min( 4, G4int(pOriginal/3.0) );
01578 const G4double nucsup[] = { 1.0, 0.8, 0.6, 0.5, 0.4 };
01579
01580
01581
01582
01583
01584 for( i=0; i<nuclearExcitationCount; ++i )
01585 {
01586 G4ReactionProduct* pVec = new G4ReactionProduct();
01587 if( G4UniformRand() < nucsup[momentumBin] )
01588 {
01589 if( G4UniformRand() > 1.0-atomicNumber/atomicWeight )
01590
01591 pVec->SetDefinition( aProton );
01592 else
01593 pVec->SetDefinition( aNeutron );
01594 ++backwardNucleonCount;
01595 ++extraNucleonCount;
01596 extraNucleonMass += pVec->GetMass()/GeV;
01597 }
01598 else
01599 {
01600 G4double ran = G4UniformRand();
01601 if( ran < 0.3181 )
01602 pVec->SetDefinition( aPiPlus );
01603 else if( ran < 0.6819 )
01604 pVec->SetDefinition( aPiZero );
01605 else
01606 pVec->SetDefinition( aPiMinus );
01607 }
01608 pVec->SetSide( -2 );
01609 extraMass += pVec->GetMass()/GeV;
01610 pVec->SetNewlyAdded( true );
01611 vec.SetElement( vecLen++, pVec );
01612
01613 }
01614 }
01615
01616 G4double forwardEnergy = (centerofmassEnergy-cMass-bMass)/2.0 +cMass - forwardMass;
01617 G4double backwardEnergy = (centerofmassEnergy-cMass-bMass)/2.0 +bMass - backwardMass;
01618 G4double eAvailable = centerofmassEnergy - (forwardMass+backwardMass);
01619 G4bool secondaryDeleted;
01620 G4double pMass;
01621 while( eAvailable <= 0.0 )
01622 {
01623 secondaryDeleted = false;
01624 for( i=(vecLen-1); i>=0; --i )
01625 {
01626 if( vec[i]->GetSide() == 1 && vec[i]->GetMayBeKilled())
01627 {
01628 pMass = vec[i]->GetMass()/GeV;
01629 for( G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
01630 --forwardCount;
01631 forwardEnergy += pMass;
01632 forwardMass -= pMass;
01633 secondaryDeleted = true;
01634 break;
01635 }
01636 else if( vec[i]->GetSide() == -1 && vec[i]->GetMayBeKilled())
01637 {
01638 pMass = vec[i]->GetMass()/GeV;
01639 for( G4int j=i; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
01640 --backwardCount;
01641 backwardEnergy += pMass;
01642 backwardMass -= pMass;
01643 secondaryDeleted = true;
01644 break;
01645 }
01646 }
01647 if( secondaryDeleted )
01648 {
01649 G4ReactionProduct *temp = vec[vecLen-1];
01650 delete temp;
01651 --vecLen;
01652
01653 }
01654 else
01655 {
01656 if( vecLen == 0 )
01657 {
01658 return false;
01659 }
01660 if( targetParticle.GetSide() == -1 )
01661 {
01662 pMass = targetParticle.GetMass()/GeV;
01663 targetParticle = *vec[0];
01664 for( G4int j=0; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
01665 --backwardCount;
01666 backwardEnergy += pMass;
01667 backwardMass -= pMass;
01668 secondaryDeleted = true;
01669 }
01670 else if( targetParticle.GetSide() == 1 )
01671 {
01672 pMass = targetParticle.GetMass()/GeV;
01673 targetParticle = *vec[0];
01674 for( G4int j=0; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
01675 --forwardCount;
01676 forwardEnergy += pMass;
01677 forwardMass -= pMass;
01678 secondaryDeleted = true;
01679 }
01680 if( secondaryDeleted )
01681 {
01682 G4ReactionProduct *temp = vec[vecLen-1];
01683 delete temp;
01684 --vecLen;
01685
01686 }
01687 else
01688 {
01689 if( currentParticle.GetSide() == -1 )
01690 {
01691 pMass = currentParticle.GetMass()/GeV;
01692 currentParticle = *vec[0];
01693 for( G4int j=0; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
01694 --backwardCount;
01695 backwardEnergy += pMass;
01696 backwardMass -= pMass;
01697 secondaryDeleted = true;
01698 }
01699 else if( currentParticle.GetSide() == 1 )
01700 {
01701 pMass = currentParticle.GetMass()/GeV;
01702 currentParticle = *vec[0];
01703 for( G4int j=0; j<(vecLen-1); ++j )*vec[j] = *vec[j+1];
01704 --forwardCount;
01705 forwardEnergy += pMass;
01706 forwardMass -= pMass;
01707 secondaryDeleted = true;
01708 }
01709 if( secondaryDeleted )
01710 {
01711 G4ReactionProduct *temp = vec[vecLen-1];
01712 delete temp;
01713 --vecLen;
01714
01715 }
01716 else break;
01717 }
01718 }
01719 eAvailable = centerofmassEnergy - (forwardMass+backwardMass);
01720 }
01721
01722
01723
01724
01725
01726
01727
01728 G4double rmc = 0.0, rmd = 0.0;
01729 const G4double cpar[] = { 0.6, 0.6, 0.35, 0.15, 0.10 };
01730 const G4double gpar[] = { 2.6, 2.6, 1.8, 1.30, 1.20 };
01731
01732 if( forwardCount == 0) return false;
01733
01734 if( forwardCount == 1 )rmc = forwardMass;
01735 else
01736 {
01737
01738 G4int ntc = std::max(1, std::min(5,forwardCount))-1;
01739 rmc = forwardMass + std::pow(-std::log(1.0-G4UniformRand()),cpar[ntc-1])/gpar[ntc-1];
01740 }
01741 if( backwardCount == 1 )rmd = backwardMass;
01742 else
01743 {
01744
01745 G4int ntc = std::max(1, std::min(5,backwardCount));
01746 rmd = backwardMass + std::pow(-std::log(1.0-G4UniformRand()),cpar[ntc-1])/gpar[ntc-1];
01747 }
01748 while( rmc+rmd > centerofmassEnergy )
01749 {
01750 if( (rmc <= forwardMass) && (rmd <= backwardMass) )
01751 {
01752 G4double temp = 0.999*centerofmassEnergy/(rmc+rmd);
01753 rmc *= temp;
01754 rmd *= temp;
01755 }
01756 else
01757 {
01758 rmc = 0.1*forwardMass + 0.9*rmc;
01759 rmd = 0.1*backwardMass + 0.9*rmd;
01760 }
01761 }
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774 G4ReactionProduct pseudoParticle[8];
01775 for( i=0; i<8; ++i )pseudoParticle[i].SetZero();
01776
01777 pseudoParticle[1].SetMass( mOriginal*GeV );
01778 pseudoParticle[1].SetTotalEnergy( etOriginal*GeV );
01779 pseudoParticle[1].SetMomentum( 0.0, 0.0, pOriginal*GeV );
01780
01781 pseudoParticle[2].SetMass( protonMass*MeV );
01782 pseudoParticle[2].SetTotalEnergy( protonMass*MeV );
01783 pseudoParticle[2].SetMomentum( 0.0, 0.0, 0.0 );
01784
01785
01786
01787 pseudoParticle[0] = pseudoParticle[1] + pseudoParticle[2];
01788 pseudoParticle[1].Lorentz( pseudoParticle[1], pseudoParticle[0] );
01789 pseudoParticle[2].Lorentz( pseudoParticle[2], pseudoParticle[0] );
01790
01791 const G4double pfMin = 0.0001;
01792 G4double pf = (centerofmassEnergy*centerofmassEnergy+rmd*rmd-rmc*rmc);
01793 pf *= pf;
01794 pf -= 4*centerofmassEnergy*centerofmassEnergy*rmd*rmd;
01795 pf = std::sqrt( std::max(pf,pfMin) )/(2.0*centerofmassEnergy);
01796
01797
01798
01799 pseudoParticle[3].SetMass( rmc*GeV );
01800 pseudoParticle[3].SetTotalEnergy( std::sqrt(pf*pf+rmc*rmc)*GeV );
01801
01802 pseudoParticle[4].SetMass( rmd*GeV );
01803 pseudoParticle[4].SetTotalEnergy( std::sqrt(pf*pf+rmd*rmd)*GeV );
01804
01805
01806
01807 const G4double bMin = 0.01;
01808 const G4double b1 = 4.0;
01809 const G4double b2 = 1.6;
01810 G4double t = std::log( 1.0-G4UniformRand() ) / std::max( bMin, b1+b2*std::log(pOriginal) );
01811 G4double t1 =
01812 pseudoParticle[1].GetTotalEnergy()/GeV - pseudoParticle[3].GetTotalEnergy()/GeV;
01813 G4double pin = pseudoParticle[1].GetMomentum().mag()/GeV;
01814 G4double tacmin = t1*t1 - (pin-pf)*(pin-pf);
01815
01816
01817
01818 const G4double smallValue = 1.0e-10;
01819 G4double dumnve = 4.0*pin*pf;
01820 if( dumnve == 0.0 )dumnve = smallValue;
01821 G4double ctet = std::max( -1.0, std::min( 1.0, 1.0+2.0*(t-tacmin)/dumnve ) );
01822 dumnve = std::max( 0.0, 1.0-ctet*ctet );
01823 G4double stet = std::sqrt(dumnve);
01824 G4double phi = G4UniformRand() * twopi;
01825
01826
01827
01828 pseudoParticle[3].SetMomentum( pf*stet*std::sin(phi)*GeV,
01829 pf*stet*std::cos(phi)*GeV,
01830 pf*ctet*GeV );
01831 pseudoParticle[4].SetMomentum( pseudoParticle[3].GetMomentum() * (-1.0) );
01832
01833
01834
01835 G4double pp, pp1, rthnve, phinve;
01836 if( nuclearExcitationCount > 0 )
01837 {
01838 const G4double ga = 1.2;
01839 G4double ekit1 = 0.04;
01840 G4double ekit2 = 0.6;
01841 if( ekOriginal <= 5.0 )
01842 {
01843 ekit1 *= ekOriginal*ekOriginal/25.0;
01844 ekit2 *= ekOriginal*ekOriginal/25.0;
01845 }
01846 const G4double a = (1.0-ga)/(std::pow(ekit2,(1.0-ga)) - std::pow(ekit1,(1.0-ga)));
01847 for( i=0; i<vecLen; ++i )
01848 {
01849 if( vec[i]->GetSide() == -2 )
01850 {
01851 G4double kineticE =
01852 std::pow( (G4UniformRand()*(1.0-ga)/a+std::pow(ekit1,(1.0-ga))), (1.0/(1.0-ga)) );
01853 vec[i]->SetKineticEnergy( kineticE*GeV );
01854 G4double vMass = vec[i]->GetMass()/MeV;
01855 G4double totalE = kineticE + vMass;
01856 pp = std::sqrt( std::abs(totalE*totalE-vMass*vMass) );
01857 G4double cost = std::min( 1.0, std::max( -1.0, std::log(2.23*G4UniformRand()+0.383)/0.96 ) );
01858 G4double sint = std::sqrt( std::max( 0.0, (1.0-cost*cost) ) );
01859 phi = twopi*G4UniformRand();
01860 vec[i]->SetMomentum( pp*sint*std::sin(phi)*MeV,
01861 pp*sint*std::cos(phi)*MeV,
01862 pp*cost*MeV );
01863 vec[i]->Lorentz( *vec[i], pseudoParticle[0] );
01864 }
01865 }
01866
01867 }
01868
01869
01870
01871 currentParticle.SetMomentum( pseudoParticle[3].GetMomentum() );
01872 currentParticle.SetTotalEnergy( pseudoParticle[3].GetTotalEnergy() );
01873
01874 targetParticle.SetMomentum( pseudoParticle[4].GetMomentum() );
01875 targetParticle.SetTotalEnergy( pseudoParticle[4].GetTotalEnergy() );
01876
01877 pseudoParticle[5].SetMomentum( pseudoParticle[3].GetMomentum() * (-1.0) );
01878 pseudoParticle[5].SetMass( pseudoParticle[3].GetMass() );
01879 pseudoParticle[5].SetTotalEnergy( pseudoParticle[3].GetTotalEnergy() );
01880
01881 pseudoParticle[6].SetMomentum( pseudoParticle[4].GetMomentum() * (-1.0) );
01882 pseudoParticle[6].SetMass( pseudoParticle[4].GetMass() );
01883 pseudoParticle[6].SetTotalEnergy( pseudoParticle[4].GetTotalEnergy() );
01884
01885 G4double wgt;
01886
01887 if( forwardCount > 1 )
01888 {
01889 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> tempV;
01890 tempV.Initialize( forwardCount );
01891 G4bool constantCrossSection = true;
01892 G4int tempLen = 0;
01893 if( currentParticle.GetSide() == 1 )
01894 tempV.SetElement( tempLen++, ¤tParticle );
01895 if( targetParticle.GetSide() == 1 )
01896 tempV.SetElement( tempLen++, &targetParticle );
01897 for( i=0; i<vecLen; ++i )
01898 {
01899 if( vec[i]->GetSide() == 1 )
01900 {
01901 if( tempLen < 18 )
01902 tempV.SetElement( tempLen++, vec[i] );
01903 else
01904 {
01905 vec[i]->SetSide( -1 );
01906 continue;
01907 }
01908 }
01909 }
01910 if( tempLen >= 2 )
01911 {
01912 wgt = GenerateNBodyEvent( pseudoParticle[3].GetMass()/MeV,
01913 constantCrossSection, tempV, tempLen );
01914 if( currentParticle.GetSide() == 1 )
01915 currentParticle.Lorentz( currentParticle, pseudoParticle[5] );
01916 if( targetParticle.GetSide() == 1 )
01917 targetParticle.Lorentz( targetParticle, pseudoParticle[5] );
01918 for( i=0; i<vecLen; ++i )
01919 {
01920 if( vec[i]->GetSide() == 1 )vec[i]->Lorentz( *vec[i], pseudoParticle[5] );
01921 }
01922 }
01923 }
01924
01925 if( backwardCount > 1 )
01926 {
01927 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> tempV;
01928 tempV.Initialize( backwardCount );
01929 G4bool constantCrossSection = true;
01930 G4int tempLen = 0;
01931 if( currentParticle.GetSide() == -1 )
01932 tempV.SetElement( tempLen++, ¤tParticle );
01933 if( targetParticle.GetSide() == -1 )
01934 tempV.SetElement( tempLen++, &targetParticle );
01935 for( i=0; i<vecLen; ++i )
01936 {
01937 if( vec[i]->GetSide() == -1 )
01938 {
01939 if( tempLen < 18 )
01940 tempV.SetElement( tempLen++, vec[i] );
01941 else
01942 {
01943 vec[i]->SetSide( -2 );
01944 vec[i]->SetKineticEnergy( 0.0 );
01945 vec[i]->SetMomentum( 0.0, 0.0, 0.0 );
01946 continue;
01947 }
01948 }
01949 }
01950 if( tempLen >= 2 )
01951 {
01952 wgt = GenerateNBodyEvent( pseudoParticle[4].GetMass()/MeV,
01953 constantCrossSection, tempV, tempLen );
01954 if( currentParticle.GetSide() == -1 )
01955 currentParticle.Lorentz( currentParticle, pseudoParticle[6] );
01956 if( targetParticle.GetSide() == -1 )
01957 targetParticle.Lorentz( targetParticle, pseudoParticle[6] );
01958 for( i=0; i<vecLen; ++i )
01959 {
01960 if( vec[i]->GetSide() == -1 )vec[i]->Lorentz( *vec[i], pseudoParticle[6] );
01961 }
01962 }
01963 }
01964
01965
01966
01967
01968 G4int numberofFinalStateNucleons = 0;
01969 if( currentParticle.GetDefinition() ==aProton ||
01970 currentParticle.GetDefinition() == aNeutron ||
01971 currentParticle.GetDefinition() == aSigmaMinus||
01972 currentParticle.GetDefinition() == G4SigmaPlus::SigmaPlus()||
01973 currentParticle.GetDefinition() == G4SigmaZero::SigmaZero()||
01974 currentParticle.GetDefinition() == G4XiZero::XiZero()||
01975 currentParticle.GetDefinition() == G4XiMinus::XiMinus()||
01976 currentParticle.GetDefinition() == G4OmegaMinus::OmegaMinus()||
01977 currentParticle.GetDefinition() == G4Lambda::Lambda()) ++numberofFinalStateNucleons;
01978 currentParticle.Lorentz( currentParticle, pseudoParticle[2] );
01979 if( targetParticle.GetDefinition() ==aProton ||
01980 targetParticle.GetDefinition() == aNeutron ||
01981 targetParticle.GetDefinition() == G4Lambda::Lambda() ||
01982 targetParticle.GetDefinition() == G4XiZero::XiZero()||
01983 targetParticle.GetDefinition() == G4XiMinus::XiMinus()||
01984 targetParticle.GetDefinition() == G4OmegaMinus::OmegaMinus()||
01985 targetParticle.GetDefinition() == G4SigmaZero::SigmaZero()||
01986 targetParticle.GetDefinition() == G4SigmaPlus::SigmaPlus()||
01987 targetParticle.GetDefinition() == aSigmaMinus) ++numberofFinalStateNucleons;
01988 if( targetParticle.GetDefinition() ==G4AntiProton::AntiProton()) --numberofFinalStateNucleons;
01989 if( targetParticle.GetDefinition() ==G4AntiNeutron::AntiNeutron()) --numberofFinalStateNucleons;
01990 if( targetParticle.GetDefinition() ==G4AntiSigmaMinus::AntiSigmaMinus()) --numberofFinalStateNucleons;
01991 if( targetParticle.GetDefinition() ==G4AntiSigmaPlus::AntiSigmaPlus()) --numberofFinalStateNucleons;
01992 if( targetParticle.GetDefinition() ==G4AntiSigmaZero::AntiSigmaZero()) --numberofFinalStateNucleons;
01993 if( targetParticle.GetDefinition() ==G4AntiXiZero::AntiXiZero()) --numberofFinalStateNucleons;
01994 if( targetParticle.GetDefinition() ==G4AntiXiMinus::AntiXiMinus()) --numberofFinalStateNucleons;
01995 if( targetParticle.GetDefinition() ==G4AntiOmegaMinus::AntiOmegaMinus()) --numberofFinalStateNucleons;
01996 if( targetParticle.GetDefinition() ==G4AntiLambda::AntiLambda()) --numberofFinalStateNucleons;
01997 targetParticle.Lorentz( targetParticle, pseudoParticle[2] );
01998 for( i=0; i<vecLen; ++i )
01999 {
02000 if( vec[i]->GetDefinition() ==aProton ||
02001 vec[i]->GetDefinition() == aNeutron ||
02002 vec[i]->GetDefinition() == G4Lambda::Lambda() ||
02003 vec[i]->GetDefinition() == G4XiZero::XiZero() ||
02004 vec[i]->GetDefinition() == G4XiMinus::XiMinus() ||
02005 vec[i]->GetDefinition() == G4OmegaMinus::OmegaMinus() ||
02006 vec[i]->GetDefinition() == G4SigmaPlus::SigmaPlus()||
02007 vec[i]->GetDefinition() == G4SigmaZero::SigmaZero()||
02008 vec[i]->GetDefinition() == aSigmaMinus) ++numberofFinalStateNucleons;
02009 if( vec[i]->GetDefinition() ==G4AntiProton::AntiProton()) --numberofFinalStateNucleons;
02010 if( vec[i]->GetDefinition() ==G4AntiNeutron::AntiNeutron()) --numberofFinalStateNucleons;
02011 if( vec[i]->GetDefinition() ==G4AntiSigmaMinus::AntiSigmaMinus()) --numberofFinalStateNucleons;
02012 if( vec[i]->GetDefinition() ==G4AntiSigmaPlus::AntiSigmaPlus()) --numberofFinalStateNucleons;
02013 if( vec[i]->GetDefinition() ==G4AntiSigmaZero::AntiSigmaZero()) --numberofFinalStateNucleons;
02014 if( vec[i]->GetDefinition() ==G4AntiLambda::AntiLambda()) --numberofFinalStateNucleons;
02015 if( vec[i]->GetDefinition() ==G4AntiXiZero::AntiXiZero()) --numberofFinalStateNucleons;
02016 if( vec[i]->GetDefinition() ==G4AntiXiMinus::AntiXiMinus()) --numberofFinalStateNucleons;
02017 if( vec[i]->GetDefinition() ==G4AntiOmegaMinus::AntiOmegaMinus()) --numberofFinalStateNucleons;
02018 vec[i]->Lorentz( *vec[i], pseudoParticle[2] );
02019 }
02020
02021 numberofFinalStateNucleons = std::max( 1, numberofFinalStateNucleons );
02022
02023
02024
02025 G4bool dum = true;
02026 if( leadFlag )
02027 {
02028
02029
02030
02031
02032
02033
02034
02035
02036
02037 if( currentParticle.GetDefinition() == leadingStrangeParticle.GetDefinition() )
02038 dum = false;
02039 else if( targetParticle.GetDefinition() == leadingStrangeParticle.GetDefinition() )
02040 dum = false;
02041 else
02042 {
02043 for( i=0; i<vecLen; ++i )
02044 {
02045 if( vec[i]->GetDefinition() == leadingStrangeParticle.GetDefinition() )
02046 {
02047 dum = false;
02048 break;
02049 }
02050 }
02051 }
02052 if( dum )
02053 {
02054 G4double leadMass = leadingStrangeParticle.GetMass()/MeV;
02055 G4double ekin;
02056 if( ((leadMass < protonMass) && (targetParticle.GetMass()/MeV < protonMass)) ||
02057 ((leadMass >= protonMass) && (targetParticle.GetMass()/MeV >= protonMass)) )
02058 {
02059 ekin = targetParticle.GetKineticEnergy()/GeV;
02060 pp1 = targetParticle.GetMomentum().mag()/MeV;
02061 targetParticle.SetDefinition( leadingStrangeParticle.GetDefinition() );
02062 targetParticle.SetKineticEnergy( ekin*GeV );
02063 pp = targetParticle.GetTotalMomentum()/MeV;
02064 if( pp1 < 1.0e-3 )
02065 {
02066 rthnve = pi*G4UniformRand();
02067 phinve = twopi*G4UniformRand();
02068 targetParticle.SetMomentum( pp*std::sin(rthnve)*std::cos(rthnve)*MeV,
02069 pp*std::sin(rthnve)*std::sin(rthnve)*MeV,
02070 pp*std::cos(rthnve)*MeV );
02071 }
02072 else
02073 targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
02074
02075 targetHasChanged = true;
02076 }
02077 else
02078 {
02079 ekin = currentParticle.GetKineticEnergy()/GeV;
02080 pp1 = currentParticle.GetMomentum().mag()/MeV;
02081 currentParticle.SetDefinition( leadingStrangeParticle.GetDefinition() );
02082 currentParticle.SetKineticEnergy( ekin*GeV );
02083 pp = currentParticle.GetTotalMomentum()/MeV;
02084 if( pp1 < 1.0e-3 )
02085 {
02086 rthnve = pi*G4UniformRand();
02087 phinve = twopi*G4UniformRand();
02088 currentParticle.SetMomentum( pp*std::sin(rthnve)*std::cos(rthnve)*MeV,
02089 pp*std::sin(rthnve)*std::sin(rthnve)*MeV,
02090 pp*std::cos(rthnve)*MeV );
02091 }
02092 else
02093 currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
02094
02095 incidentHasChanged = true;
02096 }
02097 }
02098 }
02099
02100
02101
02102
02103 pseudoParticle[4].SetMass( mOriginal*GeV );
02104 pseudoParticle[4].SetTotalEnergy( etOriginal*GeV );
02105 pseudoParticle[4].SetMomentum( 0.0, 0.0, pOriginal*GeV );
02106
02107 G4ParticleDefinition * aOrgDef = modifiedOriginal.GetDefinition();
02108 G4int diff = 0;
02109 if(aOrgDef == G4Proton::Proton() || aOrgDef == G4Neutron::Neutron() ) diff = 1;
02110 if(numberofFinalStateNucleons == 1) diff = 0;
02111 pseudoParticle[5].SetMomentum( 0.0, 0.0, 0.0 );
02112 pseudoParticle[5].SetMass( protonMass*(numberofFinalStateNucleons-diff)*MeV );
02113 pseudoParticle[5].SetTotalEnergy( protonMass*(numberofFinalStateNucleons-diff)*MeV );
02114
02115
02116 G4double theoreticalKinetic =
02117 pseudoParticle[4].GetTotalEnergy()/GeV + pseudoParticle[5].GetTotalEnergy()/GeV;
02118
02119 pseudoParticle[6] = pseudoParticle[4] + pseudoParticle[5];
02120 pseudoParticle[4].Lorentz( pseudoParticle[4], pseudoParticle[6] );
02121 pseudoParticle[5].Lorentz( pseudoParticle[5], pseudoParticle[6] );
02122
02123 if( vecLen < 16 )
02124 {
02125 G4ReactionProduct tempR[130];
02126
02127 tempR[0] = currentParticle;
02128 tempR[1] = targetParticle;
02129 for( i=0; i<vecLen; ++i )tempR[i+2] = *vec[i];
02130
02131 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> tempV;
02132 tempV.Initialize( vecLen+2 );
02133 G4bool constantCrossSection = true;
02134 G4int tempLen = 0;
02135 for( i=0; i<vecLen+2; ++i )tempV.SetElement( tempLen++, &tempR[i] );
02136
02137 if( tempLen >= 2 )
02138 {
02139
02140 wgt = GenerateNBodyEvent(
02141 pseudoParticle[4].GetTotalEnergy()/MeV+pseudoParticle[5].GetTotalEnergy()/MeV,
02142 constantCrossSection, tempV, tempLen );
02143 theoreticalKinetic = 0.0;
02144 for( i=0; i<vecLen+2; ++i )
02145 {
02146 pseudoParticle[7].SetMomentum( tempV[i]->GetMomentum() );
02147 pseudoParticle[7].SetMass( tempV[i]->GetMass() );
02148 pseudoParticle[7].SetTotalEnergy( tempV[i]->GetTotalEnergy() );
02149 pseudoParticle[7].Lorentz( pseudoParticle[7], pseudoParticle[5] );
02150 theoreticalKinetic += pseudoParticle[7].GetKineticEnergy()/GeV;
02151 }
02152 }
02153
02154
02155 }
02156 else
02157 {
02158 theoreticalKinetic -=
02159 ( currentParticle.GetMass()/GeV + targetParticle.GetMass()/GeV );
02160 for( i=0; i<vecLen; ++i )theoreticalKinetic -= vec[i]->GetMass()/GeV;
02161 }
02162 G4double simulatedKinetic =
02163 currentParticle.GetKineticEnergy()/GeV + targetParticle.GetKineticEnergy()/GeV;
02164 for( i=0; i<vecLen; ++i )simulatedKinetic += vec[i]->GetKineticEnergy()/GeV;
02165
02166
02167
02168
02169
02170 if( simulatedKinetic != 0.0 )
02171 {
02172 wgt = (theoreticalKinetic)/simulatedKinetic;
02173 currentParticle.SetKineticEnergy( wgt*currentParticle.GetKineticEnergy() );
02174 pp = currentParticle.GetTotalMomentum()/MeV;
02175 pp1 = currentParticle.GetMomentum().mag()/MeV;
02176 if( pp1 < 0.001*MeV )
02177 {
02178 rthnve = pi * G4UniformRand();
02179 phinve = twopi * G4UniformRand();
02180 currentParticle.SetMomentum( pp*std::sin(rthnve)*std::cos(phinve)*MeV,
02181 pp*std::sin(rthnve)*std::sin(phinve)*MeV,
02182 pp*std::cos(rthnve)*MeV );
02183 }
02184 else
02185 currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
02186
02187 targetParticle.SetKineticEnergy( wgt*targetParticle.GetKineticEnergy() );
02188 pp = targetParticle.GetTotalMomentum()/MeV;
02189 pp1 = targetParticle.GetMomentum().mag()/MeV;
02190 if( pp1 < 0.001*MeV )
02191 {
02192 rthnve = pi * G4UniformRand();
02193 phinve = twopi * G4UniformRand();
02194 targetParticle.SetMomentum( pp*std::sin(rthnve)*std::cos(phinve)*MeV,
02195 pp*std::sin(rthnve)*std::sin(phinve)*MeV,
02196 pp*std::cos(rthnve)*MeV );
02197 }
02198 else
02199 targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
02200
02201 for( i=0; i<vecLen; ++i )
02202 {
02203 vec[i]->SetKineticEnergy( wgt*vec[i]->GetKineticEnergy() );
02204 pp = vec[i]->GetTotalMomentum()/MeV;
02205 pp1 = vec[i]->GetMomentum().mag()/MeV;
02206 if( pp1 < 0.001 )
02207 {
02208 rthnve = pi * G4UniformRand();
02209 phinve = twopi * G4UniformRand();
02210 vec[i]->SetMomentum( pp*std::sin(rthnve)*std::cos(phinve)*MeV,
02211 pp*std::sin(rthnve)*std::sin(phinve)*MeV,
02212 pp*std::cos(rthnve)*MeV );
02213 }
02214 else
02215 vec[i]->SetMomentum( vec[i]->GetMomentum() * (pp/pp1) );
02216 }
02217 }
02218
02219 Rotate( numberofFinalStateNucleons, pseudoParticle[4].GetMomentum(),
02220 modifiedOriginal, originalIncident, targetNucleus,
02221 currentParticle, targetParticle, vec, vecLen );
02222
02223
02224
02225
02226
02227 if( atomicWeight >= 1.5 )
02228 {
02229
02230
02231
02232
02233
02234 G4double epnb, edta;
02235 G4int npnb = 0;
02236 G4int ndta = 0;
02237
02238 epnb = targetNucleus.GetPNBlackTrackEnergy();
02239 edta = targetNucleus.GetDTABlackTrackEnergy();
02240 const G4double pnCutOff = 0.001;
02241 const G4double dtaCutOff = 0.001;
02242 const G4double kineticMinimum = 1.e-6;
02243 const G4double kineticFactor = -0.005;
02244
02245 G4double sprob = 0.0;
02246 const G4double ekIncident = originalIncident->GetKineticEnergy()/GeV;
02247 if( ekIncident >= 5.0 )sprob = std::min( 1.0, 0.6*std::log(ekIncident-4.0) );
02248
02249 if( epnb >= pnCutOff )
02250 {
02251 npnb = Poisson((1.5+1.25*numberofFinalStateNucleons)*epnb/(epnb+edta));
02252 if( numberofFinalStateNucleons + npnb > atomicWeight )
02253 npnb = G4int(atomicWeight - numberofFinalStateNucleons);
02254 npnb = std::min( npnb, 127-vecLen );
02255 }
02256 if( edta >= dtaCutOff )
02257 {
02258 ndta = Poisson( (1.5+1.25*numberofFinalStateNucleons)*edta/(epnb+edta) );
02259 ndta = std::min( ndta, 127-vecLen );
02260 }
02261 G4double spall = numberofFinalStateNucleons;
02262
02263
02264 AddBlackTrackParticles( epnb, npnb, edta, ndta, sprob, kineticMinimum, kineticFactor,
02265 modifiedOriginal, spall, targetNucleus,
02266 vec, vecLen );
02267
02268
02269 }
02270
02271
02272
02273
02274
02275 if( (atomicWeight >= 1.5) && (atomicWeight <= 230.0) && (ekOriginal <= 0.2) )
02276 currentParticle.SetTOF( 1.0-500.0*std::exp(-ekOriginal/0.04)*std::log(G4UniformRand()) );
02277 else
02278 currentParticle.SetTOF( 1.0 );
02279
02280
02281 return true;
02282 }
02283
02284 void FullModelReactionDynamics::TwoBody(
02285 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> &vec,
02286 G4int &vecLen,
02287 G4ReactionProduct &modifiedOriginal,
02288 const G4DynamicParticle *,
02289 G4ReactionProduct ¤tParticle,
02290 G4ReactionProduct &targetParticle,
02291 const G4Nucleus &targetNucleus,
02292 G4bool & )
02293 {
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304 G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
02305 G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
02306 G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
02307 G4ParticleDefinition *aKaonPlus = G4KaonPlus::KaonPlus();
02308 G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
02309 G4ParticleDefinition *aKaonZeroS = G4KaonZeroShort::KaonZeroShort();
02310 G4ParticleDefinition *aKaonZeroL = G4KaonZeroLong::KaonZeroLong();
02311
02312
02313 static const G4double expxu = 82.;
02314 static const G4double expxl = -expxu;
02315
02316 const G4double ekOriginal = modifiedOriginal.GetKineticEnergy()/GeV;
02317 const G4double etOriginal = modifiedOriginal.GetTotalEnergy()/GeV;
02318 const G4double mOriginal = modifiedOriginal.GetMass()/GeV;
02319 const G4double pOriginal = modifiedOriginal.GetMomentum().mag()/GeV;
02320 G4double currentMass = currentParticle.GetMass()/GeV;
02321 G4double targetMass = targetParticle.GetDefinition()->GetPDGMass()/GeV;
02322
02323 targetMass = targetParticle.GetMass()/GeV;
02324 const G4double atomicWeight = targetNucleus.GetN();
02325
02326 G4double etCurrent = currentParticle.GetTotalEnergy()/GeV;
02327 G4double pCurrent = currentParticle.GetTotalMomentum()/GeV;
02328
02329 G4double cmEnergy = std::sqrt( currentMass*currentMass +
02330 targetMass*targetMass +
02331 2.0*targetMass*etCurrent );
02332
02333
02334
02335
02336
02337
02338
02339 if( (pCurrent < 0.1) || (cmEnergy < 0.01) )
02340 {
02341 targetParticle.SetMass( 0.0 );
02342 }
02343 else
02344 {
02345
02346
02347
02348
02349
02350
02351
02352
02353
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374 G4double pf = cmEnergy*cmEnergy + targetMass*targetMass - currentMass*currentMass;
02375 pf = pf*pf - 4*cmEnergy*cmEnergy*targetMass*targetMass;
02376
02377
02378 if( pf <= 0.)
02379 {
02380 for(G4int i=0; i<vecLen; i++) delete vec[i];
02381 vecLen = 0;
02382 throw G4HadronicException(__FILE__, __LINE__, "FullModelReactionDynamics::TwoBody: pf is too small ");
02383 }
02384
02385 pf = std::sqrt( pf ) / ( 2.0*cmEnergy );
02386
02387
02388
02389 G4ReactionProduct pseudoParticle[3];
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415 pseudoParticle[0].SetMass( currentMass*GeV );
02416 pseudoParticle[0].SetTotalEnergy( etCurrent*GeV );
02417 pseudoParticle[0].SetMomentum( 0.0, 0.0, pCurrent*GeV );
02418
02419 pseudoParticle[1].SetMomentum( 0.0, 0.0, 0.0 );
02420 pseudoParticle[1].SetMass( targetMass*GeV );
02421 pseudoParticle[1].SetKineticEnergy( 0.0 );
02422
02423
02424
02425
02426 pseudoParticle[2] = pseudoParticle[0] + pseudoParticle[1];
02427 pseudoParticle[0].Lorentz( pseudoParticle[0], pseudoParticle[2] );
02428 pseudoParticle[1].Lorentz( pseudoParticle[1], pseudoParticle[2] );
02429
02430
02431
02432 currentParticle.SetTotalEnergy( std::sqrt(pf*pf+currentMass*currentMass)*GeV );
02433 targetParticle.SetTotalEnergy( std::sqrt(pf*pf+targetMass*targetMass)*GeV );
02434
02435
02436
02437 const G4double cb = 0.01;
02438 const G4double b1 = 4.225;
02439 const G4double b2 = 1.795;
02440
02441
02442
02443 G4ParticleTable* theParticleTable = G4ParticleTable::GetParticleTable();
02444 G4double ptemp=0;
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457 G4double b = std::max( cb, b1+b2*std::log(pOriginal) );
02458
02459 G4double btrang = b * 4.0 * pf * pseudoParticle[0].GetMomentum().mag()/GeV;
02460
02461 G4double exindt = -1.0;
02462 exindt += std::exp(std::max(-btrang,expxl));
02463
02464
02465
02466 G4double ctet = 1.0 + 2*std::log( 1.0+G4UniformRand()*exindt ) / btrang;
02467 if( std::fabs(ctet) > 1.0 )ctet > 0.0 ? ctet = 1.0 : ctet = -1.0;
02468 G4double stet = std::sqrt( (1.0-ctet)*(1.0+ctet) );
02469 G4double phi = twopi * G4UniformRand();
02470
02471
02472
02473 if(
02474 targetParticle.GetDefinition() == aKaonMinus ||
02475 targetParticle.GetDefinition() == aKaonZeroL ||
02476 targetParticle.GetDefinition() == aKaonZeroS ||
02477 targetParticle.GetDefinition() == aKaonPlus ||
02478 targetParticle.GetDefinition() == aPiMinus ||
02479 targetParticle.GetDefinition() == aPiZero ||
02480 targetParticle.GetDefinition() == aPiPlus )
02481 {
02482 currentParticle.SetMomentum( -pf*stet*std::sin(phi)*GeV,
02483 -pf*stet*std::cos(phi)*GeV,
02484 -pf*ctet*GeV );
02485 }
02486 else
02487 {
02488 currentParticle.SetMomentum( pf*stet*std::sin(phi)*GeV,
02489 pf*stet*std::cos(phi)*GeV,
02490 pf*ctet*GeV );
02491 }
02492 targetParticle.SetMomentum( currentParticle.GetMomentum() * (-1.0) );
02493
02494
02495
02496 currentParticle.Lorentz( currentParticle, pseudoParticle[1] );
02497 targetParticle.Lorentz( targetParticle, pseudoParticle[1] );
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507 Defs1( modifiedOriginal, currentParticle, targetParticle, vec, vecLen );
02508
02509 G4double pp, pp1, ekin;
02510 if( atomicWeight >= 1.5 )
02511 {
02512 const G4double cfa = 0.025*((atomicWeight-1.)/120.)*std::exp(-(atomicWeight-1.)/120.);
02513 pp1 = currentParticle.GetMomentum().mag()/MeV;
02514 if( pp1 >= 1.0 )
02515 {
02516 ekin = currentParticle.GetKineticEnergy()/MeV - cfa*(1.0+0.5*normal())*GeV;
02517 ekin = std::max( 0.0001*GeV, ekin );
02518 currentParticle.SetKineticEnergy( ekin*MeV );
02519 pp = currentParticle.GetTotalMomentum()/MeV;
02520 currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
02521 }
02522 pp1 = targetParticle.GetMomentum().mag()/MeV;
02523 if( pp1 >= 1.0 )
02524 {
02525 ekin = targetParticle.GetKineticEnergy()/MeV - cfa*(1.0+normal()/2.)*GeV;
02526 ekin = std::max( 0.0001*GeV, ekin );
02527 targetParticle.SetKineticEnergy( ekin*MeV );
02528 pp = targetParticle.GetTotalMomentum()/MeV;
02529 targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
02530 }
02531 }
02532 }
02533
02534 if( atomicWeight >= 1.5 )
02535 {
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546 G4double epnb, edta;
02547 G4int npnb=0, ndta=0;
02548
02549 epnb = targetNucleus.GetPNBlackTrackEnergy();
02550 edta = targetNucleus.GetDTABlackTrackEnergy();
02551 const G4double pnCutOff = 0.0001;
02552 const G4double dtaCutOff = 0.0001;
02553 const G4double kineticMinimum = 0.0001;
02554 const G4double kineticFactor = -0.010;
02555 G4double sprob = 0.0;
02556 if( epnb >= pnCutOff )
02557 {
02558 npnb = Poisson( epnb/0.02 );
02559
02560
02561
02562
02563
02564 if( npnb > atomicWeight )npnb = G4int(atomicWeight);
02565 if( (epnb > pnCutOff) && (npnb <= 0) )npnb = 1;
02566 npnb = std::min( npnb, 127-vecLen );
02567 }
02568 if( edta >= dtaCutOff )
02569 {
02570 ndta = G4int(2.0 * std::log(atomicWeight));
02571 ndta = std::min( ndta, 127-vecLen );
02572 }
02573 G4double spall = 0.0;
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592 AddBlackTrackParticles( epnb, npnb, edta, ndta, sprob, kineticMinimum, kineticFactor,
02593 modifiedOriginal, spall, targetNucleus,
02594 vec, vecLen );
02595
02596
02597 }
02598
02599
02600
02601 if( (atomicWeight >= 1.5) && (atomicWeight <= 230.0) && (ekOriginal <= 0.2) )
02602 currentParticle.SetTOF( 1.0-500.0*std::exp(-ekOriginal/0.04)*std::log(G4UniformRand()) );
02603 else
02604 currentParticle.SetTOF( 1.0 );
02605 return;
02606 }
02607
02608 G4double FullModelReactionDynamics::GenerateNBodyEvent(
02609 const G4double totalEnergy,
02610 const G4bool constantCrossSection,
02611 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> &vec,
02612 G4int &vecLen )
02613 {
02614
02615
02616
02617
02618 G4int i;
02619 const G4double expxu = 82.;
02620 const G4double expxl = -expxu;
02621 if( vecLen < 2 )
02622 {
02623 G4cerr << "*** Error in FullModelReactionDynamics::GenerateNBodyEvent" << G4endl;
02624 G4cerr << " number of particles < 2" << G4endl;
02625 G4cerr << "totalEnergy = " << totalEnergy << "MeV, vecLen = " << vecLen << G4endl;
02626 return -1.0;
02627 }
02628 G4double mass[18];
02629 G4double energy[18];
02630 G4double pcm[3][18];
02631
02632
02633
02634
02635
02636
02637 G4double totalMass = 0.0;
02638 G4double extraMass = 0;
02639 G4double sm[18];
02640
02641
02642 for( i=0; i<vecLen; ++i )
02643 {
02644 mass[i] = vec[i]->GetMass()/GeV;
02645 if(vec[i]->GetSide() == -2) extraMass+=vec[i]->GetMass()/GeV;
02646 vec[i]->SetMomentum( 0.0, 0.0, 0.0 );
02647 pcm[0][i] = 0.0;
02648 pcm[1][i] = 0.0;
02649 pcm[2][i] = 0.0;
02650 energy[i] = mass[i];
02651 totalMass += mass[i];
02652 sm[i] = totalMass;
02653 }
02654 G4double totalE = totalEnergy/GeV;
02655 if( totalMass > totalE )
02656 {
02657
02658
02659
02660 totalE = totalMass;
02661
02662
02663
02664
02665
02666 return -1.0;
02667 }
02668 G4double kineticEnergy = totalE - totalMass;
02669 G4double emm[18];
02670
02671 emm[0] = mass[0];
02672 emm[vecLen-1] = totalE;
02673 if( vecLen > 2 )
02674 {
02675 G4double ran[18];
02676 for( i=0; i<vecLen; ++i )ran[i] = G4UniformRand();
02677 for( i=0; i<vecLen-2; ++i )
02678 {
02679 for( G4int j=vecLen-2; j>i; --j )
02680 {
02681 if( ran[i] > ran[j] )
02682 {
02683 G4double temp = ran[i];
02684 ran[i] = ran[j];
02685 ran[j] = temp;
02686 }
02687 }
02688 }
02689 for( i=1; i<vecLen-1; ++i )emm[i] = ran[i-1]*kineticEnergy + sm[i];
02690 }
02691
02692 G4bool lzero = true;
02693 G4double wtmax = 0.0;
02694 if( constantCrossSection )
02695 {
02696 G4double emmax = kineticEnergy + mass[0];
02697 G4double emmin = 0.0;
02698 for( i=1; i<vecLen; ++i )
02699 {
02700 emmin += mass[i-1];
02701 emmax += mass[i];
02702 G4double wtfc = 0.0;
02703 if( emmax*emmax > 0.0 )
02704 {
02705 G4double arg = emmax*emmax
02706 + (emmin*emmin-mass[i]*mass[i])*(emmin*emmin-mass[i]*mass[i])/(emmax*emmax)
02707 - 2.0*(emmin*emmin+mass[i]*mass[i]);
02708 if( arg > 0.0 )wtfc = 0.5*std::sqrt( arg );
02709 }
02710 if( wtfc == 0.0 )
02711 {
02712 lzero = false;
02713 break;
02714 }
02715 wtmax += std::log( wtfc );
02716 }
02717 if( lzero )
02718 wtmax = -wtmax;
02719 else
02720 wtmax = expxu;
02721 }
02722 else
02723 {
02724
02725 const G4double ffq[18] = { 0., 3.141592, 19.73921, 62.01255, 129.8788, 204.0131,
02726 256.3704, 268.4705, 240.9780, 189.2637,
02727 132.1308, 83.0202, 47.4210, 24.8295,
02728 12.0006, 5.3858, 2.2560, 0.8859 };
02729 wtmax = std::log( std::pow( kineticEnergy, vecLen-2 ) * ffq[vecLen-1] / totalE );
02730 }
02731 lzero = true;
02732 G4double pd[50];
02733
02734 for( i=0; i<vecLen-1; ++i )
02735 {
02736 pd[i] = 0.0;
02737 if( emm[i+1]*emm[i+1] > 0.0 )
02738 {
02739 G4double arg = emm[i+1]*emm[i+1]
02740 + (emm[i]*emm[i]-mass[i+1]*mass[i+1])*(emm[i]*emm[i]-mass[i+1]*mass[i+1])
02741 /(emm[i+1]*emm[i+1])
02742 - 2.0*(emm[i]*emm[i]+mass[i+1]*mass[i+1]);
02743 if( arg > 0.0 )pd[i] = 0.5*std::sqrt( arg );
02744 }
02745 if( pd[i] <= 0.0 )
02746 lzero = false;
02747 else
02748 wtmax += std::log( pd[i] );
02749 }
02750 G4double weight = 0.0;
02751 if( lzero )weight = std::exp( std::max(std::min(wtmax,expxu),expxl) );
02752
02753 G4double bang, cb, sb, s0, s1, s2, c, s, esys, a, b, gama, beta;
02754 pcm[0][0] = 0.0;
02755 pcm[1][0] = pd[0];
02756 pcm[2][0] = 0.0;
02757 for( i=1; i<vecLen; ++i )
02758 {
02759 pcm[0][i] = 0.0;
02760 pcm[1][i] = -pd[i-1];
02761 pcm[2][i] = 0.0;
02762 bang = twopi*G4UniformRand();
02763 cb = std::cos(bang);
02764 sb = std::sin(bang);
02765 c = 2.0*G4UniformRand() - 1.0;
02766 s = std::sqrt( std::fabs( 1.0-c*c ) );
02767 if( i < vecLen-1 )
02768 {
02769 esys = std::sqrt(pd[i]*pd[i] + emm[i]*emm[i]);
02770 beta = pd[i]/esys;
02771 gama = esys/emm[i];
02772 for( G4int j=0; j<=i; ++j )
02773 {
02774 s0 = pcm[0][j];
02775 s1 = pcm[1][j];
02776 s2 = pcm[2][j];
02777 energy[j] = std::sqrt( s0*s0 + s1*s1 + s2*s2 + mass[j]*mass[j] );
02778 a = s0*c - s1*s;
02779 pcm[1][j] = s0*s + s1*c;
02780 b = pcm[2][j];
02781 pcm[0][j] = a*cb - b*sb;
02782 pcm[2][j] = a*sb + b*cb;
02783 pcm[1][j] = gama*(pcm[1][j] + beta*energy[j]);
02784 }
02785 }
02786 else
02787 {
02788 for( G4int j=0; j<=i; ++j )
02789 {
02790 s0 = pcm[0][j];
02791 s1 = pcm[1][j];
02792 s2 = pcm[2][j];
02793 energy[j] = std::sqrt( s0*s0 + s1*s1 + s2*s2 + mass[j]*mass[j] );
02794 a = s0*c - s1*s;
02795 pcm[1][j] = s0*s + s1*c;
02796 b = pcm[2][j];
02797 pcm[0][j] = a*cb - b*sb;
02798 pcm[2][j] = a*sb + b*cb;
02799 }
02800 }
02801 }
02802 for( i=0; i<vecLen; ++i )
02803 {
02804 vec[i]->SetMomentum( pcm[0][i]*GeV, pcm[1][i]*GeV, pcm[2][i]*GeV );
02805 vec[i]->SetTotalEnergy( energy[i]*GeV );
02806 }
02807
02808
02809
02810
02811
02812
02813
02814
02815 return weight;
02816 }
02817
02818 G4double
02819 FullModelReactionDynamics::normal()
02820 {
02821 G4double ran = -6.0;
02822 for( G4int i=0; i<12; ++i )ran += G4UniformRand();
02823 return ran;
02824 }
02825
02826 G4int
02827 FullModelReactionDynamics::Poisson( G4double x )
02828 {
02829 G4int iran;
02830 G4double ran;
02831
02832 if( x > 9.9 )
02833 iran = static_cast<G4int>(std::max( 0.0, x+normal()*std::sqrt(x) ) );
02834 else {
02835 G4int mm = G4int(5.0*x);
02836 if( mm <= 0 )
02837 {
02838 G4double p1 = x*std::exp(-x);
02839 G4double p2 = x*p1/2.0;
02840 G4double p3 = x*p2/3.0;
02841 ran = G4UniformRand();
02842 if( ran < p3 )
02843 iran = 3;
02844 else if( ran < p2 )
02845 iran = 2;
02846 else if( ran < p1 )
02847 iran = 1;
02848 else
02849 iran = 0;
02850 }
02851 else
02852 {
02853 iran = 0;
02854 G4double r = std::exp(-x);
02855 ran = G4UniformRand();
02856 if( ran > r )
02857 {
02858 G4double rrr;
02859 G4double rr = r;
02860 for( G4int i=1; i<=mm; ++i )
02861 {
02862 iran++;
02863 if( i > 5 )
02864 rrr = std::exp(i*std::log(x)-(i+0.5)*std::log((G4double)i)+i-0.9189385);
02865 else
02866 rrr = std::pow(x,i)/Factorial(i);
02867 rr += r*rrr;
02868 if( ran <= rr )break;
02869 }
02870 }
02871 }
02872 }
02873 return iran;
02874 }
02875
02876 G4int
02877 FullModelReactionDynamics::Factorial( G4int n )
02878 {
02879 G4int m = std::min(n,10);
02880 G4int result = 1;
02881 if( m <= 1 )return result;
02882 for( G4int i=2; i<=m; ++i )result *= i;
02883 return result;
02884 }
02885
02886 void FullModelReactionDynamics::Defs1(
02887 const G4ReactionProduct &modifiedOriginal,
02888 G4ReactionProduct ¤tParticle,
02889 G4ReactionProduct &targetParticle,
02890 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> &vec,
02891 G4int &vecLen )
02892 {
02893 const G4double pjx = modifiedOriginal.GetMomentum().x()/MeV;
02894 const G4double pjy = modifiedOriginal.GetMomentum().y()/MeV;
02895 const G4double pjz = modifiedOriginal.GetMomentum().z()/MeV;
02896 const G4double p = modifiedOriginal.GetMomentum().mag()/MeV;
02897 if( pjx*pjx+pjy*pjy > 0.0 )
02898 {
02899 G4double cost, sint, ph, cosp, sinp, pix, piy, piz;
02900 cost = pjz/p;
02901 sint = 0.5 * ( std::sqrt(std::abs((1.0-cost)*(1.0+cost))) + std::sqrt(pjx*pjx+pjy*pjy)/p );
02902 if( pjy < 0.0 )
02903 ph = 3*halfpi;
02904 else
02905 ph = halfpi;
02906 if( std::abs( pjx ) > 0.001*MeV )ph = std::atan2(pjy,pjx);
02907 cosp = std::cos(ph);
02908 sinp = std::sin(ph);
02909 pix = currentParticle.GetMomentum().x()/MeV;
02910 piy = currentParticle.GetMomentum().y()/MeV;
02911 piz = currentParticle.GetMomentum().z()/MeV;
02912 currentParticle.SetMomentum( cost*cosp*pix*MeV - sinp*piy+sint*cosp*piz*MeV,
02913 cost*sinp*pix*MeV + cosp*piy+sint*sinp*piz*MeV,
02914 -sint*pix*MeV + cost*piz*MeV );
02915 pix = targetParticle.GetMomentum().x()/MeV;
02916 piy = targetParticle.GetMomentum().y()/MeV;
02917 piz = targetParticle.GetMomentum().z()/MeV;
02918 targetParticle.SetMomentum( cost*cosp*pix*MeV - sinp*piy+sint*cosp*piz*MeV,
02919 cost*sinp*pix*MeV + cosp*piy+sint*sinp*piz*MeV,
02920 -sint*pix*MeV + cost*piz*MeV );
02921 for( G4int i=0; i<vecLen; ++i )
02922 {
02923 pix = vec[i]->GetMomentum().x()/MeV;
02924 piy = vec[i]->GetMomentum().y()/MeV;
02925 piz = vec[i]->GetMomentum().z()/MeV;
02926 vec[i]->SetMomentum( cost*cosp*pix*MeV - sinp*piy+sint*cosp*piz*MeV,
02927 cost*sinp*pix*MeV + cosp*piy+sint*sinp*piz*MeV,
02928 -sint*pix*MeV + cost*piz*MeV );
02929 }
02930 }
02931 else
02932 {
02933 if( pjz < 0.0 )
02934 {
02935 currentParticle.SetMomentum( -currentParticle.GetMomentum().z() );
02936 targetParticle.SetMomentum( -targetParticle.GetMomentum().z() );
02937 for( G4int i=0; i<vecLen; ++i )
02938 vec[i]->SetMomentum( -vec[i]->GetMomentum().z() );
02939 }
02940 }
02941 }
02942
02943 void FullModelReactionDynamics::Rotate(
02944 const G4double numberofFinalStateNucleons,
02945 const G4ThreeVector &temp,
02946 const G4ReactionProduct &modifiedOriginal,
02947 const G4HadProjectile *originalIncident,
02948 const G4Nucleus &targetNucleus,
02949 G4ReactionProduct ¤tParticle,
02950 G4ReactionProduct &targetParticle,
02951 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> &vec,
02952 G4int &vecLen )
02953 {
02954
02955
02956
02957
02958
02959 const G4double atomicWeight = targetNucleus.GetN();
02960 const G4double logWeight = std::log(atomicWeight);
02961
02962 G4ParticleDefinition *aPiMinus = G4PionMinus::PionMinus();
02963 G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
02964 G4ParticleDefinition *aPiZero = G4PionZero::PionZero();
02965
02966 G4int i;
02967 G4ThreeVector pseudoParticle[4];
02968 for( i=0; i<4; ++i )pseudoParticle[i].set(0,0,0);
02969 pseudoParticle[0] = currentParticle.GetMomentum()
02970 + targetParticle.GetMomentum();
02971 for( i=0; i<vecLen; ++i )
02972 pseudoParticle[0] = pseudoParticle[0] + (vec[i]->GetMomentum());
02973
02974
02975
02976 G4float pp, pp1;
02977 G4double alekw, p, rthnve, phinve;
02978 G4double r1, r2, a1, ran1, ran2, xxh, exh, pxTemp, pyTemp, pzTemp;
02979
02980 r1 = twopi*G4UniformRand();
02981 r2 = G4UniformRand();
02982 a1 = std::sqrt(-2.0*std::log(r2));
02983 ran1 = a1*std::sin(r1)*0.020*numberofFinalStateNucleons*GeV;
02984 ran2 = a1*std::cos(r1)*0.020*numberofFinalStateNucleons*GeV;
02985 G4ThreeVector fermi(ran1, ran2, 0);
02986
02987 pseudoParticle[0] = pseudoParticle[0]+fermi;
02988 pseudoParticle[2] = temp;
02989 pseudoParticle[3] = pseudoParticle[0];
02990
02991 pseudoParticle[1] = pseudoParticle[2].cross(pseudoParticle[3]);
02992 G4double rotation = 2.*pi*G4UniformRand();
02993 pseudoParticle[1] = pseudoParticle[1].rotate(rotation, pseudoParticle[3]);
02994 pseudoParticle[2] = pseudoParticle[3].cross(pseudoParticle[1]);
02995 for(G4int ii=1; ii<=3; ii++)
02996 {
02997 p = pseudoParticle[ii].mag();
02998 if( p == 0.0 )
02999 pseudoParticle[ii]= G4ThreeVector( 0.0, 0.0, 0.0 );
03000 else
03001 pseudoParticle[ii]= pseudoParticle[ii] * (1./p);
03002 }
03003
03004 pxTemp = pseudoParticle[1].dot(currentParticle.GetMomentum());
03005 pyTemp = pseudoParticle[2].dot(currentParticle.GetMomentum());
03006 pzTemp = pseudoParticle[3].dot(currentParticle.GetMomentum());
03007 currentParticle.SetMomentum( pxTemp, pyTemp, pzTemp );
03008
03009 pxTemp = pseudoParticle[1].dot(targetParticle.GetMomentum());
03010 pyTemp = pseudoParticle[2].dot(targetParticle.GetMomentum());
03011 pzTemp = pseudoParticle[3].dot(targetParticle.GetMomentum());
03012 targetParticle.SetMomentum( pxTemp, pyTemp, pzTemp );
03013
03014 for( i=0; i<vecLen; ++i )
03015 {
03016 pxTemp = pseudoParticle[1].dot(vec[i]->GetMomentum());
03017 pyTemp = pseudoParticle[2].dot(vec[i]->GetMomentum());
03018 pzTemp = pseudoParticle[3].dot(vec[i]->GetMomentum());
03019 vec[i]->SetMomentum( pxTemp, pyTemp, pzTemp );
03020 }
03021
03022
03023
03024
03025 Defs1( modifiedOriginal, currentParticle, targetParticle, vec, vecLen );
03026 G4double ekin;
03027 G4double dekin = 0.0;
03028 G4double ek1 = 0.0;
03029 G4int npions = 0;
03030 if( atomicWeight >= 1.5 )
03031 {
03032
03033
03034 const G4double alem[] = { 1.40, 2.30, 2.70, 3.00, 3.40, 4.60, 7.00 };
03035 const G4double val0[] = { 0.00, 0.40, 0.48, 0.51, 0.54, 0.60, 0.65 };
03036 alekw = std::log( originalIncident->GetKineticEnergy()/GeV );
03037 exh = 1.0;
03038 if( alekw > alem[0] )
03039 {
03040 exh = val0[6];
03041 for( G4int j=1; j<7; ++j )
03042 {
03043 if( alekw < alem[j] )
03044 {
03045 G4double rcnve = (val0[j] - val0[j-1]) / (alem[j] - alem[j-1]);
03046 exh = rcnve * alekw + val0[j-1] - rcnve * alem[j-1];
03047 break;
03048 }
03049 }
03050 exh = 1.0 - exh;
03051 }
03052 const G4double cfa = 0.025*((atomicWeight-1.)/120.)*std::exp(-(atomicWeight-1.)/120.);
03053 ekin = currentParticle.GetKineticEnergy()/GeV - cfa*(1+normal()/2.0);
03054 ekin = std::max( 1.0e-6, ekin );
03055 xxh = 1.0;
03056
03057
03058
03059
03060 dekin += ekin*(1.0-xxh);
03061 ekin *= xxh;
03062
03063
03064
03065
03066
03067
03068
03069 currentParticle.SetKineticEnergy( ekin*GeV );
03070 pp = currentParticle.GetTotalMomentum()/MeV;
03071 pp1 = currentParticle.GetMomentum().mag()/MeV;
03072 if( pp1 < 0.001*MeV )
03073 {
03074 rthnve = pi*G4UniformRand();
03075 phinve = twopi*G4UniformRand();
03076 currentParticle.SetMomentum( pp*std::sin(rthnve)*std::cos(phinve)*MeV,
03077 pp*std::sin(rthnve)*std::sin(phinve)*MeV,
03078 pp*std::cos(rthnve)*MeV );
03079 }
03080 else
03081 currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
03082 ekin = targetParticle.GetKineticEnergy()/GeV - cfa*(1+normal()/2.0);
03083 ekin = std::max( 1.0e-6, ekin );
03084 xxh = 1.0;
03085 if( ( (modifiedOriginal.GetDefinition() == aPiPlus) ||
03086 (modifiedOriginal.GetDefinition() == aPiMinus) ) &&
03087 (targetParticle.GetDefinition() == aPiZero) &&
03088 (G4UniformRand() < logWeight) )xxh = exh;
03089 dekin += ekin*(1.0-xxh);
03090 ekin *= xxh;
03091 if( (targetParticle.GetDefinition() == aPiPlus) ||
03092 (targetParticle.GetDefinition() == aPiZero) ||
03093 (targetParticle.GetDefinition() == aPiMinus) )
03094 {
03095 ++npions;
03096 ek1 += ekin;
03097 }
03098 targetParticle.SetKineticEnergy( ekin*GeV );
03099 pp = targetParticle.GetTotalMomentum()/MeV;
03100 pp1 = targetParticle.GetMomentum().mag()/MeV;
03101 if( pp1 < 0.001*MeV )
03102 {
03103 rthnve = pi*G4UniformRand();
03104 phinve = twopi*G4UniformRand();
03105 targetParticle.SetMomentum( pp*std::sin(rthnve)*std::cos(phinve)*MeV,
03106 pp*std::sin(rthnve)*std::sin(phinve)*MeV,
03107 pp*std::cos(rthnve)*MeV );
03108 }
03109 else
03110 targetParticle.SetMomentum( targetParticle.GetMomentum() * (pp/pp1) );
03111 for( i=0; i<vecLen; ++i )
03112 {
03113 ekin = vec[i]->GetKineticEnergy()/GeV - cfa*(1+normal()/2.0);
03114 ekin = std::max( 1.0e-6, ekin );
03115 xxh = 1.0;
03116 if( ( (modifiedOriginal.GetDefinition() == aPiPlus) ||
03117 (modifiedOriginal.GetDefinition() == aPiMinus) ) &&
03118 (vec[i]->GetDefinition() == aPiZero) &&
03119 (G4UniformRand() < logWeight) )xxh = exh;
03120 dekin += ekin*(1.0-xxh);
03121 ekin *= xxh;
03122 if( (vec[i]->GetDefinition() == aPiPlus) ||
03123 (vec[i]->GetDefinition() == aPiZero) ||
03124 (vec[i]->GetDefinition() == aPiMinus) )
03125 {
03126 ++npions;
03127 ek1 += ekin;
03128 }
03129 vec[i]->SetKineticEnergy( ekin*GeV );
03130 pp = vec[i]->GetTotalMomentum()/MeV;
03131 pp1 = vec[i]->GetMomentum().mag()/MeV;
03132 if( pp1 < 0.001*MeV )
03133 {
03134 rthnve = pi*G4UniformRand();
03135 phinve = twopi*G4UniformRand();
03136 vec[i]->SetMomentum( pp*std::sin(rthnve)*std::cos(phinve)*MeV,
03137 pp*std::sin(rthnve)*std::sin(phinve)*MeV,
03138 pp*std::cos(rthnve)*MeV );
03139 }
03140 else
03141 vec[i]->SetMomentum( vec[i]->GetMomentum() * (pp/pp1) );
03142 }
03143 }
03144 if( (ek1 != 0.0) && (npions > 0) )
03145 {
03146 dekin = 1.0 + dekin/ek1;
03147
03148
03149
03150 if( (currentParticle.GetDefinition() == aPiPlus) ||
03151 (currentParticle.GetDefinition() == aPiZero) ||
03152 (currentParticle.GetDefinition() == aPiMinus) )
03153 {
03154 currentParticle.SetKineticEnergy(
03155 std::max( 0.001*MeV, dekin*currentParticle.GetKineticEnergy() ) );
03156 pp = currentParticle.GetTotalMomentum()/MeV;
03157 pp1 = currentParticle.GetMomentum().mag()/MeV;
03158 if( pp1 < 0.001 )
03159 {
03160 rthnve = pi*G4UniformRand();
03161 phinve = twopi*G4UniformRand();
03162 currentParticle.SetMomentum( pp*std::sin(rthnve)*std::cos(phinve)*MeV,
03163 pp*std::sin(rthnve)*std::sin(phinve)*MeV,
03164 pp*std::cos(rthnve)*MeV );
03165 }
03166 else
03167 currentParticle.SetMomentum( currentParticle.GetMomentum() * (pp/pp1) );
03168 }
03169
03170
03171
03172
03173
03174
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186
03187
03188 for( i=0; i<vecLen; ++i )
03189 {
03190 if( (vec[i]->GetDefinition() == aPiPlus) ||
03191 (vec[i]->GetDefinition() == aPiZero) ||
03192 (vec[i]->GetDefinition() == aPiMinus) )
03193 {
03194 vec[i]->SetKineticEnergy( std::max( 0.001*MeV, dekin*vec[i]->GetKineticEnergy() ) );
03195 pp = vec[i]->GetTotalMomentum()/MeV;
03196 pp1 = vec[i]->GetMomentum().mag()/MeV;
03197 if( pp1 < 0.001 )
03198 {
03199 rthnve = pi*G4UniformRand();
03200 phinve = twopi*G4UniformRand();
03201 vec[i]->SetMomentum( pp*std::sin(rthnve)*std::cos(phinve)*MeV,
03202 pp*std::sin(rthnve)*std::sin(phinve)*MeV,
03203 pp*std::cos(rthnve)*MeV );
03204 }
03205 else
03206 vec[i]->SetMomentum( vec[i]->GetMomentum() * (pp/pp1) );
03207 }
03208 }
03209 }
03210 }
03211
03212 void FullModelReactionDynamics::AddBlackTrackParticles(
03213 const G4double epnb,
03214 const G4int npnb,
03215 const G4double edta,
03216 const G4int ndta,
03217 const G4double sprob,
03218 const G4double kineticMinimum,
03219 const G4double kineticFactor,
03220 const G4ReactionProduct &modifiedOriginal,
03221 G4double spall,
03222 const G4Nucleus &targetNucleus,
03223 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> &vec,
03224 G4int &vecLen )
03225 {
03226
03227
03228
03229
03230
03231
03232
03233
03234 G4ParticleDefinition *aProton = G4Proton::Proton();
03235 G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
03236 G4ParticleDefinition *aDeuteron = G4Deuteron::Deuteron();
03237 G4ParticleDefinition *aTriton = G4Triton::Triton();
03238 G4ParticleDefinition *anAlpha = G4Alpha::Alpha();
03239
03240 const G4double ekOriginal = modifiedOriginal.GetKineticEnergy()/MeV;
03241 const G4double atomicWeight = targetNucleus.GetN();
03242 const G4double atomicNumber = targetNucleus.GetZ();
03243
03244 const G4double ika1 = 3.6;
03245 const G4double ika2 = 35.56;
03246 const G4double ika3 = 6.45;
03247 const G4double sp1 = 1.066;
03248
03249 G4int i;
03250 G4double pp;
03251
03252 G4double kinCreated = 0;
03253 G4double cfa = 0.025*((atomicWeight-1.0)/120.0) * std::exp(-(atomicWeight-1.0)/120.0);
03254 if( npnb > 0)
03255 {
03256 G4double backwardKinetic = 0.0;
03257 G4int local_npnb = npnb;
03258 for( i=0; i<npnb; ++i ) if( G4UniformRand() < sprob ) local_npnb--;
03259 G4double ekin = epnb/local_npnb;
03260
03261 for( i=0; i<local_npnb; ++i )
03262 {
03263 G4ReactionProduct * p1 = new G4ReactionProduct();
03264 if( backwardKinetic > epnb )
03265 {
03266 delete p1;
03267 break;
03268 }
03269 G4double ran = G4UniformRand();
03270 G4double kinetic = -ekin*std::log(ran) - cfa*(1.0+0.5*normal());
03271 if( kinetic < 0.0 )kinetic = -0.010*std::log(ran);
03272 backwardKinetic += kinetic;
03273 if( backwardKinetic > epnb )
03274 kinetic = std::max( kineticMinimum, epnb-(backwardKinetic-kinetic) );
03275 if( G4UniformRand() > (1.0-atomicNumber/atomicWeight) )
03276 p1->SetDefinition( aProton );
03277 else
03278 p1->SetDefinition( aNeutron );
03279 vec.SetElement( vecLen, p1 );
03280 ++spall;
03281 G4double cost = G4UniformRand() * 2.0 - 1.0;
03282 G4double sint = std::sqrt(std::fabs(1.0-cost*cost));
03283 G4double phi = twopi * G4UniformRand();
03284 vec[vecLen]->SetNewlyAdded( true );
03285 vec[vecLen]->SetKineticEnergy( kinetic*GeV );
03286 kinCreated+=kinetic;
03287 pp = vec[vecLen]->GetTotalMomentum()/MeV;
03288 vec[vecLen]->SetMomentum( pp*sint*std::sin(phi)*MeV,
03289 pp*sint*std::cos(phi)*MeV,
03290 pp*cost*MeV );
03291 vecLen++;
03292
03293 }
03294 if( (atomicWeight >= 10.0) && (ekOriginal <= 2.0*GeV) )
03295 {
03296 G4double ekw = ekOriginal/GeV;
03297 G4int ika, kk = 0;
03298 if( ekw > 1.0 )ekw *= ekw;
03299 ekw = std::max( 0.1, ekw );
03300 ika = G4int(ika1*std::exp((atomicNumber*atomicNumber/atomicWeight-ika2)/ika3)/ekw);
03301 if( ika > 0 )
03302 {
03303 for( i=(vecLen-1); i>=0; --i )
03304 {
03305 if( (vec[i]->GetDefinition() == aProton) && vec[i]->GetNewlyAdded() )
03306 {
03307 vec[i]->SetDefinitionAndUpdateE( aNeutron );
03308 if( ++kk > ika )break;
03309 }
03310 }
03311 }
03312 }
03313 }
03314 if( ndta > 0 )
03315 {
03316 G4double backwardKinetic = 0.0;
03317 G4int local_ndta=ndta;
03318 for( i=0; i<ndta; ++i )if( G4UniformRand() < sprob )local_ndta--;
03319 G4double ekin = edta/local_ndta;
03320
03321 for( i=0; i<local_ndta; ++i )
03322 {
03323 G4ReactionProduct *p2 = new G4ReactionProduct();
03324 if( backwardKinetic > edta )
03325 {
03326 delete p2;
03327 break;
03328 }
03329 G4double ran = G4UniformRand();
03330 G4double kinetic = -ekin*std::log(ran)-cfa*(1.+0.5*normal());
03331 if( kinetic < 0.0 )kinetic = kineticFactor*std::log(ran);
03332 backwardKinetic += kinetic;
03333 if( backwardKinetic > edta )kinetic = edta-(backwardKinetic-kinetic);
03334 if( kinetic < 0.0 )kinetic = kineticMinimum;
03335 G4double cost = 2.0*G4UniformRand() - 1.0;
03336 G4double sint = std::sqrt(std::max(0.0,(1.0-cost*cost)));
03337 G4double phi = twopi*G4UniformRand();
03338 ran = G4UniformRand();
03339 if( ran <= 0.60 )
03340 p2->SetDefinition( aDeuteron );
03341 else if( ran <= 0.90 )
03342 p2->SetDefinition( aTriton );
03343 else
03344 p2->SetDefinition( anAlpha );
03345 spall += p2->GetMass()/GeV * sp1;
03346 if( spall > atomicWeight )
03347 {
03348 delete p2;
03349 break;
03350 }
03351 vec.SetElement( vecLen, p2 );
03352 vec[vecLen]->SetNewlyAdded( true );
03353 vec[vecLen]->SetKineticEnergy( kinetic*GeV );
03354 kinCreated+=kinetic;
03355 pp = vec[vecLen]->GetTotalMomentum()/MeV;
03356 vec[vecLen++]->SetMomentum( pp*sint*std::sin(phi)*MeV,
03357 pp*sint*std::cos(phi)*MeV,
03358 pp*cost*MeV );
03359
03360 }
03361 }
03362
03363 }
03364
03365 void FullModelReactionDynamics::MomentumCheck(
03366 const G4ReactionProduct &modifiedOriginal,
03367 G4ReactionProduct ¤tParticle,
03368 G4ReactionProduct &targetParticle,
03369 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> &vec,
03370 G4int &vecLen )
03371 {
03372 const G4double pOriginal = modifiedOriginal.GetTotalMomentum()/MeV;
03373 G4double testMomentum = currentParticle.GetMomentum().mag()/MeV;
03374 G4double pMass;
03375 if( testMomentum >= pOriginal )
03376 {
03377 pMass = currentParticle.GetMass()/MeV;
03378 currentParticle.SetTotalEnergy(
03379 std::sqrt( pMass*pMass + pOriginal*pOriginal )*MeV );
03380 currentParticle.SetMomentum(
03381 currentParticle.GetMomentum() * (pOriginal/testMomentum) );
03382 }
03383 testMomentum = targetParticle.GetMomentum().mag()/MeV;
03384 if( testMomentum >= pOriginal )
03385 {
03386 pMass = targetParticle.GetMass()/MeV;
03387 targetParticle.SetTotalEnergy(
03388 std::sqrt( pMass*pMass + pOriginal*pOriginal )*MeV );
03389 targetParticle.SetMomentum(
03390 targetParticle.GetMomentum() * (pOriginal/testMomentum) );
03391 }
03392 for( G4int i=0; i<vecLen; ++i )
03393 {
03394 testMomentum = vec[i]->GetMomentum().mag()/MeV;
03395 if( testMomentum >= pOriginal )
03396 {
03397 pMass = vec[i]->GetMass()/MeV;
03398 vec[i]->SetTotalEnergy(
03399 std::sqrt( pMass*pMass + pOriginal*pOriginal )*MeV );
03400 vec[i]->SetMomentum( vec[i]->GetMomentum() * (pOriginal/testMomentum) );
03401 }
03402 }
03403 }
03404
03405 void FullModelReactionDynamics::ProduceStrangeParticlePairs(
03406 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> &vec,
03407 G4int &vecLen,
03408 const G4ReactionProduct &modifiedOriginal,
03409 const G4DynamicParticle *originalTarget,
03410 G4ReactionProduct ¤tParticle,
03411 G4ReactionProduct &targetParticle,
03412 G4bool &incidentHasChanged,
03413 G4bool &targetHasChanged )
03414 {
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424 if( vecLen == 0 )return;
03425
03426
03427
03428 if( currentParticle.GetMass() == 0.0 || targetParticle.GetMass() == 0.0 )return;
03429
03430 const G4double etOriginal = modifiedOriginal.GetTotalEnergy()/GeV;
03431 const G4double mOriginal = modifiedOriginal.GetDefinition()->GetPDGMass()/GeV;
03432 G4double targetMass = originalTarget->GetDefinition()->GetPDGMass()/GeV;
03433 G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
03434 targetMass*targetMass +
03435 2.0*targetMass*etOriginal );
03436 G4double currentMass = currentParticle.GetMass()/GeV;
03437 G4double availableEnergy = centerofmassEnergy-(targetMass+currentMass);
03438 if( availableEnergy <= 1.0 )return;
03439
03440 G4ParticleDefinition *aProton = G4Proton::Proton();
03441 G4ParticleDefinition *anAntiProton = G4AntiProton::AntiProton();
03442 G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
03443 G4ParticleDefinition *anAntiNeutron = G4AntiNeutron::AntiNeutron();
03444 G4ParticleDefinition *aSigmaMinus = G4SigmaMinus::SigmaMinus();
03445 G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
03446 G4ParticleDefinition *aSigmaZero = G4SigmaZero::SigmaZero();
03447 G4ParticleDefinition *anAntiSigmaMinus = G4AntiSigmaMinus::AntiSigmaMinus();
03448 G4ParticleDefinition *anAntiSigmaPlus = G4AntiSigmaPlus::AntiSigmaPlus();
03449 G4ParticleDefinition *anAntiSigmaZero = G4AntiSigmaZero::AntiSigmaZero();
03450 G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
03451 G4ParticleDefinition *aKaonPlus = G4KaonPlus::KaonPlus();
03452 G4ParticleDefinition *aKaonZL = G4KaonZeroLong::KaonZeroLong();
03453 G4ParticleDefinition *aKaonZS = G4KaonZeroShort::KaonZeroShort();
03454 G4ParticleDefinition *aLambda = G4Lambda::Lambda();
03455 G4ParticleDefinition *anAntiLambda = G4AntiLambda::AntiLambda();
03456
03457 const G4double protonMass = aProton->GetPDGMass()/GeV;
03458 const G4double sigmaMinusMass = aSigmaMinus->GetPDGMass()/GeV;
03459
03460
03461
03462 const G4double avrs[] = {3.,4.,5.,6.,7.,8.,9.,10.,20.,30.,40.,50.};
03463
03464 G4int ibin, i3, i4;
03465 G4double avk, avy, avn, ran;
03466 G4int i = 1;
03467 while( (i<12) && (centerofmassEnergy>avrs[i]) )++i;
03468 if( i == 12 )
03469 ibin = 11;
03470 else
03471 ibin = i;
03472
03473
03474
03475
03476 if( vecLen == 1 )
03477 {
03478 i3 = 0;
03479 i4 = 1;
03480 }
03481 else
03482 {
03483 G4double ran = G4UniformRand();
03484 while( ran == 1.0 )ran = G4UniformRand();
03485 i4 = i3 = G4int( vecLen*ran );
03486 while( i3 == i4 )
03487 {
03488 ran = G4UniformRand();
03489 while( ran == 1.0 )ran = G4UniformRand();
03490 i4 = G4int( vecLen*ran );
03491 }
03492 }
03493
03494
03495
03496 const G4double avkkb[] = { 0.0015, 0.005, 0.012, 0.0285, 0.0525, 0.075,
03497 0.0975, 0.123, 0.28, 0.398, 0.495, 0.573 };
03498 const G4double avky[] = { 0.005, 0.03, 0.064, 0.095, 0.115, 0.13,
03499 0.145, 0.155, 0.20, 0.205, 0.210, 0.212 };
03500 const G4double avnnb[] = { 0.00001, 0.0001, 0.0006, 0.0025, 0.01, 0.02,
03501 0.04, 0.05, 0.12, 0.15, 0.18, 0.20 };
03502
03503 avk = (std::log(avkkb[ibin])-std::log(avkkb[ibin-1]))*(centerofmassEnergy-avrs[ibin-1])
03504 /(avrs[ibin]-avrs[ibin-1]) + std::log(avkkb[ibin-1]);
03505 avk = std::exp(avk);
03506
03507 avy = (std::log(avky[ibin])-std::log(avky[ibin-1]))*(centerofmassEnergy-avrs[ibin-1])
03508 /(avrs[ibin]-avrs[ibin-1]) + std::log(avky[ibin-1]);
03509 avy = std::exp(avy);
03510
03511 avn = (std::log(avnnb[ibin])-std::log(avnnb[ibin-1]))*(centerofmassEnergy-avrs[ibin-1])
03512 /(avrs[ibin]-avrs[ibin-1]) + std::log(avnnb[ibin-1]);
03513 avn = std::exp(avn);
03514
03515 if( avk+avy+avn <= 0.0 )return;
03516
03517 if( currentMass < protonMass )avy /= 2.0;
03518 if( targetMass < protonMass )avy = 0.0;
03519 avy += avk+avn;
03520 avk += avn;
03521 ran = G4UniformRand();
03522 if( ran < avn )
03523 {
03524 if( availableEnergy < 2.0 )return;
03525 if( vecLen == 1 )
03526 {
03527 G4ReactionProduct *p1 = new G4ReactionProduct;
03528 if( G4UniformRand() < 0.5 )
03529 {
03530 vec[0]->SetDefinition( aNeutron );
03531 p1->SetDefinition( anAntiNeutron );
03532 (G4UniformRand() < 0.5) ? p1->SetSide( -1 ) : p1->SetSide( 1 );
03533 vec[0]->SetMayBeKilled(false);
03534 p1->SetMayBeKilled(false);
03535 }
03536 else
03537 {
03538 vec[0]->SetDefinition( aProton );
03539 p1->SetDefinition( anAntiProton );
03540 (G4UniformRand() < 0.5) ? p1->SetSide( -1 ) : p1->SetSide( 1 );
03541 vec[0]->SetMayBeKilled(false);
03542 p1->SetMayBeKilled(false);
03543 }
03544 vec.SetElement( vecLen++, p1 );
03545
03546 }
03547 else
03548 {
03549 if( G4UniformRand() < 0.5 )
03550 {
03551 vec[i3]->SetDefinition( aNeutron );
03552 vec[i4]->SetDefinition( anAntiNeutron );
03553 vec[i3]->SetMayBeKilled(false);
03554 vec[i4]->SetMayBeKilled(false);
03555 }
03556 else
03557 {
03558 vec[i3]->SetDefinition( aProton );
03559 vec[i4]->SetDefinition( anAntiProton );
03560 vec[i3]->SetMayBeKilled(false);
03561 vec[i4]->SetMayBeKilled(false);
03562 }
03563 }
03564 }
03565 else if( ran < avk )
03566 {
03567 if( availableEnergy < 1.0 )return;
03568
03569 const G4double kkb[] = { 0.2500, 0.3750, 0.5000, 0.5625, 0.6250,
03570 0.6875, 0.7500, 0.8750, 1.000 };
03571 const G4int ipakkb1[] = { 10, 10, 10, 11, 11, 12, 12, 11, 12 };
03572 const G4int ipakkb2[] = { 13, 11, 12, 11, 12, 11, 12, 13, 13 };
03573 ran = G4UniformRand();
03574 i = 0;
03575 while( (i<9) && (ran>=kkb[i]) )++i;
03576 if( i == 9 )return;
03577
03578
03579
03580
03581 switch( ipakkb1[i] )
03582 {
03583 case 10:
03584 vec[i3]->SetDefinition( aKaonPlus );
03585 vec[i3]->SetMayBeKilled(false);
03586 break;
03587 case 11:
03588 vec[i3]->SetDefinition( aKaonZS );
03589 vec[i3]->SetMayBeKilled(false);
03590 break;
03591 case 12:
03592 vec[i3]->SetDefinition( aKaonZL );
03593 vec[i3]->SetMayBeKilled(false);
03594 break;
03595 }
03596 if( vecLen == 1 )
03597 {
03598 G4ReactionProduct *p1 = new G4ReactionProduct;
03599 switch( ipakkb2[i] )
03600 {
03601 case 11:
03602 p1->SetDefinition( aKaonZS );
03603 p1->SetMayBeKilled(false);
03604 break;
03605 case 12:
03606 p1->SetDefinition( aKaonZL );
03607 p1->SetMayBeKilled(false);
03608 break;
03609 case 13:
03610 p1->SetDefinition( aKaonMinus );
03611 p1->SetMayBeKilled(false);
03612 break;
03613 }
03614 (G4UniformRand() < 0.5) ? p1->SetSide( -1 ) : p1->SetSide( 1 );
03615 vec.SetElement( vecLen++, p1 );
03616
03617 }
03618 else
03619 {
03620 switch( ipakkb2[i] )
03621 {
03622 case 11:
03623 vec[i4]->SetDefinition( aKaonZS );
03624 vec[i4]->SetMayBeKilled(false);
03625 break;
03626 case 12:
03627 vec[i4]->SetDefinition( aKaonZL );
03628 vec[i4]->SetMayBeKilled(false);
03629 break;
03630 case 13:
03631 vec[i4]->SetDefinition( aKaonMinus );
03632 vec[i4]->SetMayBeKilled(false);
03633 break;
03634 }
03635 }
03636 }
03637 else if( ran < avy )
03638 {
03639 if( availableEnergy < 1.6 )return;
03640
03641 const G4double ky[] = { 0.200, 0.300, 0.400, 0.550, 0.625, 0.700,
03642 0.800, 0.850, 0.900, 0.950, 0.975, 1.000 };
03643 const G4int ipaky1[] = { 18, 18, 18, 20, 20, 20, 21, 21, 21, 22, 22, 22 };
03644 const G4int ipaky2[] = { 10, 11, 12, 10, 11, 12, 10, 11, 12, 10, 11, 12 };
03645 const G4int ipakyb1[] = { 19, 19, 19, 23, 23, 23, 24, 24, 24, 25, 25, 25 };
03646 const G4int ipakyb2[] = { 13, 12, 11, 13, 12, 11, 13, 12, 11, 13, 12, 11 };
03647 ran = G4UniformRand();
03648 i = 0;
03649 while( (i<12) && (ran>ky[i]) )++i;
03650 if( i == 12 )return;
03651 if( (currentMass<protonMass) || (G4UniformRand()<0.5) )
03652 {
03653
03654
03655
03656
03657
03658 switch( ipaky1[i] )
03659 {
03660 case 18:
03661 targetParticle.SetDefinition( aLambda );
03662 break;
03663 case 20:
03664 targetParticle.SetDefinition( aSigmaPlus );
03665 break;
03666 case 21:
03667 targetParticle.SetDefinition( aSigmaZero );
03668 break;
03669 case 22:
03670 targetParticle.SetDefinition( aSigmaMinus );
03671 break;
03672 }
03673 targetHasChanged = true;
03674 switch( ipaky2[i] )
03675 {
03676 case 10:
03677 vec[i3]->SetDefinition( aKaonPlus );
03678 vec[i3]->SetMayBeKilled(false);
03679 break;
03680 case 11:
03681 vec[i3]->SetDefinition( aKaonZS );
03682 vec[i3]->SetMayBeKilled(false);
03683 break;
03684 case 12:
03685 vec[i3]->SetDefinition( aKaonZL );
03686 vec[i3]->SetMayBeKilled(false);
03687 break;
03688 }
03689 }
03690 else
03691 {
03692
03693
03694 if( (currentParticle.GetDefinition() == anAntiProton) ||
03695 (currentParticle.GetDefinition() == anAntiNeutron) ||
03696 (currentParticle.GetDefinition() == anAntiLambda) ||
03697 (currentMass > sigmaMinusMass) )
03698 {
03699 switch( ipakyb1[i] )
03700 {
03701 case 19:
03702 currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
03703 break;
03704 case 23:
03705 currentParticle.SetDefinitionAndUpdateE( anAntiSigmaPlus );
03706 break;
03707 case 24:
03708 currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
03709 break;
03710 case 25:
03711 currentParticle.SetDefinitionAndUpdateE( anAntiSigmaMinus );
03712 break;
03713 }
03714 incidentHasChanged = true;
03715 switch( ipakyb2[i] )
03716 {
03717 case 11:
03718 vec[i3]->SetDefinition( aKaonZS );
03719 vec[i3]->SetMayBeKilled(false);
03720 break;
03721 case 12:
03722 vec[i3]->SetDefinition( aKaonZL );
03723 vec[i3]->SetMayBeKilled(false);
03724 break;
03725 case 13:
03726 vec[i3]->SetDefinition( aKaonMinus );
03727 vec[i3]->SetMayBeKilled(false);
03728 break;
03729 }
03730 }
03731 else
03732 {
03733 switch( ipaky1[i] )
03734 {
03735 case 18:
03736 currentParticle.SetDefinitionAndUpdateE( aLambda );
03737 break;
03738 case 20:
03739 currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
03740 break;
03741 case 21:
03742 currentParticle.SetDefinitionAndUpdateE( aSigmaZero );
03743 break;
03744 case 22:
03745 currentParticle.SetDefinitionAndUpdateE( aSigmaMinus );
03746 break;
03747 }
03748 incidentHasChanged = true;
03749 switch( ipaky2[i] )
03750 {
03751 case 10:
03752 vec[i3]->SetDefinition( aKaonPlus );
03753 vec[i3]->SetMayBeKilled(false);
03754 break;
03755 case 11:
03756 vec[i3]->SetDefinition( aKaonZS );
03757 vec[i3]->SetMayBeKilled(false);
03758 break;
03759 case 12:
03760 vec[i3]->SetDefinition( aKaonZL );
03761 vec[i3]->SetMayBeKilled(false);
03762 break;
03763 }
03764 }
03765 }
03766 }
03767 else return;
03768
03769
03770
03771
03772
03773
03774
03775
03776
03777 currentMass = currentParticle.GetMass()/GeV;
03778 targetMass = targetParticle.GetMass()/GeV;
03779
03780 G4double energyCheck = centerofmassEnergy-(currentMass+targetMass);
03781 for( i=0; i<vecLen; ++i )
03782 {
03783 energyCheck -= vec[i]->GetMass()/GeV;
03784 if( energyCheck < 0.0 )
03785 {
03786 vecLen = std::max( 0, --i );
03787 G4int j;
03788 for(j=i; j<vecLen; j++) delete vec[j];
03789 break;
03790 }
03791 }
03792 return;
03793 }
03794
03795 void
03796 FullModelReactionDynamics::NuclearReaction(
03797 G4FastVector<G4ReactionProduct,4> &vec,
03798 G4int &vecLen,
03799 const G4HadProjectile *originalIncident,
03800 const G4Nucleus &targetNucleus,
03801 const G4double theAtomicMass,
03802 const G4double *mass )
03803 {
03804
03805
03806
03807
03808 G4ParticleDefinition *aGamma = G4Gamma::Gamma();
03809 G4ParticleDefinition *aProton = G4Proton::Proton();
03810 G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
03811 G4ParticleDefinition *aDeuteron = G4Deuteron::Deuteron();
03812 G4ParticleDefinition *aTriton = G4Triton::Triton();
03813 G4ParticleDefinition *anAlpha = G4Alpha::Alpha();
03814
03815 const G4double aProtonMass = aProton->GetPDGMass()/MeV;
03816 const G4double aNeutronMass = aNeutron->GetPDGMass()/MeV;
03817 const G4double aDeuteronMass = aDeuteron->GetPDGMass()/MeV;
03818 const G4double aTritonMass = aTriton->GetPDGMass()/MeV;
03819 const G4double anAlphaMass = anAlpha->GetPDGMass()/MeV;
03820
03821 G4ReactionProduct currentParticle;
03822 currentParticle = *originalIncident;
03823
03824
03825
03826
03827
03828 G4double p = currentParticle.GetTotalMomentum();
03829 G4double pp = currentParticle.GetMomentum().mag();
03830 if( pp <= 0.001*MeV )
03831 {
03832 G4double phinve = twopi*G4UniformRand();
03833 G4double rthnve = std::acos( std::max( -1.0, std::min( 1.0, -1.0 + 2.0*G4UniformRand() ) ) );
03834 currentParticle.SetMomentum( p*std::sin(rthnve)*std::cos(phinve),
03835 p*std::sin(rthnve)*std::sin(phinve),
03836 p*std::cos(rthnve) );
03837 }
03838 else
03839 currentParticle.SetMomentum( currentParticle.GetMomentum() * (p/pp) );
03840
03841
03842
03843 G4double currentKinetic = currentParticle.GetKineticEnergy()/MeV;
03844 G4double currentMass = currentParticle.GetDefinition()->GetPDGMass()/MeV;
03845 G4double qv = currentKinetic + theAtomicMass + currentMass;
03846
03847 G4double qval[9];
03848 qval[0] = qv - mass[0];
03849 qval[1] = qv - mass[1] - aNeutronMass;
03850 qval[2] = qv - mass[2] - aProtonMass;
03851 qval[3] = qv - mass[3] - aDeuteronMass;
03852 qval[4] = qv - mass[4] - aTritonMass;
03853 qval[5] = qv - mass[5] - anAlphaMass;
03854 qval[6] = qv - mass[6] - aNeutronMass - aNeutronMass;
03855 qval[7] = qv - mass[7] - aNeutronMass - aProtonMass;
03856 qval[8] = qv - mass[8] - aProtonMass - aProtonMass;
03857
03858 if( currentParticle.GetDefinition() == aNeutron )
03859 {
03860 const G4double A = targetNucleus.GetN();
03861 if( G4UniformRand() > ((A-1.0)/230.0)*((A-1.0)/230.0) )
03862 qval[0] = 0.0;
03863 if( G4UniformRand() >= currentKinetic/7.9254*A )
03864 qval[2] = qval[3] = qval[4] = qval[5] = qval[8] = 0.0;
03865 }
03866 else
03867 qval[0] = 0.0;
03868
03869 G4int i;
03870 qv = 0.0;
03871 for( i=0; i<9; ++i )
03872 {
03873 if( mass[i] < 500.0*MeV )qval[i] = 0.0;
03874 if( qval[i] < 0.0 )qval[i] = 0.0;
03875 qv += qval[i];
03876 }
03877 G4double qv1 = 0.0;
03878 G4double ran = G4UniformRand();
03879 G4int index;
03880 for( index=0; index<9; ++index )
03881 {
03882 if( qval[index] > 0.0 )
03883 {
03884 qv1 += qval[index]/qv;
03885 if( ran <= qv1 )break;
03886 }
03887 }
03888 if( index == 9 )
03889 {
03890 throw G4HadronicException(__FILE__, __LINE__,
03891 "FullModelReactionDynamics::NuclearReaction: inelastic reaction kinematically not possible");
03892 }
03893 G4double ke = currentParticle.GetKineticEnergy()/GeV;
03894 G4int nt = 2;
03895 if( (index>=6) || (G4UniformRand()<std::min(0.5,ke*10.0)) )nt = 3;
03896
03897 G4ReactionProduct **v = new G4ReactionProduct * [3];
03898 v[0] = new G4ReactionProduct;
03899 v[1] = new G4ReactionProduct;
03900 v[2] = new G4ReactionProduct;
03901
03902 v[0]->SetMass( mass[index]*MeV );
03903 switch( index )
03904 {
03905 case 0:
03906 v[1]->SetDefinition( aGamma );
03907 v[2]->SetDefinition( aGamma );
03908 break;
03909 case 1:
03910 v[1]->SetDefinition( aNeutron );
03911 v[2]->SetDefinition( aGamma );
03912 break;
03913 case 2:
03914 v[1]->SetDefinition( aProton );
03915 v[2]->SetDefinition( aGamma );
03916 break;
03917 case 3:
03918 v[1]->SetDefinition( aDeuteron );
03919 v[2]->SetDefinition( aGamma );
03920 break;
03921 case 4:
03922 v[1]->SetDefinition( aTriton );
03923 v[2]->SetDefinition( aGamma );
03924 break;
03925 case 5:
03926 v[1]->SetDefinition( anAlpha );
03927 v[2]->SetDefinition( aGamma );
03928 break;
03929 case 6:
03930 v[1]->SetDefinition( aNeutron );
03931 v[2]->SetDefinition( aNeutron );
03932 break;
03933 case 7:
03934 v[1]->SetDefinition( aNeutron );
03935 v[2]->SetDefinition( aProton );
03936 break;
03937 case 8:
03938 v[1]->SetDefinition( aProton );
03939 v[2]->SetDefinition( aProton );
03940 break;
03941 }
03942
03943
03944
03945 G4ReactionProduct pseudo1;
03946 pseudo1.SetMass( theAtomicMass*MeV );
03947 pseudo1.SetTotalEnergy( theAtomicMass*MeV );
03948 G4ReactionProduct pseudo2 = currentParticle + pseudo1;
03949 pseudo2.SetMomentum( pseudo2.GetMomentum() * (-1.0) );
03950
03951
03952
03953 G4FastVector<G4ReactionProduct,MYGHADLISTSIZE> tempV;
03954 tempV.Initialize( nt );
03955 G4int tempLen = 0;
03956 tempV.SetElement( tempLen++, v[0] );
03957 tempV.SetElement( tempLen++, v[1] );
03958 if( nt == 3 )tempV.SetElement( tempLen++, v[2] );
03959 G4bool constantCrossSection = true;
03960 GenerateNBodyEvent( pseudo2.GetMass()/MeV, constantCrossSection, tempV, tempLen );
03961 v[0]->Lorentz( *v[0], pseudo2 );
03962 v[1]->Lorentz( *v[1], pseudo2 );
03963 if( nt == 3 )v[2]->Lorentz( *v[2], pseudo2 );
03964
03965 G4bool particleIsDefined = false;
03966 if( v[0]->GetMass()/MeV - aProtonMass < 0.1 )
03967 {
03968 v[0]->SetDefinition( aProton );
03969 particleIsDefined = true;
03970 }
03971 else if( v[0]->GetMass()/MeV - aNeutronMass < 0.1 )
03972 {
03973 v[0]->SetDefinition( aNeutron );
03974 particleIsDefined = true;
03975 }
03976 else if( v[0]->GetMass()/MeV - aDeuteronMass < 0.1 )
03977 {
03978 v[0]->SetDefinition( aDeuteron );
03979 particleIsDefined = true;
03980 }
03981 else if( v[0]->GetMass()/MeV - aTritonMass < 0.1 )
03982 {
03983 v[0]->SetDefinition( aTriton );
03984 particleIsDefined = true;
03985 }
03986 else if( v[0]->GetMass()/MeV - anAlphaMass < 0.1 )
03987 {
03988 v[0]->SetDefinition( anAlpha );
03989 particleIsDefined = true;
03990 }
03991 currentParticle.SetKineticEnergy(
03992 std::max( 0.001, currentParticle.GetKineticEnergy()/MeV ) );
03993 p = currentParticle.GetTotalMomentum();
03994 pp = currentParticle.GetMomentum().mag();
03995 if( pp <= 0.001*MeV )
03996 {
03997 G4double phinve = twopi*G4UniformRand();
03998 G4double rthnve = std::acos( std::max( -1.0, std::min( 1.0, -1.0 + 2.0*G4UniformRand() ) ) );
03999 currentParticle.SetMomentum( p*std::sin(rthnve)*std::cos(phinve),
04000 p*std::sin(rthnve)*std::sin(phinve),
04001 p*std::cos(rthnve) );
04002 }
04003 else
04004 currentParticle.SetMomentum( currentParticle.GetMomentum() * (p/pp) );
04005
04006 if( particleIsDefined )
04007 {
04008 v[0]->SetKineticEnergy(
04009 std::max( 0.001, 0.5*G4UniformRand()*v[0]->GetKineticEnergy()/MeV ) );
04010 p = v[0]->GetTotalMomentum();
04011 pp = v[0]->GetMomentum().mag();
04012 if( pp <= 0.001*MeV )
04013 {
04014 G4double phinve = twopi*G4UniformRand();
04015 G4double rthnve = std::acos( std::max(-1.0,std::min(1.0,-1.0+2.0*G4UniformRand())) );
04016 v[0]->SetMomentum( p*std::sin(rthnve)*std::cos(phinve),
04017 p*std::sin(rthnve)*std::sin(phinve),
04018 p*std::cos(rthnve) );
04019 }
04020 else
04021 v[0]->SetMomentum( v[0]->GetMomentum() * (p/pp) );
04022 }
04023 if( (v[1]->GetDefinition() == aDeuteron) ||
04024 (v[1]->GetDefinition() == aTriton) ||
04025 (v[1]->GetDefinition() == anAlpha) )
04026 v[1]->SetKineticEnergy(
04027 std::max( 0.001, 0.5*G4UniformRand()*v[1]->GetKineticEnergy()/MeV ) );
04028 else
04029 v[1]->SetKineticEnergy( std::max( 0.001, v[1]->GetKineticEnergy()/MeV ) );
04030
04031 p = v[1]->GetTotalMomentum();
04032 pp = v[1]->GetMomentum().mag();
04033 if( pp <= 0.001*MeV )
04034 {
04035 G4double phinve = twopi*G4UniformRand();
04036 G4double rthnve = std::acos( std::max(-1.0,std::min(1.0,-1.0+2.0*G4UniformRand())) );
04037 v[1]->SetMomentum( p*std::sin(rthnve)*std::cos(phinve),
04038 p*std::sin(rthnve)*std::sin(phinve),
04039 p*std::cos(rthnve) );
04040 }
04041 else
04042 v[1]->SetMomentum( v[1]->GetMomentum() * (p/pp) );
04043
04044 if( nt == 3 )
04045 {
04046 if( (v[2]->GetDefinition() == aDeuteron) ||
04047 (v[2]->GetDefinition() == aTriton) ||
04048 (v[2]->GetDefinition() == anAlpha) )
04049 v[2]->SetKineticEnergy(
04050 std::max( 0.001, 0.5*G4UniformRand()*v[2]->GetKineticEnergy()/MeV ) );
04051 else
04052 v[2]->SetKineticEnergy( std::max( 0.001, v[2]->GetKineticEnergy()/MeV ) );
04053
04054 p = v[2]->GetTotalMomentum();
04055 pp = v[2]->GetMomentum().mag();
04056 if( pp <= 0.001*MeV )
04057 {
04058 G4double phinve = twopi*G4UniformRand();
04059 G4double rthnve = std::acos( std::max(-1.0,std::min(1.0,-1.0+2.0*G4UniformRand())) );
04060 v[2]->SetMomentum( p*std::sin(rthnve)*std::cos(phinve),
04061 p*std::sin(rthnve)*std::sin(phinve),
04062 p*std::cos(rthnve) );
04063 }
04064 else
04065 v[2]->SetMomentum( v[2]->GetMomentum() * (p/pp) );
04066 }
04067 G4int del;
04068 for(del=0; del<vecLen; del++) delete vec[del];
04069 vecLen = 0;
04070 if( particleIsDefined )
04071 {
04072 vec.SetElement( vecLen++, v[0] );
04073 }
04074 else
04075 {
04076 delete v[0];
04077 }
04078 vec.SetElement( vecLen++, v[1] );
04079 if( nt == 3 )
04080 {
04081 vec.SetElement( vecLen++, v[2] );
04082 }
04083 else
04084 {
04085 delete v[2];
04086 }
04087 delete [] v;
04088 return;
04089 }
04090
04091
04092