G4RPGAntiSigmaPlusInelastic.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 // $Id$
00027 //
00028  
00029 #include "G4RPGAntiSigmaPlusInelastic.hh"
00030 #include "G4PhysicalConstants.hh"
00031 #include "G4SystemOfUnits.hh"
00032 #include "Randomize.hh"
00033 
00034 G4HadFinalState*
00035 G4RPGAntiSigmaPlusInelastic::ApplyYourself( const G4HadProjectile &aTrack,
00036                                             G4Nucleus &targetNucleus )
00037 { 
00038   const G4HadProjectile *originalIncident = &aTrack;
00039   if (originalIncident->GetKineticEnergy()<= 0.1*MeV) 
00040   {
00041     theParticleChange.SetStatusChange(isAlive);
00042     theParticleChange.SetEnergyChange(aTrack.GetKineticEnergy());
00043     theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 
00044     return &theParticleChange;      
00045   }
00046 
00047   // Choose the target particle
00048 
00049   G4DynamicParticle *originalTarget = targetNucleus.ReturnTargetParticle();
00050     
00051   if( verboseLevel > 1 )
00052   {
00053     const G4Material *targetMaterial = aTrack.GetMaterial();
00054     G4cout << "G4RPGAntiSigmaPlusInelastic::ApplyYourself called" << G4endl;
00055     G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
00056     G4cout << "target material = " << targetMaterial->GetName() << ", ";
00057     G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
00058            << G4endl;
00059   }
00060 
00061   // Fermi motion and evaporation
00062   // As of Geant3, the Fermi energy calculation had not been Done
00063 
00064     G4double ek = originalIncident->GetKineticEnergy()/MeV;
00065     G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
00066     G4ReactionProduct modifiedOriginal;
00067     modifiedOriginal = *originalIncident;
00068     
00069     G4double tkin = targetNucleus.Cinema( ek );
00070     ek += tkin;
00071     modifiedOriginal.SetKineticEnergy( ek*MeV );
00072     G4double et = ek + amas;
00073     G4double p = std::sqrt( std::abs((et-amas)*(et+amas)) );
00074     G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
00075     if( pp > 0.0 )
00076     {
00077       G4ThreeVector momentum = modifiedOriginal.GetMomentum();
00078       modifiedOriginal.SetMomentum( momentum * (p/pp) );
00079     }
00080     //
00081     // calculate black track energies
00082     //
00083     tkin = targetNucleus.EvaporationEffects( ek );
00084     ek -= tkin;
00085     modifiedOriginal.SetKineticEnergy( ek*MeV );
00086     et = ek + amas;
00087     p = std::sqrt( std::abs((et-amas)*(et+amas)) );
00088     pp = modifiedOriginal.GetMomentum().mag()/MeV;
00089     if( pp > 0.0 )
00090     {
00091       G4ThreeVector momentum = modifiedOriginal.GetMomentum();
00092       modifiedOriginal.SetMomentum( momentum * (p/pp) );
00093     }
00094     G4ReactionProduct currentParticle = modifiedOriginal;
00095     G4ReactionProduct targetParticle;
00096     targetParticle = *originalTarget;
00097     currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
00098     targetParticle.SetSide( -1 );  // target always goes in backward hemisphere
00099     G4bool incidentHasChanged = false;
00100     G4bool targetHasChanged = false;
00101     G4bool quasiElastic = false;
00102     G4FastVector<G4ReactionProduct,GHADLISTSIZE> vec;  // vec will contain the secondary particles
00103     G4int vecLen = 0;
00104     vec.Initialize( 0 );
00105     
00106     const G4double cutOff = 0.1;
00107     const G4double anni = std::min( 1.3*currentParticle.GetTotalMomentum()/GeV, 0.4 );
00108     if( (currentParticle.GetKineticEnergy()/MeV > cutOff) || (G4UniformRand() > anni) )
00109       Cascade( vec, vecLen,
00110                originalIncident, currentParticle, targetParticle,
00111                incidentHasChanged, targetHasChanged, quasiElastic );
00112     
00113     CalculateMomenta( vec, vecLen,
00114                       originalIncident, originalTarget, modifiedOriginal,
00115                       targetNucleus, currentParticle, targetParticle,
00116                       incidentHasChanged, targetHasChanged, quasiElastic );
00117     
00118     SetUpChange( vec, vecLen,
00119                  currentParticle, targetParticle,
00120                  incidentHasChanged );
00121     
00122   delete originalTarget;
00123   return &theParticleChange;
00124 }
00125 
00126  
00127 void G4RPGAntiSigmaPlusInelastic::Cascade(
00128    G4FastVector<G4ReactionProduct,GHADLISTSIZE> &vec,
00129    G4int& vecLen,
00130    const G4HadProjectile *originalIncident,
00131    G4ReactionProduct &currentParticle,
00132    G4ReactionProduct &targetParticle,
00133    G4bool &incidentHasChanged,
00134    G4bool &targetHasChanged,
00135    G4bool &quasiElastic )
00136 {
00137   // Derived from H. Fesefeldt's original FORTRAN code CASASP
00138   // AntiSigmaPlus undergoes interaction with nucleon within a nucleus.  Check if it is
00139   // energetically possible to produce pions/kaons.  In not, assume nuclear excitation
00140   // occurs and input particle is degraded in energy. No other particles are produced.
00141   // If reaction is possible, find the correct number of pions/protons/neutrons
00142   // produced using an interpolation to multiplicity data.  Replace some pions or
00143   // protons/neutrons by kaons or strange baryons according to the average
00144   // multiplicity per Inelastic reaction.
00145 
00146   const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
00147   const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
00148   const G4double pOriginal = originalIncident->GetTotalMomentum()/MeV;
00149   const G4double targetMass = targetParticle.GetMass()/MeV;
00150   G4double centerofmassEnergy = std::sqrt( mOriginal*mOriginal +
00151                                       targetMass*targetMass +
00152                                       2.0*targetMass*etOriginal );
00153   G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
00154     
00155     static G4bool first = true;
00156     const G4int numMul = 1200;
00157     const G4int numMulA = 400;
00158     const G4int numSec = 60;
00159     static G4double protmul[numMul], protnorm[numSec]; // proton constants
00160     static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
00161     static G4double protmulA[numMulA], protnormA[numSec]; // proton constants
00162     static G4double neutmulA[numMulA], neutnormA[numSec]; // neutron constants
00163     // np = number of pi+, nneg = number of pi-, nz = number of pi0
00164     G4int counter, nt=0, np=0, nneg=0, nz=0;
00165     G4double test;
00166     const G4double c = 1.25;    
00167     const G4double b[] = { 0.7, 0.7 };
00168     if( first )       // compute normalization constants, this will only be Done once
00169     {
00170       first = false;
00171       G4int i;
00172       for( i=0; i<numMul; ++i )protmul[i] = 0.0;
00173       for( i=0; i<numSec; ++i )protnorm[i] = 0.0;
00174       counter = -1;
00175       for( np=0; np<(numSec/3); ++np )
00176       {
00177         for( nneg=std::max(0,np-1); nneg<=(np+1); ++nneg )
00178         {
00179           for( nz=0; nz<numSec/3; ++nz )
00180           {
00181             if( ++counter < numMul )
00182             {
00183               nt = np+nneg+nz;
00184               if( nt>0 && nt<=numSec )
00185               {
00186                 protmul[counter] = Pmltpc(np,nneg,nz,nt,b[0],c);
00187                 protnorm[nt-1] += protmul[counter];
00188               }
00189             }
00190           }
00191         }
00192       }
00193       for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
00194       for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
00195       counter = -1;
00196       for( np=0; np<numSec/3; ++np )
00197       {
00198         for( nneg=np; nneg<=(np+2); ++nneg )
00199         {
00200           for( nz=0; nz<numSec/3; ++nz )
00201           {
00202             if( ++counter < numMul )
00203             {
00204               nt = np+nneg+nz;
00205               if( nt>0 && nt<=numSec )
00206               {
00207                 neutmul[counter] = Pmltpc(np,nneg,nz,nt,b[1],c);
00208                 neutnorm[nt-1] += neutmul[counter];
00209               }
00210             }
00211           }
00212         }
00213       }
00214       for( i=0; i<numSec; ++i )
00215       {
00216         if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
00217         if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
00218       }
00219       //
00220       // do the same for annihilation channels
00221       //
00222       for( i=0; i<numMulA; ++i )protmulA[i] = 0.0;
00223       for( i=0; i<numSec; ++i )protnormA[i] = 0.0;
00224       counter = -1;
00225       for( np=1; np<(numSec/3); ++np )
00226       {
00227         nneg = np;
00228         for( nz=0; nz<numSec/3; ++nz )
00229         {
00230           if( ++counter < numMulA )
00231           {
00232             nt = np+nneg+nz;
00233             if( nt>1 && nt<=numSec )
00234             {
00235               protmulA[counter] = Pmltpc(np,nneg,nz,nt,b[0],c);
00236               protnormA[nt-1] += protmulA[counter];
00237             }
00238           }
00239         }
00240       }
00241       for( i=0; i<numMulA; ++i )neutmulA[i] = 0.0;
00242       for( i=0; i<numSec; ++i )neutnormA[i] = 0.0;
00243       counter = -1;
00244        for( np=0; np<numSec/3; ++np )
00245        {
00246         nneg = np+1;
00247         for( nz=0; nz<numSec/3; ++nz )
00248         {
00249           if( ++counter < numMulA )
00250           {
00251             nt = np+nneg+nz;
00252             if( nt>1 && nt<=numSec )
00253             {
00254               neutmulA[counter] = Pmltpc(np,nneg,nz,nt,b[1],c);
00255               neutnormA[nt-1] += neutmulA[counter];
00256             }
00257           }
00258         }
00259       }
00260       for( i=0; i<numSec; ++i )
00261       {
00262         if( protnormA[i] > 0.0 )protnormA[i] = 1.0/protnormA[i];
00263         if( neutnormA[i] > 0.0 )neutnormA[i] = 1.0/neutnormA[i];
00264       }
00265     }   // end of initialization
00266     
00267     const G4double expxu = 82.;           // upper bound for arg. of exp
00268     const G4double expxl = -expxu;        // lower bound for arg. of exp
00269     G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
00270     G4ParticleDefinition *aProton = G4Proton::Proton();
00271     G4ParticleDefinition *aPiPlus = G4PionPlus::PionPlus();
00272     G4ParticleDefinition *anAntiLambda = G4AntiLambda::AntiLambda();
00273     G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
00274     G4ParticleDefinition *aKaonPlus = G4KaonPlus::KaonPlus();
00275     G4ParticleDefinition *aKaonZL = G4KaonZeroLong::KaonZeroLong();
00276     G4ParticleDefinition *anAntiSigmaZero = G4AntiSigmaZero::AntiSigmaZero();
00277     const G4double anhl[] = {1.00,1.00,1.00,1.00,1.00,1.00,1.00,1.00,0.97,0.88,
00278                              0.85,0.81,0.75,0.64,0.64,0.55,0.55,0.45,0.47,0.40,
00279                              0.39,0.36,0.33,0.10,0.01};
00280     G4int iplab = G4int( pOriginal/GeV*10.0 );
00281     if( iplab >  9 )iplab = G4int( (pOriginal/GeV- 1.0)*5.0  ) + 10;
00282     if( iplab > 14 )iplab = G4int(  pOriginal/GeV- 2.0       ) + 15;
00283     if( iplab > 22 )iplab = G4int( (pOriginal/GeV-10.0)/10.0 ) + 23;
00284     if( iplab > 24 )iplab = 24;
00285     if( G4UniformRand() > anhl[iplab] )
00286     {
00287       if( availableEnergy <= aPiPlus->GetPDGMass()/MeV )
00288       {
00289         quasiElastic = true;
00290         return;
00291       }
00292       G4double n, anpn;
00293       GetNormalizationConstant( availableEnergy, n, anpn );
00294       G4double ran = G4UniformRand();
00295       G4double dum, excs = 0.0;
00296       if( targetParticle.GetDefinition() == aProton )
00297       {
00298         counter = -1;
00299         for( np=0; np<numSec/3 && ran>=excs; ++np )
00300         {
00301           for( nneg=std::max(0,np-1); nneg<=(np+1) && ran>=excs; ++nneg )
00302           {
00303             for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
00304             {
00305               if( ++counter < numMul )
00306               {
00307                 nt = np+nneg+nz;
00308                 if( (nt>0) && (nt<=numSec) )
00309                 {
00310                   test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
00311                   dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
00312                   if( std::fabs(dum) < 1.0 )
00313                   {
00314                     if( test >= 1.0e-10 )excs += dum*test;
00315                   }
00316                   else
00317                     excs += dum*test;
00318                 }
00319               }
00320             }
00321           }
00322         }
00323         if( ran >= excs )  // 3 previous loops continued to the end
00324         {
00325           quasiElastic = true;
00326           return;
00327         }
00328         np--; nneg--; nz--;
00329         G4int ncht = std::min( 3, std::max( 1, np-nneg+2 ) );
00330         switch( ncht )
00331         {
00332          case 1:
00333            if( G4UniformRand() < 0.5 )
00334              currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
00335            else
00336              currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
00337            incidentHasChanged = true;
00338            break;
00339          case 2:
00340            if( G4UniformRand() >= 0.5 )
00341            {
00342              if( G4UniformRand() < 0.5 )
00343                currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
00344              else
00345                currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
00346              incidentHasChanged = true;
00347            }             
00348            targetParticle.SetDefinitionAndUpdateE( aNeutron );
00349            targetHasChanged = true;
00350            break;
00351          case 3:
00352            targetParticle.SetDefinitionAndUpdateE( aNeutron );
00353            targetHasChanged = true;
00354            break;
00355         }
00356       }
00357       else  // target must be a neutron
00358       {
00359         counter = -1;
00360         for( np=0; np<numSec/3 && ran>=excs; ++np )
00361         {
00362           for( nneg=np; nneg<=(np+2) && ran>=excs; ++nneg )
00363           {
00364             for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
00365             {
00366               if( ++counter < numMul )
00367               {
00368                 nt = np+nneg+nz;
00369                 if( (nt>0) && (nt<=numSec) )
00370                 {
00371                   test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
00372                   dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
00373                   if( std::fabs(dum) < 1.0 )
00374                   {
00375                     if( test >= 1.0e-10 )excs += dum*test;
00376                   }
00377                   else
00378                     excs += dum*test;
00379                 }
00380               }
00381             }
00382           }
00383         }
00384         if( ran >= excs )  // 3 previous loops continued to the end
00385         {
00386           quasiElastic = true;
00387           return;
00388         }
00389         np--; nneg--; nz--;
00390         G4int ncht = std::min( 3, std::max( 1, np-nneg+3 ) );
00391         switch( ncht )
00392         {
00393          case 1:
00394            if( G4UniformRand() < 0.5 )
00395              currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
00396            else
00397              currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
00398            incidentHasChanged = true;
00399            targetParticle.SetDefinitionAndUpdateE( aProton );
00400            targetHasChanged = true;
00401            break;
00402          case 2:
00403            if( G4UniformRand() < 0.5 )
00404            {
00405              if( G4UniformRand() < 0.5 )
00406              {
00407                currentParticle.SetDefinitionAndUpdateE( anAntiLambda );
00408                incidentHasChanged = true;
00409              }
00410              else
00411              {
00412                targetParticle.SetDefinitionAndUpdateE( aProton );
00413                targetHasChanged = true;
00414              }
00415            }
00416            else
00417            {
00418              if( G4UniformRand() < 0.5 )
00419              {
00420                currentParticle.SetDefinitionAndUpdateE( anAntiSigmaZero );
00421                incidentHasChanged = true;
00422              }
00423              else
00424              {
00425                targetParticle.SetDefinitionAndUpdateE( aProton );
00426                targetHasChanged = true;
00427              }
00428            }
00429            break;
00430          case 3:
00431            break;
00432         }
00433       }
00434     }
00435     else  // random number <= anhl[iplab]
00436     {
00437       if( centerofmassEnergy <= aPiPlus->GetPDGMass()/MeV+aKaonPlus->GetPDGMass()/MeV )
00438       {
00439         quasiElastic = true;
00440         return;
00441       }
00442       G4double n, anpn;
00443       GetNormalizationConstant( -centerofmassEnergy, n, anpn );
00444       G4double ran = G4UniformRand();
00445       G4double dum, excs = 0.0;
00446       if( targetParticle.GetDefinition() == aProton )
00447       {
00448         counter = -1;
00449         for( np=1; np<numSec/3 && ran>=excs; ++np )
00450         {
00451           nneg = np;
00452           for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
00453           {
00454             if( ++counter < numMulA )
00455             {
00456               nt = np+nneg+nz;
00457               if( nt>1 && nt<=numSec )
00458               {
00459                 test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
00460                 dum = (pi/anpn)*nt*protmulA[counter]*protnormA[nt-1]/(2.0*n*n);
00461                 if( std::fabs(dum) < 1.0 )
00462                 {
00463                   if( test >= 1.0e-10 )excs += dum*test;
00464                 }
00465                 else
00466                   excs += dum*test;
00467               }
00468             }
00469           }
00470         }
00471         if( ran >= excs )  // 3 previous loops continued to the end
00472         {
00473           quasiElastic = true;
00474           return;
00475         }
00476         np--; nz--;
00477       }
00478       else  // target must be a neutron
00479       {
00480         counter = -1;
00481         for( np=0; np<numSec/3 && ran>=excs; ++np )
00482         {
00483           nneg = np+1;
00484           for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
00485           {
00486             if( ++counter < numMulA )
00487             {
00488               nt = np+nneg+nz;
00489               if( nt>1 && nt<=numSec )
00490               {
00491                 test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
00492                 dum = (pi/anpn)*nt*neutmulA[counter]*neutnormA[nt-1]/(2.0*n*n);
00493                 if( std::fabs(dum) < 1.0 )
00494                 {
00495                   if( test >= 1.0e-10 )excs += dum*test;
00496                 }
00497                 else
00498                   excs += dum*test;
00499               }
00500             }
00501           }
00502         }
00503         if( ran >= excs )  // 3 previous loops continued to the end
00504         {
00505           quasiElastic = true;
00506           return;
00507         }
00508         np--; nz--;
00509       }
00510       if( nz > 0 )
00511       {
00512         if( nneg > 0 )
00513         {
00514           if( G4UniformRand() < 0.5 )
00515           {
00516             vec.Initialize( 1 );
00517             G4ReactionProduct *p= new G4ReactionProduct;
00518             p->SetDefinition( aKaonMinus );
00519             (G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
00520             vec.SetElement( vecLen++, p );
00521             --nneg;
00522           }
00523           else
00524           {
00525             vec.Initialize( 1 );
00526             G4ReactionProduct *p= new G4ReactionProduct ;
00527             p->SetDefinition( aKaonZL );
00528             (G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
00529             vec.SetElement( vecLen++, p );
00530             --nz;
00531           }
00532         }
00533         else   // nneg == 0
00534         {
00535           vec.Initialize( 1 );
00536           G4ReactionProduct *p = new G4ReactionProduct;
00537           p->SetDefinition( aKaonZL );
00538           (G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
00539           vec.SetElement( vecLen++, p );
00540           --nz;
00541         }
00542       }
00543       else    //  nz == 0
00544       {
00545         if( nneg > 0 )
00546         {
00547           vec.Initialize( 1 );
00548           G4ReactionProduct *p = new G4ReactionProduct;
00549           p->SetDefinition( aKaonMinus );
00550           (G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
00551           vec.SetElement( vecLen++, p );
00552           --nneg;
00553         }
00554       }
00555       currentParticle.SetMass( 0.0 );
00556       targetParticle.SetMass( 0.0 );
00557     }
00558 
00559   SetUpPions( np, nneg, nz, vec, vecLen );
00560   return;
00561 }
00562 
00563  /* end of file */
00564  

Generated on Mon May 27 17:49:44 2013 for Geant4 by  doxygen 1.4.7