G4HEProtonInelastic.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 // G4 Process: Gheisha High Energy Collision model.
00030 // This includes the high energy cascading model, the two-body-resonance model
00031 // and the low energy two-body model. Not included are the low energy stuff 
00032 // like nuclear reactions, nuclear fission without any cascading and all
00033 // processes for particles at rest.  
00034 // First work done by J.L.Chuma and F.W.Jones, TRIUMF, June 96.  
00035 // H. Fesefeldt, RWTH-Aachen, 23-October-1996
00036  
00037 #include "G4HEProtonInelastic.hh"
00038 #include "globals.hh"
00039 #include "G4ios.hh"
00040 #include "G4PhysicalConstants.hh"
00041 
00042 void G4HEProtonInelastic::ModelDescription(std::ostream& outFile) const
00043 {
00044   outFile << "G4HEProtonInelastic is one of the High Energy\n"
00045           << "Parameterized (HEP) models used to implement inelastic\n"
00046           << "proton scattering from nuclei.  It is a re-engineered\n"
00047           << "version of the GHEISHA code of H. Fesefeldt.  It divides the\n"
00048           << "initial collision products into backward- and forward-going\n"
00049           << "clusters which are then decayed into final state hadrons.\n"
00050           << "The model does not conserve energy on an event-by-event\n"
00051           << "basis.  It may be applied to protons with initial energies\n"
00052           << "above 20 GeV.\n";
00053 }
00054 
00055 
00056 G4HadFinalState*
00057 G4HEProtonInelastic::ApplyYourself(const G4HadProjectile& aTrack,
00058                                    G4Nucleus& targetNucleus)
00059 {
00060   G4HEVector* pv = new G4HEVector[MAXPART];
00061   const G4HadProjectile* aParticle = &aTrack;
00062   const G4double A = targetNucleus.GetA_asInt();
00063   const G4double Z = targetNucleus.GetZ_asInt();
00064   G4HEVector incidentParticle(aParticle);
00065      
00066   G4double atomicNumber = Z;
00067   G4double atomicWeight = A;
00068 
00069   if (verboseLevel > 1)
00070     G4cout << "Z , A = " << atomicNumber << "  " << atomicWeight << G4endl;
00071 
00072   G4int incidentCode = incidentParticle.getCode();
00073   G4double incidentMass = incidentParticle.getMass();
00074   G4double incidentTotalEnergy = incidentParticle.getEnergy();
00075 
00076   // G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
00077   // DHW 19 May 2011: variable set but not used
00078 
00079   G4double incidentKineticEnergy = incidentParticle.getKineticEnergy();
00080 
00081   if (incidentKineticEnergy < 1.)
00082     G4cout << "GHEProtonInelastic: incident energy < 1 GeV" << G4endl;
00083 
00084   if (verboseLevel > 1) {
00085     G4cout << "G4HEProtonInelastic::ApplyYourself" << G4endl;
00086     G4cout << "incident particle " << incidentParticle.getName() << " " 
00087            << "mass "              << incidentMass << " " 
00088            << "kinetic energy "    << incidentKineticEnergy
00089            << G4endl;
00090     G4cout << "target material with (A,Z) = (" 
00091            << atomicWeight << "," << atomicNumber << ")" << G4endl;
00092   }
00093     
00094   G4double inelasticity = NuclearInelasticity(incidentKineticEnergy, 
00095                                               atomicWeight, atomicNumber);
00096   if (verboseLevel > 1)
00097     G4cout << "nuclear inelasticity = " << inelasticity << G4endl;
00098 
00099   incidentKineticEnergy -= inelasticity;
00100     
00101   G4double excitationEnergyGNP = 0.;
00102   G4double excitationEnergyDTA = 0.; 
00103 
00104   G4double excitation = NuclearExcitation(incidentKineticEnergy,
00105                                           atomicWeight, atomicNumber,
00106                                           excitationEnergyGNP,
00107                                           excitationEnergyDTA);
00108 
00109   if (verboseLevel > 1)
00110     G4cout << "nuclear excitation = " << excitation << " "
00111            << excitationEnergyGNP << " " << excitationEnergyDTA << G4endl;             
00112 
00113   incidentKineticEnergy -= excitation;
00114   incidentTotalEnergy = incidentKineticEnergy + incidentMass;
00115   // incidentTotalMomentum = std::sqrt( (incidentTotalEnergy-incidentMass)
00116   //                                   *(incidentTotalEnergy+incidentMass));
00117   // DHW 19 May 2011: variable set but not used
00118 
00119   G4HEVector targetParticle;
00120   if (G4UniformRand() < atomicNumber/atomicWeight) { 
00121     targetParticle.setDefinition("Proton");
00122   } else { 
00123     targetParticle.setDefinition("Neutron");
00124   }
00125 
00126   G4double targetMass = targetParticle.getMass();
00127   G4double centerOfMassEnergy = std::sqrt(incidentMass*incidentMass
00128                                         + targetMass*targetMass
00129                                         + 2.0*targetMass*incidentTotalEnergy);
00130   G4double availableEnergy = centerOfMassEnergy - targetMass - incidentMass;
00131 
00132   // In the original Gheisha code, the inElastic flag was defined as follows:
00133   //   G4bool inElastic = InElasticCrossSectionInFirstInt
00134   //              (availableEnergy, incidentCode, incidentTotalMomentum);
00135   // For unknown reasons, it was replaced by the following code in Geant???
00136 
00137   G4bool inElastic = true;
00138   //  if (G4UniformRand() < elasticCrossSection/totalCrossSection) inElastic = false;    
00139 
00140   vecLength = 0;
00141         
00142   if (verboseLevel > 1)
00143     G4cout << "ApplyYourself: CallFirstIntInCascade for particle "
00144            << incidentCode << G4endl;
00145 
00146   G4bool successful = false; 
00147     
00148   FirstIntInCasProton(inElastic, availableEnergy, pv, vecLength,
00149                       incidentParticle, targetParticle, atomicWeight);
00150 
00151   if (verboseLevel > 1)
00152     G4cout << "ApplyYourself::StrangeParticlePairProduction" << G4endl;
00153 
00154   if ((vecLength > 0) && (availableEnergy > 1.)) 
00155     StrangeParticlePairProduction(availableEnergy, centerOfMassEnergy,
00156                                   pv, vecLength,
00157                                   incidentParticle, targetParticle);
00158 
00159   HighEnergyCascading(successful, pv, vecLength,
00160                       excitationEnergyGNP, excitationEnergyDTA,
00161                       incidentParticle, targetParticle,
00162                       atomicWeight, atomicNumber);
00163   if (!successful)
00164     HighEnergyClusterProduction(successful, pv, vecLength,
00165                                 excitationEnergyGNP, excitationEnergyDTA,
00166                                 incidentParticle, targetParticle,
00167                                 atomicWeight, atomicNumber);
00168   if (!successful) 
00169     MediumEnergyCascading(successful, pv, vecLength, 
00170                           excitationEnergyGNP, excitationEnergyDTA, 
00171                           incidentParticle, targetParticle,
00172                           atomicWeight, atomicNumber);
00173 
00174   if (!successful)
00175     MediumEnergyClusterProduction(successful, pv, vecLength,
00176                                   excitationEnergyGNP, excitationEnergyDTA,       
00177                                   incidentParticle, targetParticle,
00178                                   atomicWeight, atomicNumber);
00179   if (!successful)
00180     QuasiElasticScattering(successful, pv, vecLength,
00181                            excitationEnergyGNP, excitationEnergyDTA,
00182                            incidentParticle, targetParticle, 
00183                            atomicWeight, atomicNumber);
00184   if (!successful)
00185     ElasticScattering(successful, pv, vecLength,
00186                       incidentParticle,    
00187                       atomicWeight, atomicNumber);
00188 
00189   if (!successful)
00190     G4cout << "GHEInelasticInteraction::ApplyYourself fails to produce final state particles" 
00191            << G4endl;
00192 
00193   FillParticleChange(pv, vecLength);
00194   delete [] pv;
00195   theParticleChange.SetStatusChange(stopAndKill);
00196   return &theParticleChange;
00197 }
00198 
00199 
00200 void
00201 G4HEProtonInelastic::FirstIntInCasProton(G4bool& inElastic,
00202                                          const G4double availableEnergy,
00203                                          G4HEVector pv[],
00204                                          G4int& vecLen,
00205                                          const G4HEVector& incidentParticle,
00206                                          const G4HEVector& targetParticle,
00207                                          const G4double atomicWeight)
00208 
00209 // Proton undergoes interaction with nucleon within a nucleus.  Check if it is
00210 // energetically possible to produce pions/kaons.  In not, assume nuclear excitation
00211 // occurs and input particle is degraded in energy. No other particles are produced.
00212 // If reaction is possible, find the correct number of pions/protons/neutrons
00213 // produced using an interpolation to multiplicity data.  Replace some pions or
00214 // protons/neutrons by kaons or strange baryons according to the average
00215 // multiplicity per inelastic reaction.
00216 {
00217   static const G4double expxu = 82.;     // upper bound for arg. of exp
00218   static const G4double expxl = -expxu;  // lower bound for arg. of exp
00219 
00220   static const G4double protb = 0.7;
00221   static const G4double neutb = 0.35;
00222   static const G4double c = 1.25;
00223 
00224   static const G4int numMul = 1200;
00225   static const G4int numSec = 60;
00226 
00227   G4int neutronCode = Neutron.getCode();
00228   G4int protonCode = Proton.getCode();
00229   G4double pionMass = PionPlus.getMass();
00230 
00231   G4int targetCode = targetParticle.getCode();
00232   G4double incidentTotalMomentum = incidentParticle.getTotalMomentum();
00233 
00234   static G4bool first = true;
00235   static G4double protmul[numMul], protnorm[numSec];  // proton constants
00236   static G4double neutmul[numMul], neutnorm[numSec];  // neutron constants
00237 
00238   //  misc. local variables
00239   //  npos = number of pi+,  nneg = number of pi-,  nzero = number of pi0
00240 
00241   G4int i, counter, nt, npos, nneg, nzero;
00242 
00243   if (first) { 
00244     // compute normalization constants, this will only be done once
00245     first = false;
00246     for (i=0; i<numMul; i++) protmul[i] = 0.0;
00247     for (i=0; i<numSec; i++) protnorm[i] = 0.0;
00248     counter = -1;
00249     for (npos=0; npos<(numSec/3); npos++) {
00250       for (nneg=Imax(0,npos-2); nneg<=npos; nneg++) {
00251         for (nzero=0; nzero<numSec/3; nzero++) {
00252           if (++counter < numMul) {
00253             nt = npos+nneg+nzero;
00254             if ( (nt>0) && (nt<=numSec) ) {
00255               protmul[counter] = pmltpc(npos,nneg,nzero,nt,protb,c)
00256                                  /(Factorial(2-npos+nneg)*Factorial(npos-nneg)) ;
00257               protnorm[nt-1] += protmul[counter];
00258             }
00259           }
00260         }
00261       }
00262     }
00263 
00264     for( i=0; i<numMul; i++ )neutmul[i]  = 0.0;
00265     for( i=0; i<numSec; i++ )neutnorm[i] = 0.0;
00266     counter = -1;
00267     for (npos=0; npos<numSec/3; npos++) {
00268       for (nneg=Imax(0,npos-1); nneg<=(npos+1); nneg++) {
00269         for (nzero=0; nzero<numSec/3; nzero++) {
00270           if (++counter < numMul) {
00271             nt = npos+nneg+nzero;
00272             if ( (nt>0) && (nt<=numSec) ) {
00273               neutmul[counter] = pmltpc(npos,nneg,nzero,nt,neutb,c)
00274                                  /(Factorial(1-npos+nneg)*Factorial(1+npos-nneg));
00275               neutnorm[nt-1] += neutmul[counter];
00276             }
00277           }
00278         }
00279       }
00280     }
00281     for (i=0; i<numSec; i++) {
00282       if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
00283       if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
00284     }
00285   }                   // end of initialization
00286 
00287          
00288   // initialize the first two places
00289   // the same as beam and target                                    
00290   pv[0] = incidentParticle;
00291   pv[1] = targetParticle;
00292   vecLen = 2;
00293 
00294   if (!inElastic) {    // quasi-elastic scattering, no pions produced
00295     if (targetCode == neutronCode) {
00296       G4double cech[] = {0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.06, 0.04, 0.005, 0.};
00297       G4int iplab = G4int( Amin( 9.0, incidentTotalMomentum*2.5 ) );
00298       if (G4UniformRand() < cech[iplab]/std::pow(atomicWeight,0.42) ) {
00299         // charge exchange  pi+ n -> pi0 p
00300         pv[0] = PionZero;
00301         pv[1] = Proton;
00302       }
00303     }
00304     return;
00305   } else if (availableEnergy <= pionMass) return;
00306 
00307   //   inelastic scattering
00308   npos = 0, nneg = 0, nzero = 0;
00309   G4double eab = availableEnergy;
00310   G4int ieab = G4int( eab*5.0 );
00311    
00312   G4double supp[] = {0., 0.4, 0.55, 0.65, 0.75, 0.82, 0.86, 0.90, 0.94, 0.98};
00313   if ( (ieab <= 9) && (G4UniformRand() >= supp[ieab]) ) {
00314     // suppress high multiplicity events at low momentum
00315     //   only one additional pion will be produced
00316     G4double w0, wp, wm, wt, ran;
00317     if (targetCode == protonCode) {    // target is a proton 
00318       w0 = - sqr(1.+protb)/(2.*c*c);
00319       wp = w0 = std::exp(w0);
00320       if (G4UniformRand() < w0/(w0+wp) ) {
00321         npos = 0;
00322         nneg = 0;
00323         nzero = 1;
00324       } else {
00325         npos = 1;
00326         nneg = 0;
00327         nzero = 0; }       
00328       } else {     // target is a neutron
00329         w0 = -sqr(1.+neutb)/(2.*c*c);
00330         w0 = std::exp(w0);
00331         wp = w0/2.;
00332         wm = -sqr(-1.+neutb)/(2.*c*c);
00333            wm = std::exp(wm)/2.;
00334            wt = w0+wp+wm;
00335            wp = w0+wp;
00336            ran = G4UniformRand();
00337            if( ran < w0/wt)
00338              { npos = 0; nneg = 0; nzero = 1; }       
00339            else if( ran < wp/wt)
00340              { npos = 1; nneg = 0; nzero = 0; }       
00341            else
00342              { npos = 0; nneg = 1; nzero = 0; }       
00343       }
00344     } else {
00345       // number of total particles vs. centre of mass Energy - 2*proton mass
00346    
00347       G4double aleab = std::log(availableEnergy);
00348       G4double n = 3.62567+aleab*(0.665843+aleab*(0.336514
00349                     + aleab*(0.117712+0.0136912*aleab))) - 2.0;
00350    
00351        // normalization constant for kno-distribution.
00352        // calculate first the sum of all constants, check for numerical problems.   
00353        G4double test, dum, anpn = 0.0;
00354 
00355        for (nt=1; nt<=numSec; nt++) {
00356          test = std::exp( Amin( expxu, Amax( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
00357          dum = pi*nt/(2.0*n*n);
00358          if (std::fabs(dum) < 1.0) { 
00359            if( test >= 1.0e-10 )anpn += dum*test;
00360          } else { 
00361            anpn += dum*test;
00362          }
00363        }
00364    
00365        G4double ran = G4UniformRand();
00366        G4double excs = 0.0;
00367        if( targetCode == protonCode ) 
00368          {
00369            counter = -1;
00370            for (npos=0; npos<numSec/3; npos++) {
00371              for (nneg=Imax(0,npos-2); nneg<=npos; nneg++) {
00372                for (nzero=0; nzero<numSec/3; nzero++) {
00373                  if (++counter < numMul) {
00374                    nt = npos+nneg+nzero;
00375                    if ( (nt>0) && (nt<=numSec) ) {
00376                      test = std::exp( Amin( expxu, Amax( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
00377                      dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
00378                      if (std::fabs(dum) < 1.0) { 
00379                        if( test >= 1.0e-10 )excs += dum*test;
00380                      } else { 
00381                        excs += dum*test;
00382                      }
00383                      if (ran < excs) goto outOfLoop;      //------------------>
00384                    }
00385                  }
00386                }
00387              }
00388            }
00389        
00390            // 3 previous loops continued to the end
00391            inElastic = false;                 // quasi-elastic scattering   
00392            return;
00393          }
00394        else   
00395          {                                         // target must be a neutron
00396            counter = -1;
00397            for (npos=0; npos<numSec/3; npos++) {
00398              for (nneg=Imax(0,npos-1); nneg<=(npos+1); nneg++) {
00399                for (nzero=0; nzero<numSec/3; nzero++) {
00400                  if (++counter < numMul) {
00401                    nt = npos+nneg+nzero;
00402                    if ( (nt>=1) && (nt<=numSec) ) {
00403                      test = std::exp( Amin( expxu, Amax( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
00404                      dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
00405                      if (std::fabs(dum) < 1.0) { 
00406                        if( test >= 1.0e-10 )excs += dum*test;
00407                      } else { 
00408                        excs += dum*test;
00409                      }
00410                      if (ran < excs) goto outOfLoop;       // ------------->
00411                    }
00412                  }
00413                }
00414              }
00415            }
00416            // 3 previous loops continued to the end
00417            inElastic = false;                     // quasi-elastic scattering.
00418            return;
00419          }
00420      } 
00421    outOfLoop:           //  <-----------------------------------------------   
00422     
00423    if( targetCode == protonCode)
00424      {
00425        if( npos == nneg)
00426          {
00427          }
00428        else if (npos == (1+nneg))
00429          {
00430            if( G4UniformRand() < 0.5)
00431              {
00432                pv[1] = Neutron;
00433              }
00434            else
00435              {
00436                pv[0] = Neutron;
00437              }
00438          }
00439        else      
00440          {
00441            pv[0] = Neutron;
00442            pv[1] = Neutron;
00443          } 
00444      }  
00445    else
00446      {
00447        if( npos == nneg)
00448          {
00449            if( G4UniformRand() < 0.25)
00450              {
00451                pv[0] = Neutron;
00452                pv[1] = Proton;
00453              }
00454            else
00455              {
00456              }
00457          } 
00458        else if ( npos == (1+nneg))
00459          {
00460            pv[0] = Neutron;
00461          }
00462        else
00463          {
00464            pv[1] = Proton;
00465          }
00466      }      
00467 
00468 
00469    nt = npos + nneg + nzero;
00470    while ( nt > 0)
00471        {
00472          G4double ran = G4UniformRand();
00473          if ( ran < (G4double)npos/nt)
00474             { 
00475               if( npos > 0 ) 
00476                 { pv[vecLen++] = PionPlus;
00477                   npos--;
00478                 }
00479             }
00480          else if ( ran < (G4double)(npos+nneg)/nt)
00481             {   
00482               if( nneg > 0 )
00483                 { 
00484                   pv[vecLen++] = PionMinus;
00485                   nneg--;
00486                 }
00487             }
00488          else
00489             {
00490               if( nzero > 0 )
00491                 { 
00492                   pv[vecLen++] = PionZero;
00493                   nzero--;
00494                 }
00495             }
00496          nt = npos + nneg + nzero;
00497        } 
00498    if (verboseLevel > 1)
00499       {
00500         G4cout << "Particles produced: " ;
00501         G4cout << pv[0].getName() << " " ;
00502         G4cout << pv[1].getName() << " " ;
00503         for (i=2; i < vecLen; i++)   
00504             { 
00505               G4cout << pv[i].getName() << " " ;
00506             }
00507          G4cout << G4endl;
00508       }
00509    return;
00510  }
00511 
00512 
00513 
00514 
00515 
00516 
00517 
00518 
00519 

Generated on Mon May 27 17:48:30 2013 for Geant4 by  doxygen 1.4.7