// // ******************************************************************** // * 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: G4EmCorrections.cc,v 1.58 2010/06/04 09:28:46 vnivanch Exp $ // GEANT4 tag $Name: geant4-09-04-beta-cand-01 $ // // ------------------------------------------------------------------- // // GEANT4 Class // // File name: G4EmCorrections // // Author: Vladimir Ivanchenko // // Creation date: 13.01.2005 // // Modifications: // 05.05.2005 V.Ivanchenko Fix misprint in Mott term // 26.11.2005 V.Ivanchenko Fix effective charge for heavy ions using original paper // 28.04.2006 V.Ivanchenko General cleanup, add finite size corrections // 13.05.2006 V.Ivanchenko Add corrections for ion stopping // 08.05.2007 V.Ivanchenko Use G4IonTable for ion mass instead of NistTable to avoid // division by zero // 29.02.2008 V.Ivanchenko use expantions for log and power function // 21.04.2008 Updated computations for ions (V.Ivanchenko) // 20.05.2008 Removed Finite Size correction (V.Ivanchenko) // // // Class Description: // // This class provides calculation of EM corrections to ionisation // // ------------------------------------------------------------------- // #include "G4EmCorrections.hh" #include "Randomize.hh" #include "G4ParticleTable.hh" #include "G4IonTable.hh" #include "G4VEmModel.hh" #include "G4Proton.hh" #include "G4GenericIon.hh" #include "G4LPhysicsFreeVector.hh" #include "G4PhysicsLogVector.hh" #include "G4ProductionCutsTable.hh" #include "G4MaterialCutsCouple.hh" #include "G4AtomicShells.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4EmCorrections::G4EmCorrections() { particle = 0; curParticle= 0; material = 0; curMaterial= 0; curVector = 0; kinEnergy = 0.0; ionLEModel = 0; ionHEModel = 0; nIons = 0; verbose = 1; ncouples = 0; massFactor = 1.0; eth = 2.0*MeV; nbinCorr = 20; eCorrMin = 25.*keV; eCorrMax = 250.*MeV; nist = G4NistManager::Instance(); ionTable = G4ParticleTable::GetParticleTable()->GetIonTable(); Initialise(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4EmCorrections::~G4EmCorrections() { for(G4int i=0; i 1) { G4cout << "EmCorrections: E(MeV)= " << e/MeV << " Barkas= " << Barkas << " Bloch= " << Bloch << " Mott= " << Mott << " Sum= " << sum << " q2= " << q2 << G4endl; } sum *= material->GetElectronDensity() * q2 * twopi_mc2_rcl2 /beta2; return sum; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4EmCorrections::IonBarkasCorrection(const G4ParticleDefinition* p, const G4Material* mat, G4double e) { // . Z^3 Barkas effect in the stopping power of matter for charged particles // J.C Ashley and R.H.Ritchie // Physical review B Vol.5 No.7 1 April 1972 pagg. 2393-2397 // and ICRU49 report // valid for kineticEnergy < 0.5 MeV SetupKinematics(p, mat, e); G4double res = 0.0; if(tau > 0.0) res = 2.0*BarkasCorrection(p, mat, e)* material->GetElectronDensity() * q2 * twopi_mc2_rcl2 /beta2; return res; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4EmCorrections::ComputeIonCorrections(const G4ParticleDefinition* p, const G4Material* mat, G4double e) { // . Z^3 Barkas effect in the stopping power of matter for charged particles // J.C Ashley and R.H.Ritchie // Physical review B Vol.5 No.7 1 April 1972 pagg. 2393-2397 // and ICRU49 report // valid for kineticEnergy < 0.5 MeV // Other corrections from S.P.Ahlen Rev. Mod. Phys., Vol 52, No1, 1980 SetupKinematics(p, mat, e); if(tau <= 0.0) { return 0.0; } G4double Barkas = BarkasCorrection (p, mat, e); G4double Bloch = BlochCorrection (p, mat, e); G4double Mott = MottCorrection (p, mat, e); G4double sum = 2.0*(Barkas*(charge - 1.0)/charge + Bloch) + Mott; if(verbose > 1) { G4cout << "EmCorrections: E(MeV)= " << e/MeV << " Barkas= " << Barkas << " Bloch= " << Bloch << " Mott= " << Mott << " Sum= " << sum << G4endl; } sum *= material->GetElectronDensity() * q2 * twopi_mc2_rcl2 /beta2; if(verbose > 1) { G4cout << " Sum= " << sum << G4endl; } return sum; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4EmCorrections::IonHighOrderCorrections(const G4ParticleDefinition* p, const G4MaterialCutsCouple* couple, G4double e) { // . Z^3 Barkas effect in the stopping power of matter for charged particles // J.C Ashley and R.H.Ritchie // Physical review B Vol.5 No.7 1 April 1972 pagg. 2393-2397 // and ICRU49 report // valid for kineticEnergy < 0.5 MeV // Other corrections from S.P.Ahlen Rev. Mod. Phys., Vol 52, No1, 1980 G4double sum = 0.0; if(ionHEModel) { G4int Z = G4int(p->GetPDGCharge()/eplus + 0.5); if(Z >= 100) Z = 99; else if(Z < 1) Z = 1; // fill vector if(thcorr[Z].size() == 0) { thcorr[Z].resize(ncouples); G4double ethscaled = eth*p->GetPDGMass()/proton_mass_c2; for(size_t i=0; i= iz) b = 1.8; else if(17 >= iz) b = 1.4; else if(18 == iz) b = 1.8; else if(25 >= iz) b = 1.4; else if(50 >= iz) b = 1.35; G4double W = b/std::sqrt(X); G4double val; if(W <= engBarkas[0]) val = corBarkas[0]; else if(W >= engBarkas[46]) val = corBarkas[46]*engBarkas[46]/W; else { G4int iw = Index(W, engBarkas, 47); val = Value(W, engBarkas[iw], engBarkas[iw+1], corBarkas[iw], corBarkas[iw+1]); } // G4cout << "i= " << i << " b= " << b << " W= " << W // << " Z= " << Z << " X= " << X << " val= " << val<< G4endl; BarkasTerm += val*atomDensity[i] / (std::sqrt(Z*X)*X); } BarkasTerm *= 1.29*charge/material->GetTotNbOfAtomsPerVolume(); // temporary protection if(charge < -7.0 ) { BarkasTerm *= (-7.0/charge); } return BarkasTerm; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4EmCorrections::BlochCorrection(const G4ParticleDefinition* p, const G4Material* mat, G4double e) { SetupKinematics(p, mat, e); G4double y2 = q2/ba2; G4double term = 1.0/(1.0 + y2); G4double del; G4double j = 1.0; do { j += 1.0; del = 1.0/(j* (j*j + y2)); term += del; } while (del > 0.01*term); G4double res = -y2*term; // temporary protection if(q2 > 49. && res < -0.2) { res = -0.2; } return res; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4EmCorrections::MottCorrection(const G4ParticleDefinition* p, const G4Material* mat, G4double e) { SetupKinematics(p, mat, e); G4double mterm = CLHEP::pi*fine_structure_const*beta*charge; return mterm; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4EmCorrections::NuclearDEDX(const G4ParticleDefinition* p, const G4Material* mat, G4double e, G4bool fluct) { G4double nloss = 0.0; if(e <= 0.0) return nloss; SetupKinematics(p, mat, e); lossFlucFlag = fluct; // Projectile nucleus G4double z1 = std::abs(particle->GetPDGCharge()/eplus); G4double m1 = mass/amu_c2; // loop for the elements in the material for (G4int iel=0; ielGetZ(); G4double m2 = element->GetA()*mole/g ; nloss += (NuclearStoppingPower(kinEnergy, z1, z2, m1, m2)) * atomDensity[iel] ; } nloss *= theZieglerFactor; return nloss; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4EmCorrections::NuclearStoppingPower(G4double kineticEnergy, G4double z1, G4double z2, G4double m1, G4double m2) { G4double energy = kineticEnergy/keV ; // energy in keV G4double nloss = 0.0; G4double rm; if(z1 > 1.5) rm = (m1 + m2) * ( Z23[G4int(z1)] + Z23[G4int(z2)] ) ; else rm = (m1 + m2) * nist->GetZ13(G4int(z2)); G4double er = 32.536 * m2 * energy / ( z1 * z2 * rm ) ; // reduced energy if (er >= ed[0]) nloss = a[0]; else { // the table is inverse in energy for (G4int i=102; i>=0; i--) { if (er <= ed[i]) { nloss = (a[i] - a[i+1])*(er - ed[i+1])/(ed[i] - ed[i+1]) + a[i+1]; break; } } } // Stragling if(lossFlucFlag) { // G4double sig = 4.0 * m1 * m2 / ((m1 + m2)*(m1 + m2)* // (4.0 + 0.197*std::pow(er,-1.6991)+6.584*std::pow(er,-1.0494))) ; G4double sig = 4.0 * m1 * m2 / ((m1 + m2)*(m1 + m2)* (4.0 + 0.197/(er*er) + 6.584/er)); nloss *= G4RandGauss::shoot(1.0,sig) ; } nloss *= 8.462 * z1 * z2 * m1 / rm ; // Return to [ev/(10^15 atoms/cm^2] if ( nloss < 0.0) nloss = 0.0 ; return nloss; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... G4double G4EmCorrections::EffectiveChargeCorrection(const G4ParticleDefinition* p, const G4Material* mat, G4double ekin) { G4double factor = 1.0; if(p->GetPDGCharge() <= 2.5*eplus || nIons <= 0) return factor; /* if(verbose > 1) { G4cout << "EffectiveChargeCorrection: " << p->GetParticleName() << " in " << mat->GetName() << " ekin(MeV)= " << ekin/MeV << G4endl; } */ if(p != curParticle || mat != curMaterial) { curParticle = p; curMaterial = mat; curVector = 0; currentZ = p->GetAtomicNumber(); if(verbose > 1) { G4cout << "G4EmCorrections::EffectiveChargeCorrection: Zion= " << currentZ << " Aion= " << p->GetPDGMass()/amu_c2 << G4endl; } massFactor = proton_mass_c2/p->GetPDGMass(); idx = -1; for(G4int i=0; iGetParticleName() << " in " << materialName[idx] << " Ion Z= " << Z << " A= " << A << " massRatio= " << massRatio << G4endl; } G4PhysicsLogVector* vv = new G4PhysicsLogVector(eCorrMin,eCorrMax,nbinCorr); vv->SetSpline(true); G4double e, eion, dedx, dedx1; G4double eth0 = v->Energy(0); G4double escal = eth/massRatio; G4double qe = effCharge.EffectiveChargeSquareRatio(ion, curMaterial, escal); G4double dedxt = ionLEModel->ComputeDEDXPerVolume(curMaterial, p, eth, eth)*qe; G4double dedx1t = ionHEModel->ComputeDEDXPerVolume(curMaterial, p, eth, eth)*qe + ComputeIonCorrections(curParticle, curMaterial, escal); G4double rest = escal*(dedxt - dedx1t); //G4cout << "Escal(MeV)= "<GetTableSize(); if(currmat.size() != ncouples) { currmat.resize(ncouples); size_t i; for(i=0; i<100; i++) {thcorr[i].clear();} for(i=0; iGetMaterialCutsCouple(i)->GetMaterial(); G4String nam = currmat[i]->GetName(); for(G4int j=0; j