// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // //$Id: G4AnalyticalEcpssrKCrossSection.cc,v 1.2 2010/06/09 07:15:50 mantero Exp $ // GEANT4 tag $Name: geant4-09-04-beta-cand-01 $ // //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... #include "globals.hh" #include "G4AnalyticalEcpssrKCrossSection.hh" #include "G4AtomicTransitionManager.hh" #include "G4NistManager.hh" #include "G4Proton.hh" #include "G4Alpha.hh" #include #include #include "G4SemiLogInterpolation.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4AnalyticalEcpssrKCrossSection::G4AnalyticalEcpssrKCrossSection() { // Storing FK data needed for medium velocities region char *path = getenv("G4LEDATA"); if (!path) G4Exception("G4AnalyticalEcpssrKCrossSection::G4AnalyticalEcpssrKCrossSection() G4LEDATA environment variable not set"); std::ostringstream fileName; fileName << path << "/pixe/uf/FK.dat"; std::ifstream FK(fileName.str().c_str()); if (!FK) G4Exception("G4AnalyticalEcpssrKCrossSection::G4AnalyticalEcpssrKCrossSection() error opening FK data file"); dummyVec.push_back(0.); while(!FK.eof()) { double x; double y; FK>>x>>y; // Mandatory vector initialization if (x != dummyVec.back()) { dummyVec.push_back(x); aVecMap[x].push_back(-1.); } FK>>FKData[x][y]; if (y != aVecMap[x].back()) aVecMap[x].push_back(y); } // Storing C coefficients for high velocity formula G4String fileC1("pixe/uf/c1"); tableC1 = new G4DNACrossSectionDataSet(new G4SemiLogInterpolation, 1.,1.); tableC1->LoadData(fileC1); G4String fileC2("pixe/uf/c2"); tableC2 = new G4DNACrossSectionDataSet(new G4SemiLogInterpolation, 1.,1.); tableC2->LoadData(fileC2); G4String fileC3("pixe/uf/c3"); tableC3 = new G4DNACrossSectionDataSet(new G4SemiLogInterpolation, 1.,1.); tableC3->LoadData(fileC3); // verboseLevel=0; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... void print (G4double elem) { G4cout << elem << " "; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4AnalyticalEcpssrKCrossSection::~G4AnalyticalEcpssrKCrossSection() { delete tableC1; delete tableC2; delete tableC3; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4AnalyticalEcpssrKCrossSection::ExpIntFunction(G4int n,G4double x) { // this "ExpIntFunction" function allows fast evaluation of the n order exponential integral function En(x) G4int i; G4int ii; G4int nm1; G4double a; G4double b; G4double c; G4double d; G4double del; G4double fact; G4double h; G4double psi; G4double ans = 0; const G4double euler= 0.5772156649; const G4int maxit= 100; const G4double fpmin = 1.0e-30; const G4double eps = 1.0e-7; nm1=n-1; if (n<0 || x<0.0 || (x==0.0 && (n==0 || n==1))) { G4cout << "G4AnalyticalEcpssrKCrossSection::ExpIntFunction: VERY Bad arguments in ExpIntFunction" << G4endl; G4cout << n << ", " << x << G4endl; } else { if (n==0) ans=std::exp(-x)/x; else { if (x==0.0) ans=1.0/nm1; else { if (x > 1.0) { b=x+n; c=1.0/fpmin; d=1.0/b; h=d; for (i=1;i<=maxit;i++) { a=-i*(nm1+i); b +=2.0; d=1.0/(a*d+b); c=b+a/c; del=c*d; h *=del; if (std::fabs(del-1.0) < eps) { ans=h*std::exp(-x); return ans; } } } else { ans = (nm1!=0 ? 1.0/nm1 : -std::log(x)-euler); fact=1.0; for (i=1;i<=maxit;i++) { fact *=-x/i; if (i !=nm1) del = -fact/(i-nm1); else { psi = -euler; for (ii=1;ii<=nm1;ii++) psi +=1.0/ii; del=fact*(-std::log(x)+psi); } ans += del; if (std::fabs(del) < std::fabs(ans)*eps) return ans; } } } } } return ans; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4AnalyticalEcpssrKCrossSection::CalculateCrossSection(G4int zTarget,G4double massIncident, G4double energyIncident) { // this K-CrossSection calculation method is done according to W.Brandt and G.Lapicki, Phys.Rev.A23(1981)// G4NistManager* massManager = G4NistManager::Instance(); G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance(); G4double zIncident = 0; G4Proton* aProtone = G4Proton::Proton(); G4Alpha* aAlpha = G4Alpha::Alpha(); if (massIncident == aProtone->GetPDGMass() ) { zIncident = (aProtone->GetPDGCharge())/eplus; } else { if (massIncident == aAlpha->GetPDGMass()) { zIncident = (aAlpha->GetPDGCharge())/eplus; } else { G4cout << "*** WARNING in G4AnalyticalEcpssrKCrossSection::CalculateCrossSection : we can treat only Proton or Alpha incident particles " << G4endl; return 0; } } if (verboseLevel>0) G4cout << " massIncident=" << massIncident<< G4endl; G4double kBindingEnergy = transitionManager->Shell(zTarget,0)->BindingEnergy(); if (verboseLevel>0) G4cout << " kBindingEnergy=" << kBindingEnergy/eV<< G4endl; G4double massTarget = (massManager->GetAtomicMassAmu(zTarget))*amu_c2; if (verboseLevel>0) G4cout << " massTarget=" << massTarget<< G4endl; G4double systemMass =((massIncident*massTarget)/(massIncident+massTarget))/electron_mass_c2; //the mass of the system (projectile, target) if (verboseLevel>0) G4cout << " systemMass=" << systemMass<< G4endl; const G4double zkshell= 0.3; G4double screenedzTarget = zTarget-zkshell; // screenedzTarget is the screened nuclear charge of the target const G4double rydbergMeV= 13.6056923e-6; G4double tetaK = kBindingEnergy/((screenedzTarget*screenedzTarget)*rydbergMeV); //tetaK denotes the reduced binding energy of the electron if (verboseLevel>0) G4cout << " tetaK=" << tetaK<< G4endl; G4double velocity =(2./(tetaK*screenedzTarget))*std::pow(((energyIncident*electron_mass_c2)/(massIncident*rydbergMeV)),0.5); if (verboseLevel>0) G4cout << " velocity=" << velocity<< G4endl; const G4double bohrPow2Barn=(Bohr_radius*Bohr_radius)/barn ; if (verboseLevel>0) G4cout << " bohrPow2Barn=" << bohrPow2Barn<< G4endl; G4double sigma0 = 8.*pi*(zIncident*zIncident)*bohrPow2Barn*std::pow(screenedzTarget,-4.); //sigma0 is the initial cross section of K shell at stable state if (verboseLevel>0) G4cout << " sigma0=" << sigma0<< G4endl; const G4double kAnalyticalApproximation= 1.5; G4double x = kAnalyticalApproximation/velocity; if (verboseLevel>0) G4cout << " x=" << x<< G4endl; G4double electrIonizationEnergy; if ((0.< x) && (x <= 0.035)) { electrIonizationEnergy= 0.75*pi*(std::log(1./(x*x))-1.); } else { if ( (0.035 < x) && (x <=3.)) { electrIonizationEnergy =std::exp(-2.*x)/(0.031+(0.213*std::pow(x,0.5))+(0.005*x)-(0.069*std::pow(x,3./2.))+(0.324*x*x)); } else { if ( (3.< x) && (x<=11.)) { electrIonizationEnergy =2.*std::exp(-2.*x)/std::pow(x,1.6); } else electrIonizationEnergy =0.; } } if (verboseLevel>0) G4cout << " electrIonizationEnergy=" << electrIonizationEnergy<< G4endl; G4double hFunction =(electrIonizationEnergy*2.)/(tetaK*std::pow(velocity,3)); //hFunction represents the correction for polarization effet if (verboseLevel>0) G4cout << " hFunction=" << hFunction<< G4endl; G4double gFunction = (1.+(9.*velocity)+(31.*velocity*velocity)+(98.*std::pow(velocity,3.))+(12.*std::pow(velocity,4.))+(25.*std::pow(velocity,5.)) +(4.2*std::pow(velocity,6.))+(0.515*std::pow(velocity,7.)))/std::pow(1.+velocity,9.); //gFunction represents the correction for binding effet if (verboseLevel>0) G4cout << " gFunction=" << gFunction<< G4endl; //----------------------------------------------------------------------------------------------------------------------------- G4double sigmaPSS = 1.+(((2.*zIncident)/(screenedzTarget*tetaK))*(gFunction-hFunction)); //describes the perturbed stationnairy state of the affected atomic electon if (verboseLevel>0) G4cout << " sigmaPSS=" << sigmaPSS<< G4endl; if (verboseLevel>0) G4cout << " sigmaPSS*tetaK=" << sigmaPSS*tetaK<< G4endl; //---------------------------------------------------------------------------------------------------------------------------- const G4double cNaturalUnit= 1/fine_structure_const; // it's the speed of light according to Atomic-Unit-System if (verboseLevel>0) G4cout << " cNaturalUnit=" << cNaturalUnit<< G4endl; G4double ykFormula=0.4*(screenedzTarget/cNaturalUnit)*(screenedzTarget/cNaturalUnit)/(velocity/sigmaPSS); if (verboseLevel>0) G4cout << " ykFormula=" << ykFormula<< G4endl; G4double relativityCorrection = std::pow((1.+(1.1*ykFormula*ykFormula)),0.5)+ykFormula;// the relativistic correction parameter if (verboseLevel>0) G4cout << " relativityCorrection=" << relativityCorrection<< G4endl; G4double reducedVelocity = velocity*std::pow(relativityCorrection,0.5); // presents the reduced collision velocity parameter if (verboseLevel>0) G4cout << " reducedVelocity=" << reducedVelocity<< G4endl; G4double etaOverTheta2 = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget) /(sigmaPSS*tetaK)/(sigmaPSS*tetaK); if (verboseLevel>0) G4cout << " etaOverTheta2=" << etaOverTheta2<< G4endl; G4double universalFunction = 0; // low velocity formula if ( velocity < 1. ) { if (verboseLevel>0) G4cout << " Notice : FK is computed from low velocity formula" << G4endl; universalFunction = (std::pow(2.,9.)/45.)*std::pow(reducedVelocity/sigmaPSS,8.)*std::pow((1.+(1.72*(reducedVelocity/sigmaPSS)*(reducedVelocity/sigmaPSS))),-4.);// is the reduced universal cross section if (verboseLevel>0) G4cout << " universalFunction by Brandt 1981 =" << universalFunction<< G4endl; } else { if ( etaOverTheta2 > 86.6 && (sigmaPSS*tetaK) > 0.4 && (sigmaPSS*tetaK) < 2.9996 ) { // High and medium energies. Method from Rice 1977 on tabvles from Benka 1978 if (verboseLevel>0) G4cout << " Notice : FK is computed from high velocity formula" << G4endl; if (verboseLevel>0) G4cout << " sigmaPSS*tetaK=" << sigmaPSS*tetaK << G4endl; G4double C1= tableC1->FindValue(sigmaPSS*tetaK); G4double C2= tableC2->FindValue(sigmaPSS*tetaK); G4double C3= tableC3->FindValue(sigmaPSS*tetaK); if (verboseLevel>0) G4cout << " C1=" << C1 << G4endl; if (verboseLevel>0) G4cout << " C2=" << C2 << G4endl; if (verboseLevel>0) G4cout << " C3=" << C3 << G4endl; G4double etaK = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget); if (verboseLevel>0) G4cout << " etaK=" << etaK << G4endl; G4double etaT = (sigmaPSS*tetaK)*(sigmaPSS*tetaK)*(86.6); // at any theta, the largest tabulated etaOverTheta2 is 86.6 if (verboseLevel>0) G4cout << " etaT=" << etaT << G4endl; G4double fKT = FunctionFK((sigmaPSS*tetaK),86.6)*(etaT/(sigmaPSS*tetaK)); if (FunctionFK((sigmaPSS*tetaK),86.6)<=0.) { G4cout << "*** WARNING in G4AnalyticalEcpssrKCrossSection::CalculateCrossSection : unable to interpolate FK function in high velocity region ! ***" << G4endl; return 0; } if (verboseLevel>0) G4cout << " FunctionFK=" << FunctionFK((sigmaPSS*tetaK),86.6) << G4endl; if (verboseLevel>0) G4cout << " fKT=" << fKT << G4endl; G4double GK = C2/(4*etaK) + C3/(32*etaK*etaK); if (verboseLevel>0) G4cout << " GK=" << GK << G4endl; G4double GT = C2/(4*etaT) + C3/(32*etaT*etaT); if (verboseLevel>0) G4cout << " GT=" << GT << G4endl; G4double DT = fKT - C1*std::log(etaT) + GT; if (verboseLevel>0) G4cout << " DT=" << DT << G4endl; G4double fKK = C1*std::log(etaK) + DT - GK; if (verboseLevel>0) G4cout << " fKK=" << fKK << G4endl; G4double universalFunction3= fKK/(etaK/tetaK); if (verboseLevel>0) G4cout << " universalFunction3=" << universalFunction3 << G4endl; universalFunction=universalFunction3; } else if ( etaOverTheta2 >= 1.e-3 && etaOverTheta2 <= 86.6 && (sigmaPSS*tetaK) >= 0.4 && (sigmaPSS*tetaK) <= 2.9996 ) { // From Benka 1978 if (verboseLevel>0) G4cout << " Notice : FK is computed from INTERPOLATED data" << G4endl; G4double universalFunction2 = FunctionFK((sigmaPSS*tetaK),etaOverTheta2); if (universalFunction2<=0) { G4cout << "*** WARNING : G4AnalyticalEcpssrKCrossSection::CalculateCrossSection is unable to interpolate FK function in medium velocity region ! ***" << G4endl; return 0; } if (verboseLevel>0) G4cout << " universalFunction2=" << universalFunction2 << " for theta=" << sigmaPSS*tetaK << " and etaOverTheta2=" << etaOverTheta2 << G4endl; universalFunction=universalFunction2; } } //---------------------------------------------------------------------------------------------------------------------- G4double sigmaPSSR = (sigma0/(sigmaPSS*tetaK))*universalFunction; //sigmaPSSR is the straight-line K-shell ionization cross section if (verboseLevel>0) G4cout << " sigmaPSSR=" << sigmaPSSR<< G4endl; //----------------------------------------------------------------------------------------------------------------------- G4double pssDeltaK = (4./(systemMass*sigmaPSS*tetaK))*(sigmaPSS/velocity)*(sigmaPSS/velocity); if (verboseLevel>0) G4cout << " pssDeltaK=" << pssDeltaK<< G4endl; G4double energyLoss = std::pow(1-pssDeltaK,0.5); //energyLoss incorporates the straight-line energy-loss if (verboseLevel>0) G4cout << " energyLoss=" << energyLoss<< G4endl; G4double energyLossFunction = (std::pow(2.,-9)/8.)*((((9.*energyLoss)-1.)*std::pow(1.+energyLoss,9.))+(((9.*energyLoss)+1.)*std::pow(1.-energyLoss,9.)));//energy loss function if (verboseLevel>0) G4cout << " energyLossFunction=" << energyLossFunction<< G4endl; //---------------------------------------------------------------------------------------------------------------------------------------------- G4double coulombDeflection = (4.*pi*zIncident/systemMass)*std::pow(tetaK*sigmaPSS,-2.)*std::pow(velocity/sigmaPSS,-3.)*(zTarget/screenedzTarget); //incorporates Coulomb deflection parameter if (verboseLevel>0) G4cout << " cParameter-short=" << coulombDeflection<< G4endl; G4double cParameter = 2.*coulombDeflection/(energyLoss*(energyLoss+1.)); if (verboseLevel>0) G4cout << " cParameter-full=" << cParameter<< G4endl; G4double coulombDeflectionFunction = 9.*ExpIntFunction(10,cParameter); //this function describes Coulomb-deflection effect if (verboseLevel>0) G4cout << " ExpIntFunction(10,cParameter) =" << ExpIntFunction(10,cParameter) << G4endl; if (verboseLevel>0) G4cout << " coulombDeflectionFunction =" << coulombDeflectionFunction << G4endl; //-------------------------------------------------------------------------------------------------------------------------------------------------- G4double crossSection = 0; crossSection = energyLossFunction* coulombDeflectionFunction*sigmaPSSR; //this ECPSSR cross section is estimated at perturbed-stationnairy-state(PSS) //and it's reduced by the energy-loss(E),the Coulomb deflection(C), //and the relativity(R) effects //-------------------------------------------------------------------------------------------------------------------------------------------------- if (crossSection >= 0) { return crossSection; } else {return 0;} } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4AnalyticalEcpssrKCrossSection::FunctionFK(G4double k, G4double theta) { G4double sigma = 0.; G4double valueT1 = 0; G4double valueT2 = 0; G4double valueE21 = 0; G4double valueE22 = 0; G4double valueE12 = 0; G4double valueE11 = 0; G4double xs11 = 0; G4double xs12 = 0; G4double xs21 = 0; G4double xs22 = 0; // PROTECTION TO ALLOW INTERPOLATION AT MINIMUM AND MAXIMUM EtaK/Theta2 values // (in particular for FK computation at 8.66EXX for high velocity formula) if ( theta==8.66e-3 || theta==8.66e-2 || theta==8.66e-1 || theta==8.66e+0 || theta==8.66e+1 ) theta=theta-1e-12; if ( theta==1.e-3 || theta==1.e-2 || theta==1.e-1 || theta==1.e+00 || theta==1.e+01 ) theta=theta+1e-12; // END PROTECTION std::vector::iterator t2 = std::upper_bound(dummyVec.begin(),dummyVec.end(), k); std::vector::iterator t1 = t2-1; std::vector::iterator e12 = std::upper_bound(aVecMap[(*t1)].begin(),aVecMap[(*t1)].end(), theta); std::vector::iterator e11 = e12-1; std::vector::iterator e22 = std::upper_bound(aVecMap[(*t2)].begin(),aVecMap[(*t2)].end(), theta); std::vector::iterator e21 = e22-1; valueT1 =*t1; valueT2 =*t2; valueE21 =*e21; valueE22 =*e22; valueE12 =*e12; valueE11 =*e11; xs11 = FKData[valueT1][valueE11]; xs12 = FKData[valueT1][valueE12]; xs21 = FKData[valueT2][valueE21]; xs22 = FKData[valueT2][valueE22]; /* if (verboseLevel>0) { G4cout << "x1= " << valueT1 << G4endl; G4cout << " vector of y for x1" << G4endl; for_each (aVecMap[(*t1)].begin(),aVecMap[(*t1)].end(), print); G4cout << G4endl; G4cout << "x2= " << valueT2 << G4endl; G4cout << " vector of y for x2" << G4endl; for_each (aVecMap[(*t2)].begin(),aVecMap[(*t2)].end(), print); G4cout << G4endl; G4cout << " " << valueT1 << " " << valueT2 << " " << valueE11 << " " << valueE12 << " " << valueE21<< " " << valueE22 << " " << xs11 << " " << xs12 << " " << xs21 << " " << xs22 << " " << G4endl; } */ G4double xsProduct = xs11 * xs12 * xs21 * xs22; if (xs11==0 || xs12==0 ||xs21==0 ||xs22==0) return (0.); if (xsProduct != 0.) { sigma = QuadInterpolator( valueE11, valueE12, valueE21, valueE22, xs11, xs12, xs21, xs22, valueT1, valueT2, k, theta ); } return sigma; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4AnalyticalEcpssrKCrossSection::LinLogInterpolate(G4double e1, G4double e2, G4double e, G4double xs1, G4double xs2) { G4double d1 = std::log(xs1); G4double d2 = std::log(xs2); G4double value = std::exp(d1 + (d2 - d1)*(e - e1)/ (e2 - e1)); return value; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4AnalyticalEcpssrKCrossSection::LogLogInterpolate(G4double e1, G4double e2, G4double e, G4double xs1, G4double xs2) { G4double a = (std::log10(xs2)-std::log10(xs1)) / (std::log10(e2)-std::log10(e1)); G4double b = std::log10(xs2) - a*std::log10(e2); G4double sigma = a*std::log10(e) + b; G4double value = (std::pow(10.,sigma)); return value; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4AnalyticalEcpssrKCrossSection::QuadInterpolator(G4double e11, G4double e12, G4double e21, G4double e22, G4double xs11, G4double xs12, G4double xs21, G4double xs22, G4double t1, G4double t2, G4double t, G4double e) { // Log-Log G4double interpolatedvalue1 = LogLogInterpolate(e11, e12, e, xs11, xs12); G4double interpolatedvalue2 = LogLogInterpolate(e21, e22, e, xs21, xs22); G4double value = LogLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2); /* // Lin-Log G4double interpolatedvalue1 = LinLogInterpolate(e11, e12, e, xs11, xs12); G4double interpolatedvalue2 = LinLogInterpolate(e21, e22, e, xs21, xs22); G4double value = LinLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2); */ return value; }