G4RPGXiZeroInelastic.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 "G4RPGXiZeroInelastic.hh"
00030 #include "G4PhysicalConstants.hh"
00031 #include "G4SystemOfUnits.hh"
00032 #include "Randomize.hh"
00033  
00034 G4HadFinalState*
00035 G4RPGXiZeroInelastic::ApplyYourself(const G4HadProjectile& aTrack,
00036                                     G4Nucleus& targetNucleus)
00037 {    
00038   const G4HadProjectile *originalIncident = &aTrack;
00039   if (originalIncident->GetKineticEnergy() <= 0.1*MeV) {
00040     theParticleChange.SetStatusChange(isAlive);
00041     theParticleChange.SetEnergyChange(aTrack.GetKineticEnergy());
00042     theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit()); 
00043     return &theParticleChange;      
00044   }
00045 
00046   // create the target particle
00047   G4DynamicParticle* originalTarget = targetNucleus.ReturnTargetParticle();
00048     
00049   if (verboseLevel > 1) {
00050     const G4Material *targetMaterial = aTrack.GetMaterial();
00051     G4cout << "G4RPGXiZeroInelastic::ApplyYourself called" << G4endl;
00052     G4cout << "kinetic energy = " << originalIncident->GetKineticEnergy()/MeV << "MeV, ";
00053     G4cout << "target material = " << targetMaterial->GetName() << ", ";
00054     G4cout << "target particle = " << originalTarget->GetDefinition()->GetParticleName()
00055            << G4endl;
00056   }
00057 
00058   // Fermi motion and evaporation
00059   // As of Geant3, the Fermi energy calculation had not been Done
00060   G4double ek = originalIncident->GetKineticEnergy()/MeV;
00061   G4double amas = originalIncident->GetDefinition()->GetPDGMass()/MeV;
00062   G4ReactionProduct modifiedOriginal;
00063   modifiedOriginal = *originalIncident;
00064     
00065     G4double tkin = targetNucleus.Cinema( ek );
00066     ek += tkin;
00067     modifiedOriginal.SetKineticEnergy( ek*MeV );
00068     G4double et = ek + amas;
00069     G4double p = std::sqrt( std::abs((et-amas)*(et+amas)) );
00070     G4double pp = modifiedOriginal.GetMomentum().mag()/MeV;
00071     if( pp > 0.0 )
00072     {
00073       G4ThreeVector momentum = modifiedOriginal.GetMomentum();
00074       modifiedOriginal.SetMomentum( momentum * (p/pp) );
00075     }
00076     //
00077     // calculate black track energies
00078     //
00079     tkin = targetNucleus.EvaporationEffects( ek );
00080     ek -= tkin;
00081     modifiedOriginal.SetKineticEnergy( ek*MeV );
00082     et = ek + amas;
00083     p = std::sqrt( std::abs((et-amas)*(et+amas)) );
00084     pp = modifiedOriginal.GetMomentum().mag()/MeV;
00085     if( pp > 0.0 )
00086     {
00087       G4ThreeVector momentum = modifiedOriginal.GetMomentum();
00088       modifiedOriginal.SetMomentum( momentum * (p/pp) );
00089     }
00090   G4ReactionProduct currentParticle = modifiedOriginal;
00091   G4ReactionProduct targetParticle;
00092   targetParticle = *originalTarget;
00093   currentParticle.SetSide( 1 ); // incident always goes in forward hemisphere
00094   targetParticle.SetSide( -1 );  // target always goes in backward hemisphere
00095   G4bool incidentHasChanged = false;
00096   G4bool targetHasChanged = false;
00097   G4bool quasiElastic = false;
00098   G4FastVector<G4ReactionProduct,GHADLISTSIZE> vec;  // vec will contain the secondary particles
00099   G4int vecLen = 0;
00100   vec.Initialize( 0 );
00101     
00102   const G4double cutOff = 0.1;
00103   if (currentParticle.GetKineticEnergy()/MeV > cutOff)
00104     Cascade(vec, vecLen, originalIncident, currentParticle, targetParticle,
00105             incidentHasChanged, targetHasChanged, quasiElastic);
00106     
00107   CalculateMomenta(vec, vecLen, originalIncident, originalTarget,
00108                    modifiedOriginal, targetNucleus, currentParticle,
00109                    targetParticle, incidentHasChanged, targetHasChanged,
00110                    quasiElastic);
00111     
00112   SetUpChange(vec, vecLen, currentParticle, targetParticle, incidentHasChanged);
00113     
00114   delete originalTarget;
00115   return &theParticleChange;
00116 }
00117 
00118 
00119 void
00120 G4RPGXiZeroInelastic::Cascade(G4FastVector<G4ReactionProduct,GHADLISTSIZE> &vec,
00121                               G4int& vecLen,
00122                               const G4HadProjectile* originalIncident,
00123                               G4ReactionProduct& currentParticle,
00124                               G4ReactionProduct& targetParticle,
00125                               G4bool& incidentHasChanged,
00126                               G4bool& targetHasChanged,
00127                               G4bool& quasiElastic)
00128 {
00129   // Derived from H. Fesefeldt's original FORTRAN code CASX0
00130   //
00131   // XiZero undergoes interaction with nucleon within a nucleus.  Check if it is
00132   // energetically possible to produce pions/kaons.  In not, assume nuclear excitation
00133   // occurs and input particle is degraded in energy. No other particles are produced.
00134   // If reaction is possible, find the correct number of pions/protons/neutrons
00135   // produced using an interpolation to multiplicity data.  Replace some pions or
00136   // protons/neutrons by kaons or strange baryons according to the average
00137   // multiplicity per inelastic reaction.
00138 
00139   const G4double mOriginal = originalIncident->GetDefinition()->GetPDGMass()/MeV;
00140   const G4double etOriginal = originalIncident->GetTotalEnergy()/MeV;
00141   const G4double targetMass = targetParticle.GetMass()/MeV;
00142   G4double centerofmassEnergy = std::sqrt(mOriginal*mOriginal +
00143                                           targetMass*targetMass +
00144                                           2.0*targetMass*etOriginal);
00145   G4double availableEnergy = centerofmassEnergy-(targetMass+mOriginal);
00146   if (availableEnergy <= G4PionPlus::PionPlus()->GetPDGMass()/MeV) {
00147     quasiElastic = true;
00148     return;
00149   }
00150   static G4bool first = true;
00151   const G4int numMul = 1200;
00152   const G4int numSec = 60;
00153   static G4double protmul[numMul], protnorm[numSec]; // proton constants
00154   static G4double neutmul[numMul], neutnorm[numSec]; // neutron constants
00155 
00156   // np = number of pi+, nneg = number of pi-, nz = number of pi0
00157   G4int counter, nt=0, np=0, nneg=0, nz=0;
00158   G4double test;
00159   const G4double c = 1.25;    
00160   const G4double b[] = { 0.7, 0.7 };
00161   if (first) {  // Computation of normalization constants will only be done once
00162     first = false;
00163     G4int i;
00164     for (i = 0; i < numMul; ++i) protmul[i] = 0.0;
00165     for (i = 0; i < numSec; ++i) protnorm[i] = 0.0;
00166     counter = -1;
00167     for( np=0; np<(numSec/3); ++np )
00168       {
00169         for( nneg=std::max(0,np-2); nneg<=(np+1); ++nneg )
00170         {
00171           for( nz=0; nz<numSec/3; ++nz )
00172           {
00173             if( ++counter < numMul )
00174             {
00175               nt = np+nneg+nz;
00176               if( nt>0 && nt<=numSec )
00177               {
00178                 protmul[counter] = Pmltpc(np,nneg,nz,nt,b[0],c);
00179                 protnorm[nt-1] += protmul[counter];
00180               }
00181             }
00182           }
00183         }
00184       }
00185       for( i=0; i<numMul; ++i )neutmul[i] = 0.0;
00186       for( i=0; i<numSec; ++i )neutnorm[i] = 0.0;
00187       counter = -1;
00188       for( np=0; np<numSec/3; ++np )
00189       {
00190         for( nneg=std::max(0,np-1); nneg<=(np+2); ++nneg )
00191         {
00192           for( nz=0; nz<numSec/3; ++nz )
00193           {
00194             if( ++counter < numMul )
00195             {
00196               nt = np+nneg+nz;
00197               if( nt>0 && nt<=numSec )
00198               {
00199                 neutmul[counter] = Pmltpc(np,nneg,nz,nt,b[1],c);
00200                 neutnorm[nt-1] += neutmul[counter];
00201               }
00202             }
00203           }
00204         }
00205       }
00206       for( i=0; i<numSec; ++i )
00207       {
00208         if( protnorm[i] > 0.0 )protnorm[i] = 1.0/protnorm[i];
00209         if( neutnorm[i] > 0.0 )neutnorm[i] = 1.0/neutnorm[i];
00210       }
00211     }   // end of initialization
00212     
00213     const G4double expxu = 82.;           // upper bound for arg. of exp
00214     const G4double expxl = -expxu;        // lower bound for arg. of exp
00215     G4ParticleDefinition *aNeutron = G4Neutron::Neutron();
00216     G4ParticleDefinition *aProton = G4Proton::Proton();
00217     G4ParticleDefinition *aKaonMinus = G4KaonMinus::KaonMinus();
00218     G4ParticleDefinition *aSigmaPlus = G4SigmaPlus::SigmaPlus();
00219     G4ParticleDefinition *aXiMinus = G4XiMinus::XiMinus();
00220     //
00221     // energetically possible to produce pion(s)  -->  inelastic scattering
00222     //
00223     G4double n, anpn;
00224     GetNormalizationConstant( availableEnergy, n, anpn );
00225     G4double ran = G4UniformRand();
00226     G4double dum, excs = 0.0;
00227     if( targetParticle.GetDefinition() == aProton )
00228     {
00229       counter = -1;
00230       for( np=0; np<numSec/3 && ran>=excs; ++np )
00231       {
00232         for( nneg=std::max(0,np-2); nneg<=(np+1) && ran>=excs; ++nneg )
00233         {
00234           for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
00235           {
00236             if( ++counter < numMul )
00237             {
00238               nt = np+nneg+nz;
00239               if( nt>0 && nt<=numSec )
00240               {
00241                 test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
00242                 dum = (pi/anpn)*nt*protmul[counter]*protnorm[nt-1]/(2.0*n*n);
00243                 if( std::fabs(dum) < 1.0 )
00244                 {
00245                   if( test >= 1.0e-10 )excs += dum*test;
00246                 }
00247                 else
00248                   excs += dum*test;
00249               }
00250             }
00251           }
00252         }
00253       }
00254       if( ran >= excs )  // 3 previous loops continued to the end
00255       {
00256         quasiElastic = true;
00257         return;
00258       }
00259       np--; nneg--; nz--;
00260       //
00261       // number of secondary mesons determined by kno distribution
00262       // check for total charge of final state mesons to determine
00263       // the kind of baryons to be produced, taking into account
00264       // charge and strangeness conservation
00265       //
00266       if( np < nneg+1 )
00267       {
00268         if( np != nneg )   // charge mismatch
00269         {
00270           currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
00271           incidentHasChanged = true;
00272           //
00273           // correct the strangeness by replacing a pi- by a kaon-
00274           //
00275           vec.Initialize( 1 );
00276           G4ReactionProduct *p = new G4ReactionProduct;
00277           p->SetDefinition( aKaonMinus );
00278           (G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
00279           vec.SetElement( vecLen++, p );
00280           --nneg;
00281         }
00282       }
00283       else if( np == nneg+1 )
00284       {
00285         if( G4UniformRand() < 0.5 )
00286         {
00287           targetParticle.SetDefinitionAndUpdateE( aNeutron );
00288           targetHasChanged = true;
00289         }
00290         else
00291         {
00292           currentParticle.SetDefinitionAndUpdateE( aXiMinus );
00293           incidentHasChanged = true;
00294         }
00295       }
00296       else
00297       {
00298         currentParticle.SetDefinitionAndUpdateE( aXiMinus );
00299         incidentHasChanged = true;
00300         targetParticle.SetDefinitionAndUpdateE( aNeutron );
00301         targetHasChanged = true;
00302       }
00303     }
00304     else  // target must be a neutron
00305     {
00306       counter = -1;
00307       for( np=0; np<numSec/3 && ran>=excs; ++np )
00308       {
00309         for( nneg=std::max(0,np-1); nneg<=(np+2) && ran>=excs; ++nneg )
00310         {
00311           for( nz=0; nz<numSec/3 && ran>=excs; ++nz )
00312           {
00313             if( ++counter < numMul )
00314             {
00315               nt = np+nneg+nz;
00316               if( nt>0 && nt<=numSec )
00317               {
00318                 test = std::exp( std::min( expxu, std::max( expxl, -(pi/4.0)*(nt*nt)/(n*n) ) ) );
00319                 dum = (pi/anpn)*nt*neutmul[counter]*neutnorm[nt-1]/(2.0*n*n);
00320                 if( std::fabs(dum) < 1.0 )
00321                 {
00322                   if( test >= 1.0e-10 )excs += dum*test;
00323                 }
00324                 else
00325                   excs += dum*test;
00326               }
00327             }
00328           }
00329         }
00330       }
00331       if( ran >= excs )  // 3 previous loops continued to the end
00332       {
00333         quasiElastic = true;
00334         return;
00335       }
00336       np--; nneg--; nz--;
00337       if( np < nneg )
00338       {
00339         if( np+1 == nneg )
00340         {
00341           targetParticle.SetDefinitionAndUpdateE( aProton );
00342           targetHasChanged = true;
00343         }
00344         else   // charge mismatch
00345         {
00346           currentParticle.SetDefinitionAndUpdateE( aSigmaPlus );
00347           incidentHasChanged = true;
00348           targetParticle.SetDefinitionAndUpdateE( aProton );
00349           targetHasChanged = true;
00350           //
00351           // correct the strangeness by replacing a pi- by a kaon-
00352           //
00353           vec.Initialize( 1 );
00354           G4ReactionProduct *p = new G4ReactionProduct;
00355           p->SetDefinition( aKaonMinus );
00356           (G4UniformRand() < 0.5) ? p->SetSide( -1 ) : p->SetSide( 1 );
00357           vec.SetElement( vecLen++, p );
00358           --nneg;
00359         }
00360       }
00361       else if( np == nneg )
00362       {
00363         if( G4UniformRand() >= 0.5 )
00364         {
00365           currentParticle.SetDefinitionAndUpdateE( aXiMinus );
00366           incidentHasChanged = true;
00367           targetParticle.SetDefinitionAndUpdateE( aProton );
00368           targetHasChanged = true;
00369         }
00370       }
00371       else
00372       {
00373         currentParticle.SetDefinitionAndUpdateE( aXiMinus );
00374         incidentHasChanged = true;
00375       }        
00376   }
00377 
00378   SetUpPions(np, nneg, nz, vec, vecLen);
00379   return;
00380 }
00381 
00382  /* end of file */
00383  

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