Import Geant4 9.4.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 16:25:56 +02:00
parent 74cad5e589
commit 89a9605df1
4440 changed files with 379508 additions and 189225 deletions
@@ -0,0 +1,644 @@
//
// ********************************************************************
// * 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.5 2010/12/15 07:39:10 gunter Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "globals.hh"
#include "G4AnalyticalEcpssrKCrossSection.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4NistManager.hh"
#include "G4Proton.hh"
#include "G4Alpha.hh"
#include <math.h>
#include <iostream>
#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 * barn;
}
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<double>::iterator t2 = std::upper_bound(dummyVec.begin(),dummyVec.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator e12 = std::upper_bound(aVecMap[(*t1)].begin(),aVecMap[(*t1)].end(), theta);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e22 = std::upper_bound(aVecMap[(*t2)].begin(),aVecMap[(*t2)].end(), theta);
std::vector<double>::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;
std::for_each (aVecMap[(*t1)].begin(),aVecMap[(*t1)].end(), print);
G4cout << G4endl;
G4cout << "x2= " << valueT2 << G4endl;
G4cout << " vector of y for x2" << G4endl;
std::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;
}
@@ -0,0 +1,983 @@
//
// ********************************************************************
// * 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: G4AnalyticalEcpssrLiCrossSection.cc,v 1.4 2010/11/22 17:25:45 mantero Exp $
// GEANT4 tag $Name: geant4-09-04 $
#include "globals.hh"
#include "G4AnalyticalEcpssrLiCrossSection.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4NistManager.hh"
#include "G4Proton.hh"
#include "G4Alpha.hh"
#include <math.h>
#include <iostream>
#include "G4LinLogInterpolation.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4AnalyticalEcpssrLiCrossSection::G4AnalyticalEcpssrLiCrossSection()
{
// Storing FLi data needed for 0.2 to 3.0 velocities region
char *path = getenv("G4LEDATA");
if (!path)
G4Exception("G4ecpssrLCrossSection::G4AnalyticalEcpssrLiCrossSection() G4LEDDATA environment variable not set");
std::ostringstream fileName1;
std::ostringstream fileName2;
fileName1 << path << "/pixe/uf/FL1.dat";
fileName2 << path << "/pixe/uf/FL2.dat";
// Reading of FL1.dat
std::ifstream FL1(fileName1.str().c_str());
if (!FL1) G4Exception("G4ecpssrLCrossSection::G4AnalyticalEcpssrLiCrossSection() error opening FL1 data file");
dummyVec1.push_back(0.);
while(!FL1.eof())
{
double x1;
double y1;
FL1>>x1>>y1;
// Mandatory vector initialization
if (x1 != dummyVec1.back())
{
dummyVec1.push_back(x1);
aVecMap1[x1].push_back(-1.);
}
FL1>>FL1Data[x1][y1];
if (y1 != aVecMap1[x1].back()) aVecMap1[x1].push_back(y1);
}
// Reading of FL2.dat
std::ifstream FL2(fileName2.str().c_str());
if (!FL2) G4Exception("G4ecpssrLCrossSection::G4AnalyticalEcpssrLiCrossSection() error opening FL2 data file");
dummyVec2.push_back(0.);
while(!FL2.eof())
{
double x2;
double y2;
FL2>>x2>>y2;
// Mandatory vector initialization
if (x2 != dummyVec2.back())
{
dummyVec2.push_back(x2);
aVecMap2[x2].push_back(-1.);
}
FL2>>FL2Data[x2][y2];
if (y2 != aVecMap2[x2].back()) aVecMap2[x2].push_back(y2);
}
// Verbose level
verboseLevel=0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4AnalyticalEcpssrLiCrossSection::~G4AnalyticalEcpssrLiCrossSection()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4AnalyticalEcpssrLiCrossSection::ExpIntFunction(G4int n,G4double x)
{
// this 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 << "bad arguments in ExpIntFunction" << 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 G4AnalyticalEcpssrLiCrossSection::CalculateL1CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident)
{
//this L1-CrossSection calculation method is done according to Werner Brandt and Grzegorz Lapicki, Phys.Rev.A20 N2 (1979),
//and using data tables of O. Benka et al. At.Data Nucl.Data Tables Vol.22 No.3 (1978).
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 G4AnalyticalEcpssrLiCrossSection::CalculateL1CrossSection : Proton or Alpha incident particles only. " << G4endl;
G4cout << massIncident << ", " << aAlpha->GetPDGMass() << " (alpha)" << aProtone->GetPDGMass() << " (proton)" << G4endl;
return 0;
}
}
G4double l1BindingEnergy = transitionManager->Shell(zTarget,1)->BindingEnergy(); //Observed binding energy of L1-subshell
G4double massTarget = (massManager->GetAtomicMassAmu(zTarget))*amu_c2;
G4double systemMass =((massIncident*massTarget)/(massIncident+massTarget))/electron_mass_c2; //Mass of the system (projectile, target)
const G4double zlshell= 4.15;
G4double screenedzTarget = zTarget-zlshell; //Effective nuclear charge as seen by electrons in L1-sub shell
const G4double rydbergMeV= 13.6056923e-6;
const G4double nl= 2.;
G4double tetal1 = (l1BindingEnergy*nl*nl)/((screenedzTarget*screenedzTarget)*rydbergMeV); //Screening parameter
if (verboseLevel>0) G4cout << " tetal1=" << tetal1<< G4endl;
G4double reducedEnergy = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget);
const G4double bohrPow2Barn=(Bohr_radius*Bohr_radius)/barn ; //Bohr radius of hydrogen
G4double sigma0 = 8.*pi*(zIncident*zIncident)*bohrPow2Barn*std::pow(screenedzTarget,-4.);
G4double velocityl1 = CalculateVelocity(1, zTarget, massIncident, energyIncident); // Scaled velocity
if (verboseLevel>0) G4cout << " velocityl1=" << velocityl1<< G4endl;
const G4double l1AnalyticalApproximation= 1.5;
G4double x1 =(nl*l1AnalyticalApproximation)/velocityl1;
if (verboseLevel>0) G4cout << " x1=" << x1<< G4endl;
G4double electrIonizationEnergyl1=0.;
if ( x1<=0.035) electrIonizationEnergyl1= 0.75*pi*(std::log(1./(x1*x1))-1.);
else
{
if ( x1<=3.)
electrIonizationEnergyl1 =std::exp(-2.*x1)/(0.031+(0.213*std::pow(x1,0.5))+(0.005*x1)-(0.069*std::pow(x1,3./2.))+(0.324*x1*x1));
else
{if ( x1<=11.) electrIonizationEnergyl1 =2.*std::exp(-2.*x1)/std::pow(x1,1.6);}
}
G4double hFunctionl1 =(electrIonizationEnergyl1*2.*nl)/(tetal1*std::pow(velocityl1,3)); //takes into account the polarization effect
if (verboseLevel>0) G4cout << " hFunctionl1=" << hFunctionl1<< G4endl;
G4double gFunctionl1 = (1.+(9.*velocityl1)+(31.*velocityl1*velocityl1)+(49.*std::pow(velocityl1,3.))+(162.*std::pow(velocityl1,4.))+(63.*std::pow(velocityl1,5.))+(18.*std::pow(velocityl1,6.))+(1.97*std::pow(velocityl1,7.)))/std::pow(1.+velocityl1,9.);//takes into account the reduced binding effect
if (verboseLevel>0) G4cout << " gFunctionl1=" << gFunctionl1<< G4endl;
G4double sigmaPSS_l1 = 1.+(((2.*zIncident)/(screenedzTarget*tetal1))*(gFunctionl1-hFunctionl1)); //Binding-polarization factor
if (verboseLevel>0) G4cout << "sigmaPSS_l1 =" << sigmaPSS_l1<< G4endl;
const G4double cNaturalUnit= 137.;
G4double yl1Formula=0.4*(screenedzTarget/cNaturalUnit)*(screenedzTarget/cNaturalUnit)/(nl*velocityl1/sigmaPSS_l1);
G4double l1relativityCorrection = std::pow((1.+(1.1*yl1Formula*yl1Formula)),0.5)+yl1Formula; // Relativistic correction parameter
//G4double reducedVelocity_l1 = velocityl1*std::pow(l1relativityCorrection,0.5); //Reduced velocity parameter
G4double L1etaOverTheta2;
G4double universalFunction_l1 = 0.;
G4double sigmaPSSR_l1;
if ( velocityl1 <5. )
{
L1etaOverTheta2 =(reducedEnergy* l1relativityCorrection)/((tetal1*sigmaPSS_l1)*(tetal1*sigmaPSS_l1));
if ( ((tetal1*sigmaPSS_l1) >=0.2) && ((tetal1*sigmaPSS_l1) <=2.6670) && (L1etaOverTheta2>=0.1e-3) && (L1etaOverTheta2<=0.866e2) )
universalFunction_l1 = FunctionFL1((tetal1*sigmaPSS_l1),L1etaOverTheta2);
if (verboseLevel>0) G4cout << "at low velocity range, universalFunction_l1 =" << universalFunction_l1 << G4endl;
sigmaPSSR_l1 = (sigma0/(tetal1*sigmaPSS_l1))*universalFunction_l1;// Plane-wave Born -Aproximation L1-subshell ionisation Cross Section
if (verboseLevel>0) G4cout << " at low velocity range, sigma PWBA L1 CS = " << sigmaPSSR_l1<< G4endl;
}
else
{
L1etaOverTheta2 = reducedEnergy/(tetal1*tetal1);
if ( (tetal1 >=0.2) && (tetal1 <=2.6670) && (L1etaOverTheta2>=0.1e-3) && (L1etaOverTheta2<=0.866e2) )
universalFunction_l1 = FunctionFL1(tetal1,L1etaOverTheta2);
if (verboseLevel>0) G4cout << "at medium and high velocity range, universalFunction_l1 =" << universalFunction_l1 << G4endl;
sigmaPSSR_l1 = (sigma0/tetal1)*universalFunction_l1;// Plane-wave Born -Aproximation L1-subshell ionisation Cross Section
if (verboseLevel>0) G4cout << " sigma PWBA L1 CS at medium and high velocity range = " << sigmaPSSR_l1<< G4endl;
}
G4double pssDeltal1 = (4./(systemMass *sigmaPSS_l1*tetal1))*(sigmaPSS_l1/velocityl1)*(sigmaPSS_l1/velocityl1);
if (verboseLevel>0) G4cout << " pssDeltal1=" << pssDeltal1<< G4endl;
G4double energyLossl1 = std::pow(1-pssDeltal1,0.5);
if (verboseLevel>0) G4cout << " energyLossl1=" << energyLossl1<< G4endl;
G4double coulombDeflectionl1 =
(8.*pi*zIncident/systemMass)*std::pow(tetal1*sigmaPSS_l1,-2.)*std::pow(velocityl1/sigmaPSS_l1,-3.)*(zTarget/screenedzTarget);
G4double cParameterl1 =2.* coulombDeflectionl1/(energyLossl1*(energyLossl1+1.));
G4double coulombDeflectionFunction_l1 = 9.*ExpIntFunction(10,cParameterl1); //Coulomb-deflection effect correction
if (verboseLevel>0) G4cout << " coulombDeflectionFunction_l1 =" << coulombDeflectionFunction_l1 << G4endl;
G4double crossSection_L1 = coulombDeflectionFunction_l1 * sigmaPSSR_l1;
//ECPSSR L1 -subshell cross section is estimated at perturbed-stationnairy-state(PSS)
//and reduced by the energy-loss(E),the Coulomb deflection(C),and the relativity(R) effects
if (verboseLevel>0) G4cout << " crossSection_L1 =" << crossSection_L1 << G4endl;
if (crossSection_L1 >= 0) {
return crossSection_L1 * barn;
}
else {return 0;}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4AnalyticalEcpssrLiCrossSection::CalculateL2CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident)
{
// this L2-CrossSection calculation method is done according to Werner Brandt and Grzegorz Lapicki, Phys.Rev.A20 N2 (1979),
// and using data tables of O. Benka et al. At.Data Nucl.Data Tables Vol.22 No.3 (1978).
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 G4AnalyticalEcpssrLiCrossSection::CalculateL2CrossSection : Proton or Alpha incident particles only. " << G4endl;
G4cout << massIncident << ", " << aAlpha->GetPDGMass() << " (alpha)" << aProtone->GetPDGMass() << " (proton)" << G4endl;
return 0;
}
}
G4double l2BindingEnergy = transitionManager->Shell(zTarget,2)->BindingEnergy(); //Observed binding energy of L2-subshell
G4double massTarget = (massManager->GetAtomicMassAmu(zTarget))*amu_c2;
G4double systemMass =((massIncident*massTarget)/(massIncident+massTarget))/electron_mass_c2; //Mass of the system (projectile, target)
const G4double zlshell= 4.15;
G4double screenedzTarget = zTarget-zlshell; //Effective nuclear charge as seen by electrons in L2-subshell
const G4double rydbergMeV= 13.6056923e-6;
const G4double nl= 2.;
G4double tetal2 = (l2BindingEnergy*nl*nl)/((screenedzTarget*screenedzTarget)*rydbergMeV); //Screening parameter
if (verboseLevel>0) G4cout << " tetal2=" << tetal2<< G4endl;
G4double reducedEnergy = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget);
const G4double bohrPow2Barn=(Bohr_radius*Bohr_radius)/barn ; //Bohr radius of hydrogen
G4double sigma0 = 8.*pi*(zIncident*zIncident)*bohrPow2Barn*std::pow(screenedzTarget,-4.);
G4double velocityl2 = CalculateVelocity(2, zTarget, massIncident, energyIncident); // Scaled velocity
if (verboseLevel>0) G4cout << " velocityl2=" << velocityl2<< G4endl;
const G4double l23AnalyticalApproximation= 1.25;
G4double x2 = (nl*l23AnalyticalApproximation)/velocityl2;
if (verboseLevel>0) G4cout << " x2=" << x2<< G4endl;
G4double electrIonizationEnergyl2=0.;
if ( x2<=0.035) electrIonizationEnergyl2= 0.75*pi*(std::log(1./(x2*x2))-1.);
else
{
if ( x2<=3.)
electrIonizationEnergyl2 =std::exp(-2.*x2)/(0.031+(0.210*std::pow(x2,0.5))+(0.005*x2)-(0.069*std::pow(x2,3./2.))+(0.324*x2*x2));
else
{if ( x2<=11.) electrIonizationEnergyl2 =2.*std::exp(-2.*x2)/std::pow(x2,1.6); }
}
G4double hFunctionl2 =(electrIonizationEnergyl2*2.*nl)/(tetal2*std::pow(velocityl2,3)); //takes into account the polarization effect
if (verboseLevel>0) G4cout << " hFunctionl2=" << hFunctionl2<< G4endl;
G4double gFunctionl2 = (1.+(10.*velocityl2)+(45.*velocityl2*velocityl2)+(102.*std::pow(velocityl2,3.))+(331.*std::pow(velocityl2,4.))+(6.7*std::pow(velocityl2,5.))+(58.*std::pow(velocityl2,6.))+(7.8*std::pow(velocityl2,7.))+ (0.888*std::pow(velocityl2,8.)) )/std::pow(1.+velocityl2,10.);
//takes into account the reduced binding effect
if (verboseLevel>0) G4cout << " gFunctionl2=" << gFunctionl2<< G4endl;
G4double sigmaPSS_l2 = 1.+(((2.*zIncident)/(screenedzTarget*tetal2))*(gFunctionl2-hFunctionl2)); //Binding-polarization factor
if (verboseLevel>0) G4cout << " sigmaPSS_l2=" << sigmaPSS_l2<< G4endl;
const G4double cNaturalUnit= 137.;
G4double yl2Formula=0.15*(screenedzTarget/cNaturalUnit)*(screenedzTarget/cNaturalUnit)/(velocityl2/sigmaPSS_l2);
G4double l2relativityCorrection = std::pow((1.+(1.1*yl2Formula*yl2Formula)),0.5)+yl2Formula; // Relativistic correction parameter
G4double L2etaOverTheta2;
G4double universalFunction_l2 = 0.;
G4double sigmaPSSR_l2 ;
if ( velocityl2 < 5. )
{
L2etaOverTheta2 = (reducedEnergy*l2relativityCorrection)/((sigmaPSS_l2*tetal2)*(sigmaPSS_l2*tetal2));
if ( (tetal2*sigmaPSS_l2>=0.2) && (tetal2*sigmaPSS_l2<=2.6670) && (L2etaOverTheta2>=0.1e-3) && (L2etaOverTheta2<=0.866e2) )
universalFunction_l2 = FunctionFL2((tetal2*sigmaPSS_l2),L2etaOverTheta2);
sigmaPSSR_l2 = (sigma0/(tetal2*sigmaPSS_l2))*universalFunction_l2;
if (verboseLevel>0) G4cout << " sigma PWBA L2 CS at low velocity range = " << sigmaPSSR_l2<< G4endl;
}
else
{
L2etaOverTheta2 = reducedEnergy /(tetal2*tetal2);
if ( (tetal2>=0.2) && (tetal2<=2.6670) && (L2etaOverTheta2>=0.1e-3) && (L2etaOverTheta2<=0.866e2) )
universalFunction_l2 = FunctionFL2((tetal2),L2etaOverTheta2);
sigmaPSSR_l2 = (sigma0/tetal2)*universalFunction_l2;
if (verboseLevel>0) G4cout << " sigma PWBA L2 CS at medium and high velocity range = " << sigmaPSSR_l2<< G4endl;
}
G4double pssDeltal2 = (4./(systemMass*sigmaPSS_l2*tetal2))*(sigmaPSS_l2/velocityl2)*(sigmaPSS_l2/velocityl2);
G4double energyLossl2 = std::pow(1-pssDeltal2,0.5);
if (verboseLevel>0) G4cout << " energyLossl2=" << energyLossl2<< G4endl;
G4double coulombDeflectionl2
=(8.*pi*zIncident/systemMass)*std::pow(tetal2*sigmaPSS_l2,-2.)*std::pow(velocityl2/sigmaPSS_l2,-3.)*(zTarget/screenedzTarget);
G4double cParameterl2 = 2.*coulombDeflectionl2/(energyLossl2*(energyLossl2+1.));
G4double coulombDeflectionFunction_l2 = 11.*ExpIntFunction(12,cParameterl2); //Coulomb-deflection effect correction
if (verboseLevel>0) G4cout << " coulombDeflectionFunction_l2 =" << coulombDeflectionFunction_l2 << G4endl;
G4double crossSection_L2 = coulombDeflectionFunction_l2 * sigmaPSSR_l2;
//ECPSSR L2 -subshell cross section is estimated at perturbed-stationnairy-state(PSS)
//and reduced by the energy-loss(E),the Coulomb deflection(C),and the relativity(R) effects
if (verboseLevel>0) G4cout << " crossSection_L2 =" << crossSection_L2 << G4endl;
if (crossSection_L2 >= 0) {
return crossSection_L2 * barn;
}
else {return 0;}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4AnalyticalEcpssrLiCrossSection::CalculateL3CrossSection(G4int zTarget,G4double massIncident, G4double energyIncident)
{
//this L3-CrossSection calculation method is done according to Werner Brandt and Grzegorz Lapicki, Phys.Rev.A20 N2 (1979),
//and using data tables of O. Benka et al. At.Data Nucl.Data Tables Vol.22 No.3 (1978).
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 G4AnalyticalEcpssrLiCrossSection::CalculateL3CrossSection : Proton or Alpha incident particles only. " << G4endl;
G4cout << massIncident << ", " << aAlpha->GetPDGMass() << " (alpha)" << aProtone->GetPDGMass() << " (proton)" << G4endl;
return 0;
}
}
G4double l3BindingEnergy = transitionManager->Shell(zTarget,3)->BindingEnergy();
G4double massTarget = (massManager->GetAtomicMassAmu(zTarget))*amu_c2;
G4double systemMass =((massIncident*massTarget)/(massIncident+massTarget))/electron_mass_c2;//Mass of the system (projectile, target)
const G4double zlshell= 4.15;
G4double screenedzTarget = zTarget-zlshell;//Effective nuclear charge as seen by electrons in L3-subshell
const G4double rydbergMeV= 13.6056923e-6;
const G4double nl= 2.;
G4double tetal3 = (l3BindingEnergy*nl*nl)/((screenedzTarget*screenedzTarget)*rydbergMeV);//Screening parameter
if (verboseLevel>0) G4cout << " tetal3=" << tetal3<< G4endl;
G4double reducedEnergy = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget);
const G4double bohrPow2Barn=(Bohr_radius*Bohr_radius)/barn ;//Bohr radius of hydrogen
G4double sigma0 = 8.*pi*(zIncident*zIncident)*bohrPow2Barn*std::pow(screenedzTarget,-4.);
G4double velocityl3 = CalculateVelocity(3, zTarget, massIncident, energyIncident);// Scaled velocity
if (verboseLevel>0) G4cout << " velocityl3=" << velocityl3<< G4endl;
const G4double l23AnalyticalApproximation= 1.25;
G4double x3 = (nl*l23AnalyticalApproximation)/velocityl3;
if (verboseLevel>0) G4cout << " x3=" << x3<< G4endl;
G4double electrIonizationEnergyl3=0.;
if ( x3<=0.035) electrIonizationEnergyl3= 0.75*pi*(std::log(1./(x3*x3))-1.);
else
{
if ( x3<=3.) electrIonizationEnergyl3 =std::exp(-2.*x3)/(0.031+(0.210*std::pow(x3,0.5))+(0.005*x3)-(0.069*std::pow(x3,3./2.))+(0.324*x3*x3));
else
{
if ( x3<=11.) electrIonizationEnergyl3 =2.*std::exp(-2.*x3)/std::pow(x3,1.6);}
}
G4double hFunctionl3 =(electrIonizationEnergyl3*2.*nl)/(tetal3*std::pow(velocityl3,3));//takes into account the polarization effect
if (verboseLevel>0) G4cout << " hFunctionl3=" << hFunctionl3<< G4endl;
G4double gFunctionl3 = (1.+(10.*velocityl3)+(45.*velocityl3*velocityl3)+(102.*std::pow(velocityl3,3.))+(331.*std::pow(velocityl3,4.))+(6.7*std::pow(velocityl3,5.))+(58.*std::pow(velocityl3,6.))+(7.8*std::pow(velocityl3,7.))+ (0.888*std::pow(velocityl3,8.)) )/std::pow(1.+velocityl3,10.);
//takes into account the reduced binding effect
if (verboseLevel>0) G4cout << " gFunctionl3=" << gFunctionl3<< G4endl;
G4double sigmaPSS_l3 = 1.+(((2.*zIncident)/(screenedzTarget*tetal3))*(gFunctionl3-hFunctionl3));//Binding-polarization factor
if (verboseLevel>0) G4cout << "sigmaPSS_l3 =" << sigmaPSS_l3<< G4endl;
const G4double cNaturalUnit= 137.;
G4double yl3Formula=0.15*(screenedzTarget/cNaturalUnit)*(screenedzTarget/cNaturalUnit)/(velocityl3/sigmaPSS_l3);
G4double l3relativityCorrection = std::pow((1.+(1.1*yl3Formula*yl3Formula)),0.5)+yl3Formula; // Relativistic correction parameter
G4double L3etaOverTheta2;
G4double universalFunction_l3 = 0.;
G4double sigmaPSSR_l3;
if ( velocityl3 < 5. )
{
L3etaOverTheta2 = (reducedEnergy* l3relativityCorrection)/((sigmaPSS_l3*tetal3)*(sigmaPSS_l3*tetal3));
if ( (tetal3*sigmaPSS_l3>=0.2) && (tetal3*sigmaPSS_l3<=2.6670) && (L3etaOverTheta2>=0.1e-3) && (L3etaOverTheta2<=0.866e2) )
universalFunction_l3 = 2.*FunctionFL2((tetal3*sigmaPSS_l3), L3etaOverTheta2 );
sigmaPSSR_l3 = (sigma0/(tetal3*sigmaPSS_l3))*universalFunction_l3;
if (verboseLevel>0) G4cout << " sigma PWBA L3 CS at low velocity range = " << sigmaPSSR_l3<< G4endl;
}
else
{
L3etaOverTheta2 = reducedEnergy/(tetal3*tetal3);
if ( (tetal3>=0.2) && (tetal3<=2.6670) && (L3etaOverTheta2>=0.1e-3) && (L3etaOverTheta2<=0.866e2) )
universalFunction_l3 = 2.*FunctionFL2(tetal3, L3etaOverTheta2 );
sigmaPSSR_l3 = (sigma0/tetal3)*universalFunction_l3;
if (verboseLevel>0) G4cout << " sigma PWBA L3 CS at medium and high velocity range = " << sigmaPSSR_l3<< G4endl;
}
G4double pssDeltal3 = (4./(systemMass*sigmaPSS_l3*tetal3))*(sigmaPSS_l3/velocityl3)*(sigmaPSS_l3/velocityl3);
if (verboseLevel>0) G4cout << " pssDeltal3=" << pssDeltal3<< G4endl;
G4double energyLossl3 = std::pow(1-pssDeltal3,0.5);
if (verboseLevel>0) G4cout << " energyLossl3=" << energyLossl3<< G4endl;
G4double coulombDeflectionl3 =
(8.*pi*zIncident/systemMass)*std::pow(tetal3*sigmaPSS_l3,-2.)*std::pow(velocityl3/sigmaPSS_l3,-3.)*(zTarget/screenedzTarget);
G4double cParameterl3 = 2.*coulombDeflectionl3/(energyLossl3*(energyLossl3+1.));
G4double coulombDeflectionFunction_l3 = 11.*ExpIntFunction(12,cParameterl3);//Coulomb-deflection effect correction
if (verboseLevel>0) G4cout << " coulombDeflectionFunction_l3 =" << coulombDeflectionFunction_l3 << G4endl;
G4double crossSection_L3 = coulombDeflectionFunction_l3 * sigmaPSSR_l3;
//ECPSSR L3 -subshell cross section is estimated at perturbed-stationnairy-state(PSS)
//and reduced by the energy-loss(E),the Coulomb deflection(C),and the relativity(R) effects
if (verboseLevel>0) G4cout << " crossSection_L3 =" << crossSection_L3 << G4endl;
if (crossSection_L3 >= 0) {
return crossSection_L3 * barn;
}
else {return 0;}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4AnalyticalEcpssrLiCrossSection::CalculateVelocity(G4int subShell, G4int zTarget, G4double massIncident, G4double energyIncident)
{
G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
G4double liBindingEnergy = transitionManager->Shell(zTarget,subShell)->BindingEnergy();
G4Proton* aProtone = G4Proton::Proton();
G4Alpha* aAlpha = G4Alpha::Alpha();
if (!((massIncident == aProtone->GetPDGMass()) || (massIncident == aAlpha->GetPDGMass())))
{
G4cout << "*** WARNING in G4AnalyticalEcpssrLiCrossSection::CalculateVelocity : Proton or Alpha incident particles only. " << G4endl;
G4cout << massIncident << ", " << aAlpha->GetPDGMass() << " (alpha)" << aProtone->GetPDGMass() << " (proton)" << G4endl;
return 0;
}
const G4double zlshell= 4.15;
G4double screenedzTarget = zTarget- zlshell;
const G4double rydbergMeV= 13.6056923e-6;
const G4double nl= 2.;
G4double tetali = (liBindingEnergy*nl*nl)/(screenedzTarget*screenedzTarget*rydbergMeV);
G4double reducedEnergy = (energyIncident*electron_mass_c2)/(massIncident*rydbergMeV*screenedzTarget*screenedzTarget);
G4double velocity = 2.*nl*std::pow(reducedEnergy,0.5)/tetali;
return velocity;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4AnalyticalEcpssrLiCrossSection::FunctionFL1(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 Eta/Theta2 values
if (
theta==8.66e-4 ||
theta==8.66e-3 ||
theta==8.66e-2 ||
theta==8.66e-1 ||
theta==8.66e+00 ||
theta==8.66e+01
) theta=theta-1e-12;
if (
theta==1.e-4 ||
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<double>::iterator t2 = std::upper_bound(dummyVec1.begin(),dummyVec1.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator e12 = std::upper_bound(aVecMap1[(*t1)].begin(),aVecMap1[(*t1)].end(), theta);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e22 = std::upper_bound(aVecMap1[(*t2)].begin(),aVecMap1[(*t2)].end(), theta);
std::vector<double>::iterator e21 = e22-1;
valueT1 =*t1;
valueT2 =*t2;
valueE21 =*e21;
valueE22 =*e22;
valueE12 =*e12;
valueE11 =*e11;
xs11 = FL1Data[valueT1][valueE11];
xs12 = FL1Data[valueT1][valueE12];
xs21 = FL1Data[valueT2][valueE21];
xs22 = FL1Data[valueT2][valueE22];
if (verboseLevel>0)
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 G4AnalyticalEcpssrLiCrossSection::FunctionFL2(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 Eta/Theta2 values
if (
theta==8.66e-4 ||
theta==8.66e-3 ||
theta==8.66e-2 ||
theta==8.66e-1 ||
theta==8.66e+00 ||
theta==8.66e+01
) theta=theta-1e-12;
if (
theta==1.e-4 ||
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<double>::iterator t2 = std::upper_bound(dummyVec2.begin(),dummyVec2.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator e12 = std::upper_bound(aVecMap2[(*t1)].begin(),aVecMap2[(*t1)].end(), theta);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e22 = std::upper_bound(aVecMap2[(*t2)].begin(),aVecMap2[(*t2)].end(), theta);
std::vector<double>::iterator e21 = e22-1;
valueT1 =*t1;
valueT2 =*t2;
valueE21 =*e21;
valueE22 =*e22;
valueE12 =*e12;
valueE11 =*e11;
xs11 = FL2Data[valueT1][valueE11];
xs12 = FL2Data[valueT1][valueE12];
xs21 = FL2Data[valueT2][valueE21];
xs22 = FL2Data[valueT2][valueE22];
if (verboseLevel>0)
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 G4AnalyticalEcpssrLiCrossSection::LinLinInterpolate(G4double e1,
G4double e2,
G4double e,
G4double xs1,
G4double xs2)
{
G4double value = xs1 + (xs2 - xs1)*(e - e1)/ (e2 - e1);
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4AnalyticalEcpssrLiCrossSection::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 G4AnalyticalEcpssrLiCrossSection::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 G4AnalyticalEcpssrLiCrossSection::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);
*/
/*
// Lin-Lin
G4double interpolatedvalue1 = LinLinInterpolate(e11, e12, e, xs11, xs12);
G4double interpolatedvalue2 = LinLinInterpolate(e21, e22, e, xs21, xs22);
G4double value = LinLinInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
*/
return value;
}
@@ -25,7 +25,7 @@
//
//
// $Id: G4AtomicDeexcitation.cc,v 1.11
// GEANT4 tag $Name: geant4-09-03 $
// GEANT4 tag $Name: geant4-09-04 $
//
// Authors: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
// Alfonso Mantero (Alfonso.Mantero@ge.infn.it)
@@ -58,8 +58,8 @@ std::vector<G4DynamicParticle*>* G4AtomicDeexcitation::GenerateParticles(G4int Z
{
std::vector<G4DynamicParticle*>* vectorOfParticles;
vectorOfParticles = new std::vector<G4DynamicParticle*>;
G4DynamicParticle* aParticle;
G4int provShellId = 0;
G4int counter = 0;
@@ -112,7 +112,12 @@ std::vector<G4DynamicParticle*>* G4AtomicDeexcitation::GenerateParticles(G4int Z
// Look this in a particular way: only one auger emitted! // ????
while (provShellId > -2);
// debug
// if (vectorOfParticles->size() > 0) {
// G4cout << " DEEXCITATION!" << G4endl;
// }
return vectorOfParticles;
}
@@ -383,9 +388,7 @@ G4DynamicParticle* G4AtomicDeexcitation::GenerateAuger(G4int Z, G4int shellId)
// G4int augerOriginatingShellId = 0;
G4int numberOfPossibleAuger = 0;
numberOfPossibleAuger = anAugerTransition->AugerTransitionProbabilities(transitionRandomShellId)->size();
G4bool foundFlag = false;
while (transitionRandomShellIndex < transitionSize) {
@@ -25,7 +25,7 @@
//
//
// $Id: G4AtomicTransitionManager.cc,v 1.2 ????
// GEANT4 tag $Name: geant4-09-03 $
// GEANT4 tag $Name: geant4-09-04 $
//
// Authors: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
// Alfonso Mantero (Alfonso.Mantero@ge.infn.it)
@@ -96,19 +96,37 @@ const std::vector<G4int>* G4AugerTransition::TransitionOriginatingShellIds() con
const G4DataVector* G4AugerTransition::AugerTransitionEnergies(G4int startShellId) const
{
std::map<G4int,G4DataVector,std::less<G4int> >::const_iterator shellId = augerTransitionEnergiesMap.find(startShellId);
if (shellId == augerTransitionEnergiesMap.end() )
{G4Exception("G4AugerTransition: corresponding map element not found");}
const G4DataVector* dataSet = &(*shellId).second;
return dataSet;
}
// Returns the emission probabilities of the auger electrons, given th shell
// Returns the emission probabilities of the auger electrons, given the shell
// from wich the transition electron cames from.
const G4DataVector* G4AugerTransition::AugerTransitionProbabilities(G4int startShellId) const
{
//debugging
//if (startShellId == 1){G4cout <<"OI!!!"<< G4endl;}
std::map<G4int,G4DataVector,std::less<G4int> >::const_iterator shellId = augerTransitionProbabilitiesMap.find(startShellId);
if (shellId == augerTransitionProbabilitiesMap.end() )
{G4Exception("G4AugerTransition: corresponding map element not found");}
const G4DataVector* dataSet = &(*shellId).second;
// debugging purpose:
/* G4cout << "id: " << shellId->first << G4endl;
G4cout << "size:" << dataSet->size() << G4endl;
for (G4int i = 0; i < dataSet->size(); i++){
G4cout << (dataSet[0])[i] << G4endl;
}*/
return dataSet;
}
@@ -0,0 +1,338 @@
//
// ********************************************************************
// * 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: G4BoldyshevTripletModel.cc,v 1.2 2010/11/12 16:48:13 flongo Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
//
// Author: Gerardo Depaola & Francesco Longo
//
// History:
// --------
// 23-06-2010 First implementation as model
#include "G4BoldyshevTripletModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BoldyshevTripletModel::G4BoldyshevTripletModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),smallEnergy(4.*MeV),isInitialised(false),
crossSectionHandler(0),meanFreePathTable(0)
{
lowEnergyLimit = 4.0*electron_mass_c2;
highEnergyLimit = 100 * GeV;
SetHighEnergyLimit(highEnergyLimit);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if(verboseLevel > 0) {
G4cout << "Triplet Gamma conversion is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / MeV << " MeV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BoldyshevTripletModel::~G4BoldyshevTripletModel()
{
if (crossSectionHandler) delete crossSectionHandler;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void
G4BoldyshevTripletModel::Initialise(const G4ParticleDefinition*,
const G4DataVector&)
{
if (verboseLevel > 3)
G4cout << "Calling G4BoldyshevTripletModel::Initialise()" << G4endl;
if (crossSectionHandler)
{
crossSectionHandler->Clear();
delete crossSectionHandler;
}
// Read data tables for all materials
crossSectionHandler = new G4CrossSectionHandler();
crossSectionHandler->Initialise(0,lowEnergyLimit,100.*GeV,400);
G4String crossSectionFile = "tripdata/pp-trip-cs-"; // here only pair in electron field cs should be used
crossSectionHandler->LoadData(crossSectionFile);
//
if (verboseLevel > 0) {
G4cout << "Loaded cross section files for Livermore GammaConversion" << G4endl;
G4cout << "To obtain the total cross section this should be used only " << G4endl
<< "in connection with G4NuclearGammaConversion " << G4endl;
}
if (verboseLevel > 0) {
G4cout << "Livermore Electron Gamma Conversion model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / MeV << " MeV - "
<< HighEnergyLimit() / GeV << " GeV"
<< G4endl;
}
if(isInitialised) return;
fParticleChange = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double
G4BoldyshevTripletModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
G4double GammaEnergy,
G4double Z, G4double,
G4double, G4double)
{
if (verboseLevel > 3) {
G4cout << "Calling ComputeCrossSectionPerAtom() of G4BoldyshevTripletModel"
<< G4endl;
}
if (GammaEnergy < lowEnergyLimit || GammaEnergy > highEnergyLimit) return 0;
G4double cs = crossSectionHandler->FindValue(G4int(Z), GammaEnergy);
return cs;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BoldyshevTripletModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* ,
const G4DynamicParticle* aDynamicGamma,
G4double,
G4double)
{
// The energies of the secondary particles are sampled using
// a modified Wheeler-Lamb model (see PhysRevD 7 (1973), 26)
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4BoldyshevTripletModel" << G4endl;
G4double photonEnergy = aDynamicGamma->GetKineticEnergy();
G4ParticleMomentum photonDirection = aDynamicGamma->GetMomentumDirection();
G4double epsilon ;
G4double p0 = electron_mass_c2;
G4double positronTotEnergy, electronTotEnergy, thetaEle, thetaPos;
G4double ener_re=0., theta_re, phi_re, phi;
// Calculo de theta - elecron de recoil
G4double energyThreshold = sqrt(2.)*electron_mass_c2; // -> momentumThreshold_N = 1
energyThreshold = 1.1*electron_mass_c2;
// G4cout << energyThreshold << G4endl;
G4double momentumThreshold_c = sqrt(energyThreshold * energyThreshold - electron_mass_c2*electron_mass_c2); // momentun in MeV/c unit
G4double momentumThreshold_N = momentumThreshold_c/electron_mass_c2; // momentun in mc unit
// Calculation of recoil electron production
G4double SigmaTot = (28./9.) * std::log ( 2.* photonEnergy / electron_mass_c2 ) - 218. / 27. ;
G4double X_0 = 2. * ( sqrt(momentumThreshold_N*momentumThreshold_N + 1) -1 );
G4double SigmaQ = (82./27. - (14./9.) * log (X_0) + 4./15.*X_0 - 0.0348 * X_0 * X_0);
G4double recoilProb = G4UniformRand();
//G4cout << "SIGMA TOT " << SigmaTot << " " << "SigmaQ " << SigmaQ << " " << SigmaQ/SigmaTot << " " << recoilProb << G4endl;
if (recoilProb >= SigmaQ/SigmaTot) // create electron recoil
{
G4double cosThetaMax = ( ( energyThreshold - electron_mass_c2 ) / (momentumThreshold_c) + electron_mass_c2*
( energyThreshold + electron_mass_c2 ) / (photonEnergy*momentumThreshold_c) );
if (cosThetaMax > 1) G4cout << "ERRORE " << G4endl;
G4double r1;
G4double r2;
G4double are, bre, loga, f1_re, greject, cost;
do {
r1 = G4UniformRand();
r2 = G4UniformRand();
// cost = (pow(4./enern,0.5*r1)) ;
cost = pow(cosThetaMax,r1);
theta_re = acos(cost);
are = 1./(14.*cost*cost);
bre = (1.-5.*cost*cost)/(2.*cost);
loga = log((1.+ cost)/(1.- cost));
f1_re = 1. - bre*loga;
if ( theta_re >= 4.47*CLHEP::pi/180.)
{
greject = are*f1_re;
} else {
greject = 1. ;
}
} while(greject < r2);
// Calculo de phi - elecron de recoil
G4double r3, r4, rt;
do {
r3 = G4UniformRand();
r4 = G4UniformRand();
phi_re = twopi*r3 ;
G4double sint2 = 1. - cost*cost ;
G4double fp = 1. - sint2*loga/(2.*cost) ;
rt = (1.-cos(2.*phi_re)*fp/f1_re)/(2.*pi) ;
} while(rt < r4);
// Calculo de la energia - elecron de recoil - relacion momento maximo <-> angulo
G4double S = electron_mass_c2*(2.* photonEnergy + electron_mass_c2);
G4double D2 = 4.*S * electron_mass_c2*electron_mass_c2
+ (S - electron_mass_c2*electron_mass_c2)
*(S - electron_mass_c2*electron_mass_c2)*sin(theta_re)*sin(theta_re);
ener_re = electron_mass_c2 * (S + electron_mass_c2*electron_mass_c2)/sqrt(D2);
// G4cout << "electron de retroceso " << ener_re << " " << theta_re << " " << phi_re << G4endl;
// Recoil electron creation
G4double dxEle_re=sin(theta_re)*std::cos(phi_re),dyEle_re=sin(theta_re)*std::sin(phi_re), dzEle_re=cos(theta_re);
G4double electronRKineEnergy = std::max(0.,ener_re - electron_mass_c2) ;
G4ThreeVector electronRDirection (dxEle_re, dyEle_re, dzEle_re);
electronRDirection.rotateUz(photonDirection);
G4DynamicParticle* particle3 = new G4DynamicParticle (G4Electron::Electron(),
electronRDirection,
electronRKineEnergy);
fvect->push_back(particle3);
}
else
{
// deposito la energia ener_re - electron_mass_c2
// G4cout << "electron de retroceso " << ener_re << G4endl;
fParticleChange->ProposeLocalEnergyDeposit(ener_re - electron_mass_c2);
}
// Depaola (2004) suggested distribution for e+e- energy
// G4double t = 0.5*asinh(momentumThreshold_N);
G4double t = 0.5*log(momentumThreshold_N + sqrt(momentumThreshold_N*momentumThreshold_N+1));
G4double J1 = 0.5*(t*cosh(t)/sinh(t) - log(2.*sinh(t)));
G4double J2 = (-2./3.)*log(2.*sinh(t)) + t*cosh(t)/sinh(t) + (sinh(t)-t*pow(cosh(t),3))/(3.*pow(sinh(t),2));
G4double b = 2.*(J2-J1)/J1;
G4double n = 1 - b/6.;
G4double re=0.;
re = G4UniformRand();
G4double a = 0.;
G4double b1 = 16. - 3.*b - 36.*b*re*n + 36.*b*pow(re,2.)*pow(n,2.) +
6.*pow(b,2.)*re*n;
a = pow((b1/b),0.5);
G4double c1 = (-6. + 12.*re*n + b + 2*a)*pow(b,2.);
epsilon = (pow(c1,1./3.))/(2.*b) + (b-4.)/(2.*pow(c1,1./3.))+0.5;
G4double photonEnergy1 = photonEnergy - ener_re ; // resto al foton la energia del electron de retro.
positronTotEnergy = epsilon*photonEnergy1;
electronTotEnergy = photonEnergy1 - positronTotEnergy; // temporarly
G4double momento_e = sqrt(electronTotEnergy*electronTotEnergy -
electron_mass_c2*electron_mass_c2) ;
G4double momento_p = sqrt(positronTotEnergy*positronTotEnergy -
electron_mass_c2*electron_mass_c2) ;
thetaEle = acos((sqrt(p0*p0/(momento_e*momento_e) +1.)- p0/momento_e)) ;
thetaPos = acos((sqrt(p0*p0/(momento_p*momento_p) +1.)- p0/momento_p)) ;
phi = twopi * G4UniformRand();
G4double dxEle= std::sin(thetaEle)*std::cos(phi),dyEle= std::sin(thetaEle)*std::sin(phi),dzEle=std::cos(thetaEle);
G4double dxPos=-std::sin(thetaPos)*std::cos(phi),dyPos=-std::sin(thetaPos)*std::sin(phi),dzPos=std::cos(thetaPos);
// Kinematics of the created pair:
// the electron and positron are assumed to have a symetric angular
// distribution with respect to the Z axis along the parent photon
G4double electronKineEnergy = std::max(0.,electronTotEnergy - electron_mass_c2) ;
// SI - The range test has been removed wrt original G4LowEnergyGammaconversion class
G4ThreeVector electronDirection (dxEle, dyEle, dzEle);
electronDirection.rotateUz(photonDirection);
G4DynamicParticle* particle1 = new G4DynamicParticle (G4Electron::Electron(),
electronDirection,
electronKineEnergy);
// The e+ is always created (even with kinetic energy = 0) for further annihilation
G4double positronKineEnergy = std::max(0.,positronTotEnergy - electron_mass_c2) ;
// SI - The range test has been removed wrt original G4LowEnergyGammaconversion class
G4ThreeVector positronDirection (dxPos, dyPos, dzPos);
positronDirection.rotateUz(photonDirection);
// Create G4DynamicParticle object for the particle2
G4DynamicParticle* particle2 = new G4DynamicParticle(G4Positron::Positron(),
positronDirection, positronKineEnergy);
// Fill output vector
fvect->push_back(particle1);
fvect->push_back(particle2);
// kill incident photon
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeTrackStatus(fStopAndKill);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -24,8 +24,8 @@
// ********************************************************************
//
//
// $Id: G4CompositeEMDataSet.cc,v 1.15 2009/09/25 07:41:34 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4CompositeEMDataSet.cc,v 1.16 2010/11/26 11:51:11 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -195,6 +195,7 @@ G4bool G4CompositeEMDataSet::SaveData(const G4String& argFileName) const
std::ostringstream message;
message << "G4CompositeEMDataSet::SaveData - component " << (z-minZ) << " not found";
G4Exception(message.str().c_str());
return false;
}
if (!component->SaveData(argFileName))
@@ -0,0 +1,87 @@
//
// ********************************************************************
// * 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: G4DNAAttachment.cc,v 1.1 2010/09/08 13:46:45 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
#include "G4DNAAttachment.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4DNAAttachment::G4DNAAttachment(const G4String& processName,
G4ProcessType type):G4VEmProcess (processName, type),
isInitialised(false)
{
SetProcessSubType(51);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4DNAAttachment::~G4DNAAttachment()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4DNAAttachment::IsApplicable(const G4ParticleDefinition& p)
{
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
return (&p == G4Electron::Electron());
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAAttachment::InitialiseProcess(const G4ParticleDefinition* p)
{
if(!isInitialised)
{
isInitialised = true;
SetBuildTableFlag(false);
G4String name = p->GetParticleName();
if(name == "e-")
{
if(!Model()) SetModel(new G4DNAMeltonAttachmentModel);
Model()->SetLowEnergyLimit(4.*eV);
Model()->SetHighEnergyLimit(13.*eV);
AddEmModel(1, Model());
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4DNAAttachment::PrintInfo()
{
G4cout
<< " Total cross sections computed from "
<< Model()->GetName()
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNABornExcitationModel.cc,v 1.7 2009/08/31 14:03:29 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNABornExcitationModel.cc,v 1.10 2010/08/24 13:51:06 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
#include "G4DNABornExcitationModel.hh"
@@ -39,12 +39,6 @@ G4DNABornExcitationModel::G4DNABornExcitationModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
lowEnergyLimit = 500 * keV;
highEnergyLimit = 100 * MeV;
SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
@@ -53,19 +47,9 @@ G4DNABornExcitationModel::G4DNABornExcitationModel(const G4ParticleDefinition*,
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
//
table = 0;
//
if( verboseLevel>0 )
{
G4cout << "Born excitation model is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / MeV << " MeV"
<< G4endl;
G4cout << "Born excitation model is constructed " << G4endl;
}
}
@@ -75,50 +59,103 @@ G4DNABornExcitationModel::G4DNABornExcitationModel(const G4ParticleDefinition*,
G4DNABornExcitationModel::~G4DNABornExcitationModel()
{
// Cross section
delete table;
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
for (pos = tableData.begin(); pos != tableData.end(); ++pos)
{
G4DNACrossSectionDataSet* table = pos->second;
delete table;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNABornExcitationModel::Initialise(const G4ParticleDefinition* /*particle*/,
void G4DNABornExcitationModel::Initialise(const G4ParticleDefinition* particle,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNABornExcitationModel::Initialise()" << G4endl;
// Energy limits
G4String fileElectron("dna/sigma_excitation_e_born");
G4String fileProton("dna/sigma_excitation_p_born");
G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
G4String electron;
G4String proton;
if (LowEnergyLimit() < lowEnergyLimit)
G4double scaleFactor = (1.e-22 / 3.343) * m*m;
if (electronDef != 0)
{
G4cout << "G4DNABornExcitationModel: low energy limit increased from " <<
LowEnergyLimit()/keV << " keV to " << lowEnergyLimit/keV << " keV" << G4endl;
SetLowEnergyLimit(lowEnergyLimit);
electron = electronDef->GetParticleName();
tableFile[electron] = fileElectron;
lowEnergyLimit[electron] = 9. * eV;
highEnergyLimit[electron] = 1. * MeV;
// Cross section
G4DNACrossSectionDataSet* tableE = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
tableE->LoadData(fileElectron);
tableData[electron] = tableE;
}
else
{
G4Exception("G4DNABornExcitationModel::Initialise(): electron is not defined");
}
if (HighEnergyLimit() > highEnergyLimit)
if (protonDef != 0)
{
G4cout << "G4DNABornExcitationModel: high energy limit decreased from " <<
HighEnergyLimit()/MeV << " MeV to " << highEnergyLimit/MeV << " MeV" << G4endl;
SetHighEnergyLimit(highEnergyLimit);
proton = protonDef->GetParticleName();
tableFile[proton] = fileProton;
lowEnergyLimit[proton] = 500. * keV;
highEnergyLimit[proton] = 100. * MeV;
// Cross section
G4DNACrossSectionDataSet* tableP = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
tableP->LoadData(fileProton);
tableData[proton] = tableP;
}
else
{
G4Exception("G4DNABornExcitationModel::Initialise(): proton is not defined");
}
//
if (table == 0)
if (particle==electronDef)
{
table = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,(1e-22/3.343)*m*m );
table->LoadData("dna/sigma_excitation_p_born");
SetLowEnergyLimit(lowEnergyLimit[electron]);
SetHighEnergyLimit(highEnergyLimit[electron]);
}
if (particle==protonDef)
{
SetLowEnergyLimit(lowEnergyLimit[proton]);
SetHighEnergyLimit(highEnergyLimit[proton]);
}
if( verboseLevel>0 )
{
G4cout << "Born excitation model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / keV << " keV - "
<< HighEnergyLimit() / MeV << " MeV " << G4endl;
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / keV << " keV for "
<< particle->GetParticleName()
<< G4endl;
}
if(!isInitialised)
{
isInitialised = true;
@@ -130,77 +167,82 @@ void G4DNABornExcitationModel::Initialise(const G4ParticleDefinition* /*particle
}
// InitialiseElementSelectors(particle,cuts);
// Test if water material
flagMaterialIsWater= false;
densityWater = 0;
const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
if(theCoupleTable)
{
G4int numOfCouples = theCoupleTable->GetTableSize();
if(numOfCouples>0)
{
for (G4int i=0; i<numOfCouples; i++)
{
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
if (material->GetName() == "G4_WATER")
{
G4double density = material->GetAtomicNumDensityVector()[1];
flagMaterialIsWater = true;
densityWater = density;
if (verboseLevel > 3)
G4cout << "****** Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
}
}
} // if(numOfCouples>0)
} // if (theCoupleTable)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNABornExcitationModel::CrossSectionPerVolume(const G4Material*,
G4double G4DNABornExcitationModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double k,
G4double ekin,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNABornExcitationModel" << G4endl;
if (
particleDefinition != G4Proton::ProtonDefinition()
&&
particleDefinition != G4Electron::ElectronDefinition()
)
return 0;
// Calculate total cross section for model
G4double crossSection=0;
if (flagMaterialIsWater)
G4double lowLim = 0;
G4double highLim = 0;
G4double sigma=0;
if (material->GetName() == "G4_WATER")
{
if (particleDefinition == G4Proton::ProtonDefinition())
const G4String& particleName = particleDefinition->GetParticleName();
std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
pos1 = lowEnergyLimit.find(particleName);
if (pos1 != lowEnergyLimit.end())
{
if (k >= lowEnergyLimit && k < highEnergyLimit)
{
crossSection = table->FindValue(k);
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(keV)=" << k/keV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << crossSection/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << crossSection*densityWater/(1./cm) << G4endl;
}
lowLim = pos1->second;
}
std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
pos2 = highEnergyLimit.find(particleName);
if (pos2 != highEnergyLimit.end())
{
highLim = pos2->second;
}
} // if (flagMaterialIsWater)
return crossSection*densityWater;
if (ekin >= lowLim && ekin < highLim)
{
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
pos = tableData.find(particleName);
if (pos != tableData.end())
{
G4DNACrossSectionDataSet* table = pos->second;
if (table != 0)
{
sigma = table->FindValue(ekin);
}
}
else
{
G4Exception("G4DNABornExcitationModel::CrossSectionPerVolume: attempting to calculate cross section for wrong particle");
}
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if (waterMaterial)
return sigma*material->GetAtomicNumDensityVector()[1];
}
@@ -218,7 +260,9 @@ void G4DNABornExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>
G4double k = aDynamicParticle->GetKineticEnergy();
G4int level = RandomSelect(k);
const G4String& particleName = aDynamicParticle->GetDefinition()->GetParticleName();
G4int level = RandomSelect(k,particleName);
G4double excitationEnergy = waterStructure.ExcitationEnergy(level);
G4double newEnergy = k - excitationEnergy;
@@ -233,41 +277,55 @@ void G4DNABornExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNABornExcitationModel::RandomSelect(G4double k)
G4int G4DNABornExcitationModel::RandomSelect(G4double k, const G4String& particle)
{
G4int level = 0;
G4double* valuesBuffer = new G4double[table->NumberOfComponents()];
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
pos = tableData.find(particle);
const size_t n(table->NumberOfComponents());
size_t i(n);
G4double value = 0.;
while (i>0)
{
i--;
valuesBuffer[i] = table->GetComponent(i)->FindValue(k);
value += valuesBuffer[i];
}
value *= G4UniformRand();
i = n;
while (i > 0)
if (pos != tableData.end())
{
i--;
if (valuesBuffer[i] > value)
G4DNACrossSectionDataSet* table = pos->second;
if (table != 0)
{
delete[] valuesBuffer;
return i;
G4double* valuesBuffer = new G4double[table->NumberOfComponents()];
const size_t n(table->NumberOfComponents());
size_t i(n);
G4double value = 0.;
while (i>0)
{
i--;
valuesBuffer[i] = table->GetComponent(i)->FindValue(k);
value += valuesBuffer[i];
}
value *= G4UniformRand();
i = n;
while (i > 0)
{
i--;
if (valuesBuffer[i] > value)
{
delete[] valuesBuffer;
return i;
}
value -= valuesBuffer[i];
}
if (valuesBuffer) delete[] valuesBuffer;
}
value -= valuesBuffer[i];
}
if (valuesBuffer) delete[] valuesBuffer;
else
{
G4Exception("G4DNABornExcitationModel::RandomSelect attempting to calculate cross section for wrong particle");
}
return level;
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNABornIonisationModel.cc,v 1.14 2009/11/12 03:08:58 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNABornIonisationModel.cc,v 1.18 2010/11/03 12:22:36 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
#include "G4DNABornIonisationModel.hh"
@@ -238,45 +238,11 @@ void G4DNABornIonisationModel::Initialise(const G4ParticleDefinition* particle,
// InitialiseElementSelectors(particle,cuts);
// Test if water material
flagMaterialIsWater= false;
densityWater = 0;
const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
if(theCoupleTable)
{
G4int numOfCouples = theCoupleTable->GetTableSize();
if(numOfCouples>0)
{
for (G4int i=0; i<numOfCouples; i++)
{
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
if (material->GetName() == "G4_WATER")
{
G4double density = material->GetAtomicNumDensityVector()[1];
flagMaterialIsWater = true;
densityWater = density;
if (verboseLevel > 3)
G4cout << "****** Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
}
}
} // if(numOfCouples>0)
} // if (theCoupleTable)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNABornIonisationModel::CrossSectionPerVolume(const G4Material*,
G4double G4DNABornIonisationModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double ekin,
G4double,
@@ -299,7 +265,7 @@ G4double G4DNABornIonisationModel::CrossSectionPerVolume(const G4Material*,
G4double highLim = 0;
G4double sigma=0;
if (flagMaterialIsWater)
if (material->GetName() == "G4_WATER")
{
const G4String& particleName = particleDefinition->GetParticleName();
@@ -340,12 +306,12 @@ G4double G4DNABornIonisationModel::CrossSectionPerVolume(const G4Material*,
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*densityWater/(1./cm) << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if (waterMaterial)
return sigma*densityWater;
return sigma*material->GetAtomicNumDensityVector()[1];
}
@@ -409,49 +375,32 @@ void G4DNABornIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>
G4ThreeVector deltaDirection(dirX,dirY,dirZ);
deltaDirection.rotateUz(primaryDirection);
G4double deltaTotalMomentum = std::sqrt(secondaryKinetic*(secondaryKinetic + 2.*electron_mass_c2 ));
if (particle->GetDefinition() == G4Electron::ElectronDefinition())
{
G4double deltaTotalMomentum = std::sqrt(secondaryKinetic*(secondaryKinetic + 2.*electron_mass_c2 ));
G4double finalPx = totalMomentum*primaryDirection.x() - deltaTotalMomentum*deltaDirection.x();
G4double finalPy = totalMomentum*primaryDirection.y() - deltaTotalMomentum*deltaDirection.y();
G4double finalPz = totalMomentum*primaryDirection.z() - deltaTotalMomentum*deltaDirection.z();
G4double finalMomentum = std::sqrt(finalPx*finalPx + finalPy*finalPy + finalPz*finalPz);
finalPx /= finalMomentum;
finalPy /= finalMomentum;
finalPz /= finalMomentum;
G4double finalPx = totalMomentum*primaryDirection.x() - deltaTotalMomentum*deltaDirection.x();
G4double finalPy = totalMomentum*primaryDirection.y() - deltaTotalMomentum*deltaDirection.y();
G4double finalPz = totalMomentum*primaryDirection.z() - deltaTotalMomentum*deltaDirection.z();
G4double finalMomentum = std::sqrt(finalPx*finalPx + finalPy*finalPy + finalPz*finalPz);
finalPx /= finalMomentum;
finalPy /= finalMomentum;
finalPz /= finalMomentum;
G4ThreeVector direction;
direction.set(finalPx,finalPy,finalPz);
G4ThreeVector direction;
direction.set(finalPx,finalPy,finalPz);
fParticleChangeForGamma->ProposeMomentumDirection(direction.unit()) ;
}
else fParticleChangeForGamma->ProposeMomentumDirection(primaryDirection) ;
fParticleChangeForGamma->ProposeMomentumDirection(direction.unit()) ;
fParticleChangeForGamma->SetProposedKineticEnergy(k-bindingEnergy-secondaryKinetic);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(bindingEnergy);
G4DynamicParticle* dp = new G4DynamicParticle (G4Electron::Electron(),deltaDirection,secondaryKinetic) ;
fvect->push_back(dp);
/*
// creating neutral water molechule...
G4DNAGenericMoleculeManager *instance;
instance = G4DNAGenericMoleculeManager::Instance();
G4ParticleDefinition* waterDef = NULL;
G4Molecule* water = instance->GetMolecule("H2O");
waterDef = (G4ParticleDefinition*)water;
direction.set(0.,0.,0.);
//G4DynamicParticle* dynamicWater = new G4DynamicParticle(waterDef, direction, bindingEnergy);
G4DynamicMolecule* dynamicWater = new G4DynamicMolecule(water, direction, bindingEnergy);
//dynamicWater->RemoveElectron(ionizationShell, 1);
G4DynamicMolecule* dynamicWater2 = new G4DynamicMolecule(water, direction, bindingEnergy);
G4DynamicMolecule* dynamicWater3 = new G4DynamicMolecule(water, direction, bindingEnergy);
fvect->push_back(dynamicWater);
fvect->push_back(dynamicWater2);
fvect->push_back(dynamicWater3);
*/
}
}
@@ -511,7 +460,7 @@ G4double k, G4int shell)
if (particleDefinition == G4Proton::ProtonDefinition())
{
G4double maximumKineticEnergyTransfer = 4.* (electron_mass_c2 / proton_mass_c2) * k - (waterStructure.IonisationEnergy(shell));
G4double maximumKineticEnergyTransfer = 4.* (electron_mass_c2 / proton_mass_c2) * k;
G4double crossSectionMaximum = 0.;
for (G4double value = waterStructure.IonisationEnergy(shell);
@@ -563,7 +512,14 @@ void G4DNABornIonisationModel::RandomizeEjectedElectronDirection(G4ParticleDefin
{
G4double maxSecKinetic = 4.* (electron_mass_c2 / proton_mass_c2) * k;
phi = twopi * G4UniformRand();
cosTheta = std::sqrt(secKinetic / maxSecKinetic);
// cosTheta = std::sqrt(secKinetic / maxSecKinetic);
// Restriction below 100 eV from Emfietzoglou (2000)
if (secKinetic>100*eV) cosTheta = std::sqrt(secKinetic / maxSecKinetic);
else cosTheta = (2.*G4UniformRand())-1.;
}
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAChampionElasticModel.cc,v 1.10 2009/11/03 15:04:25 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNAChampionElasticModel.cc,v 1.16 2010/11/11 22:32:22 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
#include "G4DNAChampionElasticModel.hh"
@@ -40,10 +40,9 @@ G4DNAChampionElasticModel::G4DNAChampionElasticModel(const G4ParticleDefinition*
:G4VEmModel(nam),isInitialised(false)
{
killBelowEnergy = 8.23*eV; // Minimum e- energy for energy loss by excitation
killBelowEnergy = 4*eV;
lowEnergyLimit = 0 * eV;
lowEnergyLimitOfModel = 7.4 * eV; // The model lower energy is 7.4 eV
highEnergyLimit = 10 * MeV;
highEnergyLimit = 1. * MeV;
SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
@@ -63,6 +62,7 @@ G4DNAChampionElasticModel::G4DNAChampionElasticModel(const G4ParticleDefinition*
<< highEnergyLimit / MeV << " MeV"
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -131,14 +131,14 @@ void G4DNAChampionElasticModel::Initialise(const G4ParticleDefinition* /*particl
tableData[electron] = tableE;
// For final state
char *path = getenv("G4LEDATA");
if (!path)
G4Exception("G4FinalStateElasticChampion::Initialise: G4LEDATA environment variable not set");
std::ostringstream eFullFileName;
eFullFileName << path << "/dna/sigmadiff_elastic_e_champion.dat";
eFullFileName << path << "/dna/sigmadiff_cumulatedshort_elastic_e_champion.dat";
std::ifstream eDiffCrossSection(eFullFileName.str().c_str());
if (!eDiffCrossSection) G4Exception("G4DNAChampionElasticModel::Initialise: error opening electron DATA FILE");
@@ -150,8 +150,9 @@ void G4DNAChampionElasticModel::Initialise(const G4ParticleDefinition* /*particl
double tDummy;
double eDummy;
eDiffCrossSection>>tDummy>>eDummy;
// SI : mandatory eVecm initialization
if (tDummy != eTdummyVec.back())
{
eTdummyVec.push_back(tDummy);
@@ -160,11 +161,8 @@ void G4DNAChampionElasticModel::Initialise(const G4ParticleDefinition* /*particl
eDiffCrossSection>>eDiffCrossSectionData[tDummy][eDummy];
// SI : only if not end of file reached !
if (!eDiffCrossSection.eof()) eDiffCrossSectionData[tDummy][eDummy]*=scaleFactor;
if (eDummy != eVecm[tDummy].back()) eVecm[tDummy].push_back(eDummy);
}
// End final state
@@ -196,45 +194,11 @@ void G4DNAChampionElasticModel::Initialise(const G4ParticleDefinition* /*particl
// InitialiseElementSelectors(particle,cuts);
// Test if water material
flagMaterialIsWater= false;
densityWater = 0;
const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
if(theCoupleTable)
{
G4int numOfCouples = theCoupleTable->GetTableSize();
if(numOfCouples>0)
{
for (G4int i=0; i<numOfCouples; i++)
{
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
if (material->GetName() == "G4_WATER")
{
G4double density = material->GetAtomicNumDensityVector()[1];
flagMaterialIsWater = true;
densityWater = density;
if (verboseLevel > 3)
G4cout << "****** Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
}
}
} // if(numOfCouples>0)
} // if (theCoupleTable)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::CrossSectionPerVolume(const G4Material*,
G4double G4DNAChampionElasticModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* p,
G4double ekin,
G4double,
@@ -247,14 +211,14 @@ G4double G4DNAChampionElasticModel::CrossSectionPerVolume(const G4Material*,
G4double sigma=0;
if (flagMaterialIsWater)
if (material->GetName() == "G4_WATER")
{
const G4String& particleName = p->GetParticleName();
if (ekin < highEnergyLimit)
{
//SI : XS must not be zero otherwise sampling of secondaries method ignored
if (ekin < lowEnergyLimitOfModel) ekin = lowEnergyLimitOfModel;
if (ekin < killBelowEnergy) return DBL_MAX;
//
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
@@ -278,12 +242,12 @@ G4double G4DNAChampionElasticModel::CrossSectionPerVolume(const G4Material*,
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*densityWater/(1./cm) << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if (flagMaterialIsWater)
}
return sigma*densityWater;
return sigma*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -309,6 +273,7 @@ void G4DNAChampionElasticModel::SampleSecondaries(std::vector<G4DynamicParticle*
if (electronEnergy0>= killBelowEnergy && electronEnergy0 < highEnergyLimit)
{
G4double cosTheta = RandomizeCosTheta(electronEnergy0);
G4double phi = 2. * pi * G4UniformRand();
@@ -333,11 +298,10 @@ void G4DNAChampionElasticModel::SampleSecondaries(std::vector<G4DynamicParticle*
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::DifferentialCrossSection
(G4ParticleDefinition * particleDefinition, G4double k, G4double theta)
G4double G4DNAChampionElasticModel::Theta
(G4ParticleDefinition * particleDefinition, G4double k, G4double integrDiff)
{
G4double sigma = 0.;
G4double theta = 0.;
G4double valueT1 = 0;
G4double valueT2 = 0;
G4double valueE21 = 0;
@@ -349,18 +313,15 @@ G4double G4DNAChampionElasticModel::DifferentialCrossSection
G4double xs21 = 0;
G4double xs22 = 0;
//SI : ensure the correct computation of cross section at the 180*deg limit
if (theta==180.) theta=theta-1e-9;
if (particleDefinition == G4Electron::ElectronDefinition())
{
std::vector<double>::iterator t2 = std::upper_bound(eTdummyVec.begin(),eTdummyVec.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator e12 = std::upper_bound(eVecm[(*t1)].begin(),eVecm[(*t1)].end(), theta);
std::vector<double>::iterator e12 = std::upper_bound(eVecm[(*t1)].begin(),eVecm[(*t1)].end(), integrDiff);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e22 = std::upper_bound(eVecm[(*t2)].begin(),eVecm[(*t2)].end(), theta);
std::vector<double>::iterator e22 = std::upper_bound(eVecm[(*t2)].begin(),eVecm[(*t2)].end(), integrDiff);
std::vector<double>::iterator e21 = e22-1;
valueT1 =*t1;
@@ -374,24 +335,18 @@ G4double G4DNAChampionElasticModel::DifferentialCrossSection
xs12 = eDiffCrossSectionData[valueT1][valueE12];
xs21 = eDiffCrossSectionData[valueT2][valueE21];
xs22 = eDiffCrossSectionData[valueT2][valueE22];
}
G4double xsProduct = xs11 * xs12 * xs21 * xs22;
}
if (xs11==0 || xs12==0 ||xs21==0 ||xs22==0) return (0.);
if (xsProduct != 0.)
{
sigma = QuadInterpolator( valueE11, valueE12,
if (xs11==0 && xs12==0 && xs21==0 && xs22==0) return (0.);
theta = QuadInterpolator ( valueE11, valueE12,
valueE21, valueE22,
xs11, xs12,
xs21, xs22,
valueT1, valueT2,
k, theta );
}
return sigma;
k, integrDiff );
return theta;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -410,6 +365,20 @@ G4double G4DNAChampionElasticModel::LinLogInterpolate(G4double e1,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::LinLinInterpolate(G4double e1,
G4double e2,
G4double e,
G4double xs1,
G4double xs2)
{
G4double d1 = xs1;
G4double d2 = xs2;
G4double value = (d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::LogLogInterpolate(G4double e1,
G4double e2,
G4double e,
@@ -425,6 +394,7 @@ G4double G4DNAChampionElasticModel::LogLogInterpolate(G4double e1,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::QuadInterpolator(G4double e11, G4double e12,
G4double e21, G4double e22,
G4double xs11, G4double xs12,
@@ -432,17 +402,24 @@ G4double G4DNAChampionElasticModel::QuadInterpolator(G4double e11, G4double e12,
G4double t1, G4double t2,
G4double t, G4double e)
{
// Log-Log
// 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
// 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);
*/
// Lin-Lin
G4double interpolatedvalue1 = LinLinInterpolate(e11, e12, e, xs11, xs12);
G4double interpolatedvalue2 = LinLinInterpolate(e21, e22, e, xs21, xs22);
G4double value = LinLinInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
return value;
}
@@ -450,36 +427,16 @@ G4double G4DNAChampionElasticModel::QuadInterpolator(G4double e11, G4double e12,
G4double G4DNAChampionElasticModel::RandomizeCosTheta(G4double k)
{
// ***** Similar method as for screened Rutherford scattering
G4int iMax=180;
G4double max=0;
G4double tmp=0;
// Look for maximum :
for (G4int i=0; i<iMax; i++)
{
tmp = DifferentialCrossSection(G4Electron::ElectronDefinition(),k/eV,G4double(i)*180./(iMax-1));
if (tmp>max) max = tmp;
}
G4double integrdiff=0;
G4double uniformRand=G4UniformRand();
integrdiff = uniformRand;
G4double theta=0.;
G4double cosTheta=0.;
theta = Theta(G4Electron::ElectronDefinition(),k/eV,integrdiff);
G4double oneOverMax=0;
if (max!=0) oneOverMax = 1./max;
G4double cosTheta = 0.;
G4double fCosTheta = 0.;
do
{
cosTheta = 2. * G4UniformRand() - 1.;
fCosTheta = oneOverMax * DifferentialCrossSection(G4Electron::ElectronDefinition(),k/eV,std::acos(cosTheta)*180./pi);
}
while (fCosTheta < G4UniformRand());
if (verboseLevel > 3)
{
G4cout << "---> Cos(theta)=" << cosTheta << G4endl;
}
cosTheta= std::cos(theta*pi/180);
return cosTheta;
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAChargeDecrease.cc,v 1.3 2009/03/04 13:28:49 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNAChargeDecrease.cc,v 1.4 2010/03/18 16:36:48 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04-beta-01 $
#include "G4DNAChargeDecrease.hh"
@@ -71,7 +71,16 @@ void G4DNAChargeDecrease::InitialiseProcess(const G4ParticleDefinition* p)
G4String name = p->GetParticleName();
if( name == "proton" || name == "alpha" || name == "alpha+" )
if( name == "proton" )
{
if(!Model()) SetModel(new G4DNADingfelderChargeDecreaseModel);
Model()->SetLowEnergyLimit(100*eV);
Model()->SetHighEnergyLimit(10*MeV);
AddEmModel(1, Model());
}
if( name == "alpha" || name == "alpha+" )
{
if(!Model()) SetModel(new G4DNADingfelderChargeDecreaseModel);
Model()->SetLowEnergyLimit(1*keV);
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAChargeIncrease.cc,v 1.3 2009/03/04 13:28:49 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNAChargeIncrease.cc,v 1.4 2010/03/18 16:36:48 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04-beta-01 $
#include "G4DNAChargeIncrease.hh"
@@ -71,7 +71,16 @@ void G4DNAChargeIncrease::InitialiseProcess(const G4ParticleDefinition* p)
G4String name = p->GetParticleName();
if( name == "hydrogen" || name =="alpha+" || name =="helium" )
if( name == "hydrogen" )
{
if(!Model()) SetModel(new G4DNADingfelderChargeIncreaseModel);
Model()->SetLowEnergyLimit(100*eV);
Model()->SetHighEnergyLimit(10*MeV);
AddEmModel(1, Model());
}
if( name =="alpha+" || name =="helium" )
{
if(!Model()) SetModel(new G4DNADingfelderChargeIncreaseModel);
Model()->SetLowEnergyLimit(1*keV);
@@ -79,6 +88,7 @@ void G4DNAChargeIncrease::InitialiseProcess(const G4ParticleDefinition* p)
AddEmModel(1, Model());
}
}
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNADingfelderChargeDecreaseModel.cc,v 1.6 2009/08/13 11:32:47 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNADingfelderChargeDecreaseModel.cc,v 1.9 2010/04/06 11:00:35 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04-beta-01 $
//
#include "G4DNADingfelderChargeDecreaseModel.hh"
@@ -83,7 +83,7 @@ void G4DNADingfelderChargeDecreaseModel::Initialise(const G4ParticleDefinition*
if (protonDef != 0)
{
proton = protonDef->GetParticleName();
lowEnergyLimit[proton] = 1. * keV;
lowEnergyLimit[proton] = 100. * eV;
highEnergyLimit[proton] = 10. * MeV;
}
else
@@ -208,45 +208,11 @@ void G4DNADingfelderChargeDecreaseModel::Initialise(const G4ParticleDefinition*
// InitialiseElementSelectors(particle,cuts);
// Test if water material
flagMaterialIsWater= false;
densityWater = 0;
const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
if(theCoupleTable)
{
G4int numOfCouples = theCoupleTable->GetTableSize();
if(numOfCouples>0)
{
for (G4int i=0; i<numOfCouples; i++)
{
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
if (material->GetName() == "G4_WATER")
{
G4double density = material->GetAtomicNumDensityVector()[1];
flagMaterialIsWater = true;
densityWater = density;
if (verboseLevel > 3)
G4cout << "****** Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
}
}
} // if(numOfCouples>0)
} // if (theCoupleTable)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNADingfelderChargeDecreaseModel::CrossSectionPerVolume(const G4Material*,
G4double G4DNADingfelderChargeDecreaseModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double k,
G4double,
@@ -274,7 +240,7 @@ G4double G4DNADingfelderChargeDecreaseModel::CrossSectionPerVolume(const G4Mater
G4double highLim = 0;
G4double crossSection = 0.;
if (flagMaterialIsWater)
if (material->GetName() == "G4_WATER")
{
const G4String& particleName = particleDefinition->GetParticleName();
@@ -303,12 +269,12 @@ G4double G4DNADingfelderChargeDecreaseModel::CrossSectionPerVolume(const G4Mater
{
G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << crossSection/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << crossSection*densityWater/(1./cm) << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << crossSection*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if (flagMaterialIsWater)
}
return crossSection*densityWater;
return crossSection*material->GetAtomicNumDensityVector()[1];
}
@@ -326,6 +292,8 @@ void G4DNADingfelderChargeDecreaseModel::SampleSecondaries(std::vector<G4Dynamic
G4double inK = aDynamicParticle->GetKineticEnergy();
G4ParticleDefinition* definition = aDynamicParticle->GetDefinition();
G4double particleMass = definition->GetPDGMass();
G4int finalStateIndex = RandomSelect(inK,definition);
@@ -337,7 +305,7 @@ void G4DNADingfelderChargeDecreaseModel::SampleSecondaries(std::vector<G4Dynamic
if (definition==G4Proton::Proton())
outK = inK - n*(inK*electron_mass_c2/proton_mass_c2) - waterBindingEnergy + outgoingParticleBindingEnergy;
else
outK = inK - n*(inK*electron_mass_c2/(3728*MeV)) - waterBindingEnergy + outgoingParticleBindingEnergy;
outK = inK - n*(inK*electron_mass_c2/particleMass) - waterBindingEnergy + outgoingParticleBindingEnergy;
if (outK<0)
{
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNADingfelderChargeIncreaseModel.cc,v 1.6 2009/08/13 11:32:47 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNADingfelderChargeIncreaseModel.cc,v 1.9 2010/04/06 11:00:35 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04-beta-01 $
//
#include "G4DNADingfelderChargeIncreaseModel.hh"
@@ -84,7 +84,7 @@ void G4DNADingfelderChargeIncreaseModel::Initialise(const G4ParticleDefinition*
if (hydrogenDef != 0)
{
hydrogen = hydrogenDef->GetParticleName();
lowEnergyLimit[hydrogen] = 1. * keV;
lowEnergyLimit[hydrogen] = 100. * eV;
highEnergyLimit[hydrogen] = 10. * MeV;
}
else
@@ -199,45 +199,11 @@ void G4DNADingfelderChargeIncreaseModel::Initialise(const G4ParticleDefinition*
// InitialiseElementSelectors(particle,cuts);
// Test if water material
flagMaterialIsWater= false;
densityWater = 0;
const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
if(theCoupleTable)
{
G4int numOfCouples = theCoupleTable->GetTableSize();
if(numOfCouples>0)
{
for (G4int i=0; i<numOfCouples; i++)
{
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
if (material->GetName() == "G4_WATER")
{
G4double density = material->GetAtomicNumDensityVector()[1];
flagMaterialIsWater = true;
densityWater = density;
if (verboseLevel > 3)
G4cout << "****** Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
}
}
} // if(numOfCouples>0)
} // if (theCoupleTable)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNADingfelderChargeIncreaseModel::CrossSectionPerVolume(const G4Material*,
G4double G4DNADingfelderChargeIncreaseModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double k,
G4double,
@@ -265,7 +231,7 @@ G4double G4DNADingfelderChargeIncreaseModel::CrossSectionPerVolume(const G4Mater
G4double highLim = 0;
G4double totalCrossSection = 0.;
if (flagMaterialIsWater)
if (material->GetName() == "G4_WATER")
{
const G4String& particleName = particleDefinition->GetParticleName();
@@ -314,12 +280,12 @@ G4double G4DNADingfelderChargeIncreaseModel::CrossSectionPerVolume(const G4Mater
{
G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << totalCrossSection/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << totalCrossSection*densityWater/(1./cm) << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << totalCrossSection*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if (flagMaterialIsWater)
}
return totalCrossSection*densityWater;
return totalCrossSection*material->GetAtomicNumDensityVector()[1];
}
@@ -338,7 +304,9 @@ void G4DNADingfelderChargeIncreaseModel::SampleSecondaries(std::vector<G4Dynamic
fParticleChangeForGamma->ProposeLocalEnergyDeposit(0.);
G4ParticleDefinition* definition = aDynamicParticle->GetDefinition();
G4double particleMass = definition->GetPDGMass();
G4double inK = aDynamicParticle->GetKineticEnergy();
G4int finalStateIndex = RandomSelect(inK,definition);
@@ -352,7 +320,7 @@ void G4DNADingfelderChargeIncreaseModel::SampleSecondaries(std::vector<G4Dynamic
G4double electronK;
if (definition == instance->GetIon("hydrogen")) electronK = inK*electron_mass_c2/proton_mass_c2;
else electronK = inK*electron_mass_c2/(3728*MeV);
else electronK = inK*electron_mass_c2/(particleMass);
if (outK<0)
{
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAElastic.cc,v 1.3 2009/03/04 13:28:49 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNAElastic.cc,v 1.4 2010/09/08 14:07:16 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
#include "G4DNAElastic.hh"
@@ -61,7 +61,7 @@ void G4DNAElastic::InitialiseProcess(const G4ParticleDefinition*)
SetBuildTableFlag(false);
if(!Model()) SetModel(new G4DNAScreenedRutherfordElasticModel);
Model()->SetLowEnergyLimit(0*eV);
Model()->SetHighEnergyLimit(10*MeV);
Model()->SetHighEnergyLimit(1.*MeV);
AddEmModel(1, Model());
}
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAEmfietzoglouExcitationModel.cc,v 1.8 2009/08/13 11:32:47 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNAEmfietzoglouExcitationModel.cc,v 1.10 2010/06/08 21:50:00 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04-beta-01 $
//
#include "G4DNAEmfietzoglouExcitationModel.hh"
@@ -45,6 +45,8 @@ G4DNAEmfietzoglouExcitationModel::G4DNAEmfietzoglouExcitationModel(const G4Parti
SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
nLevels = waterExcitation.NumberOfLevels();
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
@@ -95,10 +97,6 @@ void G4DNAEmfietzoglouExcitationModel::Initialise(const G4ParticleDefinition* /*
SetHighEnergyLimit(highEnergyLimit);
}
//
nLevels = waterExcitation.NumberOfLevels();
//
if( verboseLevel>0 )
{
@@ -121,45 +119,11 @@ void G4DNAEmfietzoglouExcitationModel::Initialise(const G4ParticleDefinition* /*
// InitialiseElementSelectors(particle,cuts);
// Test if water material
flagMaterialIsWater= false;
densityWater = 0;
const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
if(theCoupleTable)
{
G4int numOfCouples = theCoupleTable->GetTableSize();
if(numOfCouples>0)
{
for (G4int i=0; i<numOfCouples; i++)
{
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
if (material->GetName() == "G4_WATER")
{
G4double density = material->GetAtomicNumDensityVector()[1];
flagMaterialIsWater = true;
densityWater = density;
if (verboseLevel > 3)
G4cout << "****** Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
}
}
} // if(numOfCouples>0)
} // if (theCoupleTable)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAEmfietzoglouExcitationModel::CrossSectionPerVolume(const G4Material*,
G4double G4DNAEmfietzoglouExcitationModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double ekin,
G4double,
@@ -172,7 +136,7 @@ G4double G4DNAEmfietzoglouExcitationModel::CrossSectionPerVolume(const G4Materia
G4double sigma=0;
if (flagMaterialIsWater)
if (material->GetName() == "G4_WATER")
{
if (particleDefinition == G4Electron::ElectronDefinition())
@@ -187,12 +151,12 @@ G4double G4DNAEmfietzoglouExcitationModel::CrossSectionPerVolume(const G4Materia
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*densityWater/(1./cm) << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if (flagMaterialIsWater)
return sigma*densityWater;
}
return sigma*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -270,6 +234,7 @@ G4double G4DNAEmfietzoglouExcitationModel::PartialCrossSection(G4double t, G4int
* std::pow((1.- (exc/t)), pj[level]);
sigma = excitationSigma / density;
}
return sigma;
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAExcitation.cc,v 1.3 2009/03/04 13:28:49 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNAExcitation.cc,v 1.7 2010/10/08 08:53:17 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
#include "G4DNAExcitation.hh"
@@ -56,6 +56,7 @@ G4bool G4DNAExcitation::IsApplicable(const G4ParticleDefinition& p)
(
&p == G4Electron::Electron()
|| &p == G4Proton::ProtonDefinition()
|| &p == instance->GetIon("hydrogen")
|| &p == instance->GetIon("alpha++")
|| &p == instance->GetIon("alpha+")
|| &p == instance->GetIon("helium")
@@ -75,9 +76,18 @@ void G4DNAExcitation::InitialiseProcess(const G4ParticleDefinition* p)
if(name == "e-")
{
// Emfietzoglou model
/*
if(!Model()) SetModel(new G4DNAEmfietzoglouExcitationModel);
Model()->SetLowEnergyLimit(8.23*eV);
Model()->SetHighEnergyLimit(10*MeV);
*/
// Born model
if(!Model()) SetModel(new G4DNABornExcitationModel);
Model()->SetLowEnergyLimit(9*eV);
Model()->SetHighEnergyLimit(1*MeV);
AddEmModel(1, Model());
}
@@ -90,17 +100,27 @@ void G4DNAExcitation::InitialiseProcess(const G4ParticleDefinition* p)
if(!Model(2)) SetModel(new G4DNABornExcitationModel,2);
Model(2)->SetLowEnergyLimit(500*keV);
Model(2)->SetHighEnergyLimit(10*MeV);
Model(2)->SetHighEnergyLimit(100*MeV);
AddEmModel(1, Model(1));
AddEmModel(2, Model(2));
}
if(name == "hydrogen")
{
if(!Model()) SetModel(new G4DNAMillerGreenExcitationModel);
Model()->SetLowEnergyLimit(10*eV);
Model()->SetHighEnergyLimit(500*keV);
AddEmModel(1, Model());
}
if( name == "alpha" || name == "alpha+" || name == "helium" )
{
if(!Model()) SetModel(new G4DNAMillerGreenExcitationModel);
Model()->SetLowEnergyLimit(1*keV);
Model()->SetHighEnergyLimit(10*MeV);
Model()->SetHighEnergyLimit(400*MeV);
AddEmModel(1, Model());
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAGenericIonsManager.cc,v 1.6 2009/06/10 13:32:36 mantero Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNAGenericIonsManager.cc,v 1.7 2010/11/03 10:44:26 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
#include "G4DNAGenericIonsManager.hh"
#include "G4Alpha.hh"
@@ -70,8 +70,49 @@ G4DNAGenericIonsManager :: G4DNAGenericIonsManager()
G4Ions *positronium1s;
G4Ions *positronium2s;
G4Ions *carbon;
G4Ions *nitrogen;
G4Ions *oxygen;
G4Ions *iron;
iron= new G4Ions(
"iron", 52.5672*GeV, 0.0*MeV, +26.0*eplus,
0, +1, 0,
0, 0, 0,
"nucleus", +26, +56, 0,
true, -1.0, 0,
false, "", 0,
0.0);
oxygen= new G4Ions(
"oxygen", 15.0074*GeV, 0.0*MeV, +8.0*eplus,
0, +1, 0,
0, 0, 0,
"nucleus", +8, +16, 0,
true, -1.0, 0,
false, "", 0,
0.0);
nitrogen= new G4Ions(
"nitrogen", 13.132*GeV, 0.0*MeV, +7.0*eplus,
0, +1, 0,
0, 0, 0,
"nucleus", +7, +14, 0,
true, -1.0, 0,
false, "", 0,
0.0);
carbon= new G4Ions(
"carbon", 11.267025440*GeV, 0.0*MeV, +6.0*eplus,
0, +1, 0,
0, 0, 0,
"nucleus", +6, +12, 0,
true, -1.0, 0,
false, "", 0,
0.0);
helium= new G4Ions(
helium= new G4Ions(
"helium", 3.727417*GeV, 0.0*MeV, +0.0*eplus,
0, +1, 0,
0, 0, 0,
@@ -80,7 +121,7 @@ G4DNAGenericIonsManager :: G4DNAGenericIonsManager()
false, "", 0,
0.0);
alphaPlus= new G4Ions("alpha+", 3.727417*GeV, 0.0*MeV, +1.0*eplus,
alphaPlus= new G4Ions("alpha+", 3.727417*GeV, 0.0*MeV, +1.0*eplus,
1, +1, 0,
0, 0, 0,
"nucleus", +1, +4, 0,
@@ -109,81 +150,17 @@ G4DNAGenericIonsManager :: G4DNAGenericIonsManager()
"", 0, 0.0);
/*
// molechules construction
G4Ions* oxonium; // H3O -- it will become H3O+
G4Ions* hydroxyl; // OH -- it will produce OH- too
G4Ions* molHydrogen; // H2
//G4Ions* hydroxide; // OH-
G4Ions* hydroPeroxide; // H2O2
G4Ions* water; // H2O -- it will become also H2O+
G4double mass = 19.02*g/Avogadro - 11*electron_mass_c2;
oxonium = new G4Ions("H3O", mass, 0, +11.0*eplus,
0, 0, 0,
0, 0, 0,
"molecule", 0, 0, 0,
true, -1.0, 0,
false, "", 0,
0.0);
mass = 17.00734*g/Avogadro - 9*electron_mass_c2;
hydroxyl = new G4Ions("OH", mass, 0, +9.0*eplus,
0, 0, 0,
0, 0, 0,
"molecule", 0, 0, 0,
true, -1.0, 0,
false, "", 0,
0.0);
mass = 2.01588*g/Avogadro - 2*electron_mass_c2;
molHydrogen = new G4Ions("H2", mass, 0, +2.0*eplus,
0, 0, 0,
0, 0, 0,
"molecule", 0, 0, 0,
true, -1.0, 0,
false, "", 0,
0.0);
mass = 34.01468*g/Avogadro - 18*electron_mass_c2;
hydroPeroxide = new G4Ions("H2O2", mass, 0, +18.0*eplus,
0, 0, 0,
0, 0, 0,
"molecule", 0, 0, 0,
true, -1.0, 0,
false, "", 0,
0.0);
mass = 18.015*g/Avogadro - 10*electron_mass_c2;
water = new G4Ions("H2O", mass, 0, +10.0*eplus,
0, 0, 0,
0, 0, 0,
"molecule", 0, 0, 0,
true, -1.0, 0,
false, "", 0,
0.0);
map["H3O" ] =oxonium;
map["OH" ] =hydroxyl;
map["H2" ] =molHydrogen;
map["H2O2"] =hydroPeroxide;
map["H2O" ] =water;
*/
map["helium" ]=helium;
map["hydrogen"]=hydrogen;
map["alpha+" ]=alphaPlus;
map["alpha++" ]=G4Alpha::Alpha();
map["Ps-1s" ]=positronium1s;
map["Ps-2s" ]=positronium2s;
map["carbon" ]=carbon;
map["nitrogen"]=nitrogen;
map["oxygen" ]=oxygen;
map["iron" ]=iron;
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAIonisation.cc,v 1.4 2009/11/02 17:00:11 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNAIonisation.cc,v 1.5 2010/09/08 14:30:45 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
#include "G4DNAIonisation.hh"
@@ -90,7 +90,7 @@ void G4DNAIonisation::InitialiseProcess(const G4ParticleDefinition* p)
if(!Model(2)) SetModel(new G4DNABornIonisationModel,2);
Model(2)->SetLowEnergyLimit(500*keV);
Model(2)->SetHighEnergyLimit(10*MeV);
Model(2)->SetHighEnergyLimit(100*MeV);
AddEmModel(1, Model(1));
AddEmModel(2, Model(2));
@@ -109,7 +109,7 @@ void G4DNAIonisation::InitialiseProcess(const G4ParticleDefinition* p)
{
if(!Model()) SetModel(new G4DNARuddIonisationModel);
Model()->SetLowEnergyLimit(0*keV);
Model()->SetHighEnergyLimit(10*MeV);
Model()->SetHighEnergyLimit(400*MeV);
AddEmModel(1, Model());
}
@@ -0,0 +1,238 @@
//
// ********************************************************************
// * 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: G4DNAMeltonAttachmentModel.cc,v 1.2 2010/09/15 05:47:33 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Created by Z. Francis
#include "G4DNAMeltonAttachmentModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAMeltonAttachmentModel::G4DNAMeltonAttachmentModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
lowEnergyLimit = 4 * eV;
lowEnergyLimitOfModel = 4 * eV;
highEnergyLimit = 13 * eV;
SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if( verboseLevel>0 )
{
G4cout << "Melton Attachment model is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / eV << " eV - "
<< highEnergyLimit / eV << " eV"
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAMeltonAttachmentModel::~G4DNAMeltonAttachmentModel()
{
// For total cross section
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
for (pos = tableData.begin(); pos != tableData.end(); ++pos)
{
G4DNACrossSectionDataSet* table = pos->second;
delete table;
}
// For final state
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAMeltonAttachmentModel::Initialise(const G4ParticleDefinition* /*particle*/,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNAMeltonAttachmentModel::Initialise()" << G4endl;
// Energy limits
if (LowEnergyLimit() < lowEnergyLimit)
{
G4cout << "G4DNAMeltonAttachmentModel: low energy limit increased from " <<
LowEnergyLimit()/eV << " eV to " << lowEnergyLimit/eV << " eV" << G4endl;
SetLowEnergyLimit(lowEnergyLimit);
}
if (HighEnergyLimit() > highEnergyLimit)
{
G4cout << "G4DNAMeltonAttachmentModel: high energy limit decreased from " <<
HighEnergyLimit()/eV << " eV to " << highEnergyLimit/eV << " eV" << G4endl;
SetHighEnergyLimit(highEnergyLimit);
}
// Reading of data files
G4double scaleFactor = 1e-18*cm*cm;
G4String fileElectron("dna/sigma_attachment_e_melton");
G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
G4String electron;
if (electronDef != 0)
{
// For total cross section
electron = electronDef->GetParticleName();
tableFile[electron] = fileElectron;
G4DNACrossSectionDataSet* tableE = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
tableE->LoadData(fileElectron);
tableData[electron] = tableE;
}
else G4Exception("G4DNAMeltonAttachmentModel::Initialise: electron is not defined");
if (verboseLevel > 2)
G4cout << "Loaded cross section data for Melton Attachment model" << G4endl;
if( verboseLevel>0 )
{
G4cout << "Melton Attachment model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / eV << " eV"
<< G4endl;
}
if(!isInitialised)
{
isInitialised = true;
if(pParticleChange)
fParticleChangeForGamma = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
else
fParticleChangeForGamma = new G4ParticleChangeForGamma();
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAMeltonAttachmentModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* p,
G4double ekin,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNAMeltonAttachmentModel" << G4endl;
// Calculate total cross section for model
G4double sigma=0;
if (material->GetName() == "G4_WATER")
{
const G4String& particleName = p->GetParticleName();
if (ekin >= lowEnergyLimit && ekin < highEnergyLimit)
{
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
pos = tableData.find(particleName);
if (pos != tableData.end())
{
G4DNACrossSectionDataSet* table = pos->second;
if (table != 0)
{
sigma = table->FindValue(ekin);
}
}
else
{
G4Exception("G4DNAMeltonAttachmentModel::ComputeCrossSectionPerVolume: attempting to calculate cross section for wrong particle");
}
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if water
return sigma*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAMeltonAttachmentModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
const G4MaterialCutsCouple* /*couple*/,
const G4DynamicParticle* aDynamicElectron,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNAMeltonAttachmentModel" << G4endl;
// Electron is killed
G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(electronEnergy0);
return ;
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAMillerGreenExcitationModel.cc,v 1.6 2009/08/13 11:32:47 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNAMillerGreenExcitationModel.cc,v 1.11 2010/10/08 08:53:17 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
#include "G4DNAMillerGreenExcitationModel.hh"
@@ -73,11 +73,13 @@ void G4DNAMillerGreenExcitationModel::Initialise(const G4ParticleDefinition* par
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
G4ParticleDefinition* hydrogenDef = instance->GetIon("hydrogen");
G4ParticleDefinition* alphaPlusPlusDef = instance->GetIon("alpha++");
G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
G4ParticleDefinition* heliumDef = instance->GetIon("helium");
G4String proton;
G4String hydrogen;
G4String alphaPlusPlus;
G4String alphaPlus;
G4String helium;
@@ -101,11 +103,30 @@ void G4DNAMillerGreenExcitationModel::Initialise(const G4ParticleDefinition* par
G4Exception("G4DNAMillerGreenExcitationModel::Initialise: proton is not defined");
}
if (hydrogenDef != 0)
{
hydrogen = hydrogenDef->GetParticleName();
lowEnergyLimit[hydrogen] = 10. * eV;
highEnergyLimit[hydrogen] = 500. * keV;
kineticEnergyCorrection[0] = 1.;
slaterEffectiveCharge[0][0] = 0.;
slaterEffectiveCharge[1][0] = 0.;
slaterEffectiveCharge[2][0] = 0.;
sCoefficient[0][0] = 0.;
sCoefficient[1][0] = 0.;
sCoefficient[2][0] = 0.;
}
else
{
G4Exception("G4DNAMillerGreenExcitationModel::Initialise: hydrogen is not defined");
}
if (alphaPlusPlusDef != 0)
{
alphaPlusPlus = alphaPlusPlusDef->GetParticleName();
lowEnergyLimit[alphaPlusPlus] = 1. * keV;
highEnergyLimit[alphaPlusPlus] = 10. * MeV;
highEnergyLimit[alphaPlusPlus] = 400. * MeV;
kineticEnergyCorrection[1] = 0.9382723/3.727417;
slaterEffectiveCharge[0][1]=0.;
@@ -124,12 +145,15 @@ void G4DNAMillerGreenExcitationModel::Initialise(const G4ParticleDefinition* par
{
alphaPlus = alphaPlusDef->GetParticleName();
lowEnergyLimit[alphaPlus] = 1. * keV;
highEnergyLimit[alphaPlus] = 10. * MeV;
highEnergyLimit[alphaPlus] = 400. * MeV;
kineticEnergyCorrection[2] = 0.9382723/3.727417;
slaterEffectiveCharge[0][2]=2.0;
slaterEffectiveCharge[1][2]=1.15;
slaterEffectiveCharge[2][2]=1.15;
// Following values provided by M. Dingfelder
slaterEffectiveCharge[1][2]=2.00;
slaterEffectiveCharge[2][2]=2.00;
//
sCoefficient[0][2]=0.7;
sCoefficient[1][2]=0.15;
sCoefficient[2][2]=0.15;
@@ -143,7 +167,7 @@ void G4DNAMillerGreenExcitationModel::Initialise(const G4ParticleDefinition* par
{
helium = heliumDef->GetParticleName();
lowEnergyLimit[helium] = 1. * keV;
highEnergyLimit[helium] = 10. * MeV;
highEnergyLimit[helium] = 400. * MeV;
kineticEnergyCorrection[3] = 0.9382723/3.727417;
slaterEffectiveCharge[0][3]=1.7;
@@ -152,6 +176,7 @@ void G4DNAMillerGreenExcitationModel::Initialise(const G4ParticleDefinition* par
sCoefficient[0][3]=0.5;
sCoefficient[1][3]=0.25;
sCoefficient[2][3]=0.25;
}
else
{
@@ -164,6 +189,12 @@ void G4DNAMillerGreenExcitationModel::Initialise(const G4ParticleDefinition* par
SetHighEnergyLimit(highEnergyLimit[proton]);
}
if (particle==hydrogenDef)
{
SetLowEnergyLimit(lowEnergyLimit[hydrogen]);
SetHighEnergyLimit(highEnergyLimit[hydrogen]);
}
if (particle==alphaPlusPlusDef)
{
SetLowEnergyLimit(lowEnergyLimit[alphaPlusPlus]);
@@ -209,40 +240,6 @@ void G4DNAMillerGreenExcitationModel::Initialise(const G4ParticleDefinition* par
// InitialiseElementSelectors(particle,cuts);
// Test if water material
flagMaterialIsWater= false;
densityWater = 0;
const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
if(theCoupleTable)
{
G4int numOfCouples = theCoupleTable->GetTableSize();
if(numOfCouples>0)
{
for (G4int i=0; i<numOfCouples; i++)
{
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
if (material->GetName() == "G4_WATER")
{
G4double density = material->GetAtomicNumDensityVector()[1];
flagMaterialIsWater = true;
densityWater = density;
if (verboseLevel > 3)
G4cout << "****** Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
}
}
} // if(numOfCouples>0)
} // if (theCoupleTable)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -264,6 +261,8 @@ G4double G4DNAMillerGreenExcitationModel::CrossSectionPerVolume(const G4Material
if (
particleDefinition != G4Proton::ProtonDefinition()
&&
particleDefinition != instance->GetIon("hydrogen")
&&
particleDefinition != instance->GetIon("alpha++")
&&
particleDefinition != instance->GetIon("alpha+")
@@ -277,7 +276,7 @@ G4double G4DNAMillerGreenExcitationModel::CrossSectionPerVolume(const G4Material
G4double highLim = 0;
G4double crossSection = 0.;
if (flagMaterialIsWater)
if (material->GetName() == "G4_WATER")
{
const G4String& particleName = particleDefinition->GetParticleName();
@@ -305,19 +304,22 @@ G4double G4DNAMillerGreenExcitationModel::CrossSectionPerVolume(const G4Material
instance = G4DNAGenericIonsManager::Instance();
// add ONE or TWO electron-water excitation for alpha+ and helium
/*
if ( particleDefinition == instance->GetIon("alpha+")
||
particleDefinition == instance->GetIon("helium")
)
{
G4DNAEmfietzoglouExcitationModel * excitationXS = new G4DNAEmfietzoglouExcitationModel();
excitationXS->Initialise(G4Electron::ElectronDefinition());
G4double sigmaExcitation=0;
G4double tmp =0.;
if (k*0.511/3728 > 7.4*eV && k*0.511/3728 < 10*keV) sigmaExcitation =
excitationXS->CrossSectionPerVolume(material,particleDefinition,k*0.511/3728,tmp,tmp)/densityWater;
if (k*0.511/3728 > 8.23*eV && k*0.511/3728 < 10*MeV ) sigmaExcitation =
excitationXS->CrossSectionPerVolume(material,G4Electron::ElectronDefinition(),k*0.511/3728,tmp,tmp)
/material->GetAtomicNumDensityVector()[1];
if ( particleDefinition == instance->GetIon("alpha+") )
crossSection = crossSection + sigmaExcitation ;
@@ -326,7 +328,29 @@ G4double G4DNAMillerGreenExcitationModel::CrossSectionPerVolume(const G4Material
crossSection = crossSection + 2*sigmaExcitation ;
delete excitationXS;
// Alternative excitation model
G4DNABornExcitationModel * excitationXS = new G4DNABornExcitationModel();
excitationXS->Initialise(G4Electron::ElectronDefinition());
G4double sigmaExcitation=0;
G4double tmp=0;
if (k*0.511/3728 > 9*eV && k*0.511/3728 < 1*MeV ) sigmaExcitation =
excitationXS->CrossSectionPerVolume(material,G4Electron::ElectronDefinition(),k*0.511/3728,tmp,tmp)
/material->GetAtomicNumDensityVector()[1];
if ( particleDefinition == instance->GetIon("alpha+") )
crossSection = crossSection + sigmaExcitation ;
if ( particleDefinition == instance->GetIon("helium") )
crossSection = crossSection + 2*sigmaExcitation ;
delete excitationXS;
}
*/
}
@@ -334,12 +358,12 @@ G4double G4DNAMillerGreenExcitationModel::CrossSectionPerVolume(const G4Material
{
G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << crossSection/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << crossSection*densityWater/(1./cm) << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << crossSection*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if (flagMaterialIsWater)
}
return crossSection*densityWater;
return crossSection*material->GetAtomicNumDensityVector()[1];
}
@@ -359,7 +383,12 @@ void G4DNAMillerGreenExcitationModel::SampleSecondaries(std::vector<G4DynamicPar
G4int level = RandomSelect(particleEnergy0,aDynamicParticle->GetDefinition());
G4double excitationEnergy = waterExcitation.ExcitationEnergy(level);
// G4double excitationEnergy = waterExcitation.ExcitationEnergy(level);
// Dingfelder's excitation levels
const G4double excitation[]={ 8.17*eV, 10.13*eV, 11.31*eV, 12.91*eV, 14.50*eV};
G4double excitationEnergy = excitation[level];
G4double newEnergy = particleEnergy0 - excitationEnergy;
if (newEnergy>0)
@@ -396,11 +425,15 @@ G4double G4DNAMillerGreenExcitationModel::PartialCrossSection(G4double k, G4int
const G4double jj[]={19820.*eV, 23490.*eV, 27770.*eV, 30830.*eV, 33080.*eV};
const G4double omegaj[]={0.85, 0.88, 0.88, 0.78, 0.78};
// Dingfelder's excitation levels
const G4double Eliq[5]={ 8.17*eV, 10.13*eV, 11.31*eV, 12.91*eV, 14.50*eV};
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == G4Proton::ProtonDefinition()) particleTypeIndex=0;
if (particleDefinition == instance->GetIon("hydrogen")) particleTypeIndex=0;
if (particleDefinition == instance->GetIon("alpha++")) particleTypeIndex=1;
if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=2;
if (particleDefinition == instance->GetIon("helium")) particleTypeIndex=3;
@@ -409,14 +442,21 @@ G4double G4DNAMillerGreenExcitationModel::PartialCrossSection(G4double k, G4int
tCorrected = k * kineticEnergyCorrection[particleTypeIndex];
// SI - added protection
if (tCorrected < waterExcitation.ExcitationEnergy(excitationLevel)) return 0;
if (tCorrected < Eliq[excitationLevel]) return 0;
//
G4int z = 10;
G4double numerator;
numerator = std::pow(z * aj[excitationLevel], omegaj[excitationLevel]) *
std::pow(tCorrected - waterExcitation.ExcitationEnergy(excitationLevel), nu);
std::pow(tCorrected - Eliq[excitationLevel], nu);
// H case : see S. Uehara et al. IJRB 77, 2, 139-154 (2001) - section 3.3
if (particleDefinition == instance->GetIon("hydrogen"))
numerator = std::pow(z * 0.75*aj[excitationLevel], omegaj[excitationLevel]) *
std::pow(tCorrected - Eliq[excitationLevel], nu);
G4double power;
power = omegaj[excitationLevel] + nu;
@@ -426,12 +466,15 @@ G4double G4DNAMillerGreenExcitationModel::PartialCrossSection(G4double k, G4int
G4double zEff = particleDefinition->GetPDGCharge() / eplus + particleDefinition->GetLeptonNumber();
zEff -= ( sCoefficient[0][particleTypeIndex] * S_1s(k, waterExcitation.ExcitationEnergy(excitationLevel), slaterEffectiveCharge[0][particleTypeIndex], 1.) +
sCoefficient[1][particleTypeIndex] * S_2s(k, waterExcitation.ExcitationEnergy(excitationLevel), slaterEffectiveCharge[1][particleTypeIndex], 2.) +
sCoefficient[2][particleTypeIndex] * S_2p(k, waterExcitation.ExcitationEnergy(excitationLevel), slaterEffectiveCharge[2][particleTypeIndex], 2.) );
zEff -= ( sCoefficient[0][particleTypeIndex] * S_1s(k, Eliq[excitationLevel], slaterEffectiveCharge[0][particleTypeIndex], 1.) +
sCoefficient[1][particleTypeIndex] * S_2s(k, Eliq[excitationLevel], slaterEffectiveCharge[1][particleTypeIndex], 2.) +
sCoefficient[2][particleTypeIndex] * S_2p(k, Eliq[excitationLevel], slaterEffectiveCharge[2][particleTypeIndex], 2.) );
if (particleDefinition == instance->GetIon("hydrogen")) zEff = 1.;
G4double cross = sigma0 * zEff * zEff * numerator / denominator;
return cross;
}
@@ -447,7 +490,11 @@ G4int G4DNAMillerGreenExcitationModel::RandomSelect(G4double k,const G4ParticleD
instance = G4DNAGenericIonsManager::Instance();
if ( particle == instance->GetIon("alpha++") ||
particle == G4Proton::ProtonDefinition() )
particle == G4Proton::ProtonDefinition()||
particle == instance->GetIon("hydrogen") ||
particle == instance->GetIon("alpha+") ||
particle == instance->GetIon("helium")
)
{
while (i > 0)
{
@@ -469,6 +516,7 @@ G4int G4DNAMillerGreenExcitationModel::RandomSelect(G4double k,const G4ParticleD
}
}
/*
// add ONE or TWO electron-water excitation for alpha+ and helium
if ( particle == instance->GetIon("alpha+")
@@ -481,14 +529,17 @@ G4int G4DNAMillerGreenExcitationModel::RandomSelect(G4double k,const G4ParticleD
i--;
G4DNAEmfietzoglouExcitationModel * excitationXS = new G4DNAEmfietzoglouExcitationModel();
excitationXS->Initialise(G4Electron::ElectronDefinition());
G4double sigmaExcitation=0;
if (k*0.511/3728 > 7.4*eV && k*0.511/3728 < 10*keV) sigmaExcitation = excitationXS->PartialCrossSection(k*0.511/3728,i);
if (k*0.511/3728 > 8.23*eV && k*0.511/3728 < 10*MeV ) sigmaExcitation = excitationXS->PartialCrossSection(k*0.511/3728,i);
G4double partial = PartialCrossSection(k,i,particle);
if (particle == instance->GetIon("alpha+")) partial = PartialCrossSection(k,i,particle) + sigmaExcitation;
if (particle == instance->GetIon("helium")) partial = PartialCrossSection(k,i,particle) + 2*sigmaExcitation;
values.push_front(partial);
value += partial;
delete excitationXS;
@@ -506,6 +557,7 @@ G4int G4DNAMillerGreenExcitationModel::RandomSelect(G4double k,const G4ParticleD
value-=values[i];
}
}
*/
return 0;
}
@@ -584,8 +636,11 @@ G4double G4DNAMillerGreenExcitationModel::R(G4double t,
// Dingfelder, in Chattanooga 2005 proceedings, p 4
G4double tElectron = 0.511/3728. * t;
G4double value = 2. * tElectron * slaterEffectiveCharge / (energyTransferred * shellNumber);
// The following is provided by M. Dingfelder
G4double H = 2.*13.60569172 * eV;
G4double value = std::sqrt ( 2. * tElectron / H ) / ( energyTransferred / H ) * (slaterEffectiveCharge/shellNumber);
return value;
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNARuddIonisationModel.cc,v 1.10 2009/08/13 11:32:47 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNARuddIonisationModel.cc,v 1.21 2010/11/04 14:52:17 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
#include "G4DNARuddIonisationModel.hh"
@@ -158,7 +158,7 @@ void G4DNARuddIonisationModel::Initialise(const G4ParticleDefinition* particle,
tableFile[alphaPlusPlus] = fileAlphaPlusPlus;
lowEnergyLimit[alphaPlusPlus] = lowEnergyLimitForZ2;
highEnergyLimit[alphaPlusPlus] = 10. * MeV;
highEnergyLimit[alphaPlusPlus] = 400. * MeV;
// Cross section
@@ -180,7 +180,7 @@ void G4DNARuddIonisationModel::Initialise(const G4ParticleDefinition* particle,
tableFile[alphaPlus] = fileAlphaPlus;
lowEnergyLimit[alphaPlus] = lowEnergyLimitForZ2;
highEnergyLimit[alphaPlus] = 10. * MeV;
highEnergyLimit[alphaPlus] = 400. * MeV;
// Cross section
@@ -201,7 +201,7 @@ void G4DNARuddIonisationModel::Initialise(const G4ParticleDefinition* particle,
tableFile[helium] = fileHelium;
lowEnergyLimit[helium] = lowEnergyLimitForZ2;
highEnergyLimit[helium] = 10. * MeV;
highEnergyLimit[helium] = 400. * MeV;
// Cross section
@@ -270,45 +270,11 @@ void G4DNARuddIonisationModel::Initialise(const G4ParticleDefinition* particle,
// InitialiseElementSelectors(particle,cuts);
// Test if water material
flagMaterialIsWater= false;
densityWater = 0;
const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
if(theCoupleTable)
{
G4int numOfCouples = theCoupleTable->GetTableSize();
if(numOfCouples>0)
{
for (G4int i=0; i<numOfCouples; i++)
{
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
if (material->GetName() == "G4_WATER")
{
G4double density = material->GetAtomicNumDensityVector()[1];
flagMaterialIsWater = true;
densityWater = density;
if (verboseLevel > 3)
G4cout << "****** Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
}
}
} // if(numOfCouples>0)
} // if (theCoupleTable)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNARuddIonisationModel::CrossSectionPerVolume(const G4Material*,
G4double G4DNARuddIonisationModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double k,
G4double,
@@ -354,7 +320,7 @@ G4double G4DNARuddIonisationModel::CrossSectionPerVolume(const G4Material*,
G4double highLim = 0;
G4double sigma=0;
if (flagMaterialIsWater)
if (material->GetName() == "G4_WATER")
{
const G4String& particleName = particleDefinition->GetParticleName();
@@ -396,50 +362,6 @@ G4double G4DNARuddIonisationModel::CrossSectionPerVolume(const G4Material*,
{
sigma = table->FindValue(k);
// BEGIN ELECTRON CORRECTION
// add ONE or TWO electron-water excitation for alpha+ and helium
if ( particleDefinition == instance->GetIon("alpha+")
||
particleDefinition == instance->GetIon("helium")
)
{
G4DNACrossSectionDataSet* electronDataset = new G4DNACrossSectionDataSet
(new G4LogLogInterpolation, eV, (1./3.343e22)*m*m);
electronDataset->LoadData("dna/sigma_ionisation_e_born");
G4double kElectron = k * 0.511/3728;
if ( particleDefinition == instance->GetIon("alpha+") )
{
G4double tmp1 = table->FindValue(k) + electronDataset->FindValue(kElectron);
delete electronDataset;
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << tmp1/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << tmp1*densityWater/(1./cm) << G4endl;
}
return tmp1*densityWater;
}
if ( particleDefinition == instance->GetIon("helium") )
{
G4double tmp2 = table->FindValue(k) + 2. * electronDataset->FindValue(kElectron);
delete electronDataset;
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << tmp2/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << tmp2*densityWater/(1./cm) << G4endl;
}
return tmp2*densityWater;
}
}
// END ELECTRON CORRECTION
}
}
else
@@ -453,12 +375,13 @@ G4double G4DNARuddIonisationModel::CrossSectionPerVolume(const G4Material*,
{
G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*densityWater/(1./cm) << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*
material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if (waterMaterial)
return sigma*densityWater;
return sigma*material->GetAtomicNumDensityVector()[1];
}
@@ -519,10 +442,12 @@ void G4DNARuddIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>
{
G4ParticleDefinition* definition = particle->GetDefinition();
G4ParticleMomentum primaryDirection = particle->GetMomentumDirection();
/*
G4double particleMass = definition->GetPDGMass();
G4double totalEnergy = k + particleMass;
G4double pSquare = k*(totalEnergy+particleMass);
G4double totalMomentum = std::sqrt(pSquare);
*/
G4int ionizationShell = RandomSelect(k,particleName);
@@ -541,6 +466,8 @@ void G4DNARuddIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>
G4ThreeVector deltaDirection(dirX,dirY,dirZ);
deltaDirection.rotateUz(primaryDirection);
// Ignored for ions on electrons
/*
G4double deltaTotalMomentum = std::sqrt(secondaryKinetic*(secondaryKinetic + 2.*electron_mass_c2 ));
G4double finalPx = totalMomentum*primaryDirection.x() - deltaTotalMomentum*deltaDirection.x();
@@ -555,35 +482,15 @@ void G4DNARuddIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>
direction.set(finalPx,finalPy,finalPz);
fParticleChangeForGamma->ProposeMomentumDirection(direction.unit()) ;
*/
fParticleChangeForGamma->ProposeMomentumDirection(primaryDirection);
fParticleChangeForGamma->SetProposedKineticEnergy(k-bindingEnergy-secondaryKinetic);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(bindingEnergy);
G4DynamicParticle* dp = new G4DynamicParticle (G4Electron::Electron(),deltaDirection,secondaryKinetic) ;
fvect->push_back(dp);
/*
// creating neutral water molechule...
G4DNAGenericMoleculeManager *instance;
instance = G4DNAGenericMoleculeManager::Instance();
G4ParticleDefinition* waterDef = NULL;
G4Molecule* water = instance->GetMolecule("H2O");
waterDef = (G4ParticleDefinition*)water;
direction.set(0.,0.,0.);
//G4DynamicParticle* dynamicWater = new G4DynamicParticle(waterDef, direction, bindingEnergy);
G4DynamicMolecule* dynamicWater = new G4DynamicMolecule(water, direction, bindingEnergy);
//dynamicWater->RemoveElectron(ionizationShell, 1);
G4DynamicMolecule* dynamicWater2 = new G4DynamicMolecule(water, direction, bindingEnergy);
G4DynamicMolecule* dynamicWater3 = new G4DynamicMolecule(water, direction, bindingEnergy);
// insertion inside secondaries
fvect->push_back(dynamicWater);
fvect->push_back(dynamicWater2);
fvect->push_back(dynamicWater3);
*/
}
// SI - not useful since low energy of model is 0 eV
@@ -622,12 +529,13 @@ G4double G4DNARuddIonisationModel::RandomizeEjectedElectronEnergy(G4ParticleDefi
G4double crossSectionMaximum = 0.;
for(G4double value=waterStructure.IonisationEnergy(shell); value<=4.*waterStructure.IonisationEnergy(shell) ; value+=0.1*eV)
for(G4double value=waterStructure.IonisationEnergy(shell); value<=5.*waterStructure.IonisationEnergy(shell) && k>=value ; value+=0.1*eV)
{
G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k, value, shell);
if(differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
}
G4double secElecKinetic = 0.;
do
@@ -669,7 +577,14 @@ void G4DNARuddIonisationModel::RandomizeEjectedElectronDirection(G4ParticleDefin
}
phi = twopi * G4UniformRand();
cosTheta = std::sqrt(secKinetic / maxSecKinetic);
//cosTheta = std::sqrt(secKinetic / maxSecKinetic);
// Restriction below 100 eV from Emfietzoglou (2000)
if (secKinetic>100*eV) cosTheta = std::sqrt(secKinetic / maxSecKinetic);
else cosTheta = (2.*G4UniformRand())-1.;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -709,6 +624,10 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
G4double D2 ;
G4double alphaConst ;
// const G4double Bj[5] = {12.61*eV, 14.73*eV, 18.55*eV, 32.20*eV, 539.7*eV};
// The following values are provided by M. dingfelder (priv. comm)
const G4double Bj[5] = {12.60*eV, 14.70*eV, 18.40*eV, 32.20*eV, 540*eV};
if (j == 4)
{
//Data For Liquid Water K SHELL from Dingfelder (Protons in Water)
@@ -732,7 +651,9 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
D1 = -0.80;
E1 = 0.38;
A2 = 1.07;
B2 = 14.6;
// Value provided by M. Dingfelder (priv. comm)
B2 = 11.6;
//
C2 = 0.60;
D2 = 0.04;
alphaConst = 0.64;
@@ -745,7 +666,12 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
instance = G4DNAGenericIonsManager::Instance();
G4double wBig = (energyTransfer - waterStructure.IonisationEnergy(ionizationLevelIndex));
G4double w = wBig / waterStructure.IonisationEnergy(ionizationLevelIndex);
if (wBig<0) return 0.;
G4double w = wBig / Bj[ionizationLevelIndex];
// Note that the following (j==4) cases are provided by M. Dingfelder (priv. comm)
if (j==4) w = wBig / waterStructure.IonisationEnergy(ionizationLevelIndex);
G4double Ry = 13.6*eV;
G4double tau = 0.;
@@ -762,11 +688,16 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
{
tau = (0.511/3728.) * k ;
}
G4double S = 4.*pi * Bohr_radius*Bohr_radius * n * std::pow((Ry/waterStructure.IonisationEnergy(ionizationLevelIndex)),2);
G4double v2 = tau / waterStructure.IonisationEnergy(ionizationLevelIndex);
G4double S = 4.*pi * Bohr_radius*Bohr_radius * n * std::pow((Ry/Bj[ionizationLevelIndex]),2);
if (j==4) S = 4.*pi * Bohr_radius*Bohr_radius * n * std::pow((Ry/waterStructure.IonisationEnergy(ionizationLevelIndex)),2);
G4double v2 = tau / Bj[ionizationLevelIndex];
if (j==4) v2 = tau / waterStructure.IonisationEnergy(ionizationLevelIndex);
G4double v = std::sqrt(v2);
G4double wc = 4.*v2 - 2.*v - (Ry/(4.*waterStructure.IonisationEnergy(ionizationLevelIndex)));
G4double wc = 4.*v2 - 2.*v - (Ry/(4.*Bj[ionizationLevelIndex]));
if (j==4) wc = 4.*v2 - 2.*v - (Ry/(4.*waterStructure.IonisationEnergy(ionizationLevelIndex)));
G4double L1 = (C1* std::pow(v,(D1))) / (1.+ E1*std::pow(v, (D1+4.)));
G4double L2 = C2*std::pow(v,(D2));
@@ -776,10 +707,20 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
G4double F1 = L1+H1;
G4double F2 = (L2*H2)/(L2+H2);
G4double sigma = CorrectionFactor(particleDefinition, k/eV)
G4double sigma = CorrectionFactor(particleDefinition, k)
* Gj[j] * (S/Bj[ionizationLevelIndex])
* ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
if (j==4) sigma = CorrectionFactor(particleDefinition, k)
* Gj[j] * (S/waterStructure.IonisationEnergy(ionizationLevelIndex))
* ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
if ( (particleDefinition == instance->GetIon("hydrogen")) && (ionizationLevelIndex==4))
// sigma = Gj[j] * (S/Bj[ionizationLevelIndex])
sigma = Gj[j] * (S/waterStructure.IonisationEnergy(ionizationLevelIndex))
* ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
if ( particleDefinition == G4Proton::ProtonDefinition()
|| particleDefinition == instance->GetIon("hydrogen")
)
@@ -800,8 +741,10 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
if (particleDefinition == instance->GetIon("alpha+") )
{
slaterEffectiveCharge[0]=2.0;
slaterEffectiveCharge[1]=1.15;
slaterEffectiveCharge[2]=1.15;
// The following values are provided by M. Dingfelder (priv. comm)
slaterEffectiveCharge[1]=2.0;
slaterEffectiveCharge[2]=2.0;
//
sCoefficient[0]=0.7;
sCoefficient[1]=0.15;
sCoefficient[2]=0.15;
@@ -822,8 +765,11 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
|| particleDefinition == instance->GetIon("alpha++")
)
{
sigma = Gj[j] * (S/waterStructure.IonisationEnergy(ionizationLevelIndex)) * ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
sigma = Gj[j] * (S/Bj[ionizationLevelIndex]) * ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
if (j==4) sigma = Gj[j] * (S/waterStructure.IonisationEnergy(ionizationLevelIndex))
* ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
G4double zEff = particleDefinition->GetPDGCharge() / eplus + particleDefinition->GetLeptonNumber();
zEff -= ( sCoefficient[0] * S_1s(k, energyTransfer, slaterEffectiveCharge[0], 1.) +
@@ -896,7 +842,9 @@ G4double G4DNARuddIonisationModel::R(G4double t,
// Dingfelder, in Chattanooga 2005 proceedings, p 4
G4double tElectron = 0.511/3728. * t;
G4double value = 2. * tElectron * slaterEffectiveChg / (energyTransferred * shellNumber);
// The following values are provided by M. Dingfelder (priv. comm)
G4double H = 2.*13.60569172 * eV;
G4double value = std::sqrt ( 2. * tElectron / H ) / ( energyTransferred / H ) * (slaterEffectiveChg/shellNumber);
return value;
}
@@ -915,8 +863,9 @@ G4double G4DNARuddIonisationModel::CorrectionFactor(G4ParticleDefinition* partic
else
if (particleDefinition == instance->GetIon("hydrogen"))
{
G4double value = (std::log(k/eV)-4.2)/0.5;
return((0.8/(1+std::exp(value))) + 0.9);
G4double value = (std::log10(k/eV)-4.2)/0.5;
// The following values are provided by M. Dingfelder (priv. comm)
return((0.6/(1+std::exp(value))) + 0.9);
}
else
{
@@ -931,31 +880,11 @@ G4int G4DNARuddIonisationModel::RandomSelect(G4double k, const G4String& particl
// BEGIN PART 1/2 OF ELECTRON CORRECTION
// add ONE or TWO electron-water excitation for alpha+ and helium
// add ONE or TWO electron-water ionisation for alpha+ and helium
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
G4double kElectron(0);
G4double electronComponent(0);
G4DNACrossSectionDataSet * electronDataset = new G4DNACrossSectionDataSet (new G4LogLogInterpolation, eV, (1./3.343e22)*m*m);
if ( particle == instance->GetIon("alpha+")->GetParticleName()
||
particle == instance->GetIon("helium")->GetParticleName()
)
{
electronDataset->LoadData("dna/sigma_ionisation_e_born");
kElectron = k * 0.511/3728;
electronComponent = electronDataset->FindValue(kElectron);
}
delete electronDataset;
// END PART 1/2 OF ELECTRON CORRECTION
G4int level = 0;
// Retrieve data table corresponding to the current particle type
@@ -979,17 +908,6 @@ G4int G4DNARuddIonisationModel::RandomSelect(G4double k, const G4String& particl
{
i--;
valuesBuffer[i] = table->GetComponent(i)->FindValue(k);
// BEGIN PART 2/2 OF ELECTRON CORRECTION
if (particle == instance->GetIon("alpha+")->GetParticleName())
{valuesBuffer[i]=table->GetComponent(i)->FindValue(k) + electronComponent; }
if (particle == instance->GetIon("helium")->GetParticleName())
{valuesBuffer[i]=table->GetComponent(i)->FindValue(k) + 2*electronComponent; }
// BEGIN PART 2/2 OF ELECTRON CORRECTION
value += valuesBuffer[i];
}
@@ -1000,6 +918,7 @@ G4int G4DNARuddIonisationModel::RandomSelect(G4double k, const G4String& particl
while (i > 0)
{
i--;
if (valuesBuffer[i] > value)
{
@@ -1017,7 +936,7 @@ G4int G4DNARuddIonisationModel::RandomSelect(G4double k, const G4String& particl
{
G4Exception("G4DNARuddIonisationModel::RandomSelect: attempting to calculate cross section for wrong particle");
}
return level;
}
@@ -0,0 +1,318 @@
//
// ********************************************************************
// * 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: G4DNASancheExcitationModel.cc,v 1.4 2010/11/11 22:32:22 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Created by Z. Francis
#include "G4DNASancheExcitationModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNASancheExcitationModel::G4DNASancheExcitationModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
lowEnergyLimit = 2 * eV;
highEnergyLimit = 100 * eV;
SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
nLevels = 9;
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if (verboseLevel > 0)
{
G4cout << "Sanche Excitation model is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / eV << " eV - "
<< highEnergyLimit / eV << " eV"
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNASancheExcitationModel::~G4DNASancheExcitationModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNASancheExcitationModel::Initialise(const G4ParticleDefinition* /*particle*/,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNASancheExcitationModel::Initialise()" << G4endl;
// Energy limits
if (LowEnergyLimit() < lowEnergyLimit)
{
G4cout << "G4DNASancheExcitationModel: low energy limit increased from " <<
LowEnergyLimit()/eV << " eV to " << lowEnergyLimit/eV << " eV" << G4endl;
SetLowEnergyLimit(lowEnergyLimit);
}
if (HighEnergyLimit() > highEnergyLimit)
{
G4cout << "G4DNASancheExcitationModel: high energy limit decreased from " <<
HighEnergyLimit()/eV << " eV to " << highEnergyLimit/eV << " eV" << G4endl;
SetHighEnergyLimit(highEnergyLimit);
}
//
if (verboseLevel > 0)
G4cout << "Sanche Excitation model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / eV << " eV"
<< G4endl;
if(!isInitialised)
{
isInitialised = true;
if(pParticleChange)
fParticleChangeForGamma = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
else
fParticleChangeForGamma = new G4ParticleChangeForGamma();
}
// InitialiseElementSelectors(particle,cuts);
char *path = getenv("G4LEDATA");
std::ostringstream eFullFileName;
eFullFileName << path << "/dna/sigma_excitationvib_e_sanche.dat";
std::ifstream input(eFullFileName.str().c_str());
if (!input)
{
G4Exception("G4DNASancheExcitationModel:::ERROR OPENING XS DATA FILE");
}
while(!input.eof())
{
double t;
input>>t;
tdummyVec.push_back(t);
input>>map1[t][0]>>map1[t][1]>>map1[t][2]>>map1[t][3]>>map1[t][4]>>map1[t][5]>>map1[t][6]>>map1[t][7]>>map1[t][8];
//G4cout<<t<<" "<<map1[t][0]<<map1[t][1]<<map1[t][2]<<map1[t][3]<<map1[t][4]<<map1[t][5]<<map1[t][6]<<map1[t][7]<<map1[t][8]<<G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNASancheExcitationModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double ekin,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNASancheExcitationModel" << G4endl;
// Calculate total cross section for model
G4double sigma=0;
if (material->GetName() == "G4_WATER")
{
if (particleDefinition == G4Electron::ElectronDefinition())
{
if (ekin >= lowEnergyLimit && ekin < highEnergyLimit)
{
sigma = Sum(ekin);
}
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if water
return sigma*2*material->GetAtomicNumDensityVector()[1];
// see papers for factor 2 description
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNASancheExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>*,
const G4MaterialCutsCouple*,
const G4DynamicParticle* aDynamicElectron,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNASancheExcitationModel" << G4endl;
G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
G4int level = RandomSelect(electronEnergy0);
G4double excitationEnergy = VibrationEnergy(level); // levels go from 0 to 8
G4double newEnergy = electronEnergy0 - excitationEnergy;
/*
if (electronEnergy0 < highEnergyLimit)
{
if (newEnergy >= lowEnergyLimit)
{
fParticleChangeForGamma->ProposeMomentumDirection(aDynamicElectron->GetMomentumDirection());
fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
}
else
{
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(electronEnergy0);
}
}
*/
if (electronEnergy0 < highEnergyLimit && newEnergy>0.)
{
fParticleChangeForGamma->ProposeMomentumDirection(aDynamicElectron->GetMomentumDirection());
fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
}
//
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNASancheExcitationModel::PartialCrossSection(G4double t, G4int level)
{
std::vector<double>::iterator t2 = std::upper_bound(tdummyVec.begin(),tdummyVec.end(), t/eV);
std::vector<double>::iterator t1 = t2-1;
double sigma = LinInterpolate((*t1), (*t2), t/eV, map1[*t1][level], map1[*t2][level]);
sigma*=1e-16*cm*cm;
if(sigma==0.)sigma=1e-30;
return (sigma);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNASancheExcitationModel::VibrationEnergy(G4int level)
{
G4double energies[9] = {0.01, 0.024, 0.061, 0.092, 0.204, 0.417, 0.460, 0.500, 0.835};
return(energies[level]*eV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNASancheExcitationModel::RandomSelect(G4double k)
{
// Level Selection Counting can be done here !
G4int i = nLevels;
G4double value = 0.;
std::deque<double> values;
while (i > 0)
{
i--;
G4double partial = PartialCrossSection(k,i);
values.push_front(partial);
value += partial;
}
value *= G4UniformRand();
i = nLevels;
while (i > 0)
{
i--;
if (values[i] > value)
{
//outcount<<i<<" "<<VibrationEnergy(i)<<G4endl;
return i;
}
value -= values[i];
}
//outcount<<0<<" "<<VibrationEnergy(0)<<G4endl;
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNASancheExcitationModel::Sum(G4double k)
{
G4double totalCrossSection = 0.;
for (G4int i=0; i<nLevels; i++)
{
totalCrossSection += PartialCrossSection(k,i);
}
return totalCrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNASancheExcitationModel::LinInterpolate(G4double e1,
G4double e2,
G4double e,
G4double xs1,
G4double xs2)
{
G4double a = (xs2 - xs1) / (e2 - e1);
G4double b = xs2 - a*e2;
G4double value = a*e + b;
// G4cout<<"interP >> "<<e1<<" "<<e2<<" "<<e<<" "<<xs1<<" "<<xs2<<" "<<a<<" "<<b<<" "<<value<<G4endl;
return value;
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAScreenedRutherfordElasticModel.cc,v 1.9 2009/08/13 11:32:47 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4DNAScreenedRutherfordElasticModel.cc,v 1.15 2010/11/11 22:32:22 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
#include "G4DNAScreenedRutherfordElasticModel.hh"
@@ -40,11 +40,10 @@ G4DNAScreenedRutherfordElasticModel::G4DNAScreenedRutherfordElasticModel
:G4VEmModel(nam),isInitialised(false)
{
killBelowEnergy = 8.23*eV; // Minimum e- energy for energy loss by excitation
killBelowEnergy = 9*eV;
lowEnergyLimit = 0 * eV;
lowEnergyLimitOfModel = 7 * eV; // The model lower energy is 7 eV
intermediateEnergyLimit = 200 * eV; // Switch between two final state models
highEnergyLimit = 10 * MeV;
highEnergyLimit = 1. * MeV;
SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
@@ -151,45 +150,11 @@ void G4DNAScreenedRutherfordElasticModel::Initialise(const G4ParticleDefinition*
// InitialiseElementSelectors(particle,cuts);
// Test if water material
flagMaterialIsWater= false;
densityWater = 0;
const G4ProductionCutsTable* theCoupleTable = G4ProductionCutsTable::GetProductionCutsTable();
if(theCoupleTable)
{
G4int numOfCouples = theCoupleTable->GetTableSize();
if(numOfCouples>0)
{
for (G4int i=0; i<numOfCouples; i++)
{
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
if (material->GetName() == "G4_WATER")
{
G4double density = material->GetAtomicNumDensityVector()[1];
flagMaterialIsWater = true;
densityWater = density;
if (verboseLevel > 3)
G4cout << "****** Water material is found with density(cm^-3)=" << density/(cm*cm*cm) << G4endl;
}
}
} // if(numOfCouples>0)
} // if (theCoupleTable)
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAScreenedRutherfordElasticModel::CrossSectionPerVolume(const G4Material*,
G4double G4DNAScreenedRutherfordElasticModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition*,
G4double ekin,
G4double,
@@ -202,15 +167,13 @@ G4double G4DNAScreenedRutherfordElasticModel::CrossSectionPerVolume(const G4Mate
G4double sigma=0;
if (flagMaterialIsWater)
if (material->GetName() == "G4_WATER")
{
if (ekin < highEnergyLimit)
{
//SI : XS must not be zero otherwise sampling of secondaries method ignored
if (ekin < lowEnergyLimitOfModel) ekin = lowEnergyLimitOfModel;
//
if (ekin < killBelowEnergy) return DBL_MAX;
G4double z = 10.;
G4double n = ScreeningFactor(ekin,z);
@@ -222,12 +185,12 @@ G4double G4DNAScreenedRutherfordElasticModel::CrossSectionPerVolume(const G4Mate
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*densityWater/(1./cm) << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if (flagMaterialIsWater)
}
return sigma*densityWater;
return sigma*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -0,0 +1,84 @@
//
// ********************************************************************
// * 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: G4DNAVibExcitation.cc,v 1.2 2010/11/11 22:32:22 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04 $
#include "G4DNAVibExcitation.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
using namespace std;
G4DNAVibExcitation::G4DNAVibExcitation(const G4String& processName,
G4ProcessType type):G4VEmProcess (processName, type),
isInitialised(false)
{
SetProcessSubType(51);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4DNAVibExcitation::~G4DNAVibExcitation()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4DNAVibExcitation::IsApplicable(const G4ParticleDefinition& p)
{
return (&p == G4Electron::Electron());
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAVibExcitation::InitialiseProcess(const G4ParticleDefinition* p)
{
if(!isInitialised)
{
isInitialised = true;
SetBuildTableFlag(false);
G4String name = p->GetParticleName();
if(name == "e-")
{
if(!Model()) SetModel(new G4DNASancheExcitationModel);
Model()->SetLowEnergyLimit(2*eV);
Model()->SetHighEnergyLimit(100*eV);
AddEmModel(1, Model());
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4DNAVibExcitation::PrintInfo()
{
G4cout
<< " Total cross sections computed from "
<< Model()->GetName()
<< G4endl;
}
@@ -24,8 +24,8 @@
// ********************************************************************
//
//
// $Id: G4EMDataSet.cc,v 1.20 2009/09/25 07:41:34 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4EMDataSet.cc,v 1.21 2010/12/02 17:37:26 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -107,7 +107,7 @@ G4EMDataSet::G4EMDataSet(G4int argZ,
if ((energies == 0) ^ (data == 0))
G4Exception("G4EMDataSet::G4EMDataSet - different size for energies and data (zero case)");
if (energies == 0) return;
//if (energies == 0) return;
if (energies->size() != data->size())
G4Exception("G4EMDataSet::G4EMDataSet - different size for energies and data");
@@ -140,7 +140,7 @@ G4EMDataSet::G4EMDataSet(G4int argZ,
if ((energies == 0) ^ (data == 0))
G4Exception("G4EMDataSet::G4EMDataSet - different size for energies and data (zero case)");
if (energies == 0) return;
//if (energies == 0) return;
if (energies->size() != data->size())
G4Exception("G4EMDataSet::G4EMDataSet - different size for energies and data");
@@ -148,7 +148,7 @@ G4EMDataSet::G4EMDataSet(G4int argZ,
if ((log_energies == 0) ^ (log_data == 0))
G4Exception("G4EMDataSet::G4EMDataSet - different size for log energies and log data (zero case)");
if (log_energies == 0) return;
//if (log_energies == 0) return;
if (log_energies->size() != log_data->size())
G4Exception("G4EMDataSet::G4EMDataSet - different size for log energies and log data");
@@ -160,11 +160,11 @@ G4EMDataSet::G4EMDataSet(G4int argZ,
G4EMDataSet::~G4EMDataSet()
{
delete algorithm;
if (energies) delete energies;
if (data) delete data;
if (pdf) delete pdf;
if (log_energies) delete log_energies;
if (log_data) delete log_data;
if (energies) { energies->clear(); delete energies; }
if (data) { data->clear(); delete data; }
if (pdf) { pdf->clear(); delete pdf; }
if (log_energies) { log_energies->clear(); delete log_energies; }
if (log_data) { log_data->clear(); delete log_data; }
}
@@ -23,6 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4Generator2BN.cc,v 1.9 2010/10/14 14:01:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// -------------------------------------------------------------------
//
@@ -44,13 +46,13 @@
//
// Class Description:
//
// Concrete base class for Bremsstrahlung Angular Distribution Generation - 2BN Distribution
// Concrete base class for Bremsstrahlung Angular Distribution Generation
// 2BN Distribution
//
// Class Description: End
//
// -------------------------------------------------------------------
//
//
//
#include "G4Generator2BN.hh"
#include "Randomize.hh"
@@ -149,7 +151,8 @@ G4double G4Generator2BN::ctab[320] =
};
G4Generator2BN::G4Generator2BN(const G4String& name):G4VBremAngularDistribution(name)
G4Generator2BN::G4Generator2BN(const G4String&)
: G4VBremAngularDistribution("AngularGen2BN")
{
b = 1.2;
index_min = -300;
@@ -171,7 +174,7 @@ G4Generator2BN::G4Generator2BN(const G4String& name):G4VBremAngularDistribution(
//
G4Generator2BN::~G4Generator2BN()
{;}
{}
//
@@ -23,6 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4Generator2BS.cc,v 1.10 2010/10/14 14:01:02 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// -------------------------------------------------------------------
//
@@ -38,31 +40,37 @@
// Creation date: 2 June 2003
//
// Modifications:
// 02 Jun 2003 First implementation acording with new design
// 05 Nov 2003 MGP Fixed std namespace
// 17 Nov 2003 MGP Fixed compilation problem on Windows
// 02 Jun 2003 First implementation acording with new design
// 05 Nov 2003 MGP Fixed std namespace
// 17 Nov 2003 MGP Fixed compilation problem on Windows
// 12 Oct 2010 V.Ivanchenko Moved RejectionFunction inline, use G4Pow to speadup
//
// Class Description:
//
// Concrete base class for Bremsstrahlung Angular Distribution Generation - 2BS Distribution
// Concrete base class for Bremsstrahlung Angular Distribution Generation
// 2BS Distribution
//
// Class Description: End
//
// -------------------------------------------------------------------
//
//
#include "G4Generator2BS.hh"
#include "Randomize.hh"
//
#include "Randomize.hh"
#include "G4Pow.hh"
G4Generator2BS::G4Generator2BS(const G4String& name):G4VBremAngularDistribution(name)
{;}
//
G4Generator2BS::G4Generator2BS(const G4String&)
: G4VBremAngularDistribution("AngularGen2BS")
{
g4pow = G4Pow::GetInstance();
}
//
G4Generator2BS::~G4Generator2BS()
{;}
{}
//
@@ -78,7 +86,6 @@ G4double G4Generator2BS::PolarAngle(const G4double initial_energy,
// National Research Council of Canada
// Departement of Medical Physics, Memorial Sloan-Kettering Cancer Center, New York
G4double theta = 0;
G4double initialTotalEnergy = (initial_energy+electron_mass_c2)/electron_mass_c2;
@@ -86,8 +93,11 @@ G4double G4Generator2BS::PolarAngle(const G4double initial_energy,
EnergyRatio = finalTotalEnergy/initialTotalEnergy;
G4double gMaxEnergy = (pi*initialTotalEnergy)*(pi*initialTotalEnergy);
G4double Zeff = std::sqrt(static_cast<G4double>(Z) * (static_cast<G4double>(Z) + 1.0));
z = (0.00008116224*(std::pow(Zeff,0.3333333)));
//G4double Zeff = std::sqrt(static_cast<G4double>(Z) * (static_cast<G4double>(Z) + 1.0));
//z = (0.00008116224*(std::pow(Zeff,0.3333333)));
// VI speadup
z = 0.00008116224*(g4pow->Z13(Z) + g4pow->Z13(Z+1));
// Rejection arguments
rejection_argument1 = (1.0+EnergyRatio*EnergyRatio);
@@ -96,11 +106,10 @@ G4double G4Generator2BS::PolarAngle(const G4double initial_energy,
((1-EnergyRatio)/(2.0*initialTotalEnergy*EnergyRatio));
// Calculate rejection function at 0, 1 and Emax
G4double gfunction0 = RejectionFunction(0);
G4double gfunction1 = RejectionFunction(1);
G4double gfunction0 = RejectionFunction(0.0);
G4double gfunction1 = RejectionFunction(1.0);
G4double gfunctionEmax = RejectionFunction(gMaxEnergy);
// Calculate Maximum value
G4double gMaximum = std::max(gfunction0,gfunction1);
gMaximum = std::max(gMaximum,gfunctionEmax);
@@ -109,35 +118,24 @@ G4double G4Generator2BS::PolarAngle(const G4double initial_energy,
do{
rand = G4UniformRand();
rand = rand/(1-rand+1.0/gMaxEnergy);
rand /= (1 - rand + 1.0/gMaxEnergy);
gfunctionTest = RejectionFunction(rand);
randTest = G4UniformRand();
}while(randTest > (gfunctionTest/gMaximum));
} while(randTest*gMaximum > gfunctionTest);
theta = std::sqrt(rand)/initialTotalEnergy;
return theta;
}
//
G4double G4Generator2BS::RejectionFunction(G4double value) const
{
G4double argument = (1+value)*(1+value);
G4double gfunction = (4+std::log(rejection_argument3+(z/argument)))*
((4*EnergyRatio*value/argument)-rejection_argument1)+rejection_argument2;
return gfunction;
}
void G4Generator2BS::PrintGeneratorInformation() const
{
G4cout << "\n" << G4endl;
G4cout << "Bremsstrahlung Angular Generator is 2BS Generator from 2BS Koch & Motz distribution (Rev Mod Phys 31(4), 920 (1959))" << G4endl;
G4cout << "Bremsstrahlung Angular Generator is 2BS Generator "
<< "from 2BS Koch & Motz distribution (Rev Mod Phys 31(4), 920 (1959))" << G4endl;
G4cout << "Sampling algorithm adapted from PIRS-0203" << G4endl;
G4cout << "\n" << G4endl;
}
@@ -23,7 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// $Id: G4IonParametrisedLossModel.cc,v 1.10 2010/11/04 12:21:48 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// ===========================================================================
// GEANT4 class source file
@@ -63,6 +64,7 @@
// modified BuildRangeVector, ComputeLossForStep
// functions accordingly, added new cache param.)
// - Removed GetRange function (AL)
// 04. 11. 2010 - Moved virtual methods to the source (VI)
//
//
// Class description:
@@ -106,14 +108,13 @@ G4IonParametrisedLossModel::G4IonParametrisedLossModel(
nmbBins(90),
nmbSubBins(100),
particleChangeLoss(0),
modelIsInitialised(false),
corrections(0),
corrFactor(1.0),
energyLossLimit(0.01),
cutEnergies(0) {
cutEnergies(0)
{
genericIon = G4GenericIon::Definition();
genericIonPDGMass = genericIon -> GetPDGMass();
corrections = G4LossTableManager::Instance() -> EmCorrections();
// The upper limit of the current model is set to 100 TeV
SetHighEnergyLimit(100.0 * TeV);
@@ -195,6 +196,62 @@ G4double G4IonParametrisedLossModel::MinEnergyCut(
// #########################################################################
G4double G4IonParametrisedLossModel::MaxSecondaryEnergy(
const G4ParticleDefinition* particle,
G4double kineticEnergy) {
// ############## Maximum energy of secondaries ##########################
// Function computes maximum energy of secondary electrons which are
// released by an ion
//
// See Geant4 physics reference manual (version 9.1), section 9.1.1
//
// Ref.: W.M. Yao et al, Jour. of Phys. G 33 (2006) 1.
// C.Caso et al. (Part. Data Group), Europ. Phys. Jour. C 3 1 (1998).
// B. Rossi, High energy particles, New York, NY: Prentice-Hall (1952).
//
// (Implementation adapted from G4BraggIonModel)
if(particle != cacheParticle) UpdateCache(particle);
G4double tau = kineticEnergy/cacheMass;
G4double tmax = 2.0 * electron_mass_c2 * tau * (tau + 2.) /
(1. + 2.0 * (tau + 1.) * cacheElecMassRatio +
cacheElecMassRatio * cacheElecMassRatio);
return tmax;
}
// #########################################################################
G4double G4IonParametrisedLossModel::GetChargeSquareRatio(
const G4ParticleDefinition* particle,
const G4Material* material,
G4double kineticEnergy) { // Kinetic energy
G4double chargeSquareRatio = corrections ->
EffectiveChargeSquareRatio(particle,
material,
kineticEnergy);
corrFactor = chargeSquareRatio *
corrections -> EffectiveChargeCorrection(particle,
material,
kineticEnergy);
return corrFactor;
}
// #########################################################################
G4double G4IonParametrisedLossModel::GetParticleCharge(
const G4ParticleDefinition* particle,
const G4Material* material,
G4double kineticEnergy) { // Kinetic energy
return corrections -> GetParticleCharge(particle, material, kineticEnergy);
}
// #########################################################################
void G4IonParametrisedLossModel::Initialise(
const G4ParticleDefinition* particle,
const G4DataVector& cuts) {
@@ -294,22 +351,9 @@ void G4IonParametrisedLossModel::Initialise(
}
}
// The particle change object is cast to G4ParticleChangeForLoss
if(! modelIsInitialised) {
modelIsInitialised = true;
corrections = G4LossTableManager::Instance() -> EmCorrections();
if(!particleChangeLoss) {
if(pParticleChange) {
particleChangeLoss = reinterpret_cast<G4ParticleChangeForLoss*>
(pParticleChange);
}
else {
particleChangeLoss = new G4ParticleChangeForLoss();
}
}
// The particle change object
if(! particleChangeLoss) {
particleChangeLoss = GetParticleChangeForLoss();
}
// The G4BraggIonModel and G4BetheBlochModel instances are initialised with
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4LivermoreBremsstrahlungModel.cc,v 1.6 2009/06/11 15:47:08 mantero Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4LivermoreBremsstrahlungModel.cc,v 1.8 2010/12/02 16:07:05 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
//
@@ -141,7 +141,7 @@ void G4LivermoreBremsstrahlungModel::Initialise(const G4ParticleDefinition* part
delete crossSectionHandler;
crossSectionHandler = 0;
}
G4VDataSetAlgorithm* interpolation = new G4SemiLogInterpolation();
G4VDataSetAlgorithm* interpolation = 0;//new G4SemiLogInterpolation();
crossSectionHandler = new G4BremsstrahlungCrossSectionHandler(energySpectrum,interpolation);
crossSectionHandler->Initialise(0,LowEnergyLimit(),HighEnergyLimit(),
fNBinEnergyLoss);
@@ -195,6 +195,7 @@ G4LivermoreBremsstrahlungModel::ComputeCrossSectionPerAtom(const G4ParticleDefin
G4cout << "G4LivermoreBremsstrahlungModel::ComputeCrossSectionPerAtom" << G4endl;
G4cout << "The cross section handler is not correctly initialized" << G4endl;
G4Exception();
return 0;
}
//The cut is already included in the crossSectionHandler
@@ -0,0 +1,381 @@
//
// ********************************************************************
// * 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: G4LivermoreGammaConversionModelRC.cc,v 1.1 2010/11/10 17:12:22 flongo Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
//
// Author: Sebastien Inserti
// 30 October 2008
//
// History:
// --------
// 12 Apr 2009 V Ivanchenko Cleanup initialisation and generation of secondaries:
// - apply internal high-energy limit only in constructor
// - do not apply low-energy limit (default is 0)
// - use CLHEP electron mass for low-enegry limit
// - remove MeanFreePath method and table
#include "G4LivermoreGammaConversionModelRC.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LivermoreGammaConversionModelRC::G4LivermoreGammaConversionModelRC(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),smallEnergy(2.*MeV),isInitialised(false),
crossSectionHandler(0),meanFreePathTable(0)
{
lowEnergyLimit = 2.0*electron_mass_c2;
highEnergyLimit = 100 * GeV;
SetHighEnergyLimit(highEnergyLimit);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if(verboseLevel > 0) {
G4cout << "Livermore Gamma conversion is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / MeV << " MeV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LivermoreGammaConversionModelRC::~G4LivermoreGammaConversionModelRC()
{
if (crossSectionHandler) delete crossSectionHandler;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void
G4LivermoreGammaConversionModelRC::Initialise(const G4ParticleDefinition*,
const G4DataVector&)
{
if (verboseLevel > 3)
G4cout << "Calling G4LivermoreGammaConversionModelRC::Initialise()" << G4endl;
if (crossSectionHandler)
{
crossSectionHandler->Clear();
delete crossSectionHandler;
}
// Read data tables for all materials
crossSectionHandler = new G4CrossSectionHandler();
crossSectionHandler->Initialise(0,lowEnergyLimit,100.*GeV,400);
G4String crossSectionFile = "pair/pp-cs-";
crossSectionHandler->LoadData(crossSectionFile);
//
if (verboseLevel > 2)
G4cout << "Loaded cross section files for PenelopeGammaConversion" << G4endl;
if (verboseLevel > 0) {
G4cout << "Livermore Gamma Conversion model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / MeV << " MeV - "
<< HighEnergyLimit() / GeV << " GeV"
<< G4endl;
}
if(isInitialised) return;
fParticleChange = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double
G4LivermoreGammaConversionModelRC::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
G4double GammaEnergy,
G4double Z, G4double,
G4double, G4double)
{
if (verboseLevel > 3) {
G4cout << "Calling ComputeCrossSectionPerAtom() of G4LivermoreGammaConversionModelRC"
<< G4endl;
}
if (GammaEnergy < lowEnergyLimit || GammaEnergy > highEnergyLimit) return 0;
G4double cs = crossSectionHandler->FindValue(G4int(Z), GammaEnergy);
return cs;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LivermoreGammaConversionModelRC::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicGamma,
G4double,
G4double)
{
// The energies of the e+ e- secondaries are sampled using the Bethe - Heitler
// cross sections with Coulomb correction. A modified version of the random
// number techniques of Butcher & Messel is used (Nuc Phys 20(1960),15).
// Note 1 : Effects due to the breakdown of the Born approximation at low
// energy are ignored.
// Note 2 : The differential cross section implicitly takes account of
// pair creation in both nuclear and atomic electron fields. However triplet
// prodution is not generated.
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4LivermoreGammaConversionModelRC" << G4endl;
G4double photonEnergy = aDynamicGamma->GetKineticEnergy();
G4ParticleMomentum photonDirection = aDynamicGamma->GetMomentumDirection();
G4double epsilon ;
G4double epsilon0 = electron_mass_c2 / photonEnergy ;
G4double electronTotEnergy;
G4double positronTotEnergy;
// Do it fast if photon energy < 2. MeV
if (photonEnergy < smallEnergy )
{
epsilon = epsilon0 + (0.5 - epsilon0) * G4UniformRand();
if (CLHEP::RandBit::shootBit())
{
electronTotEnergy = (1. - epsilon) * photonEnergy;
positronTotEnergy = epsilon * photonEnergy;
}
else
{
positronTotEnergy = (1. - epsilon) * photonEnergy;
electronTotEnergy = epsilon * photonEnergy;
}
}
else
{
// Select randomly one element in the current material
//const G4Element* element = crossSectionHandler->SelectRandomElement(couple,photonEnergy);
const G4ParticleDefinition* particle = aDynamicGamma->GetDefinition();
const G4Element* element = SelectRandomAtom(couple,particle,photonEnergy);
G4cout << "G4LivermoreGammaConversionModelRC::SampleSecondaries" << G4endl;
if (element == 0)
{
G4cout << "G4LivermoreGammaConversionModelRC::SampleSecondaries - element = 0"
<< G4endl;
return;
}
G4IonisParamElm* ionisation = element->GetIonisation();
if (ionisation == 0)
{
G4cout << "G4LivermoreGammaConversionModelRC::SampleSecondaries - ionisation = 0"
<< G4endl;
return;
}
// Extract Coulomb factor for this Element
G4double fZ = 8. * (ionisation->GetlogZ3());
if (photonEnergy > 50. * MeV) fZ += 8. * (element->GetfCoulomb());
// Limits of the screening variable
G4double screenFactor = 136. * epsilon0 / (element->GetIonisation()->GetZ3()) ;
G4double screenMax = std::exp ((42.24 - fZ)/8.368) - 0.952 ;
G4double screenMin = std::min(4.*screenFactor,screenMax) ;
// Limits of the energy sampling
G4double epsilon1 = 0.5 - 0.5 * std::sqrt(1. - screenMin / screenMax) ;
G4double epsilonMin = std::max(epsilon0,epsilon1);
G4double epsilonRange = 0.5 - epsilonMin ;
// Sample the energy rate of the created electron (or positron)
G4double screen;
G4double gReject ;
G4double f10 = ScreenFunction1(screenMin) - fZ;
G4double f20 = ScreenFunction2(screenMin) - fZ;
G4double normF1 = std::max(f10 * epsilonRange * epsilonRange,0.);
G4double normF2 = std::max(1.5 * f20,0.);
G4double a=393.3750918, b=115.3070201, c=810.6428451, d=19.96497475, e=1016.874592, f=1.936685510,
g=751.2140962, h=0.099751048, i=299.9466339, j=0.002057250, k=49.81034926;
G4double aa=-18.6371131, bb=-1729.95248, cc=9450.971186, dd=106336.0145, ee=55143.09287, ff=-117602.840,
gg=-721455.467, hh=693957.8635, ii=156266.1085, jj=533209.9347;
G4double Rechazo = 0.;
G4double logepsMin = log(epsilonMin);
G4double NormaRC = a + b*logepsMin + c/logepsMin + d*pow(logepsMin,2.) + e/pow(logepsMin,2.) + f*pow(logepsMin,3.) +
g/pow(logepsMin,3.) + h*pow(logepsMin,4.) + i/pow(logepsMin,4.) + j*pow(logepsMin,5.) +
k/pow(logepsMin,5.);
do {
do {
if (normF1 / (normF1 + normF2) > G4UniformRand() )
{
epsilon = 0.5 - epsilonRange * std::pow(G4UniformRand(), 0.3333) ;
screen = screenFactor / (epsilon * (1. - epsilon));
gReject = (ScreenFunction1(screen) - fZ) / f10 ;
}
else
{
epsilon = epsilonMin + epsilonRange * G4UniformRand();
screen = screenFactor / (epsilon * (1 - epsilon));
gReject = (ScreenFunction2(screen) - fZ) / f20 ;
}
} while ( gReject < G4UniformRand() );
if (CLHEP::RandBit::shootBit()) epsilon = (1. - epsilon); // Extención de Epsilon hasta 1.
G4double logepsilon = log(epsilon);
G4double deltaP_R1 = 1. + (a + b*logepsilon + c/logepsilon + d*pow(logepsilon,2.) + e/pow(logepsilon,2.) +
f*pow(logepsilon,3.) + g/pow(logepsilon,3.) + h*pow(logepsilon,4.) + i/pow(logepsilon,4.) +
j*pow(logepsilon,5.) + k/pow(logepsilon,5.))/100.;
G4double deltaP_R2 = 1.+((aa + cc*logepsilon + ee*pow(logepsilon,2.) + gg*pow(logepsilon,3.) + ii*pow(logepsilon,4.))
/ (1. + bb*logepsilon + dd*pow(logepsilon,2.) + ff*pow(logepsilon,3.) + hh*pow(logepsilon,4.)
+ jj*pow(logepsilon,5.) ))/100.;
if (epsilon <= 0.5)
{
Rechazo = deltaP_R1/NormaRC;
}
else
{
Rechazo = deltaP_R2/NormaRC;
}
G4cout << Rechazo << " " << NormaRC << " " << epsilon << G4endl;
} while (Rechazo < G4UniformRand() );
electronTotEnergy = (1. - epsilon) * photonEnergy;
positronTotEnergy = epsilon * photonEnergy;
} // End of epsilon sampling
// Fix charges randomly
// Scattered electron (positron) angles. ( Z - axis along the parent photon)
// Universal distribution suggested by L. Urban (Geant3 manual (1993) Phys211),
// derived from Tsai distribution (Rev. Mod. Phys. 49, 421 (1977)
G4double u;
const G4double a1 = 0.625;
G4double a2 = 3. * a1;
// G4double d = 27. ;
// if (9. / (9. + d) > G4UniformRand())
if (0.25 > G4UniformRand())
{
u = - std::log(G4UniformRand() * G4UniformRand()) / a1 ;
}
else
{
u = - std::log(G4UniformRand() * G4UniformRand()) / a2 ;
}
G4double thetaEle = u*electron_mass_c2/electronTotEnergy;
G4double thetaPos = u*electron_mass_c2/positronTotEnergy;
G4double phi = twopi * G4UniformRand();
G4double dxEle= std::sin(thetaEle)*std::cos(phi),dyEle= std::sin(thetaEle)*std::sin(phi),dzEle=std::cos(thetaEle);
G4double dxPos=-std::sin(thetaPos)*std::cos(phi),dyPos=-std::sin(thetaPos)*std::sin(phi),dzPos=std::cos(thetaPos);
// Kinematics of the created pair:
// the electron and positron are assumed to have a symetric angular
// distribution with respect to the Z axis along the parent photon
G4double electronKineEnergy = std::max(0.,electronTotEnergy - electron_mass_c2) ;
// SI - The range test has been removed wrt original G4LowEnergyGammaconversion class
G4ThreeVector electronDirection (dxEle, dyEle, dzEle);
electronDirection.rotateUz(photonDirection);
G4DynamicParticle* particle1 = new G4DynamicParticle (G4Electron::Electron(),
electronDirection,
electronKineEnergy);
// The e+ is always created (even with kinetic energy = 0) for further annihilation
G4double positronKineEnergy = std::max(0.,positronTotEnergy - electron_mass_c2) ;
// SI - The range test has been removed wrt original G4LowEnergyGammaconversion class
G4ThreeVector positronDirection (dxPos, dyPos, dzPos);
positronDirection.rotateUz(photonDirection);
// Create G4DynamicParticle object for the particle2
G4DynamicParticle* particle2 = new G4DynamicParticle(G4Positron::Positron(),
positronDirection, positronKineEnergy);
// Fill output vector
// G4cout << "Cree el e+ " << epsilon << G4endl;
fvect->push_back(particle1);
fvect->push_back(particle2);
// kill incident photon
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeTrackStatus(fStopAndKill);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LivermoreGammaConversionModelRC::ScreenFunction1(G4double screenVariable)
{
// Compute the value of the screening function 3*phi1 - phi2
G4double value;
if (screenVariable > 1.)
value = 42.24 - 8.368 * std::log(screenVariable + 0.952);
else
value = 42.392 - screenVariable * (7.796 - 1.961 * screenVariable);
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LivermoreGammaConversionModelRC::ScreenFunction2(G4double screenVariable)
{
// Compute the value of the screening function 1.5*phi1 - 0.5*phi2
G4double value;
if (screenVariable > 1.)
value = 42.24 - 8.368 * std::log(screenVariable + 0.952);
else
value = 41.405 - screenVariable * (5.828 - 0.8945 * screenVariable);
return value;
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4LivermoreIonisationModel.cc,v 1.7 2009/10/23 09:30:08 pandola Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4LivermoreIonisationModel.cc,v 1.13 2010/12/02 16:06:29 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
//
@@ -43,6 +43,12 @@
// 23 Oct 2009 L Pandola
// - atomic deexcitation managed via G4VEmModel::DeexcitationFlag() is
// set as "true" (default would be false)
// 12 Oct 2010 L Pandola
// - add debugging information about energy in
// SampleDeexcitationAlongStep()
// - generate fluorescence SampleDeexcitationAlongStep() only above
// the cuts.
//
//
#include "G4LivermoreIonisationModel.hh"
@@ -84,11 +90,10 @@ G4LivermoreIonisationModel::G4LivermoreIonisationModel(const G4ParticleDefinitio
SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
//
verboseLevel = 0;
//
//By default: use deexcitation, not auger
SetDeexcitationFlag(true);
ActivateAuger(false);
//
//
// Notice: the fluorescence along step is generated only if it is
// set by the PROCESS (e.g. G4eIonisation) via the command
@@ -125,7 +130,7 @@ void G4LivermoreIonisationModel::Initialise(const G4ParticleDefinition* particle
energySpectrum = 0;
}
energySpectrum = new G4eIonisationSpectrum();
if (verboseLevel > 0)
if (verboseLevel > 3)
G4cout << "G4VEnergySpectrum is initialized" << G4endl;
//Initialize cross section handler
@@ -142,8 +147,12 @@ void G4LivermoreIonisationModel::Initialise(const G4ParticleDefinition* particle
crossSectionHandler->Clear();
crossSectionHandler->LoadShellData("ioni/ion-ss-cs-");
//This is used to retrieve cross section values later on
crossSectionHandler->BuildMeanFreePathForMaterials(&cuts);
G4VEMDataSet* emdata =
crossSectionHandler->BuildMeanFreePathForMaterials(&cuts);
//The method BuildMeanFreePathForMaterials() is required here only to force
//the building of an internal table: the output pointer can be deleted
delete emdata;
//Fluorescence data
transitionManager = G4AtomicTransitionManager::Instance();
if (shellVacancy) delete shellVacancy;
@@ -159,7 +168,7 @@ void G4LivermoreIonisationModel::Initialise(const G4ParticleDefinition* particle
<< G4endl;
}
if (verboseLevel > 1)
if (verboseLevel > 3)
{
G4cout << "Cross section data: " << G4endl;
crossSectionHandler->PrintData();
@@ -194,6 +203,7 @@ G4double G4LivermoreIonisationModel::ComputeCrossSectionPerAtom(const G4Particle
G4cout << "G4LivermoreIonisationModel::ComputeCrossSectionPerAtom" << G4endl;
G4cout << "The cross section handler is not correctly initialized" << G4endl;
G4Exception();
return 0;
}
//The cut is already included in the crossSectionHandler
@@ -387,6 +397,8 @@ void G4LivermoreIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle
{
theEnergyDeposit -= e;
fvect->push_back(aSecondary);
aSecondary = 0;
(*secondaryVector)[i]=0;
}
else
{
@@ -395,6 +407,8 @@ void G4LivermoreIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle
}
}
}
//secondaryVector = 0;
delete secondaryVector;
}
}
}
@@ -440,10 +454,14 @@ void G4LivermoreIonisationModel::SampleDeexcitationAlongStep(const G4Material* t
//(including fluctuations) and produces explicit fluorescence/Auger
//secondaries. The eloss value is updated.
G4double energyLossBefore = eloss;
if (verboseLevel > 2)
G4cout << "Energy loss along step before deexcitation : " << energyLossBefore/keV <<
" keV" << G4endl;
if (verboseLevel > 2)
{
G4cout << "-----------------------------------------------------------" << G4endl;
G4cout << " SampleDeexcitationAlongStep() from G4LivermoreIonisation" << G4endl;
G4cout << "Energy loss along step before deexcitation : " << energyLossBefore/keV <<
" keV" << G4endl;
}
G4double incidentEnergy = theTrack.GetDynamicParticle()->GetKineticEnergy();
G4ProductionCutsTable* theCoupleTable =
@@ -453,9 +471,6 @@ void G4LivermoreIonisationModel::SampleDeexcitationAlongStep(const G4Material* t
G4double cutg = (*(theCoupleTable->GetEnergyCutsVector(0)))[index];
G4double cute = (*(theCoupleTable->GetEnergyCutsVector(1)))[index];
//Notice: in LowEnergyIonisation, fluorescence is always generated above 250 eV
//not above the tracking cut.
//G4double cutForLowEnergySecondaryParticles = 250.0*eV;
std::vector<G4DynamicParticle*>* deexcitationProducts =
new std::vector<G4DynamicParticle*>;
@@ -505,7 +520,10 @@ void G4LivermoreIonisationModel::SampleDeexcitationAlongStep(const G4Material* t
if (aSecondary)
{
e = aSecondary->GetKineticEnergy();
if ( eTot + e <= eloss )
G4double itsCut = cutg;
if (aSecondary->GetParticleDefinition() == G4Electron::Electron())
itsCut = cute;
if ( eTot + e <= eloss && e > itsCut )
{
eTot += e;
deexcitationProducts->push_back(aSecondary);
@@ -524,10 +542,14 @@ void G4LivermoreIonisationModel::SampleDeexcitationAlongStep(const G4Material* t
}
}
G4double energyLossInFluorescence = 0.0;
size_t nSecondaries = deexcitationProducts->size();
if (nSecondaries > 0)
{
fParticleChange->SetNumberOfSecondaries(nSecondaries);
//You may have already secondaries produced by SampleSubCutSecondaries()
//at the process G4VEnergyLossProcess
G4int secondariesBefore = fParticleChange->GetNumberOfSecondaries();
fParticleChange->SetNumberOfSecondaries(nSecondaries+secondariesBefore);
const G4StepPoint* preStep = theTrack.GetStep()->GetPreStepPoint();
const G4StepPoint* postStep = theTrack.GetStep()->GetPostStepPoint();
G4ThreeVector r = preStep->GetPosition();
@@ -538,7 +560,7 @@ void G4LivermoreIonisationModel::SampleDeexcitationAlongStep(const G4Material* t
deltaT -= t;
G4double time, q;
G4ThreeVector position;
for (size_t i=0; i<nSecondaries; i++)
{
G4DynamicParticle* part = (*deexcitationProducts)[i];
@@ -553,6 +575,7 @@ void G4LivermoreIonisationModel::SampleDeexcitationAlongStep(const G4Material* t
position = deltaR*q;
position += r;
G4Track* newTrack = new G4Track(part, time, position);
energyLossInFluorescence += eSecondary;
pParticleChange->AddSecondary(newTrack);
}
else
@@ -566,9 +589,32 @@ void G4LivermoreIonisationModel::SampleDeexcitationAlongStep(const G4Material* t
}
delete deexcitationProducts;
//Check and verbosities. Ensure energy conservation
if (verboseLevel > 2)
G4cout << "Energy loss along step after deexcitation : " << eloss/keV <<
" keV" << G4endl;
{
G4cout << "Energy loss along step after deexcitation : " << eloss/keV <<
" keV" << G4endl;
}
if (verboseLevel > 1)
{
G4cout << "------------------------------------------------------------------" << G4endl;
G4cout << "Energy in fluorescence: " << energyLossInFluorescence/keV << " keV" << G4endl;
G4cout << "Residual energy loss: " << eloss/keV << " keV " << G4endl;
G4cout << "Total final: " << (energyLossInFluorescence+eloss)/keV << " keV" << G4endl;
G4cout << "Total initial: " << energyLossBefore/keV << " keV" << G4endl;
G4cout << "------------------------------------------------------------------" << G4endl;
}
if (verboseLevel > 0)
{
if (std::fabs(energyLossBefore-energyLossInFluorescence-eloss)>10*eV)
{
G4cout << "Found energy non-conservation at SampleDeexcitationAlongStep() " << G4endl;
G4cout << "Energy in fluorescence: " << energyLossInFluorescence/keV << " keV" << G4endl;
G4cout << "Residual energy loss: " << eloss/keV << " keV " << G4endl;
G4cout << "Total final: " << (energyLossInFluorescence+eloss)/keV << " keV" << G4endl;
G4cout << "Total initial: " << energyLossBefore/keV << " keV" << G4endl;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -579,6 +625,7 @@ void G4LivermoreIonisationModel::InitialiseFluorescence()
G4DataVector* energyVector = 0;
size_t binForFluo = fNBinEnergyLoss/10;
//Used to produce a log-spaced energy grid. To be deleted at the end.
G4PhysicsLogVector* eVector = new G4PhysicsLogVector(LowEnergyLimit(),HighEnergyLimit(),
binForFluo);
const G4ProductionCutsTable* theCoupleTable=
@@ -655,9 +702,11 @@ void G4LivermoreIonisationModel::InitialiseFluorescence()
G4VEMDataSet* p = new G4EMDataSet(iZ,energyVector,ksi,interp,1.,1.);
xsis->AddComponent(p);
}
if(verboseLevel>0) xsis->PrintData();
if(verboseLevel>3) xsis->PrintData();
shellVacancy->AddXsiTable(xsis);
}
if (eVector)
delete eVector;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,349 @@
//
// ********************************************************************
// * 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: G4LivermoreNuclearGammaConversionModel.cc,v 1.1 2010/11/10 17:09:16 flongo Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
//
// Author: Sebastien Inserti
// 30 October 2008
//
// History:
// --------
// 12 Apr 2009 V Ivanchenko Cleanup initialisation and generation of secondaries:
// - apply internal high-energy limit only in constructor
// - do not apply low-energy limit (default is 0)
// - use CLHEP electron mass for low-enegry limit
// - remove MeanFreePath method and table
#include "G4LivermoreNuclearGammaConversionModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LivermoreNuclearGammaConversionModel::G4LivermoreNuclearGammaConversionModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),smallEnergy(2.*MeV),isInitialised(false),
crossSectionHandler(0),meanFreePathTable(0)
{
lowEnergyLimit = 2.0*electron_mass_c2;
highEnergyLimit = 100 * GeV;
SetHighEnergyLimit(highEnergyLimit);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if(verboseLevel > 0) {
G4cout << "Livermore Nuclear Gamma conversion is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / MeV << " MeV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LivermoreNuclearGammaConversionModel::~G4LivermoreNuclearGammaConversionModel()
{
if (crossSectionHandler) delete crossSectionHandler;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void
G4LivermoreNuclearGammaConversionModel::Initialise(const G4ParticleDefinition*,
const G4DataVector&)
{
if (verboseLevel > 3)
G4cout << "Calling G4LivermoreNuclearGammaConversionModel::Initialise()" << G4endl;
if (crossSectionHandler)
{
crossSectionHandler->Clear();
delete crossSectionHandler;
}
// Read data tables for all materials
crossSectionHandler = new G4CrossSectionHandler();
crossSectionHandler->Initialise(0,lowEnergyLimit,100.*GeV,400);
G4String crossSectionFile = "pairdata/pp-pair-cs-"; // here only pair in nuclear field cs should be used
crossSectionHandler->LoadData(crossSectionFile);
//
if (verboseLevel > 0) {
G4cout << "Loaded cross section files for Livermore GammaConversion" << G4endl;
G4cout << "To obtain the total cross section this should be used only " << G4endl
<< "in connection with G4ElectronGammaConversion " << G4endl;
}
if (verboseLevel > 0) {
G4cout << "Livermore Nuclear Gamma Conversion model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / MeV << " MeV - "
<< HighEnergyLimit() / GeV << " GeV"
<< G4endl;
}
if(isInitialised) return;
fParticleChange = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double
G4LivermoreNuclearGammaConversionModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
G4double GammaEnergy,
G4double Z, G4double,
G4double, G4double)
{
if (verboseLevel > 3) {
G4cout << "Calling ComputeCrossSectionPerAtom() of G4LivermoreNuclearGammaConversionModel"
<< G4endl;
}
if (GammaEnergy < lowEnergyLimit || GammaEnergy > highEnergyLimit) return 0;
G4double cs = crossSectionHandler->FindValue(G4int(Z), GammaEnergy);
return cs;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LivermoreNuclearGammaConversionModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicGamma,
G4double,
G4double)
{
// The energies of the e+ e- secondaries are sampled using the Bethe - Heitler
// cross sections with Coulomb correction. A modified version of the random
// number techniques of Butcher & Messel is used (Nuc Phys 20(1960),15).
// Note 1 : Effects due to the breakdown of the Born approximation at low
// energy are ignored.
// Note 2 : The differential cross section implicitly takes account of
// pair creation in both nuclear and atomic electron fields. However triplet
// prodution is not generated.
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4LivermoreNuclearGammaConversionModel" << G4endl;
G4double photonEnergy = aDynamicGamma->GetKineticEnergy();
G4ParticleMomentum photonDirection = aDynamicGamma->GetMomentumDirection();
G4double epsilon ;
G4double epsilon0 = electron_mass_c2 / photonEnergy ;
// Do it fast if photon energy < 2. MeV
if (photonEnergy < smallEnergy )
{
epsilon = epsilon0 + (0.5 - epsilon0) * G4UniformRand();
}
else
{
// Select randomly one element in the current material
//const G4Element* element = crossSectionHandler->SelectRandomElement(couple,photonEnergy);
const G4ParticleDefinition* particle = aDynamicGamma->GetDefinition();
const G4Element* element = SelectRandomAtom(couple,particle,photonEnergy);
if (element == 0)
{
G4cout << "G4LivermoreNuclearGammaConversionModel::SampleSecondaries - element = 0"
<< G4endl;
return;
}
G4IonisParamElm* ionisation = element->GetIonisation();
if (ionisation == 0)
{
G4cout << "G4LivermoreNuclearGammaConversionModel::SampleSecondaries - ionisation = 0"
<< G4endl;
return;
}
// Extract Coulomb factor for this Element
G4double fZ = 8. * (ionisation->GetlogZ3());
if (photonEnergy > 50. * MeV) fZ += 8. * (element->GetfCoulomb());
// Limits of the screening variable
G4double screenFactor = 136. * epsilon0 / (element->GetIonisation()->GetZ3()) ;
G4double screenMax = std::exp ((42.24 - fZ)/8.368) - 0.952 ;
G4double screenMin = std::min(4.*screenFactor,screenMax) ;
// Limits of the energy sampling
G4double epsilon1 = 0.5 - 0.5 * std::sqrt(1. - screenMin / screenMax) ;
G4double epsilonMin = std::max(epsilon0,epsilon1);
G4double epsilonRange = 0.5 - epsilonMin ;
// Sample the energy rate of the created electron (or positron)
G4double screen;
G4double gReject ;
G4double f10 = ScreenFunction1(screenMin) - fZ;
G4double f20 = ScreenFunction2(screenMin) - fZ;
G4double normF1 = std::max(f10 * epsilonRange * epsilonRange,0.);
G4double normF2 = std::max(1.5 * f20,0.);
do {
if (normF1 / (normF1 + normF2) > G4UniformRand() )
{
epsilon = 0.5 - epsilonRange * std::pow(G4UniformRand(), 0.3333) ;
screen = screenFactor / (epsilon * (1. - epsilon));
gReject = (ScreenFunction1(screen) - fZ) / f10 ;
}
else
{
epsilon = epsilonMin + epsilonRange * G4UniformRand();
screen = screenFactor / (epsilon * (1 - epsilon));
gReject = (ScreenFunction2(screen) - fZ) / f20 ;
}
} while ( gReject < G4UniformRand() );
} // End of epsilon sampling
// Fix charges randomly
G4double electronTotEnergy;
G4double positronTotEnergy;
if (CLHEP::RandBit::shootBit())
{
electronTotEnergy = (1. - epsilon) * photonEnergy;
positronTotEnergy = epsilon * photonEnergy;
}
else
{
positronTotEnergy = (1. - epsilon) * photonEnergy;
electronTotEnergy = epsilon * photonEnergy;
}
// Scattered electron (positron) angles. ( Z - axis along the parent photon)
// Universal distribution suggested by L. Urban (Geant3 manual (1993) Phys211),
// derived from Tsai distribution (Rev. Mod. Phys. 49, 421 (1977)
G4double u;
const G4double a1 = 0.625;
G4double a2 = 3. * a1;
// G4double d = 27. ;
// if (9. / (9. + d) > G4UniformRand())
if (0.25 > G4UniformRand())
{
u = - std::log(G4UniformRand() * G4UniformRand()) / a1 ;
}
else
{
u = - std::log(G4UniformRand() * G4UniformRand()) / a2 ;
}
G4double thetaEle = u*electron_mass_c2/electronTotEnergy;
G4double thetaPos = u*electron_mass_c2/positronTotEnergy;
G4double phi = twopi * G4UniformRand();
G4double dxEle= std::sin(thetaEle)*std::cos(phi),dyEle= std::sin(thetaEle)*std::sin(phi),dzEle=std::cos(thetaEle);
G4double dxPos=-std::sin(thetaPos)*std::cos(phi),dyPos=-std::sin(thetaPos)*std::sin(phi),dzPos=std::cos(thetaPos);
// Kinematics of the created pair:
// the electron and positron are assumed to have a symetric angular
// distribution with respect to the Z axis along the parent photon
G4double electronKineEnergy = std::max(0.,electronTotEnergy - electron_mass_c2) ;
// SI - The range test has been removed wrt original G4LowEnergyGammaconversion class
G4ThreeVector electronDirection (dxEle, dyEle, dzEle);
electronDirection.rotateUz(photonDirection);
G4DynamicParticle* particle1 = new G4DynamicParticle (G4Electron::Electron(),
electronDirection,
electronKineEnergy);
// The e+ is always created (even with kinetic energy = 0) for further annihilation
G4double positronKineEnergy = std::max(0.,positronTotEnergy - electron_mass_c2) ;
// SI - The range test has been removed wrt original G4LowEnergyGammaconversion class
G4ThreeVector positronDirection (dxPos, dyPos, dzPos);
positronDirection.rotateUz(photonDirection);
// Create G4DynamicParticle object for the particle2
G4DynamicParticle* particle2 = new G4DynamicParticle(G4Positron::Positron(),
positronDirection, positronKineEnergy);
// Fill output vector
fvect->push_back(particle1);
fvect->push_back(particle2);
// kill incident photon
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeTrackStatus(fStopAndKill);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LivermoreNuclearGammaConversionModel::ScreenFunction1(G4double screenVariable)
{
// Compute the value of the screening function 3*phi1 - phi2
G4double value;
if (screenVariable > 1.)
value = 42.24 - 8.368 * std::log(screenVariable + 0.952);
else
value = 42.392 - screenVariable * (7.796 - 1.961 * screenVariable);
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LivermoreNuclearGammaConversionModel::ScreenFunction2(G4double screenVariable)
{
// Compute the value of the screening function 1.5*phi1 - 0.5*phi2
G4double value;
if (screenVariable > 1.)
value = 42.24 - 8.368 * std::log(screenVariable + 0.952);
else
value = 41.405 - screenVariable * (5.828 - 0.8945 * screenVariable);
return value;
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4LivermorePhotoElectricModel.cc,v 1.9 2009/10/23 09:31:03 pandola Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4LivermorePhotoElectricModel.cc,v 1.12 2010/10/13 07:15:42 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
//
// Author: Sebastien Inserti
@@ -42,7 +42,10 @@
// 23 Oct 2009 L Pandola
// - atomic deexcitation managed via G4VEmModel::DeexcitationFlag() is
// set as "true" (default would be false)
//
// 15 Mar 2010 L Pandola
// - removed methods to set explicitely fluorescence cuts.
// Main cuts from G4ProductionCutsTable are always used
//
#include "G4LivermorePhotoElectricModel.hh"
@@ -61,11 +64,7 @@ G4LivermorePhotoElectricModel::G4LivermorePhotoElectricModel(const G4ParticleDef
highEnergyLimit = 100 * GeV;
// SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
//Set atomic deexcitation by default
SetDeexcitationFlag(true);
ActivateAuger(false);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
@@ -73,6 +72,11 @@ G4LivermorePhotoElectricModel::G4LivermorePhotoElectricModel(const G4ParticleDef
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
//Set atomic deexcitation by default
SetDeexcitationFlag(true);
ActivateAuger(false);
if(verboseLevel>0) {
G4cout << "Livermore PhotoElectric is constructed " << G4endl
<< "Energy range: "
@@ -124,9 +128,7 @@ G4LivermorePhotoElectricModel::Initialise(const G4ParticleDefinition*,
G4String shellCrossSectionFile = "phot/pe-ss-cs-";
shellCrossSectionHandler->LoadShellData(shellCrossSectionFile);
// SI - Simple generator is buggy
//generatorName = "geant4.6.2";
//ElectronAngularGenerator = new G4PhotoElectricAngularGeneratorSimple("GEANTSimpleGenerator"); // default generator
// default generator
ElectronAngularGenerator =
new G4PhotoElectricAngularGeneratorSauterGavrila("GEANTSauterGavrilaGenerator");
@@ -297,25 +299,17 @@ G4LivermorePhotoElectricModel::SampleSecondaries(std::vector<G4DynamicParticle*>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LivermorePhotoElectricModel::SetCutForLowEnSecPhotons(G4double cut)
void G4LivermorePhotoElectricModel::ActivateAuger(G4bool augerbool)
{
cutForLowEnergySecondaryPhotons = cut;
deexcitationManager.SetCutForSecondaryPhotons(cut);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LivermorePhotoElectricModel::SetCutForLowEnSecElectrons(G4double cut)
{
cutForLowEnergySecondaryElectrons = cut;
deexcitationManager.SetCutForAugerElectrons(cut);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LivermorePhotoElectricModel::ActivateAuger(G4bool val)
{
deexcitationManager.ActivateAugerElectronProduction(val);
if (!DeexcitationFlag() && augerbool)
{
G4cout << "WARNING - G4LivermorePhotoElectricModel" << G4endl;
G4cout << "The use of the Atomic Deexcitation Manager is set to false " << G4endl;
G4cout << "Therefore, Auger electrons will be not generated anyway" << G4endl;
}
deexcitationManager.ActivateAugerElectronProduction(augerbool);
if (verboseLevel > 1)
G4cout << "Auger production set to " << augerbool << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -131,10 +131,7 @@ void G4LivermorePolarizedGammaConversionModel::Initialise(const G4ParticleDefini
if(isInitialised) return;
if(pParticleChange)
fParticleChange = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
else
fParticleChange = new G4ParticleChangeForGamma();
fParticleChange = GetParticleChangeForGamma();
isInitialised = true;
}
@@ -218,7 +215,10 @@ void G4LivermorePolarizedGammaConversionModel::SampleSecondaries(std::vector<G4D
// Select randomly one element in the current material
// G4int Z = crossSectionHandler->SelectRandomAtom(couple,photonEnergy);
const G4Element* element = crossSectionHandler->SelectRandomElement(couple,photonEnergy);
//const G4Element* element = crossSectionHandler->SelectRandomElement(couple,photonEnergy);
const G4ParticleDefinition* particle = aDynamicGamma->GetDefinition();
const G4Element* element = SelectRandomAtom(couple,particle,photonEnergy);
if (element == 0)
{
@@ -49,6 +49,9 @@ G4LivermorePolarizedPhotoElectricModel::G4LivermorePolarizedPhotoElectricModel(c
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
SetDeexcitationFlag(true);
ActivateAuger(false);
G4cout << "Livermore Polarized PhotoElectric is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
@@ -61,7 +64,7 @@ G4LivermorePolarizedPhotoElectricModel::G4LivermorePolarizedPhotoElectricModel(c
G4LivermorePolarizedPhotoElectricModel::~G4LivermorePolarizedPhotoElectricModel()
{
if (meanFreePathTable) delete meanFreePathTable;
// if (meanFreePathTable) delete meanFreePathTable;
if (crossSectionHandler) delete crossSectionHandler;
if (shellCrossSectionHandler) delete shellCrossSectionHandler;
}
@@ -89,22 +92,24 @@ void G4LivermorePolarizedPhotoElectricModel::Initialise(const G4ParticleDefiniti
}
/*
// Energy limits
if (LowEnergyLimit() < lowEnergyLimit)
{
G4cout << "G4LivermorePolarizedPhotoElectricModel: low energy limit increased from " <<
LowEnergyLimit()/eV << " eV to " << lowEnergyLimit << " eV" << G4endl;
SetLowEnergyLimit(lowEnergyLimit);
}
{
G4cout << "G4LivermorePolarizedPhotoElectricModel: low energy limit increased from " <<
LowEnergyLimit()/eV << " eV to " << lowEnergyLimit << " eV" << G4endl;
SetLowEnergyLimit(lowEnergyLimit);
}
if (HighEnergyLimit() > highEnergyLimit)
{
G4cout << "G4LivermorePolarizedPhotoElectricModel: high energy limit decreased from " <<
HighEnergyLimit()/GeV << " GeV to " << highEnergyLimit << " GeV" << G4endl;
SetHighEnergyLimit(highEnergyLimit);
}
{
G4cout << "G4LivermorePolarizedPhotoElectricModel: high energy limit decreased from " <<
HighEnergyLimit()/GeV << " GeV to " << highEnergyLimit << " GeV" << G4endl;
SetHighEnergyLimit(highEnergyLimit);
}
*/
// Reading of data files - all materials are read
crossSectionHandler = new G4CrossSectionHandler;
@@ -113,7 +118,7 @@ void G4LivermorePolarizedPhotoElectricModel::Initialise(const G4ParticleDefiniti
crossSectionHandler->LoadData(crossSectionFile);
meanFreePathTable = 0;
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
// meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
shellCrossSectionHandler = new G4CrossSectionHandler();
shellCrossSectionHandler->Clear();
@@ -124,7 +129,7 @@ void G4LivermorePolarizedPhotoElectricModel::Initialise(const G4ParticleDefiniti
//
if (verboseLevel > 2)
G4cout << "Loaded cross section files for Livermore Polarized PhotoElectric model" << G4endl;
InitialiseElementSelectors(particle,cuts);
G4cout << "Livermore Polarized PhotoElectric model is initialized " << G4endl
@@ -137,11 +142,14 @@ void G4LivermorePolarizedPhotoElectricModel::Initialise(const G4ParticleDefiniti
if(isInitialised) return;
if(pParticleChange)
/* if(pParticleChange)
fParticleChange = reinterpret_cast<G4ParticleChangeForGamma*>(pParticleChange);
else
fParticleChange = new G4ParticleChangeForGamma();
*/
fParticleChange = GetParticleChangeForGamma();
isInitialised = true;
}
@@ -178,28 +186,29 @@ void G4LivermorePolarizedPhotoElectricModel::SampleSecondaries(std::vector<G4Dyn
G4cout << "Calling SampleSecondaries() of G4LivermorePolarizedPhotoElectricModel" << G4endl;
G4double photonEnergy = aDynamicGamma->GetKineticEnergy();
// Within energy limit?
G4ThreeVector gammaPolarization0 = aDynamicGamma->GetPolarization();
G4ThreeVector photonDirection = aDynamicGamma->GetMomentumDirection();
// kill incident photon
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeTrackStatus(fStopAndKill);
// low-energy gamma is absorpted by this process
if(photonEnergy <= lowEnergyLimit)
if (photonEnergy <= lowEnergyLimit)
{
fParticleChange->ProposeTrackStatus(fStopAndKill);
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeLocalEnergyDeposit(photonEnergy);
return;
}
G4ThreeVector gammaPolarization0 = aDynamicGamma->GetPolarization();
// Protection: a polarisation parallel to the
// direction causes problems;
// in that case find a random polarization
G4ThreeVector photonDirection = aDynamicGamma->GetMomentumDirection();
// Make sure that the polarization vector is perpendicular to the
// gamma direction. If not
if(!(gammaPolarization0.isOrthogonal(photonDirection, 1e-6))||(gammaPolarization0.mag()==0))
{ // only for testing now
gammaPolarization0 = GetRandomPolarization(photonDirection);
@@ -211,14 +220,18 @@ void G4LivermorePolarizedPhotoElectricModel::SampleSecondaries(std::vector<G4Dyn
gammaPolarization0 = GetPerpendicularPolarization(photonDirection, gammaPolarization0);
}
}
// End of Protection
// G4double E0_m = photonEnergy / electron_mass_c2 ;
// Select randomly one element in the current material
G4int Z = crossSectionHandler->SelectRandomAtom(couple,photonEnergy);
// G4int Z = crossSectionHandler->SelectRandomAtom(couple,photonEnergy);
const G4ParticleDefinition* particle = aDynamicGamma->GetDefinition();
const G4Element* elm = SelectRandomAtom(couple->GetMaterial(),particle,photonEnergy);
G4int Z = (G4int)elm->GetZ();
// Select the ionised shell in the current atom according to shell cross sections
@@ -228,16 +241,9 @@ void G4LivermorePolarizedPhotoElectricModel::SampleSecondaries(std::vector<G4Dyn
const G4AtomicShell* shell = transitionManager->Shell(Z,shellIndex);
G4double bindingEnergy = shell->BindingEnergy();
G4int shellId = shell->ShellId();
// Create lists of pointers to DynamicParticles (photons and electrons)
// (Is the electron vector necessary? To be checked)
std::vector<G4DynamicParticle*>* photonVector = 0;
std::vector<G4DynamicParticle*> electronVector;
G4double energyDeposit = 0.0;
// Primary outgoing electron
G4double eKineticEnergy = photonEnergy - bindingEnergy;
@@ -255,7 +261,7 @@ void G4LivermorePolarizedPhotoElectricModel::SampleSecondaries(std::vector<G4Dyn
G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),
electronDirection,
eKineticEnergy);
electronVector.push_back(electron);
fvect->push_back(electron);
}
else
{
@@ -263,113 +269,111 @@ void G4LivermorePolarizedPhotoElectricModel::SampleSecondaries(std::vector<G4Dyn
}
G4int nElectrons = electronVector.size();
size_t nTotPhotons = 0;
G4int nPhotons=0;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t index = couple->GetIndex();
G4double cutg = (*(theCoupleTable->GetEnergyCutsVector(0)))[index];
cutg = std::min(cutForLowEnergySecondaryPhotons,cutg);
G4double cute = (*(theCoupleTable->GetEnergyCutsVector(1)))[index];
cute = std::min(cutForLowEnergySecondaryPhotons,cute);
G4DynamicParticle* aPhoton;
// Generation of fluorescence
// Data in EADL are available only for Z > 5
// Protection to avoid generating photons in the unphysical case of
// shell binding energy > photon energy
if (Z > 5 && (bindingEnergy > cutg || bindingEnergy > cute))
{
photonVector = deexcitationManager.GenerateParticles(Z,shellId);
nTotPhotons = photonVector->size();
for (size_t k=0; k<nTotPhotons; k++)
{
aPhoton = (*photonVector)[k];
if (aPhoton)
{
G4double itsCut = cutg;
if(aPhoton->GetDefinition() == G4Electron::Electron()) itsCut = cute;
G4double itsEnergy = aPhoton->GetKineticEnergy();
if (itsEnergy > itsCut && itsEnergy <= bindingEnergy)
// deexcitation
if(DeexcitationFlag() && Z > 5) {
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t index = couple->GetIndex();
G4double cutg = (*(theCoupleTable->GetEnergyCutsVector(0)))[index];
//cutg = std::min(cutForLowEnergySecondaryPhotons,cutg);
G4double cute = (*(theCoupleTable->GetEnergyCutsVector(1)))[index];
//cute = std::min(cutForLowEnergySecondaryPhotons,cute);
// G4DynamicParticle* aPhoton;
// Generation of fluorescence
// Data in EADL are available only for Z > 5
// Protection to avoid generating photons in the unphysical case of
// shell binding energy > photon energy
if (bindingEnergy > cutg || bindingEnergy > cute)
{
G4DynamicParticle* aPhoton;
deexcitationManager.SetCutForSecondaryPhotons(cutg);
deexcitationManager.SetCutForAugerElectrons(cute);
std::vector<G4DynamicParticle*>* photonVector =
deexcitationManager.GenerateParticles(Z,shellId);
size_t nTotPhotons = photonVector->size();
for (size_t k=0; k<nTotPhotons; k++)
{
aPhoton = (*photonVector)[k];
if (aPhoton)
{
G4double itsEnergy = aPhoton->GetKineticEnergy();
if (itsEnergy <= bindingEnergy)
{
nPhotons++;
// Local energy deposit is given as the sum of the
// energies of incident photons minus the energies
// of the outcoming fluorescence photons
bindingEnergy -= itsEnergy;
fvect->push_back(aPhoton);
}
else
{
delete aPhoton;
(*photonVector)[k] = 0;
}
}
}
delete photonVector;
}
}
// excitation energy left
fParticleChange->ProposeLocalEnergyDeposit(bindingEnergy);
}
}
else
{
delete aPhoton;
(*photonVector)[k] = 0;
}
}
}
}
/*
energyDeposit += bindingEnergy;
// Final state
for (G4int l = 0; l<nElectrons; l++ )
{
aPhoton = electronVector[l];
if(aPhoton) {
fvect->push_back(aPhoton);
}
}
{
aPhoton = electronVector[l];
if(aPhoton) {
fvect->push_back(aPhoton);
}
}
for ( size_t ll = 0; ll < nTotPhotons; ll++)
{
aPhoton = (*photonVector)[ll];
if(aPhoton) {
fvect->push_back(aPhoton);
}
{
aPhoton = (*photonVector)[ll];
if(aPhoton) {
fvect->push_back(aPhoton);
}
}
delete photonVector;
if (energyDeposit < 0)
delete photonVector;
if (energyDeposit < 0)
{
G4cout << "WARNING - "
<< "G4LowEnergyPhotoElectric::PostStepDoIt - Negative energy deposit"
<< G4endl;
energyDeposit = 0;
G4cout << "WARNING - "
<< "G4LowEnergyPhotoElectric::PostStepDoIt - Negative energy deposit"
<< G4endl;
energyDeposit = 0;
}
// kill incident photon
// kill incident photon
fParticleChange->ProposeMomentumDirection( 0., 0., 0. );
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeTrackStatus(fStopAndKill);
fParticleChange->ProposeLocalEnergyDeposit(energyDeposit);
}
*/
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LivermorePolarizedPhotoElectricModel::SetCutForLowEnSecPhotons(G4double cut)
void G4LivermorePolarizedPhotoElectricModel::ActivateAuger(G4bool augerbool)
{
cutForLowEnergySecondaryPhotons = cut;
deexcitationManager.SetCutForSecondaryPhotons(cut);
}
if (!DeexcitationFlag() && augerbool)
{
G4cout << "WARNING - G4LivermorePolarizedPhotoElectricModel" << G4endl;
G4cout << "The use of the Atomic Deexcitation Manager is set to false " << G4endl;
G4cout << "Therefore, Auger electrons will be not generated anyway" << G4endl;
}
deexcitationManager.ActivateAugerElectronProduction(augerbool);
if (verboseLevel > 1)
G4cout << "Auger production set to " << augerbool << G4endl;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LivermorePolarizedPhotoElectricModel::SetCutForLowEnSecElectrons(G4double cut)
{
cutForLowEnergySecondaryElectrons = cut;
deexcitationManager.SetCutForAugerElectrons(cut);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LivermorePolarizedPhotoElectricModel::ActivateAuger(G4bool val)
{
deexcitationManager.ActivateAugerElectronProduction(val);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -525,29 +529,31 @@ void G4LivermorePolarizedPhotoElectricModel::SystemOfRefChange
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LivermorePolarizedPhotoElectricModel::GetMeanFreePath(const G4Track& track,
G4double,
G4ForceCondition*)
{
const G4DynamicParticle* photon = track.GetDynamicParticle();
G4double energy = photon->GetKineticEnergy();
G4Material* material = track.GetMaterial();
// size_t materialIndex = material->GetIndex();
G4double meanFreePath = DBL_MAX;
// if (energy > highEnergyLimit)
// meanFreePath = meanFreePathTable->FindValue(highEnergyLimit,materialIndex);
// else if (energy < lowEnergyLimit) meanFreePath = DBL_MAX;
// else meanFreePath = meanFreePathTable->FindValue(energy,materialIndex);
G4double cross = shellCrossSectionHandler->ValueForMaterial(material,energy);
if(cross > 0.0) meanFreePath = 1.0/cross;
return meanFreePath;
}
/*
G4double G4LivermorePolarizedPhotoElectricModel::GetMeanFreePath(const G4Track& track,
G4double,
G4ForceCondition*)
{
const G4DynamicParticle* photon = track.GetDynamicParticle();
G4double energy = photon->GetKineticEnergy();
G4Material* material = track.GetMaterial();
// size_t materialIndex = material->GetIndex();
G4double meanFreePath = DBL_MAX;
// if (energy > highEnergyLimit)
// meanFreePath = meanFreePathTable->FindValue(highEnergyLimit,materialIndex);
// else if (energy < lowEnergyLimit) meanFreePath = DBL_MAX;
// else meanFreePath = meanFreePathTable->FindValue(energy,materialIndex);
G4double cross = shellCrossSectionHandler->ValueForMaterial(material,energy);
if(cross > 0.0) meanFreePath = 1.0/cross;
return meanFreePath;
}
*/
@@ -1,102 +0,0 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4ModifiedTsai
//
// Author: Andreia Trindade (andreia@lip.pt)
// Pedro Rodrigues (psilva@lip.pt)
// Luis Peralta (luis@lip.pt)
//
// Creation date: 21 March 2003
//
// Modifications:
// 21 Mar 2003 A. Trindade First implementation acording with new design
// 24 Mar 2003 & Fix in Tsai generator in order to prevent theta generation above pi
//
// Class Description:
//
// Concrete base class for Bremsstrahlung Angular Distribution Generation - Tsai Model
//
// Class Description: End
//
// -------------------------------------------------------------------
//
//
#include "G4ModifiedTsai.hh"
#include "Randomize.hh"
//
G4ModifiedTsai::G4ModifiedTsai(const G4String& name):G4VBremAngularDistribution(name)
{;}
//
G4ModifiedTsai::~G4ModifiedTsai()
{;}
//
G4double G4ModifiedTsai::PolarAngle(const G4double initial_energy,
const G4double, // final_energy
const G4int ) // Z
{
// Sample gamma angle (Z - axis along the parent particle).
// Universal distribution suggested by L. Urban (Geant3 manual (1993)
// Phys211) derived from Tsai distribution (Rev Mod Phys 49,421(1977))
G4double totalEnergy = initial_energy + electron_mass_c2;
const G4double a1 = 0.625, a2 = 3.*a1, d = 27.;
G4double u, theta = 0;
do{
u = - std::log(G4UniformRand()*G4UniformRand());
if (9./(9.+d) > G4UniformRand()) u /= a1;
else u /= a2;
theta = u*electron_mass_c2/totalEnergy;
}while(u > (totalEnergy*pi/electron_mass_c2));
return theta;
}
//
void G4ModifiedTsai::PrintGeneratorInformation() const
{
G4cout << "\n" << G4endl;
G4cout << "Bremsstrahlung Angular Generator is Modified Tsai" << G4endl;
G4cout << "Universal distribution suggested by L. Urban (Geant3 manual (1993) Phys211)" << G4endl;
G4cout << "Derived from Tsai distribution (Rev Mod Phys 49,421(1977)) \n" << G4endl;
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//$Id: G4OrlicLCrossSection.cc,v 1.6.2.2 2009/12/11 18:44:44 japost Exp $
// GEANT4 tag $Name: geant4-09-03 $
//$Id: G4OrlicLiCrossSection.cc,v 1.6 2010/11/22 18:32:00 mantero Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Haifa Ben Abdelouahed
//
@@ -33,6 +33,8 @@
// -----------
// 23 Apr 2008 H. Ben Abdelouahed 1st implementation
// 28 Apr 2008 MGP Major revision according to a design iteration
// 21 Apr 2009 ALF Some correction for compatibility to G4VShellCrossSection
// and changed name to G4OrlicLiCrossSection
//
// -------------------------------------------------------------------
// Class description:
@@ -42,16 +44,21 @@
#include "globals.hh"
#include "G4OrlicLCrossSection.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4OrlicLiCrossSection.hh"
#include "G4Proton.hh"
G4OrlicLCrossSection::G4OrlicLCrossSection()
{ }
G4OrlicLiCrossSection::G4OrlicLiCrossSection()
{
G4OrlicLCrossSection::~G4OrlicLCrossSection()
{ }
transitionManager = G4AtomicTransitionManager::Instance();
}
G4OrlicLiCrossSection::~G4OrlicLiCrossSection()
{
}
//this L-CrossSection calculation method is done according to
//I.ORLIC, C.H.SOW and S.M.TANG,International Journal of PIXE.Vol.4(1997) 217-230
@@ -59,11 +66,15 @@ G4OrlicLCrossSection::~G4OrlicLCrossSection()
//*****************************************************************************************************************************************
G4double G4OrlicLCrossSection::CalculateL1CrossSection(G4int zTarget, G4double energyIncident)
G4double G4OrlicLiCrossSection::CalculateL1CrossSection(G4int zTarget, G4double energyIncident)
{
G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
if ( (energyIncident < 0.1*MeV) || energyIncident > 10*MeV )
{return 0;}
G4double massIncident;
@@ -93,6 +104,10 @@ G4double G4OrlicLCrossSection::CalculateL1CrossSection(G4int zTarget, G4double e
if ( zTarget>=14 && zTarget<=40)
{
return 0;
/*
// parameters used for calculating total L cross section
a0=12.5081;
a1=0.2177;
a2=-0.3758;
@@ -102,7 +117,7 @@ G4double G4OrlicLCrossSection::CalculateL1CrossSection(G4int zTarget, G4double e
a6=0.;
a7=0.;
a8=0.;
a9=0.;
a9=0.; */
}
else
{
@@ -183,7 +198,7 @@ G4double G4OrlicLCrossSection::CalculateL1CrossSection(G4int zTarget, G4double e
}
else
{
G4cout << "ERREUR: L1 Cross-Section exist only for ZTarget between 14 and 92!!! " << G4endl;
G4cout << "ERROR: L1 Cross-Section exist only for ZTarget between 14 and 92!!! " << G4endl;
}
}
@@ -200,21 +215,29 @@ G4double analyticalFunction = a0 + (a1*x)+(a2*x*x)+(a3*std::pow(x,3))+(a4*std::p
G4double L1crossSection = std::exp(analyticalFunction)/(l1BindingEnergy*l1BindingEnergy);
return L1crossSection;
if (L1crossSection >= 0) {
return L1crossSection * barn;
}
else {return 0;}
}
//*****************************************************************************************************************************************
G4double G4OrlicLCrossSection::CalculateL2CrossSection(G4int zTarget, G4double energyIncident)
G4double G4OrlicLiCrossSection::CalculateL2CrossSection(G4int zTarget, G4double energyIncident)
{
G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
if ( (energyIncident < 0.1*MeV) || energyIncident > 10*MeV )
{return 0;}
G4double massIncident;
G4Proton* aProtone = G4Proton::Proton();
massIncident = aProtone->GetPDGMass();
@@ -301,7 +324,7 @@ G4double G4OrlicLCrossSection::CalculateL2CrossSection(G4int zTarget, G4double e
}
else
{
G4cout << "ERREUR: L2 Cross-Section exist only for ZTarget between 14 and 92!!! " << G4endl;
G4cout << "ERROR: L2 Cross-Section exist only for ZTarget between 14 and 92!!! " << G4endl;
}
}
@@ -317,21 +340,28 @@ G4double G4OrlicLCrossSection::CalculateL2CrossSection(G4int zTarget, G4double e
}
return L2crossSection;
if (L2crossSection >= 0) {
return L2crossSection * barn;
}
else {return 0;}
}
//*****************************************************************************************************************************************
G4double G4OrlicLCrossSection::CalculateL3CrossSection(G4int zTarget, G4double energyIncident)
G4double G4OrlicLiCrossSection::CalculateL3CrossSection(G4int zTarget, G4double energyIncident)
{
G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
if ( (energyIncident < 0.1*MeV) || energyIncident > 10*MeV )
{return 0;}
G4double massIncident;
G4Proton* aProtone = G4Proton::Proton();
massIncident = aProtone->GetPDGMass();
@@ -414,7 +444,7 @@ G4double G4OrlicLCrossSection::CalculateL3CrossSection(G4int zTarget, G4double e
}
else
{
G4cout << "ERREUR: L3 Cross-Section exist only for ZTarget between 14 and 92!!! " << G4endl;
G4cout << "ERROR: L3 Cross-Section exist only for ZTarget between 14 and 92!!! " << G4endl;
}
}
@@ -429,6 +459,10 @@ G4double G4OrlicLCrossSection::CalculateL3CrossSection(G4int zTarget, G4double e
L3crossSection = std::exp(analyticalFunction)/(l3BindingEnergy*l3BindingEnergy);
}
if (L3crossSection >= 0) {
return L3crossSection * barn;
}
else {return 0;}
return L3crossSection;
}
@@ -24,52 +24,103 @@
// ********************************************************************
//
//
// History:
// -----------
// 21 Apr 2008 H. Abdelohauwed - 1st implementation
// 29 Apr 2009 ALF Major Design Revision
//
// -------------------------------------------------------------------
// Class description:
// Low Energy Electromagnetic Physics, Cross section, p ionisation, K shell
// Further documentation available from http://www.ge.infn.it/geant4/lowE
// -------------------------------------------------------------------
#include "globals.hh"
#include "G4ios.hh"
#include <fstream>
#include <iomanip>
#include "G4CompositeEMDataSet.hh"
#include "G4ShellEMDataSet.hh"
//#include "G4CompositeEMDataSet.hh"
//#include "G4ShellEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4VEMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
//#include "G4VEMDataSet.hh"
//#include "G4VDataSetAlgorithm.hh"
#include "G4LogLogInterpolation.hh"
#include "G4PaulKCrossSection.hh"
#include "G4Proton.hh"
#include "G4Alpha.hh"
G4PaulKCrossSection::G4PaulKCrossSection()
{ }
{
G4PaulKCrossSection::~G4PaulKCrossSection()
{ }
G4double G4PaulKCrossSection::CalculateKCrossSection(G4int zTarget,G4int zIncident, G4double energyIncident)
{
G4String fileName;
interpolation = new G4LogLogInterpolation();
if (zIncident == 1)
{ fileName = "kcsPaul/kcs-";}
else
{
if (zIncident == 2)
{ fileName = "kacsPaul/kacs-";}
/*
G4String path = getenv("G4LEDATA");
if (!path)
G4Exception("G4paulKCrossSection::G4paulKCrossSection: G4LEDATA environment variable not set");
G4cout << path + "/kcsPaul/kcs-" << G4endl;
*/
for (G4int i=4; i<93; i++) {
protonDataSetMap[i] = new G4EMDataSet(i,interpolation);
protonDataSetMap[i]->LoadData("pixe/kpcsPaul/kcs-");
}
for (G4int i=6; i<93; i++) {
alphaDataSetMap[i] = new G4EMDataSet(i,interpolation);
alphaDataSetMap[i]->LoadData("pixe/kacsPaul/kacs-");
}
}
G4PaulKCrossSection::~G4PaulKCrossSection()
{
protonDataSetMap.clear();
alphaDataSetMap.clear();
}
G4double G4PaulKCrossSection::CalculateKCrossSection(G4int zTarget,G4double massIncident, G4double energyIncident)
{
G4VDataSetAlgorithm* interpolation = new G4LogLogInterpolation();
G4VEMDataSet* dataSet;
dataSet = new G4EMDataSet(zTarget,interpolation);
G4Proton* aProtone = G4Proton::Proton();
G4Alpha* aAlpha = G4Alpha::Alpha();
dataSet->LoadData(fileName);
G4double sigma = 0;
G4double sigma = dataSet->FindValue(energyIncident/MeV) / barn;
return sigma;
if (massIncident == aProtone->GetPDGMass() )
{
sigma = protonDataSetMap[zTarget]->FindValue(energyIncident/MeV);
}
else
{
if (massIncident == aAlpha->GetPDGMass())
{
sigma = alphaDataSetMap[zTarget]->FindValue(energyIncident/MeV);
}
else
{
G4cout << "we can treat only Proton or Alpha incident particles " << G4endl;
sigma = 0.;
}
}
// sigma is in internal units (mm^2)
return sigma;
}
@@ -0,0 +1,838 @@
//
// ********************************************************************
// * 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: G4Penelope08ComptonModel.cc,v 1.7 2010/07/28 07:09:16 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
//
// History:
// --------
// 15 Feb 2010 L Pandola Implementation
// 18 Mar 2010 L. Pandola Removed GetAtomsPerMolecule(), now demanded
// to G4PenelopeOscillatorManager
//
#include "G4Penelope08ComptonModel.hh"
#include "G4ParticleDefinition.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ProductionCutsTable.hh"
#include "G4DynamicParticle.hh"
#include "G4VEMDataSet.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsLogVector.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4AtomicShell.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4PenelopeOscillatorManager.hh"
#include "G4PenelopeOscillator.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4Penelope08ComptonModel::G4Penelope08ComptonModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false),oscManager(0)
{
fIntrinsicLowEnergyLimit = 100.0*eV;
fIntrinsicHighEnergyLimit = 100.0*GeV;
// SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
//
oscManager = G4PenelopeOscillatorManager::GetOscillatorManager();
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
//by default, the model will use atomic deexcitation
SetDeexcitationFlag(true);
ActivateAuger(false);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4Penelope08ComptonModel::~G4Penelope08ComptonModel()
{;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4Penelope08ComptonModel::Initialise(const G4ParticleDefinition*,
const G4DataVector&)
{
if (verboseLevel > 3)
G4cout << "Calling G4Penelope08ComptonModel::Initialise()" << G4endl;
if (verboseLevel > 0) {
G4cout << "Penelope Compton model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / keV << " keV - "
<< HighEnergyLimit() / GeV << " GeV"
<< G4endl;
}
if(isInitialised) return;
fParticleChange = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4Penelope08ComptonModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* p,
G4double energy,
G4double,
G4double)
{
// Penelope model to calculate the Compton scattering cross section:
// D. Brusa et al., Nucl. Instrum. Meth. A 379 (1996) 167
//
// The cross section for Compton scattering is calculated according to the Klein-Nishina
// formula for energy > 5 MeV.
// For E < 5 MeV it is used a parametrization for the differential cross-section dSigma/dOmega,
// which is integrated numerically in cos(theta), G4Penelope08ComptonModel::DifferentialCrossSection().
// The parametrization includes the J(p)
// distribution profiles for the atomic shells, that are tabulated from Hartree-Fock calculations
// from F. Biggs et al., At. Data Nucl. Data Tables 16 (1975) 201
//
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4Penelope08ComptonModel" << G4endl;
SetupForMaterial(p, material, energy);
//Retrieve the oscillator table for this material
G4PenelopeOscillatorTable* theTable = oscManager->GetOscillatorTableCompton(material);
G4double cs = 0;
if (energy < 5*MeV) //explicit calculation for E < 5 MeV
{
size_t numberOfOscillators = theTable->size();
for (size_t i=0;i<numberOfOscillators;i++)
{
G4PenelopeOscillator* theOsc = (*theTable)[i];
//sum contributions coming from each oscillator
cs += OscillatorTotalCrossSection(energy,theOsc);
}
}
else //use Klein-Nishina for E>5 MeV
cs = KleinNishinaCrossSection(energy,material);
//cross sections are in units of pi*classic_electr_radius^2
cs *= pi*classic_electr_radius*classic_electr_radius;
//Now, cs is the cross section *per molecule*, let's calculate the
//cross section per volume
G4double atomDensity = material->GetTotNbOfAtomsPerVolume();
G4double atPerMol = oscManager->GetAtomsPerMolecule(material);
if (verboseLevel > 3)
G4cout << "Material " << material->GetName() << " has " << atPerMol <<
"atoms per molecule" << G4endl;
G4double moleculeDensity = 0.;
if (atPerMol)
moleculeDensity = atomDensity/atPerMol;
G4double csvolume = cs*moleculeDensity;
if (verboseLevel > 2)
G4cout << "Compton mean free path at " << energy/keV << " keV for material " <<
material->GetName() << " = " << (1./csvolume)/mm << " mm" << G4endl;
return csvolume;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//This is a dummy method. Never inkoved by the tracking, it just issues
//a warning if one tries to get Cross Sections per Atom via the
//G4EmCalculator.
G4double G4Penelope08ComptonModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
G4double,
G4double,
G4double,
G4double,
G4double)
{
G4cout << "*** G4Penelope08ComptonModel -- WARNING ***" << G4endl;
G4cout << "Penelope Compton model does not calculate cross section _per atom_ " << G4endl;
G4cout << "so the result is always zero. For physics values, please invoke " << G4endl;
G4cout << "GetCrossSectionPerVolume() or GetMeanFreePath() via the G4EmCalculator" << G4endl;
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4Penelope08ComptonModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicGamma,
G4double,
G4double)
{
// Penelope model to sample the Compton scattering final state.
// D. Brusa et al., Nucl. Instrum. Meth. A 379 (1996) 167
// The model determines also the original shell from which the electron is expelled,
// in order to produce fluorescence de-excitation (from G4DeexcitationManager)
//
// The final state for Compton scattering is calculated according to the Klein-Nishina
// formula for energy > 5 MeV. In this case, the Doppler broadening is negligible and
// one can assume that the target electron is at rest.
// For E < 5 MeV it is used the parametrization for the differential cross-section dSigma/dOmega,
// to sample the scattering angle and the energy of the emerging electron, which is
// G4Penelope08ComptonModel::DifferentialCrossSection(). The rejection method is
// used to sample cos(theta). The efficiency increases monotonically with photon energy and is
// nearly independent on the Z; typical values are 35%, 80% and 95% for 1 keV, 1 MeV and 10 MeV,
// respectively.
// The parametrization includes the J(p) distribution profiles for the atomic shells, that are
// tabulated
// from Hartree-Fock calculations from F. Biggs et al., At. Data Nucl. Data Tables 16 (1975) 201.
// Doppler broadening is included.
//
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4Penelope08ComptonModel" << G4endl;
G4double photonEnergy0 = aDynamicGamma->GetKineticEnergy();
if (photonEnergy0 <= fIntrinsicLowEnergyLimit)
{
fParticleChange->ProposeTrackStatus(fStopAndKill);
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeLocalEnergyDeposit(photonEnergy0);
return ;
}
G4ParticleMomentum photonDirection0 = aDynamicGamma->GetMomentumDirection();
const G4Material* material = couple->GetMaterial();
G4PenelopeOscillatorTable* theTable = oscManager->GetOscillatorTableCompton(material);
const G4int nmax = 64;
G4double rn[nmax],pac[nmax];
G4double S=0.0;
G4double epsilon = 0.0;
G4double cosTheta = 1.0;
G4double hartreeFunc = 0.0;
G4double oscStren = 0.0;
size_t numberOfOscillators = theTable->size();
size_t targetOscillator = 0;
G4double ionEnergy = 0.0*eV;
G4double ek = photonEnergy0/electron_mass_c2;
G4double ek2 = 2.*ek+1.0;
G4double eks = ek*ek;
G4double ek1 = eks-ek2-1.0;
G4double taumin = 1.0/ek2;
G4double a1 = std::log(ek2);
G4double a2 = a1+2.0*ek*(1.0+ek)/(ek2*ek2);
G4double TST = 0;
G4double tau = 0.;
//If the incoming photon is above 5 MeV, the quicker approach based on the
//pure Klein-Nishina formula is used
if (photonEnergy0 > 5*MeV)
{
do{
do{
if ((a2*G4UniformRand()) < a1)
tau = std::pow(taumin,G4UniformRand());
else
tau = std::sqrt(1.0+G4UniformRand()*(taumin*taumin-1.0));
//rejection function
TST = (1.0+tau*(ek1+tau*(ek2+tau*eks)))/(eks*tau*(1.0+tau*tau));
}while (G4UniformRand()> TST);
epsilon=tau;
cosTheta = 1.0 - (1.0-tau)/(ek*tau);
//Target shell electrons
TST = oscManager->GetTotalZ(material)*G4UniformRand();
targetOscillator = numberOfOscillators-1; //last level
S=0.0;
G4bool levelFound = false;
for (size_t j=0;j<numberOfOscillators && !levelFound; j++)
{
S += (*theTable)[j]->GetOscillatorStrength();
if (S > TST)
{
targetOscillator = j;
levelFound = true;
}
}
//check whether the level is valid
ionEnergy = (*theTable)[targetOscillator]->GetIonisationEnergy();
}while((epsilon*photonEnergy0-photonEnergy0+ionEnergy) >0);
}
else //photonEnergy0 < 5 MeV
{
//Incoherent scattering function for theta=PI
G4double s0=0.0;
G4double pzomc=0.0;
G4double rni=0.0;
G4double aux=0.0;
for (size_t i=0;i<numberOfOscillators;i++)
{
ionEnergy = (*theTable)[i]->GetIonisationEnergy();
if (photonEnergy0 > ionEnergy)
{
G4double aux = photonEnergy0*(photonEnergy0-ionEnergy)*2.0;
hartreeFunc = (*theTable)[i]->GetHartreeFactor();
oscStren = (*theTable)[i]->GetOscillatorStrength();
pzomc = hartreeFunc*(aux-electron_mass_c2*ionEnergy)/
(electron_mass_c2*std::sqrt(2.0*aux+ionEnergy*ionEnergy));
if (pzomc > 0)
rni = 1.0-0.5*std::exp(0.5-(std::sqrt(0.5)+std::sqrt(2.0)*pzomc)*
(std::sqrt(0.5)+std::sqrt(2.0)*pzomc));
else
rni = 0.5*std::exp(0.5-(std::sqrt(0.5)-std::sqrt(2.0)*pzomc)*
(std::sqrt(0.5)-std::sqrt(2.0)*pzomc));
s0 += oscStren*rni;
}
}
//Sampling tau
G4double cdt1 = 0.;
do
{
if ((G4UniformRand()*a2) < a1)
tau = std::pow(taumin,G4UniformRand());
else
tau = std::sqrt(1.0+G4UniformRand()*(taumin*taumin-1.0));
cdt1 = (1.0-tau)/(ek*tau);
//Incoherent scattering function
S = 0.;
for (size_t i=0;i<numberOfOscillators;i++)
{
ionEnergy = (*theTable)[i]->GetIonisationEnergy();
if (photonEnergy0 > ionEnergy) //sum only on excitable levels
{
aux = photonEnergy0*(photonEnergy0-ionEnergy)*cdt1;
hartreeFunc = (*theTable)[i]->GetHartreeFactor();
oscStren = (*theTable)[i]->GetOscillatorStrength();
pzomc = hartreeFunc*(aux-electron_mass_c2*ionEnergy)/
(electron_mass_c2*std::sqrt(2.0*aux+ionEnergy*ionEnergy));
if (pzomc > 0)
rn[i] = 1.0-0.5*std::exp(0.5-(std::sqrt(0.5)+std::sqrt(2.0)*pzomc)*
(std::sqrt(0.5)+std::sqrt(2.0)*pzomc));
else
rn[i] = 0.5*std::exp(0.5-(std::sqrt(0.5)-std::sqrt(2.0)*pzomc)*
(std::sqrt(0.5)-std::sqrt(2.0)*pzomc));
S += oscStren*rn[i];
pac[i] = S;
}
else
pac[i] = S-1e-6;
}
//Rejection function
TST = S*(1.0+tau*(ek1+tau*(ek2+tau*eks)))/(eks*tau*(1.0+tau*tau));
}while ((G4UniformRand()*s0) > TST);
cosTheta = 1.0 - cdt1;
G4double fpzmax=0.0,fpz=0.0;
G4double A=0.0;
//Target electron shell
do
{
do
{
TST = S*G4UniformRand();
targetOscillator = numberOfOscillators-1; //last level
G4bool levelFound = false;
for (size_t i=0;i<numberOfOscillators && !levelFound;i++)
{
if (pac[i]>TST)
{
targetOscillator = i;
levelFound = true;
}
}
A = G4UniformRand()*rn[targetOscillator];
hartreeFunc = (*theTable)[targetOscillator]->GetHartreeFactor();
oscStren = (*theTable)[targetOscillator]->GetOscillatorStrength();
if (A < 0.5)
pzomc = (std::sqrt(0.5)-std::sqrt(0.5-std::log(2.0*A)))/
(std::sqrt(2.0)*hartreeFunc);
else
pzomc = (std::sqrt(0.5-std::log(2.0-2.0*A))-std::sqrt(0.5))/
(std::sqrt(2.0)*hartreeFunc);
} while (pzomc < -1);
// F(EP) rejection
G4double XQC = 1.0+tau*(tau-2.0*cosTheta);
G4double AF = std::sqrt(XQC)*(1.0+tau*(tau-cosTheta)/XQC);
if (AF > 0)
fpzmax = 1.0+AF*0.2;
else
fpzmax = 1.0-AF*0.2;
fpz = 1.0+AF*std::max(std::min(pzomc,0.2),-0.2);
}while ((fpzmax*G4UniformRand())>fpz);
//Energy of the scattered photon
G4double T = pzomc*pzomc;
G4double b1 = 1.0-T*tau*tau;
G4double b2 = 1.0-T*tau*cosTheta;
if (pzomc > 0.0)
epsilon = (tau/b1)*(b2+std::sqrt(std::abs(b2*b2-b1*(1.0-T))));
else
epsilon = (tau/b1)*(b2-std::sqrt(std::abs(b2*b2-b1*(1.0-T))));
} //energy < 5 MeV
//Ok, the kinematics has been calculated.
G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
G4double phi = twopi * G4UniformRand() ;
G4double dirx = sinTheta * std::cos(phi);
G4double diry = sinTheta * std::sin(phi);
G4double dirz = cosTheta ;
// Update G4VParticleChange for the scattered photon
G4ThreeVector photonDirection1(dirx,diry,dirz);
photonDirection1.rotateUz(photonDirection0);
fParticleChange->ProposeMomentumDirection(photonDirection1) ;
G4double photonEnergy1 = epsilon * photonEnergy0;
if (photonEnergy1 > 0.)
fParticleChange->SetProposedKineticEnergy(photonEnergy1) ;
else
{
fParticleChange->SetProposedKineticEnergy(0.) ;
fParticleChange->ProposeTrackStatus(fStopAndKill);
}
//Create scattered electron
G4double diffEnergy = photonEnergy0*(1-epsilon);
ionEnergy = (*theTable)[targetOscillator]->GetIonisationEnergy();
G4double Q2 =
photonEnergy0*photonEnergy0+photonEnergy1*(photonEnergy1-2.0*photonEnergy0*cosTheta);
G4double cosThetaE = 0.; //scattering angle for the electron
if (Q2 > 1.0e-12)
cosThetaE = (photonEnergy0-photonEnergy1*cosTheta)/std::sqrt(Q2);
else
cosThetaE = 1.0;
G4double sinThetaE = std::sqrt(1-cosThetaE*cosThetaE);
//Now, try to handle fluorescence
//Notice: merged levels are indicated with Z=0 and flag=30
G4int shFlag = (*theTable)[targetOscillator]->GetShellFlag();
G4int Z = (G4int) (*theTable)[targetOscillator]->GetParentZ();
//initialize here, then check photons created by Atomic-Deexcitation, and the final state e-
std::vector<G4DynamicParticle*>* photonVector=0;
const G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
G4double bindingEnergy = 0.*eV;
G4int shellId = 0;
//Real level
if (Z > 0 && shFlag<30)
{
const G4AtomicShell* shell = transitionManager->Shell(Z,shFlag-1);
bindingEnergy = shell->BindingEnergy();
shellId = shell->ShellId();
}
G4double ionEnergyInPenelopeDatabase = ionEnergy;
//protection against energy non-conservation
ionEnergy = std::max(bindingEnergy,ionEnergyInPenelopeDatabase);
//subtract the excitation energy. If not emitted by fluorescence
//the ionization energy is deposited as local energy deposition
G4double eKineticEnergy = diffEnergy - ionEnergy;
G4double localEnergyDeposit = ionEnergy;
G4double energyInFluorescence = 0.; //testing purposes only
if (eKineticEnergy < 0)
{
//It means that there was some problem/mismatch between the two databases.
//Try to make it work
//In this case available Energy (diffEnergy) < ionEnergy
//Full residual energy is deposited locally
localEnergyDeposit = diffEnergy;
eKineticEnergy = 0.0;
}
//the local energy deposit is what remains: part of this may be spent for fluorescence.
if(DeexcitationFlag() && Z > 5) {
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t index = couple->GetIndex();
G4double cutg = (*(theCoupleTable->GetEnergyCutsVector(0)))[index];
G4double cute = (*(theCoupleTable->GetEnergyCutsVector(1)))[index];
// Generation of fluorescence
// Data in EADL are available only for Z > 5
// Protection to avoid generating photons in the unphysical case of
// shell binding energy > photon energy
if (localEnergyDeposit > cutg || localEnergyDeposit > cute)
{
G4DynamicParticle* aPhoton;
deexcitationManager.SetCutForSecondaryPhotons(cutg);
deexcitationManager.SetCutForAugerElectrons(cute);
photonVector = deexcitationManager.GenerateParticles(Z,shellId);
if(photonVector)
{
size_t nPhotons = photonVector->size();
for (size_t k=0; k<nPhotons; k++)
{
aPhoton = (*photonVector)[k];
if (aPhoton)
{
G4double itsEnergy = aPhoton->GetKineticEnergy();
if (itsEnergy <= localEnergyDeposit)
{
localEnergyDeposit -= itsEnergy;
if (aPhoton->GetDefinition() == G4Gamma::Gamma())
energyInFluorescence += itsEnergy;;
fvect->push_back(aPhoton);
}
else
{
delete aPhoton;
(*photonVector)[k]=0;
}
}
}
delete photonVector;
}
}
}
//Always produce explicitely the electron
G4DynamicParticle* electron = 0;
G4double xEl = sinThetaE * std::cos(phi+pi);
G4double yEl = sinThetaE * std::sin(phi+pi);
G4double zEl = cosThetaE;
G4ThreeVector eDirection(xEl,yEl,zEl); //electron direction
eDirection.rotateUz(photonDirection0);
electron = new G4DynamicParticle (G4Electron::Electron(),
eDirection,eKineticEnergy) ;
fvect->push_back(electron);
if (localEnergyDeposit < 0)
{
G4cout << "WARNING-"
<< "G4Penelope08ComptonModel::SampleSecondaries - Negative energy deposit"
<< G4endl;
localEnergyDeposit=0.;
}
fParticleChange->ProposeLocalEnergyDeposit(localEnergyDeposit);
G4double electronEnergy = 0.;
if (verboseLevel > 1)
{
G4cout << "-----------------------------------------------------------" << G4endl;
G4cout << "Energy balance from G4Penelope08Compton" << G4endl;
G4cout << "Incoming photon energy: " << photonEnergy0/keV << " keV" << G4endl;
G4cout << "-----------------------------------------------------------" << G4endl;
G4cout << "Scattered photon: " << photonEnergy1/keV << " keV" << G4endl;
if (electron)
electronEnergy = eKineticEnergy;
G4cout << "Scattered electron " << electronEnergy/keV << " keV" << G4endl;
G4cout << "Fluorescence: " << energyInFluorescence/keV << " keV" << G4endl;
G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl;
G4cout << "Total final state: " << (photonEnergy1+electronEnergy+energyInFluorescence+
localEnergyDeposit)/keV <<
" keV" << G4endl;
G4cout << "-----------------------------------------------------------" << G4endl;
}
if (verboseLevel > 0)
{
G4double energyDiff = std::fabs(photonEnergy1+
electronEnergy+energyInFluorescence+
localEnergyDeposit-photonEnergy0);
if (energyDiff > 0.05*keV)
G4cout << "Warning from G4Penelope08Compton: problem with energy conservation: " <<
(photonEnergy1+electronEnergy+energyInFluorescence+localEnergyDeposit)/keV <<
" keV (final) vs. " <<
photonEnergy0/keV << " keV (initial)" << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4Penelope08ComptonModel::DifferentialCrossSection(G4double cosTheta,G4double energy,
G4PenelopeOscillator* osc)
{
//
// Penelope model. Single differential cross section *per electron*
// for photon Compton scattering by
// electrons in the given atomic oscillator, differential in the direction of the
// scattering photon. This is in units of pi*classic_electr_radius**2
//
// D. Brusa et al., Nucl. Instrum. Meth. A 379 (1996) 167
// The parametrization includes the J(p) distribution profiles for the atomic shells,
// that are tabulated from Hartree-Fock calculations
// from F. Biggs et al., At. Data Nucl. Data Tables 16 (1975) 201
//
G4double ionEnergy = osc->GetIonisationEnergy();
G4double harFunc = osc->GetHartreeFactor();
const G4double k2 = std::sqrt(2.);
const G4double k1 = 1./k2;
if (energy < ionEnergy)
return 0;
//energy of the Compton line
G4double cdt1 = 1.0-cosTheta;
G4double EOEC = 1.0+(energy/electron_mass_c2)*cdt1;
G4double ECOE = 1.0/EOEC;
//Incoherent scattering function (analytical profile)
G4double aux = energy*(energy-ionEnergy)*cdt1;
G4double Pzimax =
(aux - electron_mass_c2*ionEnergy)/(electron_mass_c2*std::sqrt(2*aux+ionEnergy*ionEnergy));
G4double sia = 0.0;
G4double x = harFunc*Pzimax;
if (x > 0)
sia = 1.0-0.5*std::exp(0.5-(k1+k2*x)*(k1+k2*x));
else
sia = 0.5*std::exp(0.5-(k1-k2*x)*(k1-k2*x));
//1st order correction, integral of Pz times the Compton profile.
//Calculated approximately using a free-electron gas profile
G4double pf = 3.0/(4.0*harFunc);
if (std::fabs(Pzimax) < pf)
{
G4double QCOE2 = 1.0+ECOE*ECOE-2.0*ECOE*cosTheta;
G4double p2 = Pzimax*Pzimax;
G4double dspz = std::sqrt(QCOE2)*
(1.0+ECOE*(ECOE-cosTheta)/QCOE2)*harFunc
*0.25*(2*p2-(p2*p2)/(pf*pf)-(pf*pf));
sia += std::max(dspz,-1.0*sia);
}
G4double XKN = EOEC+ECOE-1.0+cosTheta*cosTheta;
//Differential cross section (per electron, in units of pi*classic_electr_radius**2)
G4double diffCS = ECOE*ECOE*XKN*sia;
return diffCS;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4Penelope08ComptonModel::ActivateAuger(G4bool augerbool)
{
if (!DeexcitationFlag() && augerbool)
{
G4cout << "WARNING - G4Penelope08ComptonModel" << G4endl;
G4cout << "The use of the Atomic Deexcitation Manager is set to false " << G4endl;
G4cout << "Therefore, Auger electrons will be not generated anyway" << G4endl;
}
deexcitationManager.ActivateAugerElectronProduction(augerbool);
if (verboseLevel > 1)
G4cout << "Auger production set to " << augerbool << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4Penelope08ComptonModel::OscillatorTotalCrossSection(G4double energy,G4PenelopeOscillator* osc)
{
//Total cross section (integrated) for the given oscillator in units of
//pi*classic_electr_radius^2
//Integrate differential cross section for each oscillator
G4double stre = osc->GetOscillatorStrength();
// here one uses the using the 20-point
// Gauss quadrature method with an adaptive bipartition scheme
const G4int npoints=10;
const G4int ncallsmax=20000;
const G4int nst=256;
static G4double Abscissas[10] = {7.652651133497334e-02,2.2778585114164508e-01,3.7370608871541956e-01,
5.1086700195082710e-01,6.3605368072651503e-01,7.4633190646015079e-01,
8.3911697182221882e-01,9.1223442825132591e-01,9.6397192727791379e-01,
9.9312859918509492e-01};
static G4double Weights[10] = {1.5275338713072585e-01,1.4917298647260375e-01,1.4209610931838205e-01,
1.3168863844917663e-01,1.1819453196151842e-01,1.0193011981724044e-01,
8.3276741576704749e-02,6.2672048334109064e-02,4.0601429800386941e-02,
1.7614007139152118e-02};
G4double MaxError = 1e-5;
//Error control
G4double Ctol = std::min(std::max(MaxError,1e-13),1e-02);
G4double Ptol = 0.01*Ctol;
G4double Err=1e35;
//Gauss integration from -1 to 1
G4double LowPoint = -1.0;
G4double HighPoint = 1.0;
G4double h=HighPoint-LowPoint;
G4double sumga=0.0;
G4double a=0.5*(HighPoint-LowPoint);
G4double b=0.5*(HighPoint+LowPoint);
G4double c=a*Abscissas[0];
G4double d= Weights[0]*
(DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
for (G4int i=2;i<=npoints;i++)
{
c=a*Abscissas[i-1];
d += Weights[i-1]*
(DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
}
G4int icall = 2*npoints;
G4int LH=1;
G4double S[nst],x[nst],sn[nst],xrn[nst];
S[0]=d*a;
x[0]=LowPoint;
G4bool loopAgain = true;
//Adaptive bipartition scheme
do{
G4double h0=h;
h=0.5*h; //bipartition
G4double sumr=0;
G4int LHN=0;
G4double si,xa,xb,xc;
for (G4int i=1;i<=LH;i++){
si=S[i-1];
xa=x[i-1];
xb=xa+h;
xc=xa+h0;
a=0.5*(xb-xa);
b=0.5*(xb+xa);
c=a*Abscissas[0];
G4double d = Weights[0]*
(DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
for (G4int j=1;j<npoints;j++)
{
c=a*Abscissas[j];
d += Weights[j]*
(DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
}
G4double s1=d*a;
a=0.5*(xc-xb);
b=0.5*(xc+xb);
c=a*Abscissas[0];
d=Weights[0]*
(DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
for (G4int j=1;j<npoints;j++)
{
c=a*Abscissas[j];
d += Weights[j]*
(DifferentialCrossSection(b+c,energy,osc)+DifferentialCrossSection(b-c,energy,osc));
}
G4double s2=d*a;
icall=icall+4*npoints;
G4double s12=s1+s2;
if (std::abs(s12-si)<std::max(Ptol*std::abs(s12),1e-35))
sumga += s12;
else
{
sumr += s12;
LHN += 2;
sn[LHN-1]=s2;
xrn[LHN-1]=xb;
sn[LHN-2]=s1;
xrn[LHN-2]=xa;
}
if (icall>ncallsmax || LHN>nst)
{
G4cout << "G4Penelope08ComptonModel: " << G4endl;
G4cout << "LowPoint: " << LowPoint << ", High Point: " << HighPoint << G4endl;
G4cout << "Tolerance: " << MaxError << G4endl;
G4cout << "Calls: " << icall << ", Integral: " << sumga << ", Error: " << Err << G4endl;
G4cout << "Number of open subintervals: " << LHN << G4endl;
G4cout << "WARNING: the required accuracy has not been attained" << G4endl;
loopAgain = false;
}
}
Err=std::abs(sumr)/std::max(std::abs(sumr+sumga),1e-35);
if (Err < Ctol || LHN == 0)
loopAgain = false; //end of cycle
LH=LHN;
for (G4int i=0;i<LH;i++)
{
S[i]=sn[i];
x[i]=xrn[i];
}
}while(Ctol < 1.0 && loopAgain);
G4double xs = stre*sumga;
return xs;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4Penelope08ComptonModel::KleinNishinaCrossSection(G4double energy,
const G4Material* material)
{
// use Klein-Nishina formula
// total cross section in units of pi*classic_electr_radius^2
G4double cs = 0;
G4double ek =energy/electron_mass_c2;
G4double eks = ek*ek;
G4double ek2 = 1.0+ek+ek;
G4double ek1 = eks-ek2-1.0;
G4double t0 = 1.0/ek2;
G4double csl = 0.5*eks*t0*t0+ek2*t0+ek1*std::log(t0)-(1.0/t0);
G4PenelopeOscillatorTable* theTable = oscManager->GetOscillatorTableCompton(material);
for (size_t i=0;i<theTable->size();i++)
{
G4PenelopeOscillator* theOsc = (*theTable)[i];
G4double ionEnergy = theOsc->GetIonisationEnergy();
G4double tau=(energy-ionEnergy)/energy;
if (tau > t0)
{
G4double csu = 0.5*eks*tau*tau+ek2*tau+ek1*std::log(tau)-(1.0/tau);
G4double stre = theOsc->GetOscillatorStrength();
cs += stre*(csu-csl);
}
}
cs /= (ek*eks);
return cs;
}
@@ -0,0 +1,614 @@
//
// ********************************************************************
// * 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: G4Penelope08GammaConversionModel.cc,v 1.4 2010/07/28 07:09:16 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
//
// History:
// --------
// 13 Jan 2010 L Pandola First implementation (updated to Penelope08)
//
#include "G4Penelope08GammaConversionModel.hh"
#include "G4ParticleDefinition.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ProductionCutsTable.hh"
#include "G4DynamicParticle.hh"
#include "G4Element.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4PhysicsFreeVector.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4Penelope08GammaConversionModel::G4Penelope08GammaConversionModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),logAtomicCrossSection(0),fEffectiveCharge(0),fMaterialInvScreeningRadius(0),
fScreeningFunction(0),isInitialised(false)
{
fIntrinsicLowEnergyLimit = 2.0*electron_mass_c2;
fIntrinsicHighEnergyLimit = 100.0*GeV;
fSmallEnergy = 1.1*MeV;
InitializeScreeningRadii();
// SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
//
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4Penelope08GammaConversionModel::~G4Penelope08GammaConversionModel()
{
std::map <const G4int,G4PhysicsFreeVector*>::iterator i;
if (logAtomicCrossSection)
{
for (i=logAtomicCrossSection->begin();i != logAtomicCrossSection->end();i++)
if (i->second) delete i->second;
delete logAtomicCrossSection;
}
if (fEffectiveCharge)
delete fEffectiveCharge;
if (fMaterialInvScreeningRadius)
delete fMaterialInvScreeningRadius;
if (fScreeningFunction)
delete fScreeningFunction;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4Penelope08GammaConversionModel::Initialise(const G4ParticleDefinition*,
const G4DataVector&)
{
if (verboseLevel > 3)
G4cout << "Calling G4Penelope08GammaConversionModel::Initialise()" << G4endl;
// logAtomicCrossSection is created only once, since it is never cleared
if (!logAtomicCrossSection)
logAtomicCrossSection = new std::map<const G4int,G4PhysicsFreeVector*>;
//delete old material data...
if (fEffectiveCharge)
{
delete fEffectiveCharge;
fEffectiveCharge = 0;
}
if (fMaterialInvScreeningRadius)
{
delete fMaterialInvScreeningRadius;
fMaterialInvScreeningRadius = 0;
}
if (fScreeningFunction)
{
delete fScreeningFunction;
fScreeningFunction = 0;
}
//and create new ones
fEffectiveCharge = new std::map<const G4Material*,G4double>;
fMaterialInvScreeningRadius = new std::map<const G4Material*,G4double>;
fScreeningFunction = new std::map<const G4Material*,std::pair<G4double,G4double> >;
if (verboseLevel > 0) {
G4cout << "Penelope Gamma Conversion model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / MeV << " MeV - "
<< HighEnergyLimit() / GeV << " GeV"
<< G4endl;
}
if(isInitialised) return;
fParticleChange = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4Penelope08GammaConversionModel::ComputeCrossSectionPerAtom(
const G4ParticleDefinition*,
G4double energy,
G4double Z, G4double,
G4double, G4double)
{
//
// Penelope model.
// Cross section (including triplet production) read from database and managed
// through the G4CrossSectionHandler utility. Cross section data are from
// M.J. Berger and J.H. Hubbel (XCOM), Report NBSIR 887-3598
//
if (energy < fIntrinsicLowEnergyLimit)
return 0;
G4int iZ = (G4int) Z;
//read data files
if (!logAtomicCrossSection->count(iZ))
ReadDataFile(iZ);
//now it should be ok
if (!logAtomicCrossSection->count(iZ))
{
G4cout << "Problem in G4Penelope08GammaConversion::ComputeCrossSectionPerAtom"
<< G4endl;
G4Exception();
}
G4double cs = 0;
G4double logene = std::log(energy);
G4PhysicsFreeVector* theVec = logAtomicCrossSection->find(iZ)->second;
G4double logXS = theVec->Value(logene);
cs = std::exp(logXS);
if (verboseLevel > 2)
G4cout << "Gamma conversion cross section at " << energy/MeV << " MeV for Z=" << Z <<
" = " << cs/barn << " barn" << G4endl;
return cs;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void
G4Penelope08GammaConversionModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicGamma,
G4double,
G4double)
{
//
// Penelope model.
// Final state is sampled according to the Bethe-Heitler model with Coulomb
// corrections, according to the semi-empirical model of
// J. Baro' et al., Radiat. Phys. Chem. 44 (1994) 531.
//
// The model uses the high energy Coulomb correction from
// H. Davies et al., Phys. Rev. 93 (1954) 788
// and atomic screening radii tabulated from
// J.H. Hubbel et al., J. Phys. Chem. Ref. Data 9 (1980) 1023
// for Z= 1 to 92.
//
if (verboseLevel > 3)
G4cout << "Calling SamplingSecondaries() of G4Penelope08GammaConversionModel" << G4endl;
G4double photonEnergy = aDynamicGamma->GetKineticEnergy();
// Always kill primary
fParticleChange->ProposeTrackStatus(fStopAndKill);
fParticleChange->SetProposedKineticEnergy(0.);
if (photonEnergy <= fIntrinsicLowEnergyLimit)
{
fParticleChange->ProposeLocalEnergyDeposit(photonEnergy);
return ;
}
G4ParticleMomentum photonDirection = aDynamicGamma->GetMomentumDirection();
const G4Material* mat = couple->GetMaterial();
//check if material data are available
if (!fEffectiveCharge->count(mat))
InitializeScreeningFunctions(mat);
if (!fEffectiveCharge->count(mat))
{
G4cout << "Problem in G4Penelope08GammaConversion::SampleSecondaries()" << G4endl;
G4cout << "Unable to allocate the EffectiveCharge data" << G4endl;
G4Exception();
}
// eps is the fraction of the photon energy assigned to e- (including rest mass)
G4double eps = 0;
G4double eki = electron_mass_c2/photonEnergy;
//Do it fast for photon energy < 1.1 MeV (close to threshold)
if (photonEnergy < fSmallEnergy)
eps = eki + (1.0-2.0*eki)*G4UniformRand();
else
{
//Complete calculation
G4double effC = fEffectiveCharge->find(mat)->second;
G4double alz = effC*fine_structure_const;
G4double T = std::sqrt(2.0*eki);
G4double F00=(-1.774-1.210e1*alz+1.118e1*alz*alz)*T
+(8.523+7.326e1*alz-4.441e1*alz*alz)*T*T
-(1.352e1+1.211e2*alz-9.641e1*alz*alz)*T*T*T
+(8.946+6.205e1*alz-6.341e1*alz*alz)*T*T*T*T;
G4double F0b = fScreeningFunction->find(mat)->second.second;
G4double g0 = F0b + F00;
G4double invRad = fMaterialInvScreeningRadius->find(mat)->second;
G4double bmin = 4.0*eki/invRad;
std::pair<G4double,G4double> scree = GetScreeningFunctions(bmin);
G4double g1 = scree.first;
G4double g2 = scree.second;
G4double g1min = g1+g0;
G4double g2min = g2+g0;
G4double xr = 0.5-eki;
G4double a1 = 2.*g1min*xr*xr/3.;
G4double p1 = a1/(a1+g2min);
G4bool loopAgain = false;
//Random sampling of eps
do{
loopAgain = false;
if (G4UniformRand() <= p1)
{
G4double ru2m1 = 2.0*G4UniformRand()-1.0;
if (ru2m1 < 0)
eps = 0.5-xr*std::pow(std::abs(ru2m1),1./3.);
else
eps = 0.5+xr*std::pow(ru2m1,1./3.);
G4double B = eki/(invRad*eps*(1.0-eps));
scree = GetScreeningFunctions(B);
g1 = scree.first;
g1 = std::max(g1+g0,0.);
if (G4UniformRand()*g1min > g1)
loopAgain = true;
}
else
{
eps = eki+2.0*xr*G4UniformRand();
G4double B = eki/(invRad*eps*(1.0-eps));
scree = GetScreeningFunctions(B);
g2 = scree.second;
g2 = std::max(g2+g0,0.);
if (G4UniformRand()*g2min > g2)
loopAgain = true;
}
}while(loopAgain);
}
if (verboseLevel > 4)
G4cout << "Sampled eps = " << eps << G4endl;
G4double electronTotEnergy = eps*photonEnergy;
G4double positronTotEnergy = (1.0-eps)*photonEnergy;
// Scattered electron (positron) angles. ( Z - axis along the parent photon)
//electron kinematics
G4double electronKineEnergy = std::max(0.,electronTotEnergy - electron_mass_c2) ;
G4double costheta_el = G4UniformRand()*2.0-1.0;
G4double kk = std::sqrt(electronKineEnergy*(electronKineEnergy+2.*electron_mass_c2));
costheta_el = (costheta_el*electronTotEnergy+kk)/(electronTotEnergy+costheta_el*kk);
G4double phi_el = twopi * G4UniformRand() ;
G4double dirX_el = std::sqrt(1.-costheta_el*costheta_el) * std::cos(phi_el);
G4double dirY_el = std::sqrt(1.-costheta_el*costheta_el) * std::sin(phi_el);
G4double dirZ_el = costheta_el;
//positron kinematics
G4double positronKineEnergy = std::max(0.,positronTotEnergy - electron_mass_c2) ;
G4double costheta_po = G4UniformRand()*2.0-1.0;
kk = std::sqrt(positronKineEnergy*(positronKineEnergy+2.*electron_mass_c2));
costheta_po = (costheta_po*positronTotEnergy+kk)/(positronTotEnergy+costheta_po*kk);
G4double phi_po = twopi * G4UniformRand() ;
G4double dirX_po = std::sqrt(1.-costheta_po*costheta_po) * std::cos(phi_po);
G4double dirY_po = std::sqrt(1.-costheta_po*costheta_po) * std::sin(phi_po);
G4double dirZ_po = costheta_po;
// Kinematics of the created pair:
// the electron and positron are assumed to have a symetric angular
// distribution with respect to the Z axis along the parent photon
G4double localEnergyDeposit = 0. ;
if (electronKineEnergy > 0.0)
{
G4ThreeVector electronDirection ( dirX_el, dirY_el, dirZ_el);
electronDirection.rotateUz(photonDirection);
G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),
electronDirection,
electronKineEnergy);
fvect->push_back(electron);
}
else
{
localEnergyDeposit += electronKineEnergy;
electronKineEnergy = 0;
}
//Generate the positron. Real particle in any case, because it will annihilate. If below
//threshold, produce it at rest
if (positronKineEnergy < 0.0)
{
localEnergyDeposit += positronKineEnergy;
positronKineEnergy = 0; //produce it at rest
}
G4ThreeVector positronDirection(dirX_po,dirY_po,dirZ_po);
positronDirection.rotateUz(photonDirection);
G4DynamicParticle* positron = new G4DynamicParticle(G4Positron::Positron(),
positronDirection, positronKineEnergy);
fvect->push_back(positron);
//Add rest of energy to the local energy deposit
fParticleChange->ProposeLocalEnergyDeposit(localEnergyDeposit);
if (verboseLevel > 1)
{
G4cout << "-----------------------------------------------------------" << G4endl;
G4cout << "Energy balance from G4Penelope08GammaConversion" << G4endl;
G4cout << "Incoming photon energy: " << photonEnergy/keV << " keV" << G4endl;
G4cout << "-----------------------------------------------------------" << G4endl;
if (electronKineEnergy)
G4cout << "Electron (explicitely produced) " << electronKineEnergy/keV << " keV"
<< G4endl;
if (positronKineEnergy)
G4cout << "Positron (not at rest) " << positronKineEnergy/keV << " keV" << G4endl;
G4cout << "Rest masses of e+/- " << 2.0*electron_mass_c2/keV << " keV" << G4endl;
if (localEnergyDeposit)
G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl;
G4cout << "Total final state: " << (electronKineEnergy+positronKineEnergy+
localEnergyDeposit+2.0*electron_mass_c2)/keV <<
" keV" << G4endl;
G4cout << "-----------------------------------------------------------" << G4endl;
}
if (verboseLevel > 0)
{
G4double energyDiff = std::fabs(electronKineEnergy+positronKineEnergy+
localEnergyDeposit+2.0*electron_mass_c2-photonEnergy);
if (energyDiff > 0.05*keV)
G4cout << "Warning from G4Penelope08GammaConversion: problem with energy conservation: "
<< (electronKineEnergy+positronKineEnergy+
localEnergyDeposit+2.0*electron_mass_c2)/keV
<< " keV (final) vs. " << photonEnergy/keV << " keV (initial)" << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4Penelope08GammaConversionModel::ReadDataFile(const G4int Z)
{
if (verboseLevel > 2)
{
G4cout << "G4Penelope08GammaConversionModel::ReadDataFile()" << G4endl;
G4cout << "Going to read Gamma Conversion data files for Z=" << Z << G4endl;
}
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep =
"G4Penelope08GammaConversionModel - G4LEDATA environment variable not set!";
G4Exception(excep);
}
/*
Read the cross section file
*/
std::ostringstream ost;
if (Z>9)
ost << path << "/penelope/pairproduction/pdgpp" << Z << ".p08";
else
ost << path << "/penelope/pairproduction/pdgpp0" << Z << ".p08";
std::ifstream file(ost.str().c_str());
if (!file.is_open())
{
G4String excep = "G4Penelope08GammaConversionModel - data file " +
G4String(ost.str()) + " not found!";
G4Exception(excep);
}
//I have to know in advance how many points are in the data list
//to initialize the G4PhysicsFreeVector()
size_t ndata=0;
G4String line;
while( getline(file, line) )
ndata++;
ndata -= 1; //remove one header line
//G4cout << "Found: " << ndata << " lines" << G4endl;
file.clear();
file.close();
file.open(ost.str().c_str());
G4int readZ =0;
file >> readZ;
if (verboseLevel > 3)
G4cout << "Element Z=" << Z << G4endl;
//check the right file is opened.
if (readZ != Z)
{
G4cout << "G4Penelope08GammaConversionModel::ReadDataFile()" << G4endl;
G4cout << "Corrupted data file for Z=" << Z << G4endl;
G4Exception();
}
G4PhysicsFreeVector* theVec = new G4PhysicsFreeVector(ndata);
G4double ene=0,xs=0;
for (size_t i=0;i<ndata;i++)
{
file >> ene >> xs;
//dimensional quantities
ene *= eV;
xs *= barn;
if (xs < 1e-40*cm2) //protection against log(0)
xs = 1e-40*cm2;
theVec->PutValue(i,std::log(ene),std::log(xs));
}
file.close();
if (!logAtomicCrossSection)
{
G4cout << "G4Penelope08RayleighModel::ReadDataFile()" << G4endl;
G4cout << "Problem with allocation of logAtomicCrossSection data table " << G4endl;
G4Exception();
}
logAtomicCrossSection->insert(std::make_pair(Z,theVec));
return;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4Penelope08GammaConversionModel::InitializeScreeningRadii()
{
G4double temp[99] = {1.2281e+02,7.3167e+01,6.9228e+01,6.7301e+01,6.4696e+01,
6.1228e+01,5.7524e+01,5.4033e+01,5.0787e+01,4.7851e+01,4.6373e+01,
4.5401e+01,4.4503e+01,4.3815e+01,4.3074e+01,4.2321e+01,4.1586e+01,
4.0953e+01,4.0524e+01,4.0256e+01,3.9756e+01,3.9144e+01,3.8462e+01,
3.7778e+01,3.7174e+01,3.6663e+01,3.5986e+01,3.5317e+01,3.4688e+01,
3.4197e+01,3.3786e+01,3.3422e+01,3.3068e+01,3.2740e+01,3.2438e+01,
3.2143e+01,3.1884e+01,3.1622e+01,3.1438e+01,3.1142e+01,3.0950e+01,
3.0758e+01,3.0561e+01,3.0285e+01,3.0097e+01,2.9832e+01,2.9581e+01,
2.9411e+01,2.9247e+01,2.9085e+01,2.8930e+01,2.8721e+01,2.8580e+01,
2.8442e+01,2.8312e+01,2.8139e+01,2.7973e+01,2.7819e+01,2.7675e+01,
2.7496e+01,2.7285e+01,2.7093e+01,2.6911e+01,2.6705e+01,2.6516e+01,
2.6304e+01,2.6108e+01,2.5929e+01,2.5730e+01,2.5577e+01,2.5403e+01,
2.5245e+01,2.5100e+01,2.4941e+01,2.4790e+01,2.4655e+01,2.4506e+01,
2.4391e+01,2.4262e+01,2.4145e+01,2.4039e+01,2.3922e+01,2.3813e+01,
2.3712e+01,2.3621e+01,2.3523e+01,2.3430e+01,2.3331e+01,2.3238e+01,
2.3139e+01,2.3048e+01,2.2967e+01,2.2833e+01,2.2694e+01,2.2624e+01,
2.2545e+01,2.2446e+01,2.2358e+01,2.2264e+01};
//copy temporary vector in class data member
for (G4int i=0;i<99;i++)
fAtomicScreeningRadius[i] = temp[i];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4Penelope08GammaConversionModel::InitializeScreeningFunctions(const G4Material* material)
{
// This is subroutine GPPa0 of Penelope
//
// 1) calculate the effective Z for the purpose
//
G4double zeff = 0;
G4int intZ = 0;
G4int nElements = material->GetNumberOfElements();
const G4ElementVector* elementVector = material->GetElementVector();
//avoid calculations if only one building element!
if (nElements == 1)
{
zeff = (*elementVector)[0]->GetZ();
intZ = (G4int) zeff;
}
else // many elements...let's do the calculation
{
const G4double* fractionVector = material->GetVecNbOfAtomsPerVolume();
G4double atot = 0;
for (G4int i=0;i<nElements;i++)
{
G4double Zelement = (*elementVector)[i]->GetZ();
G4double Aelement = (*elementVector)[i]->GetA();
atot += Aelement*fractionVector[i];
zeff += Zelement*Aelement*fractionVector[i]; //average with the number of nuclei
}
atot /= material->GetTotNbOfAtomsPerVolume();
zeff /= (material->GetTotNbOfAtomsPerVolume()*atot);
intZ = (G4int) (zeff+0.25);
if (intZ <= 0)
intZ = 1;
if (intZ > 99)
intZ = 99;
}
if (fEffectiveCharge)
fEffectiveCharge->insert(std::make_pair(material,zeff));
//
// 2) Calculate Coulomb Correction
//
G4double alz = fine_structure_const*zeff;
G4double alzSquared = alz*alz;
G4double fc = alzSquared*(0.202059-alzSquared*
(0.03693-alzSquared*
(0.00835-alzSquared*(0.00201-alzSquared*
(0.00049-alzSquared*
(0.00012-alzSquared*0.00003)))))
+1.0/(alzSquared+1.0));
//
// 3) Screening functions and low-energy corrections
//
G4double matRadius = 2.0/ fAtomicScreeningRadius[intZ-1];
if (fMaterialInvScreeningRadius)
fMaterialInvScreeningRadius->insert(std::make_pair(material,matRadius));
std::pair<G4double,G4double> myPair(0,0);
G4double f0a = 4.0*std::log(fAtomicScreeningRadius[intZ-1]);
G4double f0b = f0a - 4.0*fc;
myPair.first = f0a;
myPair.second = f0b;
if (fScreeningFunction)
fScreeningFunction->insert(std::make_pair(material,myPair));
if (verboseLevel > 2)
{
G4cout << "Average Z for material " << material->GetName() << " = " <<
zeff << G4endl;
G4cout << "Effective radius for material " << material->GetName() << " = " <<
fAtomicScreeningRadius[intZ-1] << " m_e*c/hbar --> BCB = " <<
matRadius << G4endl;
G4cout << "Screening parameters F0 for material " << material->GetName() << " = " <<
f0a << "," << f0b << G4endl;
}
return;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::pair<G4double,G4double>
G4Penelope08GammaConversionModel::GetScreeningFunctions(G4double B)
{
// This is subroutine SCHIFF of Penelope
//
// Screening Functions F1(B) and F2(B) in the Bethe-Heitler differential cross
// section for pair production
//
std::pair<G4double,G4double> result(0.,0.);
G4double BSquared = B*B;
G4double f1 = 2.0-2.0*std::log(1.0+BSquared);
G4double f2 = f1 - 6.66666666e-1; // (-2/3)
if (B < 1.0e-10)
f1 = f1-twopi*B;
else
{
G4double a0 = 4.0*B*std::atan(1./B);
f1 = f1 - a0;
f2 += 2.0*BSquared*(4.0-a0-3.0*std::log((1.0+BSquared)/BSquared));
}
G4double g1 = 0.5*(3.0*f1-f2);
G4double g2 = 0.25*(3.0*f1+f2);
result.first = g1;
result.second = g2;
return result;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,674 @@
//
// ********************************************************************
// * 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: G4Penelope08PhotoElectricModel.cc,v 1.5 2010/07/28 07:09:16 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
//
// History:
// --------
// 08 Jan 2010 L Pandola First implementation
#include "G4Penelope08PhotoElectricModel.hh"
#include "G4ParticleDefinition.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ProductionCutsTable.hh"
#include "G4DynamicParticle.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsFreeVector.hh"
#include "G4ElementTable.hh"
#include "G4Element.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4AtomicShell.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4Penelope08PhotoElectricModel::G4Penelope08PhotoElectricModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false),logAtomicShellXS(0)
{
fIntrinsicLowEnergyLimit = 100.0*eV;
fIntrinsicHighEnergyLimit = 100.0*GeV;
// SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
//
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
//by default the model will inkove the atomic deexcitation
SetDeexcitationFlag(true);
ActivateAuger(false);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4Penelope08PhotoElectricModel::~G4Penelope08PhotoElectricModel()
{
std::map <const G4int,G4PhysicsTable*>::iterator i;
if (logAtomicShellXS)
{
for (i=logAtomicShellXS->begin();i != logAtomicShellXS->end();i++)
{
G4PhysicsTable* tab = i->second;
tab->clearAndDestroy();
delete tab;
}
}
delete logAtomicShellXS;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4Penelope08PhotoElectricModel::Initialise(const G4ParticleDefinition* particle,
const G4DataVector& cuts)
{
if (verboseLevel > 3)
G4cout << "Calling G4Penelope08PhotoElectricModel::Initialise()" << G4endl;
// logAtomicShellXS is created only once, since it is never cleared
if (!logAtomicShellXS)
logAtomicShellXS = new std::map<const G4int,G4PhysicsTable*>;
InitialiseElementSelectors(particle,cuts);
if (verboseLevel > 0) {
G4cout << "Penelope Photo-Electric model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / MeV << " MeV - "
<< HighEnergyLimit() / GeV << " GeV"
<< G4endl;
}
if(isInitialised) return;
fParticleChange = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4Penelope08PhotoElectricModel::ComputeCrossSectionPerAtom(
const G4ParticleDefinition*,
G4double energy,
G4double Z, G4double,
G4double, G4double)
{
//
// Penelope model.
//
if (verboseLevel > 3)
G4cout << "Calling ComputeCrossSectionPerAtom() of G4Penelope08PhotoElectricModel" << G4endl;
G4int iZ = (G4int) Z;
//read data files
if (!logAtomicShellXS->count(iZ))
ReadDataFile(iZ);
//now it should be ok
if (!logAtomicShellXS->count(iZ))
{
G4cout << "Problem in G4Penelope08PhotoElectricModel::ComputeCrossSectionPerAtom"
<< G4endl;
G4Exception();
}
G4double cross = 0;
G4PhysicsTable* theTable = logAtomicShellXS->find(iZ)->second;
G4PhysicsFreeVector* totalXSLog = (G4PhysicsFreeVector*) (*theTable)[0];
if (!totalXSLog)
{
G4cout << "Problem in G4Penelope08PhotoElectricModel::ComputeCrossSectionPerAtom"
<< G4endl;
G4Exception();
}
G4double logene = std::log(energy);
G4double logXS = totalXSLog->Value(logene);
cross = std::exp(logXS);
if (verboseLevel > 2)
G4cout << "Photoelectric cross section at " << energy/MeV << " MeV for Z=" << Z <<
" = " << cross/barn << " barn" << G4endl;
return cross;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4Penelope08PhotoElectricModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicGamma,
G4double,
G4double)
{
//
// Photoelectric effect, Penelope model
//
// The target atom and the target shell are sampled according to the Livermore
// database
// D.E. Cullen et al., Report UCRL-50400 (1989)
// The angular distribution of the electron in the final state is sampled
// according to the Sauter distribution from
// F. Sauter, Ann. Phys. 11 (1931) 454
// The energy of the final electron is given by the initial photon energy minus
// the binding energy. Fluorescence de-excitation is subsequently produced
// (to fill the vacancy) according to the general Geant4 G4DeexcitationManager:
// J. Stepanek, Comp. Phys. Comm. 1206 pp 1-1-9 (1997)
if (verboseLevel > 3)
G4cout << "Calling SamplingSecondaries() of G4Penelope08PhotoElectricModel" << G4endl;
G4double photonEnergy = aDynamicGamma->GetKineticEnergy();
// always kill primary
fParticleChange->ProposeTrackStatus(fStopAndKill);
fParticleChange->SetProposedKineticEnergy(0.);
if (photonEnergy <= fIntrinsicLowEnergyLimit)
{
fParticleChange->ProposeLocalEnergyDeposit(photonEnergy);
return ;
}
G4ParticleMomentum photonDirection = aDynamicGamma->GetMomentumDirection();
// Select randomly one element in the current material
if (verboseLevel > 2)
G4cout << "Going to select element in " << couple->GetMaterial()->GetName() << G4endl;
// atom can be selected efficiently if element selectors are initialised
const G4Element* anElement =
SelectRandomAtom(couple,G4Gamma::GammaDefinition(),photonEnergy);
G4int Z = (G4int) anElement->GetZ();
if (verboseLevel > 2)
G4cout << "Selected " << anElement->GetName() << G4endl;
// Select the ionised shell in the current atom according to shell cross sections
//shellIndex = 0 --> K shell
// 1-3 --> L shells
// 4-8 --> M shells
// 9 --> outer shells cumulatively
//
size_t shellIndex = SelectRandomShell(Z,photonEnergy);
if (verboseLevel > 2)
G4cout << "Selected shell " << shellIndex << " of element " << anElement->GetName() << G4endl;
// Retrieve the corresponding identifier and binding energy of the selected shell
const G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
//The number of shell cross section possibly reported in the Penelope database
//might be different from the number of shells in the G4AtomicTransitionManager
//(namely, Penelope may contain more shell, especially for very light elements).
//In order to avoid a warning message from the G4AtomicTransitionManager, I
//add this protection. Results are anyway changed, because when G4AtomicTransitionManager
//has a shellID>maxID, it sets the shellID to the last valid shell.
size_t numberOfShells = (size_t) transitionManager->NumberOfShells(Z);
if (shellIndex >= numberOfShells)
shellIndex = numberOfShells-1;
const G4AtomicShell* shell = transitionManager->Shell(Z,shellIndex);
G4double bindingEnergy = shell->BindingEnergy();
G4int shellId = shell->ShellId();
//Penelope considers only K, L and M shells. Cross sections of outer shells are
//not included in the Penelope database. If SelectRandomShell() returns
//shellIndex = 9, it means that an outer shell was ionized. In this case the
//Penelope recipe is to set bindingEnergy = 0 (the energy is entirely assigned
//to the electron) and to disregard fluorescence.
if (shellIndex == 9)
bindingEnergy = 0.*eV;
G4double localEnergyDeposit = 0.0;
G4double cosTheta = 1.0;
// Primary outcoming electron
G4double eKineticEnergy = photonEnergy - bindingEnergy;
// There may be cases where the binding energy of the selected shell is > photon energy
// In such cases do not generate secondaries
if (eKineticEnergy > 0.)
{
// The electron is created
// Direction sampled from the Sauter distribution
cosTheta = SampleElectronDirection(eKineticEnergy);
G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
G4double phi = twopi * G4UniformRand() ;
G4double dirx = sinTheta * std::cos(phi);
G4double diry = sinTheta * std::sin(phi);
G4double dirz = cosTheta ;
G4ThreeVector electronDirection(dirx,diry,dirz); //electron direction
electronDirection.rotateUz(photonDirection);
G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),
electronDirection,
eKineticEnergy);
fvect->push_back(electron);
}
else
{
bindingEnergy = photonEnergy;
}
G4double energyInFluorescence = 0; //testing purposes
//Now, take care of fluorescence, if required
if(DeexcitationFlag() && Z > 5)
{
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t indx = couple->GetIndex();
G4double cutG = (*(theCoupleTable->GetEnergyCutsVector(0)))[indx];
G4double cutE = (*(theCoupleTable->GetEnergyCutsVector(1)))[indx];
// Protection to avoid generating photons in the unphysical case of
// shell binding energy > photon energy
if (bindingEnergy > cutG || bindingEnergy > cutE)
{
deexcitationManager.SetCutForSecondaryPhotons(cutG);
deexcitationManager.SetCutForAugerElectrons(cutE);
std::vector<G4DynamicParticle*>* photonVector =
deexcitationManager.GenerateParticles(Z,shellId);
//Check for secondaries
if(photonVector)
{
for (size_t k=0; k< photonVector->size(); k++)
{
G4DynamicParticle* aPhoton = (*photonVector)[k];
if (aPhoton)
{
G4double itsEnergy = aPhoton->GetKineticEnergy();
if (itsEnergy <= bindingEnergy)
{
if(aPhoton->GetDefinition() == G4Gamma::Gamma())
energyInFluorescence += itsEnergy;
bindingEnergy -= itsEnergy;
fvect->push_back(aPhoton);
}
else
{
delete aPhoton;
(*photonVector)[k] = 0;
}
}
}
delete photonVector;
}
}
}
//Residual energy is deposited locally
localEnergyDeposit += bindingEnergy;
if (localEnergyDeposit < 0)
{
G4cout << "WARNING - "
<< "G4Penelope08PhotoElectric::PostStepDoIt - Negative energy deposit"
<< G4endl;
localEnergyDeposit = 0;
}
fParticleChange->ProposeLocalEnergyDeposit(localEnergyDeposit);
if (verboseLevel > 1)
{
G4cout << "-----------------------------------------------------------" << G4endl;
G4cout << "Energy balance from G4Penelope08PhotoElectric" << G4endl;
G4cout << "Selected shell: " << WriteTargetShell(shellIndex) << " of element " <<
anElement->GetName() << G4endl;
G4cout << "Incoming photon energy: " << photonEnergy/keV << " keV" << G4endl;
G4cout << "-----------------------------------------------------------" << G4endl;
if (eKineticEnergy)
G4cout << "Outgoing electron " << eKineticEnergy/keV << " keV" << G4endl;
G4cout << "Fluorescence: " << energyInFluorescence/keV << " keV" << G4endl;
G4cout << "Local energy deposit " << localEnergyDeposit/keV << " keV" << G4endl;
G4cout << "Total final state: " << (eKineticEnergy+energyInFluorescence+localEnergyDeposit)/keV <<
" keV" << G4endl;
G4cout << "-----------------------------------------------------------" << G4endl;
}
if (verboseLevel > 0)
{
G4double energyDiff =
std::fabs(eKineticEnergy+energyInFluorescence+localEnergyDeposit-photonEnergy);
if (energyDiff > 0.05*keV)
G4cout << "Warning from G4Penelope08PhotoElectric: problem with energy conservation: " <<
(eKineticEnergy+energyInFluorescence+localEnergyDeposit)/keV
<< " keV (final) vs. " <<
photonEnergy/keV << " keV (initial)" << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4Penelope08PhotoElectricModel::ActivateAuger(G4bool augerbool)
{
if (!DeexcitationFlag() && augerbool)
{
G4cout << "WARNING - G4Penelope08PhotoElectricModel" << G4endl;
G4cout << "The use of the Atomic Deexcitation Manager is set to false " << G4endl;
G4cout << "Therefore, Auger electrons will be not generated anyway" << G4endl;
}
deexcitationManager.ActivateAugerElectronProduction(augerbool);
if (verboseLevel > 1)
G4cout << "Auger production set to " << augerbool << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4Penelope08PhotoElectricModel::SampleElectronDirection(G4double energy)
{
G4double costheta = 1.0;
if (energy>1*GeV) return costheta;
//1) initialize energy-dependent variables
// Variable naming according to Eq. (2.24) of Penelope Manual
// (pag. 44)
G4double gamma = 1.0 + energy/electron_mass_c2;
G4double gamma2 = gamma*gamma;
G4double beta = std::sqrt((gamma2-1.0)/gamma2);
// ac corresponds to "A" of Eq. (2.31)
//
G4double ac = (1.0/beta) - 1.0;
G4double a1 = 0.5*beta*gamma*(gamma-1.0)*(gamma-2.0);
G4double a2 = ac + 2.0;
G4double gtmax = 2.0*(a1 + 1.0/ac);
G4double tsam = 0;
G4double gtr = 0;
//2) sampling. Eq. (2.31) of Penelope Manual
// tsam = 1-std::cos(theta)
// gtr = rejection function according to Eq. (2.28)
do{
G4double rand = G4UniformRand();
tsam = 2.0*ac * (2.0*rand + a2*std::sqrt(rand)) / (a2*a2 - 4.0*rand);
gtr = (2.0 - tsam) * (a1 + 1.0/(ac+tsam));
}while(G4UniformRand()*gtmax > gtr);
costheta = 1.0-tsam;
return costheta;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4Penelope08PhotoElectricModel::ReadDataFile(G4int Z)
{
if (verboseLevel > 2)
{
G4cout << "G4Penelope08PhotoElectricModel::ReadDataFile()" << G4endl;
G4cout << "Going to read PhotoElectric data files for Z=" << Z << G4endl;
}
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4Penelope08PhotoElectricModel - G4LEDATA environment variable not set!";
G4Exception(excep);
}
/*
Read the cross section file
*/
std::ostringstream ost;
if (Z>9)
ost << path << "/penelope/photoelectric/pdgph" << Z << ".p08";
else
ost << path << "/penelope/photoelectric/pdgph0" << Z << ".p08";
std::ifstream file(ost.str().c_str());
if (!file.is_open())
{
G4String excep = "G4Penelope08PhotoElectricModel - data file " + G4String(ost.str()) + " not found!";
G4Exception(excep);
}
//I have to know in advance how many points are in the data list
//to initialize the G4PhysicsFreeVector()
size_t ndata=0;
G4String line;
while( getline(file, line) )
ndata++;
ndata -= 1;
//G4cout << "Found: " << ndata << " lines" << G4endl;
file.clear();
file.close();
file.open(ost.str().c_str());
G4int readZ =0;
size_t nShells= 0;
file >> readZ >> nShells;
if (verboseLevel > 3)
G4cout << "Element Z=" << Z << " , nShells = " << nShells << G4endl;
//check the right file is opened.
if (readZ != Z || nShells <= 0)
{
G4cout << "G4Penelope08PhotoElectricModel::ReadDataFile()" << G4endl;
G4cout << "Corrupted data file for Z=" << Z << G4endl;
G4Exception();
}
G4PhysicsTable* thePhysicsTable = new G4PhysicsTable();
//the table has to contain nShell+1 G4PhysicsFreeVectors,
//(theTable)[0] --> total cross section
//(theTable)[ishell] --> cross section for shell (ishell-1)
//reserve space for the vectors
//everything is log-log
for (size_t i=0;i<nShells+1;i++)
thePhysicsTable->push_back(new G4PhysicsFreeVector(ndata));
size_t k =0;
for (k=0;k<ndata && !file.eof();k++)
{
G4double energy = 0;
G4double aValue = 0;
file >> energy ;
energy *= eV;
G4double logene = std::log(energy);
//loop on the columns
for (size_t i=0;i<nShells+1;i++)
{
file >> aValue;
aValue *= barn;
G4PhysicsFreeVector* theVec = (G4PhysicsFreeVector*) ((*thePhysicsTable)[i]);
if (aValue < 1e-40*cm2) //protection against log(0)
aValue = 1e-40*cm2;
theVec->PutValue(k,logene,std::log(aValue));
}
}
if (verboseLevel > 2)
{
G4cout << "G4Penelope08PhotoElectricModel: read " << k << " points for element Z = "
<< Z << G4endl;
}
logAtomicShellXS->insert(std::make_pair(Z,thePhysicsTable));
file.close();
return;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
size_t G4Penelope08PhotoElectricModel::SelectRandomShell(G4int Z,G4double energy)
{
G4double logEnergy = std::log(energy);
//Check if data have been read (it should be!)
if (!logAtomicShellXS->count(Z))
{
G4cout << "Problem in G4Penelope08PhotoElectricModel::SelectRandomShell" << G4endl;
G4cout << "Cannot find data for Z=" << Z << G4endl;
G4Exception();
}
size_t shellIndex = 0;
G4PhysicsTable* theTable = logAtomicShellXS->find(Z)->second;
G4DataVector* tempVector = new G4DataVector();
G4double sum = 0;
//loop on shell partial XS, retrieve the value for the given energy and store on
//a temporary vector
tempVector->push_back(sum); //first element is zero
G4PhysicsFreeVector* totalXSLog = (G4PhysicsFreeVector*) (*theTable)[0];
G4double logXS = totalXSLog->Value(logEnergy);
G4double totalXS = std::exp(logXS);
//Notice: totalXS is the total cross section and it does *not* correspond to
//the sum of partialXS's, since these include only K, L and M shells.
//
// Therefore, here one have to consider the possibility of ionisation of
// an outer shell. Conventionally, it is indicated with id=10 in Penelope
//
for (size_t k=1;k<theTable->entries();k++)
{
G4PhysicsFreeVector* partialXSLog = (G4PhysicsFreeVector*) (*theTable)[k];
G4double logXS = partialXSLog->Value(logEnergy);
G4double partialXS = std::exp(logXS);
sum += partialXS;
tempVector->push_back(sum);
}
tempVector->push_back(totalXS); //last element
G4double random = G4UniformRand()*totalXS;
/*
for (size_t i=0;i<tempVector->size(); i++)
G4cout << i << " " << (*tempVector)[i]/totalXS << G4endl;
*/
//locate bin of tempVector
//Now one has to sample according to the elements in tempVector
//This gives the left edge of the interval...
size_t lowerBound = 0;
size_t upperBound = tempVector->size()-1;
while (lowerBound <= upperBound)
{
size_t midBin = (lowerBound + upperBound)/2;
if( random < (*tempVector)[midBin])
upperBound = midBin-1;
else
lowerBound = midBin+1;
}
shellIndex = upperBound;
delete tempVector;
return shellIndex;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
size_t G4Penelope08PhotoElectricModel::GetNumberOfShellXS(G4int Z)
{
//read data files
if (!logAtomicShellXS->count(Z))
ReadDataFile(Z);
//now it should be ok
if (!logAtomicShellXS->count(Z))
{
G4cout << "Problem in G4Penelope08PhotoElectricModel::GetNumberOfShellXS()"
<< G4endl;
G4Exception();
}
//one vector is allocated for the _total_ cross section
size_t nEntries = logAtomicShellXS->find(Z)->second->entries();
return (nEntries-1);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4Penelope08PhotoElectricModel::GetShellCrossSection(G4int Z,size_t shellID,G4double energy)
{
//this forces also the loading of the data
size_t entries = GetNumberOfShellXS(Z);
if (shellID >= entries)
{
G4cout << "Element Z=" << Z << " has data for " << entries << " shells only" << G4endl;
G4cout << "so shellID should be from 0 to " << entries-1 << G4endl;
return 0;
}
G4PhysicsTable* theTable = logAtomicShellXS->find(Z)->second;
//[0] is the total XS, shellID is in the element [shellID+1]
G4PhysicsFreeVector* totalXSLog = (G4PhysicsFreeVector*) (*theTable)[shellID+1];
if (!totalXSLog)
{
G4cout << "Problem in G4Penelope08PhotoElectricModel::GetShellCrossSection()"
<< G4endl;
G4Exception();
}
G4double logene = std::log(energy);
G4double logXS = totalXSLog->Value(logene);
G4double cross = std::exp(logXS);
if (cross < 2e-40*cm2) cross = 0;
return cross;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4String G4Penelope08PhotoElectricModel::WriteTargetShell(size_t shellID)
{
G4String theShell = "outer shell";
if (shellID == 0)
theShell = "K";
else if (shellID == 1)
theShell = "L1";
else if (shellID == 2)
theShell = "L2";
else if (shellID == 3)
theShell = "L3";
else if (shellID == 4)
theShell = "M1";
else if (shellID == 5)
theShell = "M2";
else if (shellID == 6)
theShell = "M3";
else if (shellID == 7)
theShell = "M4";
else if (shellID == 8)
theShell = "M5";
return theShell;
}
File diff suppressed because it is too large Load Diff
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4PenelopeBremsstrahlungAngular.cc,v 1.8 2009/06/10 13:32:36 mantero Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4PenelopeBremsstrahlungAngular.cc,v 1.10 2010/12/01 15:20:20 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// --------------------------------------------------------------
//
@@ -77,6 +77,7 @@ void G4PenelopeBremsstrahlungAngular::InterpolationTableForZ()
{
G4String excep = "G4PenelopeBremsstrahlungAngular - G4LEDATA environment variable not set!";
G4Exception(excep);
return;
}
G4String pathString(path);
G4String pathFile = pathString + "/penelope/br-ang-pen.dat";
@@ -92,10 +93,11 @@ void G4PenelopeBremsstrahlungAngular::InterpolationTableForZ()
G4double a1,a2;
while(i != -1) {
file >> i >> j >> k >> a1 >> a2;
if (i > -1){
QQ1[i][j][k]=a1;
QQ2[i][j][k]=a2;
}
if (i > -1 && j > -1 && k >- 1)
{
QQ1[i][j][k]=a1;
QQ2[i][j][k]=a2;
}
}
file.close();
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4PenelopeBremsstrahlungContinuous.cc,v 1.12 2009/06/10 13:32:36 mantero Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4PenelopeBremsstrahlungContinuous.cc,v 1.13 2010/11/25 09:43:47 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// --------------------------------------------------------------
//
@@ -88,6 +88,7 @@ void G4PenelopeBremsstrahlungContinuous::LoadFromFile()
{
G4String excep = "G4PenelopeBremsstrahlungContinuous - G4LEDATA environment variable not set!";
G4Exception(excep);
return;
}
G4String pathString(path);
G4String filename = "br-pen-cont-";
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4PenelopeBremsstrahlungModel.cc,v 1.7 2009/06/11 15:47:08 mantero Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4PenelopeBremsstrahlungModel.cc,v 1.8 2010/11/25 09:44:05 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
// --------
@@ -182,8 +182,12 @@ void G4PenelopeBremsstrahlungModel::Initialise(const G4ParticleDefinition* parti
crossSectionHandler->LoadData("penelope/br-cs-pos-"); //cross section for positrons
//This is used to retrieve cross section values later on
crossSectionHandler->BuildMeanFreePathForMaterials();
G4VEMDataSet* emdata =
crossSectionHandler->BuildMeanFreePathForMaterials();
//The method BuildMeanFreePathForMaterials() is required here only to force
//the building of an internal table: the output pointer can be deleted
delete emdata;
if (verboseLevel > 2)
G4cout << "Loaded cross section files for PenelopeBremsstrahlungModel" << G4endl;
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4PenelopeComptonModel.cc,v 1.8 2009/10/23 09:29:24 pandola Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4PenelopeComptonModel.cc,v 1.11 2010/12/01 15:20:26 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
//
@@ -80,10 +80,6 @@ G4PenelopeComptonModel::G4PenelopeComptonModel(const G4ParticleDefinition*,
energyForIntegration = 0.0;
ZForIntegration = 1;
//by default, the model will use atomic deexcitation
SetDeexcitationFlag(true);
ActivateAuger(false);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
@@ -92,6 +88,10 @@ G4PenelopeComptonModel::G4PenelopeComptonModel(const G4ParticleDefinition*,
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
//by default, the model will use atomic deexcitation
SetDeexcitationFlag(true);
ActivateAuger(false);
//These vectors do not change when materials or cut change.
//Therefore I can read it at the constructor
ionizationEnergy = new std::map<G4int,G4DataVector*>;
@@ -107,20 +107,24 @@ G4PenelopeComptonModel::G4PenelopeComptonModel(const G4ParticleDefinition*,
G4PenelopeComptonModel::~G4PenelopeComptonModel()
{
std::map <G4int,G4DataVector*>::iterator i;
for (i=ionizationEnergy->begin();i != ionizationEnergy->end();i++)
if (i->second) delete i->second;
for (i=hartreeFunction->begin();i != hartreeFunction->end();i++)
if (i->second) delete i->second;
for (i=occupationNumber->begin();i != occupationNumber->end();i++)
if (i->second) delete i->second;
if (ionizationEnergy)
delete ionizationEnergy;
{
for (i=ionizationEnergy->begin();i != ionizationEnergy->end();i++)
if (i->second) delete i->second;
delete ionizationEnergy;
}
if (hartreeFunction)
delete hartreeFunction;
{
for (i=hartreeFunction->begin();i != hartreeFunction->end();i++)
if (i->second) delete i->second;
delete hartreeFunction;
}
if (occupationNumber)
delete occupationNumber;
{
for (i=occupationNumber->begin();i != occupationNumber->end();i++)
if (i->second) delete i->second;
delete occupationNumber;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -264,7 +268,8 @@ void G4PenelopeComptonModel::SampleSecondaries(std::vector<G4DynamicParticle*>*
G4cout << "Selected " << anElement->GetName() << G4endl;
const G4int nmax = 64;
G4double rn[nmax],pac[nmax];
G4double rn[nmax]={0.0};
G4double pac[nmax]={0.0};
G4double ki,ki1,ki2,ki3,taumin,a1,a2;
G4double tau,TST;
@@ -628,6 +633,7 @@ void G4PenelopeComptonModel::ReadData()
{
G4String excep = "G4PenelopeComptonModel - G4LEDATA environment variable not set!";
G4Exception(excep);
return;
}
G4String pathString(path);
G4String pathFile = pathString + "/penelope/compton-pen.dat";
@@ -647,15 +653,23 @@ void G4PenelopeComptonModel::ReadData()
{
G4String excep = "G4PenelopeComptonModel: problem with reading data from file";
G4Exception(excep);
return;
}
do{
G4double harOfElectronsBelowThreshold = 0;
G4int nbOfElectronsBelowThreshold = 0;
G4int nbOfElectronsBelowThreshold = 0;
file >> Z >> nLevels;
//Check for nLevels validity, before using it in a loop
if (nLevels<0 || nLevels>64)
{
G4String excep = "G4PenelopeComptonModel: corrupted data file?";
G4Exception(excep);
return;
}
G4DataVector* occVector = new G4DataVector;
G4DataVector* harVector = new G4DataVector;
G4DataVector* bindingEVector = new G4DataVector;
file >> Z >> nLevels;
for (G4int h=0;h<nLevels;h++)
{
file >> k1 >> a1 >> a2;
@@ -0,0 +1,405 @@
//
// ********************************************************************
// * 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: G4PenelopeCrossSection.cc,v 1.2 2010/12/15 07:39:14 gunter Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
//
// History:
// --------
// 18 Mar 2010 L Pandola First implementation
//
#include "G4PenelopeCrossSection.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsFreeVector.hh"
#include "G4DataVector.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
G4PenelopeCrossSection::G4PenelopeCrossSection(size_t nPointsE,size_t nShells) :
numberOfEnergyPoints(nPointsE),numberOfShells(nShells),softCrossSections(0),
hardCrossSections(0),shellCrossSections(0)
{
//check the number of points is not zero
if (!numberOfEnergyPoints)
{
G4cout << "G4PenelopeCrossSection: invalid number of energy points " << G4endl;
G4Exception();
}
isNormalized = false;
// 1) soft XS table
softCrossSections = new G4PhysicsTable();
//the table contains 3 G4PhysicsFreeVectors,
//(softCrossSections)[0] --> log XS0 vs. log E
//(softCrossSections)[1] --> log XS1 vs. log E
//(softCrossSections)[2] --> log XS2 vs. log E
//everything is log-log
for (size_t i=0;i<3;i++)
softCrossSections->push_back(new G4PhysicsFreeVector(numberOfEnergyPoints));
//2) hard XS table
hardCrossSections = new G4PhysicsTable();
//the table contains 3 G4PhysicsFreeVectors,
//(hardCrossSections)[0] --> log XH0 vs. log E
//(hardCrossSections)[1] --> log XH1 vs. log E
//(hardCrossSections)[2] --> log XH2 vs. log E
//everything is log-log
for (size_t i=0;i<3;i++)
hardCrossSections->push_back(new G4PhysicsFreeVector(numberOfEnergyPoints));
//3) shell XS table, if it is the case
if (numberOfShells)
{
shellCrossSections = new G4PhysicsTable();
//the table has to contain numberofShells G4PhysicsFreeVectors,
//(theTable)[ishell] --> cross section for shell #ishell
for (size_t i=0;i<numberOfShells;i++)
shellCrossSections->push_back(new G4PhysicsFreeVector(numberOfEnergyPoints));
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
G4PenelopeCrossSection::~G4PenelopeCrossSection()
{
//clean up tables
if (shellCrossSections)
{
shellCrossSections->clearAndDestroy();
delete shellCrossSections;
}
if (softCrossSections)
{
softCrossSections->clearAndDestroy();
delete softCrossSections;
}
if (hardCrossSections)
{
hardCrossSections->clearAndDestroy();
delete hardCrossSections;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
void G4PenelopeCrossSection::AddCrossSectionPoint(size_t binNumber,G4double energy,
G4double XH0,
G4double XH1, G4double XH2,
G4double XS0, G4double XS1,
G4double XS2)
{
if (!softCrossSections || !hardCrossSections)
{
G4cout << "Something wrong in G4PenelopeCrossSection::AddCrossSectionPoint" <<
G4endl;
G4cout << "Trying to fill un-initialized tables" << G4endl;
return;
}
//fill vectors
G4PhysicsFreeVector* theVector = (G4PhysicsFreeVector*) (*softCrossSections)[0];
if (binNumber >= numberOfEnergyPoints)
{
G4cout << "Something wrong in G4PenelopeCrossSection::AddCrossSectionPoint" <<
G4endl;
G4cout << "Trying to register more points than originally declared" << G4endl;
return;
}
G4double logEne = std::log(energy);
//XS0
G4double val = std::log(std::max(XS0,1e-42*cm2)); //avoid log(0)
theVector->PutValue(binNumber,logEne,val);
//XS1
theVector = (G4PhysicsFreeVector*) (*softCrossSections)[1];
val = std::log(std::max(XS1,1e-42*eV*cm2)); //avoid log(0)
theVector->PutValue(binNumber,logEne,val);
//XS2
theVector = (G4PhysicsFreeVector*) (*softCrossSections)[2];
val = std::log(std::max(XS2,1e-42*eV*eV*cm2)); //avoid log(0)
theVector->PutValue(binNumber,logEne,val);
//XH0
theVector = (G4PhysicsFreeVector*) (*hardCrossSections)[0];
val = std::log(std::max(XH0,1e-42*cm2)); //avoid log(0)
theVector->PutValue(binNumber,logEne,val);
//XH1
theVector = (G4PhysicsFreeVector*) (*hardCrossSections)[1];
val = std::log(std::max(XH1,1e-42*eV*cm2)); //avoid log(0)
theVector->PutValue(binNumber,logEne,val);
//XH2
theVector = (G4PhysicsFreeVector*) (*hardCrossSections)[2];
val = std::log(std::max(XH2,1e-42*eV*eV*cm2)); //avoid log(0)
theVector->PutValue(binNumber,logEne,val);
return;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
void G4PenelopeCrossSection::AddShellCrossSectionPoint(size_t binNumber,
size_t shellID,
G4double energy,
G4double xs)
{
if (!shellCrossSections)
{
G4cout << "Something wrong in G4PenelopeCrossSection::AddShellCrossSectionPoint" <<
G4endl;
G4cout << "Trying to fill un-initialized table" << G4endl;
return;
}
if (shellID >= numberOfShells)
{
G4cout << "Something wrong in G4PenelopeCrossSection::AddShellCrossSectionPoint" <<
G4endl;
G4cout << "Trying to fill shell #" << shellID << " while the maximum is "
<< numberOfShells-1 << G4endl;
return;
}
//fill vector
G4PhysicsFreeVector* theVector = (G4PhysicsFreeVector*) (*shellCrossSections)[shellID];
if (binNumber >= numberOfEnergyPoints)
{
G4cout << "Something wrong in G4PenelopeCrossSection::AddShellCrossSectionPoint" <<
G4endl;
G4cout << "Trying to register more points than originally declared" << G4endl;
return;
}
G4double logEne = std::log(energy);
G4double val = std::log(std::max(xs,1e-42*cm2)); //avoid log(0)
theVector->PutValue(binNumber,logEne,val);
return;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
G4double G4PenelopeCrossSection::GetTotalCrossSection(G4double energy)
{
G4double result = 0;
//take here XS0 + XH0
if (!softCrossSections || !hardCrossSections)
{
G4cout << "Something wrong in G4PenelopeCrossSection::GetTotalCrossSection" <<
G4endl;
G4cout << "Trying to retrieve from un-initialized tables" << G4endl;
return result;
}
// 1) soft part
G4PhysicsFreeVector* theVector = (G4PhysicsFreeVector*) (*softCrossSections)[0];
if (theVector->GetVectorLength() < numberOfEnergyPoints)
{
G4cout << "Something wrong in G4PenelopeCrossSection::GetTotalCrossSection" <<
G4endl;
G4cout << "Soft cross section table looks not filled" << G4endl;
return result;
}
G4double logene = std::log(energy);
G4double logXS = theVector->Value(logene);
G4double softXS = std::exp(logXS);
// 2) hard part
theVector = (G4PhysicsFreeVector*) (*hardCrossSections)[0];
if (theVector->GetVectorLength() < numberOfEnergyPoints)
{
G4cout << "Something wrong in G4PenelopeCrossSection::GetTotalCrossSection" <<
G4endl;
G4cout << "Hard cross section table looks not filled" << G4endl;
return result;
}
logXS = theVector->Value(logene);
G4double hardXS = std::exp(logXS);
result = hardXS + softXS;
return result;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
G4double G4PenelopeCrossSection::GetHardCrossSection(G4double energy)
{
G4double result = 0;
//take here XH0
if (!hardCrossSections)
{
G4cout << "Something wrong in G4PenelopeCrossSection::GetHardCrossSection" <<
G4endl;
G4cout << "Trying to retrieve from un-initialized tables" << G4endl;
return result;
}
G4PhysicsFreeVector* theVector = (G4PhysicsFreeVector*) (*hardCrossSections)[0];
if (theVector->GetVectorLength() < numberOfEnergyPoints)
{
G4cout << "Something wrong in G4PenelopeCrossSection::GetHardCrossSection" <<
G4endl;
G4cout << "Hard cross section table looks not filled" << G4endl;
return result;
}
G4double logene = std::log(energy);
G4double logXS = theVector->Value(logene);
result = std::exp(logXS);
return result;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
G4double G4PenelopeCrossSection::GetSoftStoppingPower(G4double energy)
{
G4double result = 0;
//take here XH0
if (!softCrossSections)
{
G4cout << "Something wrong in G4PenelopeCrossSection::GetSoftStoppingPower" <<
G4endl;
G4cout << "Trying to retrieve from un-initialized tables" << G4endl;
return result;
}
G4PhysicsFreeVector* theVector = (G4PhysicsFreeVector*) (*softCrossSections)[1];
if (theVector->GetVectorLength() < numberOfEnergyPoints)
{
G4cout << "Something wrong in G4PenelopeCrossSection::GetSoftStoppingPower" <<
G4endl;
G4cout << "Soft cross section table looks not filled" << G4endl;
return result;
}
G4double logene = std::log(energy);
G4double logXS = theVector->Value(logene);
result = std::exp(logXS);
return result;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
G4double G4PenelopeCrossSection::GetShellCrossSection(size_t shellID,G4double energy)
{
G4double result = 0;
if (!shellCrossSections)
{
G4cout << "Something wrong in G4PenelopeCrossSection::GetShellCrossSection" <<
G4endl;
G4cout << "Trying to retrieve from un-initialized tables" << G4endl;
return result;
}
if (shellID >= numberOfShells)
{
G4cout << "Something wrong in G4PenelopeCrossSection::GetShellCrossSection" <<
G4endl;
G4cout << "Trying to retrieve shell #" << shellID << " while the maximum is "
<< numberOfShells-1 << G4endl;
return result;
}
G4PhysicsFreeVector* theVector = (G4PhysicsFreeVector*) (*shellCrossSections)[shellID];
if (theVector->GetVectorLength() < numberOfEnergyPoints)
{
G4cout << "Something wrong in G4PenelopeCrossSection::GetShellCrossSection" <<
G4endl;
G4cout << "Soft cross section table looks not filled" << G4endl;
return result;
}
G4double logene = std::log(energy);
G4double logXS = theVector->Value(logene);
result = std::exp(logXS);
return result;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
void G4PenelopeCrossSection::NormalizeShellCrossSections()
{
if (isNormalized) //already done!
{
G4cout << "G4PenelopeCrossSection::NormalizeShellCrossSections()" << G4endl;
G4cout << "already invoked. Ignore it" << G4endl;
return;
}
for (size_t i=0;i<numberOfEnergyPoints;i++) //loop on energy
{
//energy grid is the same for all shells
//Recalculate manually the XS factor, to avoid problems with
//underflows
G4double normFactor = 0.;
for (size_t shellID=0;shellID<numberOfShells;shellID++)
{
G4PhysicsFreeVector* theVec =
(G4PhysicsFreeVector*) (*shellCrossSections)[shellID];
normFactor += std::exp((*theVec)[i]);
}
G4double logNormFactor = std::log(normFactor);
//Normalize
for (size_t shellID=0;shellID<numberOfShells;shellID++)
{
G4PhysicsFreeVector* theVec =
(G4PhysicsFreeVector*) (*shellCrossSections)[shellID];
G4double previousValue = (*theVec)[i]; //log(XS)
G4double logEnergy = theVec->GetLowEdgeEnergy(i);
//log(XS/normFactor) = log(XS) - log(normFactor)
theVec->PutValue(i,logEnergy,previousValue-logNormFactor);
}
}
isNormalized = true;
/*
//TESTING
for (size_t shellID=0;shellID<numberOfShells;shellID++)
{
G4cout << "SHELL " << shellID << G4endl;
G4PhysicsFreeVector* theVec =
(G4PhysicsFreeVector*) (*shellCrossSections)[shellID];
for (size_t i=0;i<numberOfEnergyPoints;i++) //loop on energy
{
G4double logene = theVec->GetLowEdgeEnergy(i);
G4cout << std::exp(logene)/MeV << " " << std::exp((*theVec)[i]) << G4endl;
}
}
*/
return;
}
@@ -71,7 +71,7 @@ std::vector<G4VEMDataSet*>* G4PenelopeCrossSectionHandler::BuildCrossSectionsFor
const G4DataVector& energyVector,
const G4DataVector* energyCuts)
{
G4int verbose = 0;
//G4int verbose = 0;
std::vector<G4VEMDataSet*>* set = new std::vector<G4VEMDataSet*>;
G4DataVector* energies;
@@ -93,11 +93,13 @@ std::vector<G4VEMDataSet*>* G4PenelopeCrossSectionHandler::BuildCrossSectionsFor
material->GetTotNbOfElectPerVolume(); //electron density
G4int nElements = material->GetNumberOfElements();
/*
if(verbose > 0) {
G4cout << "Penelope CS for " << m << "th material "
<< material->GetName()
<< " eEl= " << nElements << G4endl;
}
*/
G4double tcut = (*energyCuts)[m];
@@ -123,6 +125,7 @@ std::vector<G4VEMDataSet*>* G4PenelopeCrossSectionHandler::BuildCrossSectionsFor
particle);
value += cross * p * density;
/*
if(verbose>0 && m == 0 && e>=1. && e<=0.) {
G4cout << "G4PenIonCrossSH: e(MeV)= " << e/MeV
<< " cross= " << cross
@@ -133,6 +136,7 @@ std::vector<G4VEMDataSet*>* G4PenelopeCrossSectionHandler::BuildCrossSectionsFor
<< " Z= " << Z
<< G4endl;
}
*/
}
cs->push_back(value);
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4PenelopeGammaConversionModel.cc,v 1.6 2009/06/11 15:47:08 mantero Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4PenelopeGammaConversionModel.cc,v 1.7 2010/11/25 09:45:13 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
//
@@ -49,6 +49,7 @@
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4CrossSectionHandler.hh"
#include "G4VEMDataSet.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -104,7 +105,11 @@ void G4PenelopeGammaConversionModel::Initialise(const G4ParticleDefinition*,
G4String crossSectionFile = "penelope/pp-cs-pen-";
crossSectionHandler->LoadData(crossSectionFile);
//This is used to retrieve cross section values later on
crossSectionHandler->BuildMeanFreePathForMaterials();
G4VEMDataSet* emdata =
crossSectionHandler->BuildMeanFreePathForMaterials();
//The method BuildMeanFreePathForMaterials() is required here only to force
//the building of an internal table: the output pointer can be deleted
delete emdata;
if (verboseLevel > 2)
G4cout << "Loaded cross section files for PenelopeGammaConversion" << G4endl;
@@ -416,6 +421,7 @@ G4double G4PenelopeGammaConversionModel::GetScreeningRadius(G4double Z)
{
G4String excep = "G4PenelopeGammaConversionModel - G4LEDATA environment variable not set!";
G4Exception(excep);
return result;
}
G4String pathString(path);
G4String pathFile = pathString + "/penelope/pp-pen.dat";
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4PenelopeIonisationModel.cc,v 1.10 2009/10/23 09:29:24 pandola Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4PenelopeIonisationModel.cc,v 1.18 2010/12/01 15:20:35 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
//
@@ -41,6 +41,13 @@
// 21 Oct 2009 L Pandola Remove un-necessary fUseAtomicDeexcitation flag - now managed by
// G4VEmModel::DeexcitationFlag()
// Add ActivateAuger() method
// 15 Mar 2010 L Pandola Explicitely initialize Auger to false
// 29 Mar 2010 L Pandola Added a dummy ComputeCrossSectionPerAtom() method issueing a
// warning if users try to access atomic cross sections via
// G4EmCalculator
// 15 Apr 2010 L. Pandola Implemented model's own version of MinEnergyCut()
// 23 Apr 2010 L. Pandola Removed InitialiseElementSelectors() call. Useless here and
// triggers fake warning messages
//
#include "G4PenelopeIonisationModel.hh"
@@ -79,8 +86,7 @@ G4PenelopeIonisationModel::G4PenelopeIonisationModel(const G4ParticleDefinition*
// SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
//
// Atomic deexcitation model activated by default
SetDeexcitationFlag(true);
//
verboseLevel= 0;
// Verbosity scale:
@@ -89,6 +95,10 @@ G4PenelopeIonisationModel::G4PenelopeIonisationModel(const G4ParticleDefinition*
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
// Atomic deexcitation model activated by default
SetDeexcitationFlag(true);
ActivateAuger(false);
//These vectors do not change when materials or cut change.
//Therefore I can read it at the constructor
@@ -117,29 +127,36 @@ G4PenelopeIonisationModel::~G4PenelopeIonisationModel()
std::map <G4int,G4DataVector*>::iterator i;
for (i=ionizationEnergy->begin();i != ionizationEnergy->end();i++)
if (i->second) delete i->second;
for (i=resonanceEnergy->begin();i != resonanceEnergy->end();i++)
if (i->second) delete i->second;
for (i=occupationNumber->begin();i != occupationNumber->end();i++)
if (i->second) delete i->second;
for (i=shellFlag->begin();i != shellFlag->end();i++)
if (i->second) delete i->second;
if (ionizationEnergy)
delete ionizationEnergy;
{
for (i=ionizationEnergy->begin();i != ionizationEnergy->end();i++)
if (i->second) delete i->second;
delete ionizationEnergy;
}
if (resonanceEnergy)
delete resonanceEnergy;
{
for (i=resonanceEnergy->begin();i != resonanceEnergy->end();i++)
if (i->second) delete i->second;
delete resonanceEnergy;
}
if (occupationNumber)
delete occupationNumber;
{
for (i=occupationNumber->begin();i != occupationNumber->end();i++)
if (i->second) delete i->second;
delete occupationNumber;
}
if (shellFlag)
delete shellFlag;
{
for (i=shellFlag->begin();i != shellFlag->end();i++)
if (i->second) delete i->second;
delete shellFlag;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4PenelopeIonisationModel::Initialise(const G4ParticleDefinition* particle,
const G4DataVector& cuts)
const G4DataVector& )
{
if (verboseLevel > 3)
G4cout << "Calling G4PenelopeIonisationModel::Initialise()" << G4endl;
@@ -173,10 +190,12 @@ void G4PenelopeIonisationModel::Initialise(const G4ParticleDefinition* particle,
crossSectionFile = "penelope/ion-cs-po-";
crossSectionHandler->LoadData(crossSectionFile);
//This is used to retrieve cross section values later on
crossSectionHandler->BuildMeanFreePathForMaterials();
G4VEMDataSet* emdata =
crossSectionHandler->BuildMeanFreePathForMaterials();
//The method BuildMeanFreePathForMaterials() is required here only to force
//the building of an internal table: the output pointer can be deleted
delete emdata;
InitialiseElementSelectors(particle,cuts);
if (verboseLevel > 2)
G4cout << "Loaded cross section files for PenelopeIonisationModel" << G4endl;
@@ -279,6 +298,25 @@ G4double G4PenelopeIonisationModel::CrossSectionPerVolume(const G4Material* mate
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//This is a dummy method. Never inkoved by the tracking, it just issues
//a warning if one tries to get Cross Sections per Atom via the
//G4EmCalculator.
G4double G4PenelopeIonisationModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
G4double,
G4double,
G4double,
G4double,
G4double)
{
G4cout << "*** G4PenelopeIonisationModel -- WARNING ***" << G4endl;
G4cout << "Penelope Ionisation model does not calculate cross section _per atom_ " << G4endl;
G4cout << "so the result is always zero. For physics values, please invoke " << G4endl;
G4cout << "GetCrossSectionPerVolume() or GetMeanFreePath() via the G4EmCalculator" << G4endl;
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4PenelopeIonisationModel::ComputeDEDXPerVolume(const G4Material* material,
const G4ParticleDefinition* theParticle,
G4double kineticEnergy,
@@ -351,6 +389,14 @@ G4double G4PenelopeIonisationModel::ComputeDEDXPerVolume(const G4Material* mater
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4PenelopeIonisationModel::MinEnergyCut(const G4ParticleDefinition*,
const G4MaterialCutsCouple*)
{
return fIntrinsicLowEnergyLimit;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4PenelopeIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicParticle,
@@ -598,6 +644,7 @@ void G4PenelopeIonisationModel::ReadData()
{
G4String excep = "G4PenelopeIonisationModel - G4LEDATA environment variable not set!";
G4Exception(excep);
return;
}
G4String pathString(path);
G4String pathFile = pathString + "/penelope/ion-pen.dat";
@@ -613,17 +660,27 @@ void G4PenelopeIonisationModel::ReadData()
{
G4String excep = "G4PenelopeIonisationModel: problem with reading data from file";
G4Exception(excep);
return;
}
G4int Z=1,nLevels=0;
G4int test,test1;
do{
file >> Z >> nLevels;
//Check for nLevels validity, before using it in a loop
if (nLevels<0 || nLevels>64)
{
G4String excep = "G4PenelopeIonisationModel: corrupted data file ?";
G4Exception(excep);
return;
}
//Allocate space for storage
G4DataVector* occVector = new G4DataVector;
G4DataVector* ionEVector = new G4DataVector;
G4DataVector* resEVector = new G4DataVector;
G4DataVector* shellIndVector = new G4DataVector;
file >> Z >> nLevels;
//
G4double a1,a2,a3,a4;
G4int k1,k2,k3;
for (G4int h=0;h<nLevels;h++)
@@ -1623,6 +1680,7 @@ G4PenelopeIonisationModel::BuildCrossSectionTable(const G4ParticleDefinition* th
std::vector<G4VEMDataSet*>* set = new std::vector<G4VEMDataSet*>;
size_t nOfBins = 200;
//Temporary vector, a quick way to produce a log-spaced energy grid
G4PhysicsLogVector* theLogVector = new G4PhysicsLogVector(LowEnergyLimit(),
HighEnergyLimit(),
nOfBins);
@@ -1676,6 +1734,7 @@ G4PenelopeIonisationModel::BuildCrossSectionTable(const G4ParticleDefinition* th
}
set->push_back(setForMat);
}
delete theLogVector;
return set;
}
@@ -0,0 +1,98 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
//
// Author: Luciano Pandola
//
// History:
// --------
// 18 Dec 2008 L Pandola First implementation
#include "G4PenelopeOscillator.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PenelopeOscillator::G4PenelopeOscillator() :
hartreeFactor(0), ionisationEnergy(0*eV), resonanceEnergy(0*eV),
oscillatorStrength(0), shellFlag(-1), parentZ(0),
parentShellID(-1),cutoffRecoilResonantEnergy(0*eV)
{;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PenelopeOscillator::G4PenelopeOscillator(const G4PenelopeOscillator& right)
{
hartreeFactor = right.hartreeFactor;
ionisationEnergy = right.ionisationEnergy;
resonanceEnergy = right.resonanceEnergy;
oscillatorStrength = right.oscillatorStrength;
shellFlag = right.shellFlag;
parentZ = right.parentZ;
parentShellID = right.parentShellID;
cutoffRecoilResonantEnergy = right.cutoffRecoilResonantEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4PenelopeOscillator& G4PenelopeOscillator::operator=(const G4PenelopeOscillator& right)
{
hartreeFactor = right.hartreeFactor;
ionisationEnergy = right.ionisationEnergy;
resonanceEnergy = right.resonanceEnergy;
oscillatorStrength = right.oscillatorStrength;
shellFlag = right.shellFlag;
parentZ = right.parentZ;
parentShellID = right.parentShellID;
cutoffRecoilResonantEnergy = right.cutoffRecoilResonantEnergy;
return *this;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
int G4PenelopeOscillator::operator==(const G4PenelopeOscillator& right) const
{
//Oscillator are ordered according to the ionisation energy. They are considered to be
//equal if the ionisation energy is the same
return (ionisationEnergy == right.ionisationEnergy) ? 1 : 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
int G4PenelopeOscillator::operator>(const G4PenelopeOscillator& right) const
{
//Oscillator are ordered according to the ionisation energy.
return (ionisationEnergy > right.ionisationEnergy) ? 1 : 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
int G4PenelopeOscillator::operator<(const G4PenelopeOscillator& right) const
{
//Oscillator are ordered according to the ionisation energy.
return (ionisationEnergy < right.ionisationEnergy) ? 1 : 0;
}
File diff suppressed because it is too large Load Diff
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4PenelopePhotoElectricModel.cc,v 1.10 2009/10/23 09:29:24 pandola Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4PenelopePhotoElectricModel.cc,v 1.13 2010/11/26 11:51:11 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
//
@@ -45,6 +45,7 @@
// Initialise(), since they might be checked later on
// 21 Oct 2009 L Pandola Remove un-necessary fUseAtomicDeexcitation flag - now managed by
// G4VEmModel::DeexcitationFlag()
// 15 Mar 2010 L Pandola Explicitely initialize Auger to false
//
#include "G4PenelopePhotoElectricModel.hh"
@@ -60,6 +61,7 @@
#include "G4AtomicShell.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4VEMDataSet.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -74,9 +76,6 @@ G4PenelopePhotoElectricModel::G4PenelopePhotoElectricModel(const G4ParticleDefin
// SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
//
//by default the model will inkove the atomic deexcitation
SetDeexcitationFlag(true);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
@@ -84,6 +83,10 @@ G4PenelopePhotoElectricModel::G4PenelopePhotoElectricModel(const G4ParticleDefin
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
//by default the model will inkove the atomic deexcitation
SetDeexcitationFlag(true);
ActivateAuger(false);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -124,7 +127,11 @@ void G4PenelopePhotoElectricModel::Initialise(const G4ParticleDefinition*,
crossSectionFile = "penelope/ph-ss-cs-pen-";
shellCrossSectionHandler->LoadShellData(crossSectionFile);
//This is used to retrieve cross section values later on
crossSectionHandler->BuildMeanFreePathForMaterials();
G4VEMDataSet* emdata =
crossSectionHandler->BuildMeanFreePathForMaterials();
//The method BuildMeanFreePathForMaterials() is required here only to force
//the building of an internal table: the output pointer can be deleted
delete emdata;
if (verboseLevel > 2)
G4cout << "Loaded cross section files for PenelopePhotoElectric" << G4endl;
@@ -251,10 +258,7 @@ void G4PenelopePhotoElectricModel::SampleSecondaries(std::vector<G4DynamicPartic
// There may be cases where the binding energy of the selected shell is > photon energy
// In such cases do not generate secondaries
if (eKineticEnergy > 0.)
{
//Now check if the electron is above cuts: if so, it is created explicitely
//VI: checking cut here provides inconsistency in testing
// if (eKineticEnergy > cutE)
{
// The electron is created
// Direction sampled from the Sauter distribution
G4double cosTheta = SampleElectronDirection(eKineticEnergy);
@@ -270,12 +274,6 @@ void G4PenelopePhotoElectricModel::SampleSecondaries(std::vector<G4DynamicPartic
eKineticEnergy);
fvect->push_back(electron);
}
// else
// {
// localEnergyDeposit += eKineticEnergy;
// eKineticEnergy = 0;
// }
// }
else
{
bindingEnergy = photonEnergy;
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4PenelopeRayleighModel.cc,v 1.6 2009/06/11 15:47:08 mantero Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4PenelopeRayleighModel.cc,v 1.8 2010/11/26 11:51:11 pandola Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Luciano Pandola
//
@@ -36,6 +36,9 @@
// - do not apply low-energy limit (default is 0)
// 19 May 2009 L Pandola Explicitely set to zero pointers deleted in
// PrepareConstants(), since they might be checked later on
// 18 Dec 2009 L Pandola Added a dummy ComputeCrossSectionPerAtom() method issueing a
// warning if users try to access atomic cross sections via
// G4EmCalculator
//
#include "G4PenelopeRayleighModel.hh"
@@ -189,7 +192,14 @@ G4PenelopeRayleighModel::CrossSectionPerVolume(const G4Material* material,
//Calculate the total number of atoms per molecule
G4int atomsPerMolecule = 0;
for (G4int k=0;k<nElements;k++)
{
atomsPerMolecule += stechiometric[k];
if (verboseLevel > 2)
{
G4cout << "Element: " << (G4int) (*elementVector)[k]->GetZ() << " has " <<
stechiometric[k] << " atoms/molecule" << G4endl;
}
}
if (atomsPerMolecule)
{
isAMolecule = true;
@@ -202,7 +212,7 @@ G4PenelopeRayleighModel::CrossSectionPerVolume(const G4Material* material,
cross = cs*moleculeDensity;
}
}
if (verboseLevel > 2)
{
if (isAMolecule)
@@ -221,6 +231,25 @@ G4PenelopeRayleighModel::CrossSectionPerVolume(const G4Material* material,
return cross;
}
//This is a dummy method. Never inkoved by the tracking, it just issues
//a warning if one tries to get Cross Sections per Atom via the
//G4EmCalculator.
G4double G4PenelopeRayleighModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
G4double,
G4double,
G4double,
G4double,
G4double)
{
G4cout << "*** G4PenelopeRayleighModel -- WARNING ***" << G4endl;
G4cout << "Penelope Rayleigh model does not calculate cross section _per atom_ " << G4endl;
G4cout << "so the result is always zero. For physics values, please invoke " << G4endl;
G4cout << "GetCrossSectionPerVolume() or GetMeanFreePath() via the G4EmCalculator" << G4endl;
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4PenelopeRayleighModel::SampleSecondaries(std::vector<G4DynamicParticle*>* ,
@@ -478,8 +507,10 @@ void G4PenelopeRayleighModel::InitialiseSampling()
if (!samplingFunction_x || !samplingFunction_xNoLog)
{
G4cout << "G4PenelopeRayleighModel::InitialiseSampling(), something wrong" << G4endl;
G4cout << "It looks like G4PenelopeRayleighModel::PrepareConstants() has not been called" << G4endl;
G4cout << "It looks like G4PenelopeRayleighModel::PrepareConstants() has not been called"
<< G4endl;
G4Exception();
return;
}
if (!SamplingTable.count(theMaterial)) //material not defined yet
{
@@ -0,0 +1,205 @@
//
// ********************************************************************
// * 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: G4PenelopeSamplingData.cc,v 1.1 2010/03/17 14:18:50 pandola Exp $
// GEANT4 tag $Name: geant4-09-04-beta-01 $
//
// Author: Luciano Pandola
//
// History:
// --------
// 09 Dec 2009 L Pandola First implementation
//
#include "G4PenelopeSamplingData.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
G4PenelopeSamplingData::G4PenelopeSamplingData(G4int nPoints) :
np(nPoints)
{
//create vectors
x = new G4DataVector();
pac = new G4DataVector();
a = new G4DataVector();
b = new G4DataVector();
ITTL = new std::vector<size_t>;
ITTU = new std::vector<size_t>;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
G4PenelopeSamplingData::~G4PenelopeSamplingData()
{
if (x) delete x;
if (pac) delete pac;
if (a) delete a;
if (b) delete b;
if (ITTL) delete ITTL;
if (ITTU) delete ITTU;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
size_t G4PenelopeSamplingData::GetNumberOfStoredPoints()
{
size_t points = x->size();
//check everything is all right
if (pac->size() != points || a->size() != points ||
b->size() != points || ITTL->size() != points ||
ITTU->size() != points)
{
G4cout << "G4PenelopeSamplingData::GetNumberOfStoredPoints()" << G4endl;
G4cout << "Data vectors look to have different dimensions !" << G4endl;
G4Exception();
}
return points;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
void G4PenelopeSamplingData::Clear()
{
if (x) delete x;
if (pac) delete pac;
if (a) delete a;
if (b) delete b;
if (ITTL) delete ITTL;
if (ITTU) delete ITTU;
//create vectors
x = new G4DataVector();
pac = new G4DataVector();
a = new G4DataVector();
b = new G4DataVector();
ITTL = new std::vector<size_t>;
ITTU = new std::vector<size_t>;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...
void G4PenelopeSamplingData::AddPoint(G4double x0,G4double pac0,G4double a0,G4double b0,
size_t ITTL0,size_t ITTU0)
{
x->push_back(x0);
pac->push_back(pac0);
a->push_back(a0);
b->push_back(b0);
ITTL->push_back(ITTL0);
ITTU->push_back(ITTU0);
//check how many points we do have now
size_t nOfPoints = GetNumberOfStoredPoints();
if (nOfPoints > ((size_t)np))
{
G4cout << "G4PenelopeSamplingData::AddPoint() " << G4endl;
G4cout << "WARNING: Up to now there are " << nOfPoints << " points in the table" << G4endl;
G4cout << "while the anticipated (declared) number is " << np << G4endl;
}
return;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
void G4PenelopeSamplingData::DumpTable()
{
G4cout << "*************************************************************************" << G4endl;
G4cout << GetNumberOfStoredPoints() << " points" << G4endl;
G4cout << "*************************************************************************" << G4endl;
for (size_t i=0;i<GetNumberOfStoredPoints();i++)
{
G4cout << i << " " << (*x)[i] << " " << (*pac)[i] << " " << (*a)[i] << " " <<
(*b)[i] << " " << (*ITTL)[i] << " " << (*ITTU)[i] << G4endl;
}
G4cout << "*************************************************************************" << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
G4double G4PenelopeSamplingData::GetX(size_t index)
{
if (index < x->size())
return (*x)[index];
else
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
G4double G4PenelopeSamplingData::GetPAC(size_t index)
{
if (index < pac->size())
return (*pac)[index];
else
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
G4double G4PenelopeSamplingData::GetA(size_t index)
{
if (index < a->size())
return (*a)[index];
else
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
G4double G4PenelopeSamplingData::GetB(size_t index)
{
if (index < b->size())
return (*b)[index];
else
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo..
G4double G4PenelopeSamplingData::SampleValue(G4double maxRand)
{
//One passes here a random number in (0,1).
//Notice: it possible that is between (0,b) with b<1
size_t points = GetNumberOfStoredPoints();
size_t itn = (size_t) (maxRand*(points-1));
size_t i = (*ITTL)[itn];
size_t j = (*ITTU)[itn];
while ((j-i) > 1)
{
size_t k = (i+j)/2;
if (maxRand > (*pac)[k])
i = k;
else
j = k;
}
//Sampling from the rational inverse cumulative distribution
G4double result = 0;
G4double rr = maxRand - (*pac)[i];
if (rr > 1e-16)
{
G4double d = (*pac)[i+1]-(*pac)[i];
result = (*x)[i]+
((1.0+(*a)[i]+(*b)[i])*d*rr/
(d*d+((*a)[i]*d+(*b)[i]*rr)*rr))*((*x)[i+1]-(*x)[i]);
}
else
result = (*x)[i];
return result;
}
@@ -79,7 +79,9 @@ G4ThreeVector G4PhotoElectricAngularGeneratorSauterGavrila::GetPhotoElectronDire
if (gamma > 5.) {
G4ThreeVector direction (sinteta*cosphi, sinteta*sinphi, costeta);
return costeta;
return direction;
// Bugzilla 1120
// SI on 05/09/2010 as suggested by JG 04/09/10
}
G4double beta = std::sqrt(gamma*gamma-1.)/gamma;
@@ -0,0 +1,545 @@
//
// ********************************************************************
// * 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: G4UAtomicDeexcitation.cc,v 1.11
// GEANT4 tag $Name: geant4-09-04 $
//
// -------------------------------------------------------------------
//
// Geant4 Class file
//
// Authors: Alfonso Mantero (Alfonso.Mantero@ge.infn.it)
//
// Created 22 April 2010 from old G4UAtomicDeexcitation class
//
// Modified:
// ---------
//
//
// -------------------------------------------------------------------
//
// Class description:
// Implementation of atomic deexcitation
//
// -------------------------------------------------------------------
#include "G4UAtomicDeexcitation.hh"
#include "Randomize.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4FluoTransition.hh"
#include "G4Proton.hh"
using namespace std;
G4UAtomicDeexcitation::G4UAtomicDeexcitation():
G4VAtomDeexcitation("UAtomDeexcitation"),
minGammaEnergy(DBL_MAX),
minElectronEnergy(DBL_MAX)
{
PIXEshellCS = 0;
}
G4UAtomicDeexcitation::~G4UAtomicDeexcitation()
{
delete PIXEshellCS;
}
void G4UAtomicDeexcitation::InitialiseForNewRun()
{
transitionManager = G4AtomicTransitionManager::Instance();
// initializing PIXE
if ("" == PIXECrossSectionModel()) {
SetPIXECrossSectionModel("Empirical");
}
if (PIXECrossSectionModel() == "ECPSSR_Analytical") {
delete PIXEshellCS;
PIXEshellCS = new G4teoCrossSection("analytical");
}
else if (PIXECrossSectionModel() == "Empirical") {
delete PIXEshellCS;
PIXEshellCS = new G4empCrossSection;
}
else {
G4cout << "### G4UAtomicDeexcitation::InitialiseForNewRun WARNING "
<< G4endl;
G4cout << " PIXE cross section name " << PIXECrossSectionModel()
<< " is unknown, PIXE is disabled" << G4endl;
SetPIXEActive(false);
}
}
void G4UAtomicDeexcitation::InitialiseForExtraAtom(G4int /*Z*/)
{}
const G4AtomicShell*
G4UAtomicDeexcitation::GetAtomicShell(G4int Z, G4AtomicShellEnumerator shell)
{
return transitionManager->Shell(Z, G4int(shell));
}
void G4UAtomicDeexcitation::GenerateParticles(
std::vector<G4DynamicParticle*>* vectorOfParticles,
const G4AtomicShell* atomicShell,
G4int Z,
G4double gammaCut,
G4double eCut)
{
// Defined initial conditions
G4int givenShellId = atomicShell->ShellId();
minGammaEnergy = gammaCut;
minElectronEnergy = eCut;
// generation secondaries
G4DynamicParticle* aParticle;
G4int provShellId = 0;
G4int counter = 0;
// The aim of this loop is to generate more than one fluorecence photon
// from the same ionizing event
do
{
if (counter == 0)
// First call to GenerateParticles(...):
// givenShellId is given by the process
{
provShellId = SelectTypeOfTransition(Z, givenShellId);
if ( provShellId >0)
{
aParticle = GenerateFluorescence(Z,givenShellId,provShellId);
}
else if ( provShellId == -1)
{
aParticle = GenerateAuger(Z, givenShellId);
}
else
{
G4Exception("G4UAtomicDeexcitation: starting shell uncorrect: check it");
}
}
else
// Following calls to GenerateParticles(...):
// newShellId is given by GenerateFluorescence(...)
{
provShellId = SelectTypeOfTransition(Z,newShellId);
if (provShellId >0)
{
aParticle = GenerateFluorescence(Z,newShellId,provShellId);
}
else if ( provShellId == -1)
{
aParticle = GenerateAuger(Z, newShellId);
}
else
{
G4Exception("G4UAtomicDeexcitation: starting shell uncorrect: check it");
}
}
counter++;
if (aParticle != 0)
{
vectorOfParticles->push_back(aParticle);
// G4cout << "FLUO!" << G4endl; //debug
}
else {provShellId = -2;}
}
// Look this in a particular way: only one auger emitted! // ????
while (provShellId > -2);
}
G4double
G4UAtomicDeexcitation::GetShellIonisationCrossSectionPerAtom(
const G4ParticleDefinition* pdef,
G4int Z /*Z*/,
G4AtomicShellEnumerator shellEnum/*shell*/,
G4double kineticEnergy/*kinE*/)
{
// scaling to protons
G4double mass = proton_mass_c2;
G4double escaled = kineticEnergy*mass/(pdef->GetPDGMass());
G4double q = pdef->GetPDGCharge()/eplus;
std::vector<G4double> atomXSs = PIXEshellCS->GetCrossSection(Z,escaled,mass,0);
G4double res = 0.0;
G4int idx = G4int(shellEnum);
G4int length = atomXSs.size();
if(idx < length) { res = q*q*atomXSs[idx]; }
return res;
}
void G4UAtomicDeexcitation::SetCutForSecondaryPhotons(G4double cut)
{
minGammaEnergy = cut;
}
void G4UAtomicDeexcitation::SetCutForAugerElectrons(G4double cut)
{
minElectronEnergy = cut;
}
G4double
G4UAtomicDeexcitation::ComputeShellIonisationCrossSectionPerAtom(
const G4ParticleDefinition* p,
G4int Z,
G4AtomicShellEnumerator shell,
G4double kinE)
{
return GetShellIonisationCrossSectionPerAtom(p,Z,shell,kinE);
}
G4int G4UAtomicDeexcitation::SelectTypeOfTransition(G4int Z, G4int shellId)
{
if (shellId <=0 ) {
{G4Exception("G4UAtomicDeexcitation: zero or negative shellId");}
}
G4bool fluoTransitionFoundFlag = false;
G4int provShellId = -1;
G4int shellNum = 0;
G4int maxNumOfShells = transitionManager->NumberOfReachableShells(Z);
const G4FluoTransition* refShell = transitionManager->ReachableShell(Z,maxNumOfShells-1);
// This loop gives shellNum the value of the index of shellId
// in the vector storing the list of the shells reachable through
// a radiative transition
if ( shellId <= refShell->FinalShellId())
{
while (shellId != transitionManager->ReachableShell(Z,shellNum)->FinalShellId())
{
if(shellNum ==maxNumOfShells-1)
{
break;
}
shellNum++;
}
G4int transProb = 0; //AM change 29/6/07 was 1
G4double partialProb = G4UniformRand();
G4double partSum = 0;
const G4FluoTransition* aShell = transitionManager->ReachableShell(Z,shellNum);
G4int trSize = (aShell->TransitionProbabilities()).size();
// Loop over the shells wich can provide an electron for a
// radiative transition towards shellId:
// in every loop the partial sum of the first transProb shells
// is calculated and compared with a random number [0,1].
// If the partial sum is greater, the shell whose index is transProb
// is chosen as the starting shell for a radiative transition
// and its identity is returned
// Else, terminateded the loop, -1 is returned
while(transProb < trSize){
partSum += aShell->TransitionProbability(transProb);
if(partialProb <= partSum)
{
provShellId = aShell->OriginatingShellId(transProb);
fluoTransitionFoundFlag = true;
break;
}
transProb++;
}
// here provShellId is the right one or is -1.
// if -1, the control is passed to the Auger generation part of the package
}
else
{
provShellId = -1;
}
return provShellId;
}
G4DynamicParticle*
G4UAtomicDeexcitation::GenerateFluorescence(G4int Z, G4int shellId,
G4int provShellId )
{
//isotropic angular distribution for the outcoming photon
G4double newcosTh = 1.-2.*G4UniformRand();
G4double newsinTh = std::sqrt((1.-newcosTh)*(1. + newcosTh));
G4double newPhi = twopi*G4UniformRand();
G4double xDir = newsinTh*std::sin(newPhi);
G4double yDir = newsinTh*std::cos(newPhi);
G4double zDir = newcosTh;
G4ThreeVector newGammaDirection(xDir,yDir,zDir);
G4int shellNum = 0;
G4int maxNumOfShells = transitionManager->NumberOfReachableShells(Z);
// find the index of the shell named shellId
while (shellId != transitionManager->
ReachableShell(Z,shellNum)->FinalShellId())
{
if(shellNum == maxNumOfShells-1)
{
break;
}
shellNum++;
}
// number of shell from wich an electron can reach shellId
size_t transitionSize = transitionManager->
ReachableShell(Z,shellNum)->OriginatingShellIds().size();
size_t index = 0;
// find the index of the shell named provShellId in the vector
// storing the shells from which shellId can be reached
while (provShellId != transitionManager->
ReachableShell(Z,shellNum)->OriginatingShellId(index))
{
if(index == transitionSize-1)
{
break;
}
index++;
}
// energy of the gamma leaving provShellId for shellId
G4double transitionEnergy = transitionManager->
ReachableShell(Z,shellNum)->TransitionEnergy(index);
if (transitionEnergy < minGammaEnergy) return 0;
// This is the shell where the new vacancy is: it is the same
// shell where the electron came from
newShellId = transitionManager->
ReachableShell(Z,shellNum)->OriginatingShellId(index);
G4DynamicParticle* newPart = new G4DynamicParticle(G4Gamma::Gamma(),
newGammaDirection,
transitionEnergy);
return newPart;
}
G4DynamicParticle* G4UAtomicDeexcitation::GenerateAuger(G4int Z, G4int shellId)
{
if(!IsAugerActive()) { return 0; }
if (shellId <=0 ) {
{G4Exception("G4UAtomicDeexcitation: zero or negative shellId");}
}
// G4int provShellId = -1;
G4int maxNumOfShells = transitionManager->NumberOfReachableAugerShells(Z);
const G4AugerTransition* refAugerTransition =
transitionManager->ReachableAugerShell(Z,maxNumOfShells-1);
// This loop gives to shellNum the value of the index of shellId
// in the vector storing the list of the vacancies in the variuos shells
// that can originate a NON-radiative transition
// ---- MGP ---- Next line commented out to remove compilation warning
// G4int p = refAugerTransition->FinalShellId();
G4int shellNum = 0;
if ( shellId <= refAugerTransition->FinalShellId() )
//"FinalShellId" is final from the point of view of the elctron who makes the transition,
// being the Id of the shell in which there is a vacancy
{
G4int pippo = transitionManager->ReachableAugerShell(Z,shellNum)->FinalShellId();
if (shellId != pippo ) {
do {
shellNum++;
if(shellNum == maxNumOfShells)
{
//G4Exception("G4UAtomicDeexcitation: No Auger transition found");
return 0;
}
}
while (shellId != (transitionManager->ReachableAugerShell(Z,shellNum)->FinalShellId()) ) ;
}
// Now we have that shellnum is the shellIndex of the shell named ShellId
// G4cout << " the index of the shell is: "<<shellNum<<G4endl;
// But we have now to select two shells: one for the transition,
// and another for the auger emission.
G4int transitionLoopShellIndex = 0;
G4double partSum = 0;
const G4AugerTransition* anAugerTransition =
transitionManager->ReachableAugerShell(Z,shellNum);
// G4cout << " corresponding to the ID: "<< anAugerTransition->FinalShellId() << G4endl;
G4int transitionSize =
(anAugerTransition->TransitionOriginatingShellIds())->size();
while (transitionLoopShellIndex < transitionSize) {
std::vector<G4int>::const_iterator pos =
anAugerTransition->TransitionOriginatingShellIds()->begin();
G4int transitionLoopShellId = *(pos+transitionLoopShellIndex);
G4int numberOfPossibleAuger =
(anAugerTransition->AugerTransitionProbabilities(transitionLoopShellId))->size();
G4int augerIndex = 0;
// G4int partSum2 = 0;
if (augerIndex < numberOfPossibleAuger) {
do
{
G4double thisProb = anAugerTransition->AugerTransitionProbability(augerIndex,
transitionLoopShellId);
partSum += thisProb;
augerIndex++;
} while (augerIndex < numberOfPossibleAuger);
}
transitionLoopShellIndex++;
}
// Now we have the entire probability of an auger transition for the vacancy
// located in shellNum (index of shellId)
// AM *********************** F I X E D **************************** AM
// Here we duplicate the previous loop, this time looking to the sum of the probabilities
// to be under the random number shoot by G4 UniformRdandom. This could have been done in the
// previuos loop, while integrating the probabilities. There is a bug that will be fixed
// 5 minutes from now: a line:
// G4int numberOfPossibleAuger = (anAugerTransition->
// AugerTransitionProbabilities(transitionLoopShellId))->size();
// to be inserted.
// AM *********************** F I X E D **************************** AM
// Remains to get the same result with a single loop.
// AM *********************** F I X E D **************************** AM
// Another Bug: in EADL Auger Transition are normalized to all the transitions deriving from
// a vacancy in one shell, but not all of these are present in data tables. So if a transition
// doesn't occur in the main one a local energy deposition must occur, instead of (like now)
// generating the last transition present in EADL data.
// AM *********************** F I X E D **************************** AM
G4double totalVacancyAugerProbability = partSum;
//And now we start to select the right auger transition and emission
G4int transitionRandomShellIndex = 0;
G4int transitionRandomShellId = 1;
G4int augerIndex = 0;
partSum = 0;
G4double partialProb = G4UniformRand();
// G4int augerOriginatingShellId = 0;
G4int numberOfPossibleAuger = 0;
G4bool foundFlag = false;
while (transitionRandomShellIndex < transitionSize) {
std::vector<G4int>::const_iterator pos =
anAugerTransition->TransitionOriginatingShellIds()->begin();
transitionRandomShellId = *(pos+transitionRandomShellIndex);
augerIndex = 0;
numberOfPossibleAuger = (anAugerTransition->
AugerTransitionProbabilities(transitionRandomShellId))->size();
while (augerIndex < numberOfPossibleAuger) {
G4double thisProb =anAugerTransition->AugerTransitionProbability(augerIndex,
transitionRandomShellId);
partSum += thisProb;
if (partSum >= (partialProb*totalVacancyAugerProbability) ) { // was /
foundFlag = true;
break;
}
augerIndex++;
}
if (partSum >= (partialProb*totalVacancyAugerProbability) ) {break;} // was /
transitionRandomShellIndex++;
}
// Now we have the index of the shell from wich comes the auger electron (augerIndex),
// and the id of the shell, from which the transition e- come (transitionRandomShellid)
// If no Transition has been found, 0 is returned.
if (!foundFlag) {return 0;}
// Isotropic angular distribution for the outcoming e-
G4double newcosTh = 1.-2.*G4UniformRand();
G4double newsinTh = std::sqrt(1.-newcosTh*newcosTh);
G4double newPhi = twopi*G4UniformRand();
G4double xDir = newsinTh*std::sin(newPhi);
G4double yDir = newsinTh*std::cos(newPhi);
G4double zDir = newcosTh;
G4ThreeVector newElectronDirection(xDir,yDir,zDir);
// energy of the auger electron emitted
G4double transitionEnergy = anAugerTransition->AugerTransitionEnergy(augerIndex, transitionRandomShellId);
/*
G4cout << "AUger TransitionId " << anAugerTransition->FinalShellId() << G4endl;
G4cout << "augerIndex: " << augerIndex << G4endl;
G4cout << "transitionShellId: " << transitionRandomShellId << G4endl;
*/
if (transitionEnergy < minElectronEnergy) return 0;
// This is the shell where the new vacancy is: it is the same
// shell where the electron came from
newShellId = transitionRandomShellId;
return new G4DynamicParticle(G4Electron::Electron(),
newElectronDirection,
transitionEnergy);
}
else
{
//G4Exception("G4UAtomicDeexcitation: no auger transition found");
return 0;
}
}
@@ -24,8 +24,8 @@
// ********************************************************************
//
//
// $Id: G4VCrossSectionHandler.cc,v 1.19 2009/09/25 07:41:34 sincerti Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4VCrossSectionHandler.cc,v 1.20 2010/12/02 17:39:47 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -151,6 +151,7 @@ void G4VCrossSectionHandler::Initialise(G4VDataSetAlgorithm* algorithm,
}
else
{
delete interpolation;
interpolation = CreateInterpolation();
}
@@ -496,6 +497,7 @@ G4VEMDataSet* G4VCrossSectionHandler::BuildMeanFreePathForMaterials(const G4Data
G4VDataSetAlgorithm* algo = CreateInterpolation();
G4VEMDataSet* materialSet = new G4CompositeEMDataSet(algo);
//G4cout << "G4VCrossSectionHandler new dataset " << materialSet << G4endl;
G4DataVector* energies;
G4DataVector* data;
@@ -23,46 +23,41 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//$Id: G4VecpssrKModel.cc,v 1.2 2010/06/06 23:52:28 mantero Exp $
// GEANT4 tag $Name: geant4-09-04-beta-01 $
//
// Author: Haifa Ben Abdelouahed
//
//
// History:
// -----------
// 01 Sep 2009 ALF created
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4VBremAngularDistribution
//
// Author: Andreia Trindade (andreia@lip.pt)
// Pedro Rodrigues (psilva@lip.pt)
// Luis Peralta (luis@lip.pt)
// Maria Grazia Pia (MariaGrazia.Pia@ge.infn.it)
//
// Creation date: 21 March 2003
//
// Modifications:
//
// Class Description:
//
// Abstract base class for Bremsstrahlung Angular Distribution Generation
//
// Class Description: End
// Class description:
// Low Energy Electromagnetic Physics, Cross section, p and alpha ionisation, L shell
// Further documentation available from http://www.ge.infn.it/geant4/lowE
// -------------------------------------------------------------------
//
//
#include "G4VBremAngularDistribution.hh"
//
G4VBremAngularDistribution::G4VBremAngularDistribution(const G4String& ) // name
{;}
#include "G4VecpssrKModel.hh"
//
G4VBremAngularDistribution::~G4VBremAngularDistribution()
{;}
G4VecpssrKModel::G4VecpssrKModel()
{
void G4VBremAngularDistribution::PrintGeneratorInformation() const
{;}
}
G4VecpssrKModel::~G4VecpssrKModel()
{
}
/*
G4double G4VecpssrKModel::CalculateCrossSection(G4int,G4double,G4double)
{
}
*/
//
@@ -0,0 +1,75 @@
//
// ********************************************************************
// * 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: G4VecpssrLiModel.cc,v 1.2 2010/06/06 23:52:28 mantero Exp $
// GEANT4 tag $Name: geant4-09-04-beta-01 $
//
// Author: Haifa Ben Abdelouahed
//
//
// History:
// -----------
// 01 Sep 2009 ALF created
//
// -------------------------------------------------------------------
// Class description:
// Low Energy Electromagnetic Physics, Cross section, p and alpha ionisation, L shell
// Further documentation available from http://www.ge.infn.it/geant4/lowE
// -------------------------------------------------------------------
#include "G4VecpssrLiModel.hh"
G4VecpssrLiModel::G4VecpssrLiModel()
{
}
G4VecpssrLiModel::~G4VecpssrLiModel()
{
}
/*G4double G4VecpssrLiModel::CalculateL1CrossSection(G4int ,G4double , G4double )
{
}
G4double G4VecpssrLiModel::CalculateL2CrossSection(G4int ,G4double , G4double )
{
}
G4double G4VecpssrLiModel::CalculateL3CrossSection(G4int ,G4double , G4double )
{
}
*/
@@ -60,9 +60,11 @@ G4int G4VhShellCrossSection::SelectRandomShell(G4int Z,
G4double incidentEnergy,
G4double mass,
G4double deltaEnergy) const
// returns the shell ionized if the shell exists. If the shell is not counted, it returns -1
{
std::vector<G4double> p = Probabilities(Z,incidentEnergy,mass,deltaEnergy);
G4int shell = 0;
G4int shell = -1;
size_t nShells = p.size();
G4double q = G4UniformRand();
for (size_t i=0; i<nShells; i++) {
@@ -1,303 +0,0 @@
//
// ********************************************************************
// * 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: G4ecpssrCrossSection.cc,v 1.6.2.2 2009/12/11 18:44:44 japost Exp $
// GEANT4 tag $Name: geant4-09-03 $
//
// Author: Haifa Ben Abdelouahed
//
//
// History:
// -----------
// 21 Apr 2008 H. Ben Abdelouahed 1st implementation
// 21 Apr 2008 MGP Major revision according to a design iteration
//
// -------------------------------------------------------------------
// Class description:
// Low Energy Electromagnetic Physics, Cross section, p ionisation, K shell
// Further documentation available from http://www.ge.infn.it/geant4/lowE
// -------------------------------------------------------------------
#include "globals.hh"
#include "G4ecpssrCrossSection.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4NistManager.hh"
#include "G4Proton.hh"
#include "G4Alpha.hh"
#include <math.h>
G4ecpssrCrossSection::G4ecpssrCrossSection()
{ }
G4ecpssrCrossSection::~G4ecpssrCrossSection()
{ }
//---------------------------------this "ExpIntFunction" function allows fast evaluation of the n order exponential integral function En(x)------
G4double G4ecpssrCrossSection::ExpIntFunction(G4int n,G4double 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 << "bad arguments in ExpIntFunction" << 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;
}
//-----------------------------------------------------------------------------------------------------------
G4double G4ecpssrCrossSection::CalculateCrossSection(G4int zTarget,G4int zIncident, 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 massIncident;
if (zIncident == 1)
{
G4Proton* aProtone = G4Proton::Proton();
massIncident = aProtone->GetPDGMass();
}
else
{
if (zIncident == 2)
{
G4Alpha* aAlpha = G4Alpha::Alpha();
massIncident = aAlpha->GetPDGMass();
}
else
{
G4cout << "we can treat only Proton or Alpha incident particles " << G4endl;
massIncident =0.;
}
}
G4double kBindingEnergy = transitionManager->Shell(zTarget,0)->BindingEnergy();
G4double massTarget = (massManager->GetAtomicMassAmu(zTarget))*amu_c2;
G4double systemMass =((massIncident*massTarget)/(massIncident+massTarget))/electron_mass_c2;//the mass of the system (projectile, target)
const G4double zkshell= 0.3;
G4double screenedzTarget = zTarget-zkshell; // screenedzTarget is the screened nuclear charge of the target
const G4double rydbergMeV= 13.6e-6;
G4double tetaK = kBindingEnergy/((screenedzTarget*screenedzTarget)*rydbergMeV); //tetaK denotes the reduced binding energy of the electron
const G4double bohrPow2Barn=(Bohr_radius*Bohr_radius)/barn ;
G4double sigma0 = 8.*pi*(zIncident*zIncident)*bohrPow2Barn*std::pow(screenedzTarget,-4.); //sigma0 is the initial cross section of K shell at stable state
//---------------------------------------------------------------------------------------------------------------------
G4double velocity = CalculateVelocity( zTarget, zIncident, energyIncident); //is the scaled velocity parameter of the system
//---------------------------------------------------------------------------------------------------------------------
const G4double kAnalyticalApproximation= 1.5;
G4double x = kAnalyticalApproximation/velocity;
G4double electrIonizationEnergy;
if ( x<0.035)
{
electrIonizationEnergy= 0.75*pi*(std::log(1./(x*x))-1.);
}
else
{
if ( 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
{
electrIonizationEnergy =2.*std::exp(-2.*x)/std::pow(x,1.6); }
}
G4double hFunction =(electrIonizationEnergy*2.)/(tetaK*std::pow(velocity,3)); //hFunction represents the correction for polarization effet
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
//-----------------------------------------------------------------------------------------------------------------------------
G4double sigmaPSS = 1.+(((2.*zIncident)/(screenedzTarget*tetaK))*(gFunction-hFunction)); //describes the perturbed stationnairy state of the affected atomic electon
//----------------------------------------------------------------------------------------------------------------------------
const G4double cNaturalUnit= 1/fine_structure_const; // it's the speed of light according to Atomic-Unit-System
G4double ykFormula=0.4*(screenedzTarget/cNaturalUnit)*(screenedzTarget/cNaturalUnit)/(velocity/sigmaPSS);
G4double relativityCorrection = std::pow((1.+(1.1*ykFormula*ykFormula)),0.5)+ykFormula;// the relativistic correction parameter
G4double reducedVelocity = velocity*std::pow(relativityCorrection,0.5); // presents the reduced collision velocity parameter
G4double 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
//----------------------------------------------------------------------------------------------------------------------
G4double sigmaPSSR = (sigma0/(sigmaPSS*tetaK))*universalFunction; //sigmaPSSR is the straight-line K-shell ionization cross section
//-----------------------------------------------------------------------------------------------------------------------
G4double pssDeltaK = (4./(systemMass*sigmaPSS*tetaK))*(sigmaPSS/velocity)*(sigmaPSS/velocity);
G4double energyLoss = std::pow(1-pssDeltaK,0.5); //energyLoss incorporates the straight-line energy-loss
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
//----------------------------------------------------------------------------------------------------------------------------------------------
G4double coulombDeflection = (4.*pi*zIncident/systemMass)*std::pow(tetaK*sigmaPSS,-2.)*std::pow(velocity/sigmaPSS,-3.)*(zTarget/screenedzTarget); //incorporates Coulomb deflection parameter
G4double cParameter = 2.*coulombDeflection/(energyLoss*(energyLoss+1.));
G4double coulombDeflectionFunction = 9.*ExpIntFunction(10,cParameter); //this function describes Coulomb-deflection effect
//--------------------------------------------------------------------------------------------------------------------------------------------------
G4double 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
//--------------------------------------------------------------------------------------------------------------------------------------------------
return crossSection;
}
G4double G4ecpssrCrossSection::CalculateVelocity(G4int zTarget, G4int zIncident, G4double energyIncident)
{
G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
G4double kBindingEnergy = (transitionManager->Shell(zTarget,0)->BindingEnergy())/MeV;
G4double massIncident;
if (zIncident == 1)
{
G4Proton* aProtone = G4Proton::Proton();
massIncident = aProtone->GetPDGMass();
}
else
{
if (zIncident == 2)
{
G4Alpha* aAlpha = G4Alpha::Alpha();
massIncident = aAlpha->GetPDGMass();
}
else
{
G4cout << "we can treat only Proton or Alpha incident particles " << G4endl;
massIncident =0.;
}
}
const G4double zkshell= 0.3;
G4double screenedzTarget = zTarget- zkshell;
const G4double rydbergMeV= 13.6e-6;
G4double tetaK = kBindingEnergy/(screenedzTarget*screenedzTarget*rydbergMeV);
G4double velocity =(2./(tetaK*screenedzTarget))*std::pow(((energyIncident*electron_mass_c2)/(massIncident*rydbergMeV)),0.5);
return velocity;
}
@@ -0,0 +1,123 @@
//
// ********************************************************************
// * 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: G4empCrossSection.cc,v 1.3 2010/11/12 18:09:44 mantero Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
//
//
// History:
// -----------
// 29 Apr 2009 ALF 1st implementation
//
// -------------------------------------------------------------------
// Class description:
// empirical model for K and L Ionization CS for Protons and Alpha
// Further documentation available from http://www.ge.infn.it/geant4/lowE
// -------------------------------------------------------------------
#include "globals.hh"
#include "G4empCrossSection.hh"
#include "G4Proton.hh"
//#include "G4Alpha.hh"
//#include <math.h>
G4empCrossSection::G4empCrossSection()
:totalCS(0)
{
paulShellK = new G4PaulKCrossSection();
orlicShellLi = new G4OrlicLiCrossSection();
}
G4empCrossSection::~G4empCrossSection()
{
delete paulShellK;
delete orlicShellLi;
}
std::vector<G4double> G4empCrossSection::GetCrossSection(G4int Z,
G4double incidentEnergy,
G4double mass,
G4double deltaEnergy,
G4bool testFlag) const
{
deltaEnergy = 0;
testFlag = 0;
std::vector<G4double> crossSections;
crossSections.push_back( paulShellK->CalculateKCrossSection(Z, mass, incidentEnergy) );
G4Proton* aProtone = G4Proton::Proton();
if (mass == aProtone->GetPDGMass() ) {
crossSections.push_back( orlicShellLi->CalculateL1CrossSection(Z, incidentEnergy) );
crossSections.push_back( orlicShellLi->CalculateL2CrossSection(Z, incidentEnergy) );
crossSections.push_back( orlicShellLi->CalculateL3CrossSection(Z, incidentEnergy) );
}
return crossSections;
}
std::vector<G4double> G4empCrossSection::Probabilities(G4int Z,
G4double incidentEnergy,
G4double mass,
G4double deltaEnergy) const
{
std::vector<G4double> crossSections = GetCrossSection(Z, incidentEnergy, mass, deltaEnergy);
for (size_t i=0; i<crossSections.size(); i++ ) {
if (totalCS) {
crossSections[i] = crossSections[i]/totalCS;
}
}
return crossSections;
}
void G4empCrossSection::SetTotalCS(G4double val){
totalCS = val;
}
@@ -99,8 +99,8 @@
// 03 Oct 2005 V.Ivanchenko change logic of definition of high energy limit for
// parametrised proton model: min(user value, model limit)
// 26 Jan 2005 S. Chauvie added PrintInfoDefinition() for antiproton
// 30 Sep 2009 A.Mantero Removed dependencies to old shell Ionisation XS models
// 07 Jun 2010 Code Celaning for June beta Release
// -----------------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -120,9 +120,6 @@
#include "G4AtomicTransitionManager.hh"
#include "G4ShellVacancy.hh"
#include "G4VhShellCrossSection.hh"
#include "G4hShellCrossSection.hh"
#include "G4hShellCrossSectionExp.hh"
#include "G4hShellCrossSectionDoubleExp.hh"
#include "G4VEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4CompositeEMDataSet.hh"
@@ -131,7 +128,8 @@
#include "G4SemiLogInterpolation.hh"
#include "G4ProcessManager.hh"
#include "G4ProductionCutsTable.hh"
#include "G4teoCrossSection.hh"
#include "G4empCrossSection.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4hLowEnergyIonisation::G4hLowEnergyIonisation(const G4String& processName)
@@ -152,8 +150,7 @@ G4hLowEnergyIonisation::G4hLowEnergyIonisation(const G4String& processName)
paramStepLimit (0.005),
shellVacancy(0),
shellCS(0),
theFluo(false),
expFlag(false)
theFluo(false)
{
InitializeMe();
}
@@ -174,18 +171,12 @@ void G4hLowEnergyIonisation::InitializeMe()
minElectronEnergy = 25.*keV;
verboseLevel = 0;
//****************************************************************************
// By default the method of cross section's calculation is swiched on an
// 2nd implementation empirical model (G4hShellCrossSectionDoubleExp),
// if you want to use Gryzinski's model (G4hShellCrossSection()) or the
// 1st empiric one (G4hShellCrossSectionExp), you must change the
// selection below and switching expFlag to FALSE
//****************************************************************************
shellCS = new G4teoCrossSection("analytical");
deexcitationManager.InitialiseForNewRun();
deexcitationManager.SetAugerActive(false);
deexcitationManager.SetPIXEActive(true);
//shellCS = new G4hShellCrossSection();
//shellCS = new G4hShellCrossSectionExp();
shellCS = new G4hShellCrossSectionDoubleExp();
expFlag=true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -1002,6 +993,7 @@ G4VParticleChange* G4hLowEnergyIonisation::AlongStepDoIt(
if(newpart != 0) {
// G4cout << "AlongStep DEEXCTATION!!!" << G4endl; //debug
size_t nSecondaries = newpart->size();
aParticleChange.SetNumberOfSecondaries(nSecondaries);
G4Track* newtrack = 0;
@@ -1279,70 +1271,67 @@ G4VParticleChange* G4hLowEnergyIonisation::PostStepDoIt(
// G4cout << "Fluorescence is switched :" << theFluo << G4endl;
// Fluorescence data start from element 6
if(theFluo && Z > 5) {
// Atom total cross section for the Empiric Model
if (expFlag) {
// Atom total cross section
shellCS->SetTotalCS(totalCrossSectionMap[Z]);
}
G4int shell = shellCS->SelectRandomShell(Z, KineticEnergy,ParticleMass,DeltaKineticEnergy);
if (expFlag && shell==1) {
aParticleChange.ProposeLocalEnergyDeposit (KineticEnergy);
aParticleChange.ProposeEnergy(0);
}
const G4AtomicShell* atomicShell =
(G4AtomicTransitionManager::Instance())->Shell(Z, shell);
G4double bindingEnergy = atomicShell->BindingEnergy();
if(verboseLevel > 1) {
G4cout << "PostStep Z= " << Z << " shell= " << shell
<< " bindingE(keV)= " << bindingEnergy/keV
<< " finalE(keV)= " << finalKineticEnergy/keV
<< G4endl;
}
// Fluorescence data start from element 6
if (finalKineticEnergy >= bindingEnergy
&& (bindingEnergy >= minGammaEnergy
|| bindingEnergy >= minElectronEnergy) ) {
G4int shellId = atomicShell->ShellId();
secondaryVector = deexcitationManager.GenerateParticles(Z, shellId);
if (secondaryVector != 0) {
nSecondaries = secondaryVector->size();
for (size_t i = 0; i<nSecondaries; i++) {
aSecondary = (*secondaryVector)[i];
if (aSecondary) {
G4double e = aSecondary->GetKineticEnergy();
type = aSecondary->GetDefinition();
if (e < finalKineticEnergy &&
((type == G4Gamma::Gamma() && e > minGammaEnergy ) ||
(type == G4Electron::Electron() && e > minElectronEnergy ))) {
finalKineticEnergy -= e;
totalNumber++;
} else {
delete aSecondary;
(*secondaryVector)[i] = 0;
if (shell!=-1) {
const G4AtomicShell* atomicShell =
(G4AtomicTransitionManager::Instance())->Shell(Z, shell);
G4double bindingEnergy = atomicShell->BindingEnergy();
if(verboseLevel > 1) {
G4cout << "PostStep Z= " << Z << " shell= " << shell
<< " bindingE(keV)= " << bindingEnergy/keV
<< " finalE(keV)= " << finalKineticEnergy/keV
<< G4endl;
}
if (finalKineticEnergy >= bindingEnergy
&& (bindingEnergy >= minGammaEnergy
|| bindingEnergy >= minElectronEnergy) ) {
// G4int shellId = atomicShell->ShellId();
deexcitationManager.GenerateParticles(secondaryVector, atomicShell, Z, minGammaEnergy, minElectronEnergy);
if (secondaryVector != 0) {
// debug G4cout << "DEEXCTATION!!!" << G4endl; //debug
nSecondaries = secondaryVector->size();
for (size_t i = 0; i<nSecondaries; i++) {
aSecondary = (*secondaryVector)[i];
if (aSecondary) {
G4double e = aSecondary->GetKineticEnergy();
type = aSecondary->GetDefinition();
if (e < finalKineticEnergy &&
((type == G4Gamma::Gamma() && e > minGammaEnergy ) ||
(type == G4Electron::Electron() && e > minElectronEnergy ))) {
finalKineticEnergy -= e;
totalNumber++;
} else {
delete aSecondary;
(*secondaryVector)[i] = 0;
}
}
}
}
}
}
}
// Save delta-electrons
G4double edep = 0.0;
@@ -1400,8 +1389,26 @@ G4VParticleChange* G4hLowEnergyIonisation::PostStepDoIt(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4DynamicParticle*>*
G4hLowEnergyIonisation::DeexciteAtom(const G4MaterialCutsCouple* couple,
void G4hLowEnergyIonisation::SelectShellIonisationCS(G4String val) {
if (val == "analytical" ) {
if (shellCS) delete shellCS;
shellCS = new G4teoCrossSection(val);
}
else if (val == "empirical") {
if (shellCS) delete shellCS;
shellCS = new G4empCrossSection();
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4DynamicParticle*>* G4hLowEnergyIonisation::DeexciteAtom(const G4MaterialCutsCouple* couple,
G4double incidentEnergy,
G4double hMass,
G4double eLoss)
@@ -1447,15 +1454,15 @@ G4hLowEnergyIonisation::DeexciteAtom(const G4MaterialCutsCouple* couple,
if(stop) return 0;
// create vector of tracks of secondary particles
std::vector<G4DynamicParticle*>* partVector =
new std::vector<G4DynamicParticle*>;
std::vector<G4DynamicParticle*>* secVector = 0;
std::vector<G4DynamicParticle*>* secVector = new std::vector<G4DynamicParticle*>;
G4DynamicParticle* aSecondary = 0;
G4ParticleDefinition* type = 0;
G4double e, tkin, grej;
G4ThreeVector position;
G4int shell, shellId;
G4int shell;
// sample secondaries
@@ -1479,44 +1486,54 @@ G4hLowEnergyIonisation::DeexciteAtom(const G4MaterialCutsCouple* couple,
} while( G4UniformRand() > grej );
// Atom total cross section
shellCS->SetTotalCS(totalCrossSectionMap[Z]);
shell = shellCS->SelectRandomShell(Z,incidentEnergy,hMass,tkin);
shellId = transitionManager->Shell(Z, shell)->ShellId();
// shellId = transitionManager->Shell(Z, shell)->ShellId();
G4double maxE = transitionManager->Shell(Z, shell)->BindingEnergy();
if (maxE>minGammaEnergy || maxE>minElectronEnergy ) {
secVector = deexcitationManager.GenerateParticles(Z, shellId);
} else {
secVector = 0;
}
if (secVector) {
for (size_t l = 0; l<secVector->size(); l++) {
aSecondary = (*secVector)[l];
if(aSecondary) {
e = aSecondary->GetKineticEnergy();
type = aSecondary->GetDefinition();
if ( etot + e <= eLoss &&
( (type == G4Gamma::Gamma() && e > minGammaEnergy ) ||
(type == G4Electron::Electron() && e > minElectronEnergy) ) ) {
etot += e;
partVector->push_back(aSecondary);
} else {
delete aSecondary;
}
}
if (maxE>minGammaEnergy || maxE>minElectronEnergy )
{
deexcitationManager.GenerateParticles(secVector, transitionManager->Shell(Z, shell), Z, minGammaEnergy, minElectronEnergy);
}
if (!(secVector->empty())) {
size_t secN = secVector->size();
for (size_t l = 0; l<secN; l++) {
aSecondary = (*secVector)[l];
if(aSecondary) {
e = aSecondary->GetKineticEnergy();
type = aSecondary->GetDefinition();
if ( etot + e <= eLoss &&
( (type == G4Gamma::Gamma() && e > minGammaEnergy ) ||
(type == G4Electron::Electron() && e > minElectronEnergy) ) )
{
etot += e;
partVector->push_back(aSecondary);
}
else
{
delete aSecondary;
}
aSecondary = 0;
}
(*secVector)[l] = 0;
delete (*secVector)[l];
}
// secVector = 0;
}
delete secVector;
}
}
}
}
delete secVector;
if(partVector->empty()) {
delete partVector;
return 0;
@@ -2010,7 +2027,7 @@ void G4hLowEnergyIonisation::SetCutForAugerElectrons(G4double cut)
void G4hLowEnergyIonisation::ActivateAugerElectronProduction(G4bool val)
{
deexcitationManager.ActivateAugerElectronProduction(val);
deexcitationManager.SetAugerActive(val);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -40,8 +40,8 @@
// Class Description:
// Empiric Model for shell cross sections in proton ionisation
// -------------------------------------------------------------------
// $Id: G4hShellCrossSectionDoubleExp.cc,v 1.10 2009/06/10 13:32:36 mantero Exp $
// GEANT4 tag $Name: geant4-09-03 $
// $Id: G4hShellCrossSectionDoubleExp.cc,v 1.11 2010/02/05 08:54:12 sincerti Exp $
// GEANT4 tag $Name: geant4-09-04-beta-01 $
#include "globals.hh"
#include <vector>
@@ -55,6 +55,8 @@
G4hShellCrossSectionDoubleExp::G4hShellCrossSectionDoubleExp()
{
kShellData = new G4hShellCrossSectionDoubleExpData();
atomTotalCrossSection = 0.;
}
G4hShellCrossSectionDoubleExp::~G4hShellCrossSectionDoubleExp()
@@ -0,0 +1,134 @@
//
// ********************************************************************
// * 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: G4teoCrossSection.cc,v 1.8 2010/11/22 22:48:30 mantero Exp $
// GEANT4 tag $Name: geant4-09-04 $
//
//
//
// History:
// -----------
// 21 Apr 2009 ALF 1st implementation
// 29 Apr 2009 ALF Updated Desing for Integration
//
// -------------------------------------------------------------------
// Class description:
// Low Energy Electromagnetic Physics, Cross section, p ionisation, K shell
// Further documentation available from http://www.ge.infn.it/geant4/lowE
// -------------------------------------------------------------------
#include "globals.hh"
#include "G4teoCrossSection.hh"
//#include "G4AtomicTransitionManager.hh"
//#include "G4NistManager.hh"
#include "G4Proton.hh"
//#include "G4Alpha.hh"
//#include <math.h>
G4teoCrossSection::G4teoCrossSection(G4String shellModel)
:totalCS(0)
{
if (shellModel == "analytical") {
ecpssrShellK = new G4AnalyticalEcpssrKCrossSection();
ecpssrShellLi = new G4AnalyticalEcpssrLiCrossSection();
}
}
G4teoCrossSection::~G4teoCrossSection()
{
delete ecpssrShellK;
delete ecpssrShellLi;
}
std::vector<G4double> G4teoCrossSection::GetCrossSection(G4int Z,
G4double incidentEnergy,
G4double mass,
G4double deltaEnergy,
G4bool testFlag) const
{
deltaEnergy = 0;
testFlag = 0;
std::vector<G4double> crossSections;
crossSections.push_back( ecpssrShellK->CalculateCrossSection(Z, mass, incidentEnergy) );
// G4Proton* aProtone = G4Proton::Proton();
// if (mass == aProtone->GetPDGMass() ) {
// }
crossSections.push_back( ecpssrShellLi->CalculateL1CrossSection(Z, mass, incidentEnergy) );
crossSections.push_back( ecpssrShellLi->CalculateL2CrossSection(Z, mass, incidentEnergy) );
crossSections.push_back( ecpssrShellLi->CalculateL3CrossSection(Z, mass, incidentEnergy) );
return crossSections;
}
std::vector<G4double> G4teoCrossSection::Probabilities(G4int Z,
G4double incidentEnergy,
G4double mass,
G4double deltaEnergy) const
{
std::vector<G4double> crossSections = GetCrossSection(Z, incidentEnergy, mass, deltaEnergy);
for (size_t i=0; i<crossSections.size(); i++ ) {
if (totalCS) {
crossSections[i] = crossSections[i]/totalCS;
}
}
return crossSections;
}
void G4teoCrossSection::SetTotalCS(G4double val){
totalCS = val;
// G4cout << "totalXS set to: " << val / barn << " barns" << G4endl;
}