G4QuasiFreeRatios.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 //
00027 // $Id$
00028 //
00029 //
00030 // G4 Physics class: G4QuasiFreeRatios for N+A elastic cross sections
00031 // Created: M.V. Kossov, CERN/ITEP(Moscow), 10-OCT-01
00032 // The last update: M.V. Kossov, CERN/ITEP (Moscow) 28-Oct-11
00033 // 
00034 // ----------------------------------------------------------------------
00035 // Short description: Provides percentage of quasi-free and quasi-elastic
00036 // reactions in the inelastic reactions.
00037 // ----------------------------------------------------------------------
00038 
00039 //#define debug
00040 //#define pdebug
00041 //#define ppdebug
00042 //#define nandebug
00043 
00044 #include "G4QuasiFreeRatios.hh"
00045 #include "G4SystemOfUnits.hh"
00046 
00047 // initialisation of statics
00048 std::vector<G4double*> G4QuasiFreeRatios::vT; // Vector of pointers to LinTable in C++ heap
00049 std::vector<G4double*> G4QuasiFreeRatios::vL; // Vector of pointers to LogTable in C++ heap
00050 
00051 G4QuasiFreeRatios::G4QuasiFreeRatios()
00052 {
00053 #ifdef pdebug
00054   G4cout<<"***^^^*** G4QuasiFreeRatios singletone is created ***^^^***"<<G4endl;
00055 #endif
00056   QFreeScat=G4QFreeScattering::GetPointer();
00057 }
00058 
00059 G4QuasiFreeRatios::~G4QuasiFreeRatios()
00060 {
00061   std::vector<G4double*>::iterator pos;
00062   for(pos=vT.begin(); pos<vT.end(); ++pos) delete [] *pos;
00063   vT.clear();
00064   for(pos=vL.begin(); pos<vL.end(); ++pos) delete [] *pos;
00065   vL.clear();
00066 }
00067 
00068 // Returns Pointer to the G4VQCrossSection class
00069 G4QuasiFreeRatios* G4QuasiFreeRatios::GetPointer()
00070 {
00071   static G4QuasiFreeRatios theRatios;   // *** Static body of the QEl Cross Section ***
00072   return &theRatios;
00073 }
00074 
00075 // Calculation of pair(QuasiFree/Inelastic,QuasiElastic/QuasiFree)
00076 std::pair<G4double,G4double> G4QuasiFreeRatios::GetRatios(G4double pIU, G4int pPDG,
00077                                                            G4int tgZ,    G4int tgN)
00078 {
00079 #ifdef pdebug
00080   G4cout<<">>>IN>>>G4QFRat::GetQF:P="<<pIU<<",pPDG="<<pPDG<<",Z="<<tgZ<<",N="<<tgN<<G4endl;
00081 #endif
00082   G4double R=0.;
00083   G4double QF2In=1.;                        // Prototype of QuasiFree/Inel ratio for hN_tot
00084   G4int tgA=tgZ+tgN;
00085   if(tgA<2) return std::make_pair(QF2In,R); // No quasi-elastic on the only nucleon
00086   std::pair<G4double,G4double> ElTot=GetElTot(pIU, pPDG, tgZ, tgN); // mean (IU)
00087   //if( ( (pPDG>999 && pIU<227.) || pIU<27.) && tgA>1) R=1.; // @@ TMP to accelerate @lowE
00088   if(pPDG>999 && pIU<227. && tgZ+tgN>1) R=1.;                // To accelerate @lowE
00089   else if(ElTot.second>0.)
00090   {
00091     R=ElTot.first/ElTot.second;             // El/Total ratio (does not depend on units
00092     QF2In=GetQF2IN_Ratio(ElTot.second/millibarn, tgZ+tgN);   // QuasiFree/Inelastic ratio
00093   }
00094 #ifdef pdebug
00095   G4cout<<">>>OUT>>>G4QuasiFreeRatio::GetQF2IN_Ratio: QF2In="<<QF2In<<", R="<<R<<G4endl;
00096 #endif
00097   return std::make_pair(QF2In,R);
00098 }
00099 
00100 // Calculatio QasiFree/Inelastic Ratio as a function of total hN cross-section (mb) and A
00101 G4double G4QuasiFreeRatios::GetQF2IN_Ratio(G4double s_value, G4int A)
00102 {
00103   static const G4int    nps=150;        // Number of steps in the R(s) LinTable
00104   static const G4int    mps=nps+1;      // Number of elements in the R(s) LinTable
00105   static const G4double sma=150.;       // The first LinTabEl(s=0)=1., s>sma -> LogTable
00106   static const G4double ds=sma/nps;     // Step of the linear Table
00107   static const G4int    nls=100;        // Number of steps in the R(lns) LogTable
00108   static const G4int    mls=nls+1;      // Number of elements in the R(lns) LogTable
00109   static const G4double lsi=5.;         // The min ln(s) LogTabEl(s=148.4 < sma=150.)
00110   static const G4double lsa=9.;         // The max ln(s) LogTabEl(s=148.4 - 8103. mb)
00111   static const G4double mi=std::exp(lsi);// The min s of LogTabEl(~ 148.4 mb)
00112   static const G4double max_s=std::exp(lsa);// The max s of LogTabEl(~ 8103. mb)
00113   static const G4double dl=(lsa-lsi)/nls;// A step Log-Length of the Logarithmic Table
00114   static const G4double edl=std::exp(dl);// Multiplication step of the Logarithmic Table
00115   static const G4double toler=.01;      // The tolarence mb defining the same cross-section
00116   static G4double lastS=0.;             // The last sigma value for which R was calculated
00117   static G4double lastR=0.;             // The last ratio R which was calculated
00118   // Local Associative Data Base:
00119   static std::vector<G4int>     vA;     // Vector of calculated A
00120   static std::vector<G4double>  vH;     // Vector of max s initialized in the LinTable
00121   static std::vector<G4int>     vN;     // Vector of topBin number initialized in LinTable
00122   static std::vector<G4double>  vM;     // Vector of rel max ln(s) initialized in LogTable
00123   static std::vector<G4int>     vK;     // Vector of topBin number initialized in LogTable
00124   // Last values of the Associative Data Base:
00125   static G4int     lastA=0;             // theLast of calculated A
00126   static G4double  lastH=0.;            // theLast of max s initialized in the LinTable
00127   static G4int     lastN=0;             // theLast of topBin number initialized in LinTable
00128   static G4double  lastM=0.;            // theLast of rel max ln(s) initialized in LogTable
00129   static G4int     lastK=0;             // theLast of topBin number initialized in LogTable
00130   static G4double* lastT=0;             // theLast of pointer to LinTable in the C++ heap
00131   static G4double* lastL=0;             // theLast of pointer to LogTable in the C++ heap
00132   // LogTable is created only if necessary. The ratio R(s>8100 mb) = 0 for any nuclei
00133 #ifdef pdebug
00134   G4cout<<"+++G4QuasiFreeRatio::GetQF2IN_Ratio:A="<<A<<", s="<<s_value<<G4endl;
00135 #endif
00136   if(s_value<toler || A<2) return 1.;
00137   if(s_value>max_s) return 0.;
00138   if(A>238)
00139   {
00140     G4cout<<"-Warning-G4QuasiFreeRatio::GetQF2IN_Ratio:A="<<A<<">238, return zero"<<G4endl;
00141     return 0.;
00142   }
00143   G4int nDB=vA.size();                  // A number of nuclei already initialized in AMDB
00144   //  if(nDB && lastA==A && std::fabs(s_value-lastS)<toler) return lastR;
00145   if(nDB && lastA==A && s_value==lastS) return lastR;  // VI do not use tolerance
00146   G4bool found=false;
00147   G4int i=-1;
00148   if(nDB) for (i=0; i<nDB; i++) if(A==vA[i]) // Sirch for this A in AMDB
00149   {
00150     found=true;                         // The A value is found
00151     break;
00152   }
00153 #ifdef pdebug
00154   G4cout<<"+++G4QuasiFreeRatio::GetQF2IN_Ratio: nDB="<<nDB<<", found="<<found<<G4endl;
00155 #endif
00156   if(!nDB || !found)                    // Create new line in the AMDB
00157   {
00158     lastA = A;
00159 #ifdef pdebug
00160     G4cout<<"G4QuasiFreeRatios::GetQF2IN_Ratio: NewT, A="<<A<<", nDB="<<nDB<<G4endl;
00161 #endif
00162     lastT = new G4double[mps];          // Create the Linear Table
00163     lastN = static_cast<int>(s_value/ds)+1;   // MaxBin to be initialized in Lin Table
00164     if(lastN>nps)                       // The Lin Table should be completely initialized
00165     {
00166       lastN=nps;
00167       lastH=sma;
00168     }
00169     else lastH = lastN*ds;              // Calculate max initialized s for Lin Table
00170     G4double sv=0;
00171     lastT[0]=1.;
00172     for(G4int j=1; j<=lastN; j++)       // Calculate Lin Table values
00173     {
00174       sv+=ds;
00175       lastT[j]=CalcQF2IN_Ratio(sv,A);
00176     }
00177     lastL=new G4double[mls];            // Create the Logarithmic Table
00178     if(s_value>sma)                     // Initialize the Log Table (at least a part of it)
00179     {
00180 #ifdef pdebug
00181       G4cout<<"G4QuasiFreeRatios::GetQF2IN_Ratio: NewL, A="<<A<<", nDB="<<nDB<<G4endl;
00182 #endif
00183       G4double ls=std::log(s_value);
00184       lastK = static_cast<int>((ls-lsi)/dl)+1; // MaxBin to be initialized in Log Table
00185       if(lastK>nls)                     // The Log Table should be completely initialized
00186       {
00187         lastK=nls;
00188         lastM=lsa-lsi;                  // lastM is a ln(s)-difference (not a s-difference)
00189       }
00190       else lastM = lastK*dl;            // Calculate max initialized ln(s)-lsi for LogTab
00191       sv=mi;                            // Min s (not ln(s)) for the Log Table
00192       for(G4int j=0; j<=lastK; j++)     // Calculate Log Table values
00193       {
00194         lastL[j]=CalcQF2IN_Ratio(sv,A);
00195         if(j!=lastK) sv*=edl;
00196       }
00197     }
00198     else                                // Log Tab is not initialized for the firs call
00199     {
00200       lastK = 0;
00201       lastM = 0.;
00202     }
00203     i++;                                // Make a new record to AMDB and position on it
00204     vA.push_back(lastA);
00205     vH.push_back(lastH);
00206     vN.push_back(lastN);
00207     vM.push_back(lastM);
00208     vK.push_back(lastK);
00209     vT.push_back(lastT);
00210     vL.push_back(lastL);
00211   }
00212   else                                  // The A value was found in AMDB
00213   {
00214     lastA=vA[i];
00215     lastH=vH[i];
00216     lastN=vN[i];
00217     lastM=vM[i];
00218     lastK=vK[i];
00219     lastT=vT[i];
00220     lastL=vL[i];
00221 #ifdef pdebug
00222     G4cout<<"G4QuasiFreeRatios::GetQF2IN_Ratio: Found, s="<<s_value<<", lastM="<<lastM<<G4endl;
00223 #endif
00224     if(s_value>lastH)                          // At least Lin Table must be updated
00225     {
00226       G4int nextN=lastN+1;               // The next bin to be initialized in Lin Table (p)
00227 #ifdef pdebug
00228       G4cout<<"G4QuasiFreeRatios::GetQF2IN_Ratio: lastN="<<lastN<<" ?< nps="<<nps<<G4endl;
00229 #endif
00230       if(lastN < nps)                    // The Lin Table is not completely initialized
00231       {
00232         lastN = static_cast<int>(s_value/ds)+1;// MaxBin to be initialized in Lin Table
00233         G4double sv=lastH;
00234         if(lastN>nps)
00235         {
00236           lastN=nps;
00237           lastH=sma;
00238         }
00239         else lastH = lastN*ds;           // Calculate max initialized s for LinTab
00240         for(G4int j=nextN; j<=lastN; j++)// Calculate LogTab values
00241         {
00242           sv+=ds;
00243           lastT[j]=CalcQF2IN_Ratio(sv,A);
00244         }
00245 #ifdef pdebug
00246         G4cout<<"G4QuasiFreeRatios::GetQF2IN_Ratio: End of LinTab update"<<G4endl;
00247 #endif
00248       } // End of LinTab update
00249 #ifdef pdebug
00250       G4cout<<"G4QFRatios::GetQF2IN_Ratio: lN="<<lastN<<", nN="<<nextN<<", i="<<i<<G4endl;
00251 #endif
00252       if(lastN >= nextN)                 // The Lin Table update really took place
00253       {
00254         vH[i]=lastH;
00255         vN[i]=lastN;
00256       }
00257       G4int nextK=lastK+1;               // Possible next element in LogTable to be updated
00258       if(!lastK) nextK=0;                // The Log Table has not been filled at all
00259 #ifdef pdebug
00260       G4cout<<"G4QFRat::GetQF2IN_Ratio: sma="<<sma<<", lastK="<<lastK<<" < "<<nls<<G4endl;
00261 #endif
00262       if(s_value>sma && lastK<nls)             // LogTab must be updated (not filled completely)
00263       {
00264         G4double sv=std::exp(lastM+lsi); // Define starting s-poit (lastM will be changed)
00265         G4double ls=std::log(s_value);
00266         lastK = static_cast<int>((ls-lsi)/dl)+1; // MaxBin to be initialized in Log Table
00267         if(lastK>nls)
00268         {
00269           lastK=nls;
00270           lastM=lsa-lsi;
00271         }
00272         else lastM = lastK*dl;           // Calculate max initialized ln(s)-lsi for LogTab
00273 #ifdef pdebug
00274         G4cout<<"G4QFRat::GetQF2IN_Ratio: nK="<<nextK<<", lK="<<lastK<<", sv="<<sv<<G4endl;
00275 #endif
00276         for(G4int j=nextK; j<=lastK; j++)// Calculate LogTab values
00277         {
00278           sv*=edl;
00279 #ifdef pdebug
00280           G4cout<<"G4QFRat::GetQF2IN_Ratio: j="<<j<<", sv="<<sv<<", A="<<A<<G4endl;
00281 #endif
00282           lastL[j]=CalcQF2IN_Ratio(sv,A);
00283         }
00284 #ifdef pdebug
00285         G4cout<<"G4QuasiFreeRatios::GetQF2IN_Ratio: End of LinTab update"<<G4endl;
00286 #endif
00287       } // End of LogTab update
00288 #ifdef pdebug
00289       G4cout<<"G4QFRatios::GetQF2IN_Ratio: lK="<<lastK<<", nK="<<nextK<<", i="<<i<<G4endl;
00290 #endif
00291       if(lastK >= nextK)                 // The Lin Table update really took place
00292       {
00293         vM[i]=lastM;
00294         vK[i]=lastK;
00295       }
00296     }
00297   }
00298 #ifdef pdebug
00299   G4cout<<"G4QuasiFreeRatios::GetQF2IN_Ratio: BeforeTab s="<<s_value<<", sma="<<sma<<G4endl;
00300 #endif
00301   // Now one can use tabeles to calculate the value
00302   if(s_value<sma)                             // Use linear table
00303   {
00304     G4int n=static_cast<int>(s_value/ds);     // Low edge number of the bin
00305     G4double d=s_value-n*ds;                  // Linear shift
00306     G4double v=lastT[n];                // Base
00307     lastR=v+d*(lastT[n+1]-v)/ds;        // Result
00308   }
00309   else                                  // Use log table
00310   {
00311     G4double ls=std::log(s_value)-lsi;        // ln(s)-l_min
00312     G4int n=static_cast<int>(ls/dl);    // Low edge number of the bin
00313     G4double d=ls-n*dl;                 // Log shift
00314     G4double v=lastL[n];                // Base
00315     lastR=v+d*(lastL[n+1]-v)/dl;        // Result
00316   }
00317   if(lastR<0.) lastR=0.;
00318   if(lastR>1.) lastR=1.;
00319 #ifdef pdebug
00320   G4cout<<"G4QuasiFreeRatios::GetQF2IN_Ratio: BeforeRet lastR="<<lastR<<G4endl;
00321 #endif
00322   return lastR;
00323 } // End of CalcQF2IN_Ratio
00324 
00325 // Calculatio QasiFree/Inelastic Ratio as a function of total hN cross-section and A
00326 G4double G4QuasiFreeRatios::CalcQF2IN_Ratio(G4double s_value, G4int A)
00327 {
00328   static const G4double C=1.246;
00329   G4double s2=s_value*s_value;
00330   G4double s4=s2*s2;
00331   G4double ss=std::sqrt(std::sqrt(s_value));
00332   G4double P=7.48e-5*s2/(1.+8.77e12/s4/s4/s2);
00333   G4double E=.2644+.016/(1.+std::exp((29.54-s_value)/2.49));
00334   G4double F=ss*.1526*std::exp(-s2*ss*.0000859);
00335   return C*std::exp(-E*std::pow(G4double(A-1.),F))/std::pow(G4double(A),P);
00336 } // End of CalcQF2IN_Ratio
00337 
00338 // For hadron PDG with momentum Mom (GeV/c) on N (p/n) calculate <sig_el,sig_tot> pair (mb)
00339 std::pair<G4double,G4double> G4QuasiFreeRatios::GetElTotXS(G4double p, G4int PDG, G4bool F)
00340 {
00341   G4int ind=0;                                 // Prototype of the reaction index
00342   G4bool kfl=true;                             // Flag of K0/aK0 oscillation
00343   G4bool kf=false;
00344   if(PDG==130||PDG==310)
00345   {
00346     kf=true;
00347     if(G4UniformRand()>.5) kfl=false;
00348   }
00349   if      ( (PDG == 2212 && F) || (PDG == 2112 && !F) ) ind=0; // pp/nn
00350   else if ( (PDG == 2112 && F) || (PDG == 2212 && !F) ) ind=1; // np/pn
00351   else if ( (PDG == -211 && F) || (PDG == 211 && !F) ) ind=2; // pimp/pipn
00352   else if ( (PDG == 211 && F) || (PDG == -211 && !F) ) ind=3; // pipp/pimn
00353   else if ( PDG == -321 || PDG == -311 || (kf && !kfl) ) ind=4; // KmN/K0N
00354   else if ( PDG == 321 || PDG == 311 || (kf && kfl) ) ind=5; // KpN/aK0N
00355   else if ( PDG >  3000 && PDG <  3335) ind=6; // @@ for all hyperons - take Lambda
00356   else if ( PDG > -3335 && PDG < -2000) ind=7; // @@ for all anti-baryons (anti-p/anti-n)
00357   else {
00358     G4cout<<"*Error*G4QuasiFreeRatios::CalcElTotXS: PDG="<<PDG
00359           <<", while it is defined only for p,n,hyperons,anti-baryons,pi,K/antiK"<<G4endl;
00360     G4Exception("G4QuasiFreeRatio::CalcElTotXS:","22",FatalException,"CHIPScrash");
00361   }
00362   return QFreeScat->CalcElTot(p,ind);
00363 }
00364 
00365 // (Mean Elastic and Mean Total) Cross-Sections (mb) for PDG+(Z,N) at P=p[GeV/c]
00366 std::pair<G4double,G4double> G4QuasiFreeRatios::GetElTot(G4double pIU, G4int hPDG,
00367                                                          G4int Z,       G4int N)
00368 {
00369   G4double pGeV=pIU/gigaelectronvolt;
00370 #ifdef pdebug
00371   G4cout<<"-->G4QuasiFreeR::GetElTot: P="<<pIU<<",pPDG="<<hPDG<<",Z="<<Z<<",N="<<N<<G4endl;
00372 #endif
00373   if(Z<1 && N<1)
00374   {
00375     G4cout<<"-Warning-G4QuasiFreeRatio::GetElTot:Z="<<Z<<",N="<<N<<", return zero"<<G4endl;
00376     return std::make_pair(0.,0.);
00377   }
00378   std::pair<G4double,G4double> hp=QFreeScat->FetchElTot(pGeV, hPDG, true);
00379   std::pair<G4double,G4double> hn=QFreeScat->FetchElTot(pGeV, hPDG, false);
00380 #ifdef pdebug
00381   G4cout<<"-OUT->G4QFRat::GetElTot: hp("<<hp.first<<","<<hp.second<<"), hn("<<hn.first<<","
00382         <<hn.second<<")"<<G4endl;
00383 #endif
00384   G4double A=(Z+N)/millibarn;                // To make the result in independent units(IU)
00385   return std::make_pair((Z*hp.first+N*hn.first)/A,(Z*hp.second+N*hn.second)/A);
00386 } // End of GetElTot
00387 
00388 // (Mean Elastic and Mean Total) Cross-Sections (mb) for PDG+(Z,N) at P=p[GeV/c]
00389 std::pair<G4double,G4double> G4QuasiFreeRatios::GetChExFactor(G4double pIU, G4int hPDG,
00390                                                               G4int Z, G4int N)
00391 {
00392   G4double pGeV=pIU/gigaelectronvolt;
00393   G4double resP=0.;
00394   G4double resN=0.;
00395   if(Z<1 && N<1)
00396   {
00397     G4cout<<"-Warning-G4QuasiFreeRatio::GetChExF:Z="<<Z<<",N="<<N<<", return zero"<<G4endl;
00398     return std::make_pair(resP,resN);
00399   }
00400   G4double A=Z+N;
00401   G4double pf=0.;                              // Possibility to interact with a proton
00402   G4double nf=0.;                              // Possibility to interact with a neutron
00403   if   (hPDG==-211||hPDG==-321||hPDG==3112||hPDG==3212||hPDG==3312||hPDG==3334) pf=Z/(A+N);
00404   else if(hPDG==211||hPDG==321||hPDG==3222||hPDG==3212||hPDG==3322) nf=N/(A+Z);
00405   else if(hPDG==-311||hPDG==311||hPDG==130||hPDG==310)
00406   {
00407     G4double dA=A+A;
00408     pf=Z/(dA+N+N);
00409     nf=N/(dA+Z+Z);
00410   }
00411   G4double mult=1.;  // Factor of increasing multiplicity ( ? @@)
00412   if(pGeV>.5)
00413   {
00414     mult=1./(1.+std::log(pGeV+pGeV))/pGeV;
00415     if(mult>1.) mult=1.;
00416   }
00417   if(pf)
00418   {
00419     std::pair<G4double,G4double> hp=QFreeScat->FetchElTot(pGeV, hPDG, true);
00420     resP=pf*(hp.second/hp.first-1.)*mult;
00421   }
00422   if(nf)
00423   {
00424     std::pair<G4double,G4double> hn=QFreeScat->FetchElTot(pGeV, hPDG, false);
00425     resN=nf*(hn.second/hn.first-1.)*mult;
00426   }
00427   return std::make_pair(resP,resN);
00428 } // End of GetChExFactor
00429 
00430 // scatter (pPDG,p4M) on a virtual nucleon (NPDG,N4M), result: final pair(newN4M,newp4M)
00431 // if(newN4M.e()==0.) - below threshold, XS=0, no scattering of the progectile happened
00432 std::pair<G4LorentzVector,G4LorentzVector> G4QuasiFreeRatios::Scatter(G4int NPDG,
00433                                      G4LorentzVector N4M, G4int pPDG, G4LorentzVector p4M)
00434 {
00435   static const G4double mNeut= G4QPDGCode(2112).GetMass();
00436   static const G4double mProt= G4QPDGCode(2212).GetMass();
00437   static const G4double mDeut= G4QPDGCode(2112).GetNuclMass(1,1,0);// Mass of deuteron
00438   static const G4double mTrit= G4QPDGCode(2112).GetNuclMass(1,2,0);// Mass of tritium
00439   static const G4double mHel3= G4QPDGCode(2112).GetNuclMass(2,1,0);// Mass of Helium3
00440   static const G4double mAlph= G4QPDGCode(2112).GetNuclMass(2,2,0);// Mass of alpha
00441   static const G4double two3d= 2./3.;
00442   static const G4double two3d2= std::pow(2.,two3d); // The slope reductions for fragments
00443   static const G4double two3d3= std::pow(3.,two3d);
00444   static const G4double two3d4= std::pow(4.,two3d);
00445   G4LorentzVector pr4M=p4M/megaelectronvolt;   // Convert 4-momenta in MeV (keep p4M)
00446   N4M/=megaelectronvolt;
00447   G4LorentzVector tot4M=N4M+p4M;
00448 #ifdef ppdebug
00449   G4cerr<<"->G4QFR::Scat:p4M="<<pr4M<<",N4M="<<N4M<<",t4M="<<tot4M<<",NPDG="<<NPDG<<G4endl;
00450 #endif
00451   G4double mT=mNeut;
00452   G4int Z=0;
00453   G4int N=1;
00454   if(NPDG==2212||NPDG==90001000)
00455   {
00456     mT=mProt;
00457     Z=1;
00458     N=0;
00459   }
00460   else if(NPDG==90001001)
00461   {
00462     mT=mDeut;
00463     Z=1;
00464     N=1;
00465   }
00466   else if(NPDG==90002001)
00467   {
00468     mT=mHel3;
00469     Z=2;
00470     N=1;
00471   }
00472   else if(NPDG==90001002)
00473   {
00474     mT=mTrit;
00475     Z=1;
00476     N=2;
00477   }
00478   else if(NPDG==90002002)
00479   {
00480     mT=mAlph;
00481     Z=2;
00482     N=2;
00483   }
00484   else if(NPDG!=2112&&NPDG!=90000001)
00485   {
00486     G4cout<<"Error:G4QuasiFreeRatios::Scatter:NPDG="<<NPDG<<" is not 2212 or 2112"<<G4endl;
00487     G4Exception("G4QuasiFreeRatios::Scatter:","21",FatalException,"CHIPScomplain");
00488     //return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M);// Use this if not exception
00489   }
00490   G4double mT2=mT*mT;
00491   G4double mP2=pr4M.m2();
00492   G4double E=(tot4M.m2()-mT2-mP2)/(mT+mT);
00493 #ifdef pdebug
00494   G4cerr<<"G4QFR::Scat:qM="<<mT<<",qM2="<<mT2<<",pM2="<<mP2<<",totM2="<<tot4M.m2()<<G4endl;
00495 #endif
00496   G4double E2=E*E;
00497   if(E<0. || E2<mP2)
00498   {
00499 #ifdef ppdebug
00500     G4cerr<<"-Warning-G4QFR::Scat:*Negative Energy*E="<<E<<",E2="<<E2<<"<M2="<<mP2<<G4endl;
00501 #endif
00502     return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
00503   }
00504   G4double P=std::sqrt(E2-mP2);                   // Momentum in pseudo laboratory system
00505   G4VQCrossSection* PCSmanager=G4QProtonElasticCrossSection::GetPointer();
00506   G4VQCrossSection* NCSmanager=G4QNeutronElasticCrossSection::GetPointer();
00507 #ifdef ppdebug
00508   G4cout<<"G4QFR::Scatter: Before XS, P="<<P<<", Z="<<Z<<", N="<<N<<", PDG="<<pPDG<<G4endl;
00509 #endif
00510   // @@ Temporary NN t-dependence for all hadrons
00511   if(pPDG>3400 || pPDG<-3400) G4cout<<"-Warning-G4QuasiFree::Scatter: pPDG="<<pPDG<<G4endl;
00512   G4int PDG=2212;                                                // *TMP* instead of pPDG
00513   if(pPDG==2112||pPDG==-211||pPDG==-321) PDG=2112;               // *TMP* instead of pPDG
00514   if(!Z && N==1)                 // Change for Quasi-Elastic on neutron
00515   {
00516     Z=1;
00517     N=0;
00518     if     (PDG==2212) PDG=2112;
00519     else if(PDG==2112) PDG=2212;
00520   }
00521   G4double xSec=0.;                        // Prototype of Recalculated Cross Section *TMP*
00522   if(PDG==2212) xSec=PCSmanager->GetCrossSection(false, P, Z, N, PDG); // P CrossSect *TMP*
00523   else          xSec=NCSmanager->GetCrossSection(false, P, Z, N, PDG); // N CrossSect *TMP*
00524 #ifdef ppdebug
00525   G4cout<<"G4QuasiFreeRat::Scatter: pPDG="<<pPDG<<",P="<<P<<",CS="<<xSec/millibarn<<G4endl;
00526 #endif
00527 #ifdef nandebug
00528   if(xSec>0. || xSec<0. || xSec==0);
00529   else  G4cout<<"*Warning*G4QuasiFreeRatios::Scatter: xSec="<<xSec/millibarn<<G4endl;
00530 #endif
00531   // @@ check a possibility to separate p, n, or alpha (!)
00532   if(xSec <= 0.)                                    // The cross-section iz 0 -> Do Nothing
00533   {
00534 #ifdef ppdebug
00535     G4cerr<<"-Warning-G4QFR::Scat:**Zero XS**PDG="<<pPDG<<",NPDG="<<NPDG<<",P="<<P<<G4endl;
00536 #endif
00537     return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); //Do Nothing Action
00538   }
00539   G4double mint=0.;                        // Prototype of functional rand -t (MeV^2) *TMP*
00540   if(PDG==2212) mint=PCSmanager->GetExchangeT(Z,N,PDG);// P functional rand -t(MeV^2) *TMP*
00541   else          mint=NCSmanager->GetExchangeT(Z,N,PDG);// N functional rand -t(MeV^2) *TMP*
00542   if     (mT==mDeut)              mint/=two3d2;
00543   else if(mT==mTrit || mT==mHel3) mint/=two3d3; 
00544   else if(mT==mAlph)              mint/=two3d4; 
00545   G4double maxt=0.;                                    // Prototype of max possible -t
00546   if(PDG==2212) maxt=PCSmanager->GetHMaxT();           // max possible -t
00547   else          maxt=NCSmanager->GetHMaxT();           // max possible -t
00548 #ifdef ppdebug
00549   G4cout<<"G4QFR::Scat:PDG="<<PDG<<",P="<<P<<",X="<<xSec<<",-t="<<mint<<"<"<<maxt<<", Z="
00550         <<Z<<",N="<<N<<G4endl;
00551 #endif
00552 #ifdef nandebug
00553   if(mint>-.0000001);
00554   else  G4cout<<"*Warning*G4QFR::Scat: -t="<<mint<<G4endl;
00555 #endif
00556   G4double cost=1.-(mint+mint)/maxt; // cos(theta) in CMS
00557 #ifdef ppdebug
00558   G4cout<<"G4QFR::Scat:-t="<<mint<<"<"<<maxt<<", cost="<<cost<<", Z="<<Z<<",N="<<N<<G4endl;
00559 #endif
00560   if(cost>1. || cost<-1. || !(cost>-1. || cost<=1.))
00561   {
00562     if     (cost>1.)  cost=1.;
00563     else if(cost<-1.) cost=-1.;
00564     else
00565     {
00566       G4double tm=0.;
00567       if(PDG==2212) tm=PCSmanager->GetHMaxT();
00568       else          tm=NCSmanager->GetHMaxT();
00569       G4cerr<<"G4QuasiFreeRatio::Scat:*NAN* cost="<<cost<<",-t="<<mint<<",tm="<<tm<<G4endl;
00570       return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
00571     }
00572   }
00573   G4LorentzVector reco4M=G4LorentzVector(0.,0.,0.,mT);      // 4mom of the recoil nucleon
00574   G4LorentzVector dir4M=tot4M-G4LorentzVector(0.,0.,0.,(tot4M.e()-mT)*.01);
00575   if(!G4QHadron(tot4M).RelDecayIn2(pr4M, reco4M, dir4M, cost, cost))
00576   {
00577     G4cerr<<"G4QFR::Scat:t="<<tot4M<<tot4M.m()<<",mT="<<mT<<",mP="<<std::sqrt(mP2)<<G4endl;
00578     //G4Exception("G4QFR::Scat:","009",FatalException,"Decay of ElasticComp");
00579     return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
00580   }
00581 #ifdef ppdebug
00582   G4cout<<"G4QFR::Scat:p4M="<<pr4M<<"+r4M="<<reco4M<<",dr="<<dir4M<<",t4M="<<tot4M<<G4endl;
00583 #endif
00584   return std::make_pair(reco4M*megaelectronvolt,pr4M*megaelectronvolt); // Result
00585 } // End of Scatter
00586 
00587 // scatter (pPDG,p4M) on a virtual nucleon (NPDG,N4M), result: final pair(newN4M,newp4M)
00588 // if(newN4M.e()==0.) - below threshold, XS=0, no scattering of the progectile happened
00589 // User should himself change the charge (PDG) (e.g. pn->np, pi+n->pi0p, pi-p->pi0n etc.)
00590 std::pair<G4LorentzVector,G4LorentzVector> G4QuasiFreeRatios::ChExer(G4int NPDG,
00591                                      G4LorentzVector N4M, G4int pPDG, G4LorentzVector p4M)
00592 {
00593   static const G4double mNeut= G4QPDGCode(2112).GetMass();
00594   static const G4double mProt= G4QPDGCode(2212).GetMass();
00595   G4LorentzVector pr4M=p4M/megaelectronvolt;          // Convert 4-momenta in MeV(keep p4M)
00596   N4M/=megaelectronvolt;
00597   G4LorentzVector tot4M=N4M+p4M;
00598   G4int Z=0;
00599   G4int N=1;
00600   G4int sPDG=0;                                        // PDG code of the scattered hadron
00601   G4double mS=0.;                                      // proto of mass of scattered hadron
00602   G4double mT=mProt;                                   // mass of the recoil nucleon
00603   G4cout<<"-Warning-G4QFR::ChEx: Impossible for Omega-"<<G4endl; // Omega-
00604   if(NPDG==2212)
00605   {
00606     mT=mNeut;
00607     Z=1;
00608     N=0;
00609     if(pPDG==-211) sPDG=111;                           // pi+    -> pi0
00610     else if(pPDG==-321)
00611     {
00612       sPDG=310;                                        // K+     -> K0S
00613       if(G4UniformRand()>.5) sPDG=130;                 // K+     -> K0L
00614     }
00615     else if(pPDG==-311||pPDG==311||pPDG==130||pPDG==310) sPDG=321;  // K0     -> K+ (?)
00616     else if(pPDG==3112) sPDG=3212;                     // Sigma- -> Sigma0
00617     else if(pPDG==3212) sPDG=3222;                     // Sigma0 -> Sigma+
00618     else if(pPDG==3312) sPDG=3322;                     // Xi-    -> Xi0
00619   }
00620   else if(NPDG==2112) // Default
00621   {
00622     if(pPDG==211)  sPDG=111;                           // pi+    -> pi0
00623     else if(pPDG==321)
00624     {
00625       sPDG=310;                                        // K+     -> K0S
00626       if(G4UniformRand()>.5) sPDG=130;                 // K+     -> K0L
00627     }
00628     else if(pPDG==-311||pPDG==311||pPDG==130||pPDG==310) sPDG=-321; // K0     -> K- (?)
00629     else if(pPDG==3222) sPDG=3212;                     // Sigma+ -> Sigma0
00630     else if(pPDG==3212) sPDG=3112;                     // Sigma0 -> Sigma-
00631     else if(pPDG==3322) sPDG=3312;                     // Xi0    -> Xi-
00632   }
00633   else
00634   {
00635     G4cout<<"Error:G4QuasiFreeRatios::ChExer: NPDG="<<NPDG<<" is not 2212 or 2112"<<G4endl;
00636     G4Exception("G4QuasiFreeRatios::ChExer:","21",FatalException,"CHIPS complain");
00637     //return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M);// Use this if not exception
00638   }
00639   if(sPDG) mS=mNeut;
00640   else
00641   {
00642     G4cout<<"Error:G4QuasiFreeRatios::ChExer: BAD pPDG="<<pPDG<<", NPDG="<<NPDG<<G4endl;
00643     G4Exception("G4QuasiFreeRatios::ChExer:","21",FatalException,"CHIPS complain");
00644     //return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M);// Use this if not exception
00645   }
00646   G4double mT2=mT*mT;
00647   G4double mS2=mS*mS;
00648   G4double E=(tot4M.m2()-mT2-mS2)/(mT+mT);
00649   G4double E2=E*E;
00650   if(E<0. || E2<mS2)
00651   {
00652 #ifdef pdebug
00653     G4cerr<<"-Warning-G4QFR::ChEx:*Negative Energy*E="<<E<<",E2="<<E2<<"<M2="<<mS2<<G4endl;
00654 #endif
00655     return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
00656   }
00657   G4double P=std::sqrt(E2-mS2);                   // Momentum in pseudo laboratory system
00658   G4VQCrossSection* PCSmanager=G4QProtonElasticCrossSection::GetPointer();
00659   G4VQCrossSection* NCSmanager=G4QNeutronElasticCrossSection::GetPointer();
00660 #ifdef debug
00661   G4cout<<"G4QFR::ChExer: Before XS, P="<<P<<", Z="<<Z<<", N="<<N<<", PDG="<<pPDG<<G4endl;
00662 #endif
00663   // @@ Temporary NN t-dependence for all hadrons
00664   G4int PDG=2212;                                                // *TMP* instead of pPDG
00665   if(pPDG==2112||pPDG==-211||pPDG==-321) PDG=2112;               // *TMP* instead of pPDG
00666   if(!Z && N==1)                 // Change for Quasi-Elastic on neutron
00667   {
00668     Z=1;
00669     N=0;
00670     if     (PDG==2212) PDG=2112;
00671     else if(PDG==2112) PDG=2212;
00672   }
00673   G4double xSec=0.;                        // Prototype of Recalculated Cross Section *TMP*
00674   if(PDG==2212) xSec=PCSmanager->GetCrossSection(false, P, Z, N, PDG); // P CrossSect *TMP*
00675   else          xSec=NCSmanager->GetCrossSection(false, P, Z, N, PDG); // N CrossSect *TMP*
00676 #ifdef debug
00677   G4cout<<"G4QuasiFreeRat::ChExer: pPDG="<<pPDG<<",P="<<P<<", CS="<<xSec/millibarn<<G4endl;
00678 #endif
00679 #ifdef nandebug
00680   if(xSec>0. || xSec<0. || xSec==0);
00681   else  G4cout<<"*Warning*G4QuasiFreeRatios::ChExer: xSec="<<xSec/millibarn<<G4endl;
00682 #endif
00683   // @@ check a possibility to separate p, n, or alpha (!)
00684   if(xSec <= 0.) // The cross-section iz 0 -> Do Nothing
00685   {
00686 #ifdef pdebug
00687     G4cerr<<"-Warning-G4QFR::ChEx:**Zero XS**PDG="<<pPDG<<",NPDG="<<NPDG<<",P="<<P<<G4endl;
00688 #endif
00689     return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); //Do Nothing Action
00690   }
00691   G4double mint=0.;                        // Prototype of functional rand -t (MeV^2) *TMP*
00692   if(PDG==2212) mint=PCSmanager->GetExchangeT(Z,N,PDG);// P functional rand -t(MeV^2) *TMP*
00693   else          mint=NCSmanager->GetExchangeT(Z,N,PDG);// N functional rand -t(MeV^2) *TMP*
00694 #ifdef pdebug
00695   G4cout<<"G4QFR::ChEx:PDG="<<pPDG<<", P="<<P<<", CS="<<xSec<<", -t="<<mint<<G4endl;
00696 #endif
00697 #ifdef nandebug
00698   if(mint>-.0000001);
00699   else  G4cout<<"*Warning*G4QFR::ChExer: -t="<<mint<<G4endl;
00700 #endif
00701   G4double maxt=0.;                                    // Prototype of max possible -t
00702   if(PDG==2212) maxt=PCSmanager->GetHMaxT();           // max possible -t
00703   else          maxt=NCSmanager->GetHMaxT();           // max possible -t
00704   G4double cost=1.-mint/maxt;                          // cos(theta) in CMS
00705 #ifdef pdebug
00706   G4cout<<"G4QuasiFfreeRatio::ChExer: -t="<<mint<<", maxt="<<maxt<<", cost="<<cost<<G4endl;
00707 #endif
00708   if(cost>1. || cost<-1. || !(cost>-1. || cost<=1.))
00709   {
00710     if     (cost>1.)  cost=1.;
00711     else if(cost<-1.) cost=-1.;
00712     else
00713     {
00714       G4cerr<<"G4QuasiFreeRatio::ChExer:*NAN* c="<<cost<<",t="<<mint<<",tm="<<maxt<<G4endl;
00715       return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
00716     }
00717   }
00718   G4LorentzVector reco4M=G4LorentzVector(0.,0.,0.,mT);      // 4mom of the recoil nucleon
00719   pr4M=G4LorentzVector(0.,0.,0.,mS);                        // 4mom of the scattered hadron
00720   G4LorentzVector dir4M=tot4M-G4LorentzVector(0.,0.,0.,(tot4M.e()-mT)*.01);
00721   if(!G4QHadron(tot4M).RelDecayIn2(pr4M, reco4M, dir4M, cost, cost))
00722   {
00723     G4cerr<<"G4QFR::ChEx:t="<<tot4M<<tot4M.m()<<",mT="<<mT<<",mP="<<mS<<G4endl;
00724     //G4Exception("G4QFR::ChExer:","009",FatalException,"Decay of ElasticComp");
00725     return std::make_pair(G4LorentzVector(0.,0.,0.,0.),p4M); // Do Nothing Action
00726   }
00727 #ifdef debug
00728   G4cout<<"G4QFR::ChEx:p4M="<<p4M<<"+r4M="<<reco4M<<"="<<p4M+reco4M<<"="<<tot4M<<G4endl;
00729 #endif
00730   return std::make_pair(reco4M*megaelectronvolt,pr4M*megaelectronvolt); // Result
00731 } // End of ChExer
00732 
00733 // Calculate ChEx/El ratio (p is in independent units, (Z,N) is target, pPDG is projectile)
00734 G4double G4QuasiFreeRatios::ChExElCoef(G4double p, G4int Z, G4int N, G4int pPDG) 
00735 {
00736   p/=MeV;                                // Converted from independent units
00737   G4double A=Z+N;
00738   if(A<1.5) return 0.;
00739   G4double C=0.;
00740   if     (pPDG==2212) C=N/(A+Z);
00741   else if(pPDG==2112) C=Z/(A+N);
00742   else G4cout<<"*Warning*G4QCohChrgExchange::ChExElCoef: wrong PDG="<<pPDG<<G4endl;
00743   C*=C;                         // Coherent processes squares the amplitude
00744   // @@ This is true only for nucleons: other projectiles must be treated differently
00745   G4double sp=std::sqrt(p);
00746   G4double p2=p*p;            
00747   G4double p4=p2*p2;
00748   G4double dl1=std::log(p)-5.;
00749   G4double T=(6.75+.14*dl1*dl1+13./p)/(1.+.14/p4)+.6/(p4+.00013);
00750   G4double U=(6.25+8.33e-5/p4/p)*(p*sp+.34)/p2/p; 
00751   G4double R=U/T;
00752   return C*R*R;
00753 }

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