// // ******************************************************************** // * 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: G4BraggIonModel.cc,v 1.27 2009/11/22 18:00:23 vnivanch Exp $ // GEANT4 tag $Name: geant4-09-03 $ // // ------------------------------------------------------------------- // // GEANT4 Class file // // // File name: G4BraggIonModel // // Author: Vladimir Ivanchenko // // Creation date: 13.10.2004 // // Modifications: // 11-05-05 Major optimisation of internal interfaces (V.Ivantchenko) // 29-11-05 Do not use G4Alpha class (V.Ivantchenko) // 15-02-06 ComputeCrossSectionPerElectron, ComputeCrossSectionPerAtom (mma) // 25-04-06 Add stopping data from ASTAR (V.Ivanchenko) // 23-10-06 Reduce lowestKinEnergy to 0.25 keV (V.Ivanchenko) // 12-08-08 Added methods GetParticleCharge, GetChargeSquareRatio, // CorrectionsAlongStep needed for ions(V.Ivanchenko) // // Class Description: // // Implementation of energy loss and delta-electron production by // slow charged heavy particles // ------------------------------------------------------------------- // //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... #include "G4BraggIonModel.hh" #include "Randomize.hh" #include "G4Electron.hh" #include "G4ParticleChangeForLoss.hh" #include "G4LossTableManager.hh" #include "G4EmCorrections.hh" //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... using namespace std; G4BraggIonModel::G4BraggIonModel(const G4ParticleDefinition* p, const G4String& nam) : G4VEmModel(nam), corr(0), particle(0), fParticleChange(0), iMolecula(0), isIon(false), isInitialised(false) { if(p) SetParticle(p); SetHighEnergyLimit(2.0*MeV); HeMass = 3.727417*GeV; rateMassHe2p = HeMass/proton_mass_c2; lowestKinEnergy = 1.0*keV/rateMassHe2p; massFactor = 1000.*amu_c2/HeMass; theZieglerFactor = eV*cm2*1.0e-15; theElectron = G4Electron::Electron(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4BraggIonModel::~G4BraggIonModel() {} //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4double G4BraggIonModel::MinEnergyCut(const G4ParticleDefinition*, const G4MaterialCutsCouple* couple) { return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy(); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void G4BraggIonModel::Initialise(const G4ParticleDefinition* p, const G4DataVector&) { if(p != particle) SetParticle(p); corrFactor = chargeSquare; // always false before the run SetDeexcitationFlag(false); if(!isInitialised) { isInitialised = true; G4String pname = particle->GetParticleName(); if(particle->GetParticleType() == "nucleus" && pname != "deuteron" && pname != "triton") isIon = true; corr = G4LossTableManager::Instance()->EmCorrections(); fParticleChange = GetParticleChangeForLoss(); } } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4double G4BraggIonModel::GetChargeSquareRatio(const G4ParticleDefinition* p, const G4Material* mat, G4double kineticEnergy) { //G4cout << "G4BraggIonModel::GetChargeSquareRatio e= " << kineticEnergy << G4endl; // this method is called only for ions G4double q2 = corr->EffectiveChargeSquareRatio(p,mat,kineticEnergy); corrFactor = q2*corr->EffectiveChargeCorrection(p,mat,kineticEnergy); return corrFactor; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4double G4BraggIonModel::GetParticleCharge(const G4ParticleDefinition* p, const G4Material* mat, G4double kineticEnergy) { //G4cout << "G4BraggIonModel::GetParticleCharge e= " << kineticEnergy << G4endl; // this method is called only for ions return corr->GetParticleCharge(p,mat,kineticEnergy); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4double G4BraggIonModel::ComputeCrossSectionPerElectron( const G4ParticleDefinition* p, G4double kineticEnergy, G4double cutEnergy, G4double maxKinEnergy) { G4double cross = 0.0; G4double tmax = MaxSecondaryEnergy(p, kineticEnergy); G4double maxEnergy = std::min(tmax,maxKinEnergy); if(cutEnergy < tmax) { G4double energy = kineticEnergy + mass; G4double energy2 = energy*energy; G4double beta2 = kineticEnergy*(kineticEnergy + 2.0*mass)/energy2; cross = 1.0/cutEnergy - 1.0/maxEnergy - beta2*log(maxEnergy/cutEnergy)/tmax; cross *= twopi_mc2_rcl2*chargeSquare/beta2; } // G4cout << "BR: e= " << kineticEnergy << " tmin= " << cutEnergy // << " tmax= " << tmax << " cross= " << cross << G4endl; return cross; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4double G4BraggIonModel::ComputeCrossSectionPerAtom( const G4ParticleDefinition* p, G4double kineticEnergy, G4double Z, G4double, G4double cutEnergy, G4double maxEnergy) { G4double cross = Z*ComputeCrossSectionPerElectron (p,kineticEnergy,cutEnergy,maxEnergy); return cross; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4double G4BraggIonModel::CrossSectionPerVolume( const G4Material* material, const G4ParticleDefinition* p, G4double kineticEnergy, G4double cutEnergy, G4double maxEnergy) { G4double eDensity = material->GetElectronDensity(); G4double cross = eDensity*ComputeCrossSectionPerElectron (p,kineticEnergy,cutEnergy,maxEnergy); return cross; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4double G4BraggIonModel::ComputeDEDXPerVolume(const G4Material* material, const G4ParticleDefinition* p, G4double kineticEnergy, G4double cutEnergy) { G4double tmax = MaxSecondaryEnergy(p, kineticEnergy); G4double tmin = min(cutEnergy, tmax); G4double tkin = kineticEnergy/massRate; G4double dedx = 0.0; if(tkin > lowestKinEnergy) dedx = DEDX(material, tkin); else dedx = DEDX(material, lowestKinEnergy)*sqrt(tkin/lowestKinEnergy); if (cutEnergy < tmax) { G4double tau = kineticEnergy/mass; G4double gam = tau + 1.0; G4double bg2 = tau * (tau+2.0); G4double beta2 = bg2/(gam*gam); G4double x = tmin/tmax; dedx += (log(x) + (1.0 - x)*beta2) * twopi_mc2_rcl2 * (material->GetElectronDensity())/beta2; } // now compute the total ionization loss if (dedx < 0.0) dedx = 0.0 ; dedx *= chargeSquare; //G4cout << " tkin(MeV) = " << tkin/MeV << " dedx(MeVxcm^2/g) = " // << dedx*gram/(MeV*cm2*material->GetDensity()) // << " q2 = " << chargeSquare << G4endl; return dedx; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... void G4BraggIonModel::CorrectionsAlongStep(const G4MaterialCutsCouple* couple, const G4DynamicParticle* dp, G4double& eloss, G4double&, G4double /*length*/) { // this method is called only for ions const G4ParticleDefinition* p = dp->GetDefinition(); const G4Material* mat = couple->GetMaterial(); G4double preKinEnergy = dp->GetKineticEnergy(); G4double e = preKinEnergy - eloss*0.5; if(e < 0.0) e = preKinEnergy*0.5; G4double q2 = corr->EffectiveChargeSquareRatio(p,mat,e); GetModelOfFluctuations()->SetParticleAndCharge(p, q2); G4double qfactor = q2*corr->EffectiveChargeCorrection(p,mat,e)/corrFactor; eloss *= qfactor; //G4cout << "G4BraggIonModel::CorrectionsAlongStep e= " << e // << " qfactor= " << qfactor << " " << p->GetParticleName() <* vdp, const G4MaterialCutsCouple*, const G4DynamicParticle* dp, G4double xmin, G4double maxEnergy) { G4double tmax = MaxSecondaryKinEnergy(dp); G4double xmax = std::min(tmax, maxEnergy); if(xmin >= xmax) return; G4double kineticEnergy = dp->GetKineticEnergy(); G4double energy = kineticEnergy + mass; G4double energy2 = energy*energy; G4double beta2 = kineticEnergy*(kineticEnergy + 2.0*mass)/energy2; G4double grej = 1.0; G4double deltaKinEnergy, f; G4ThreeVector direction = dp->GetMomentumDirection(); // sampling follows ... do { G4double q = G4UniformRand(); deltaKinEnergy = xmin*xmax/(xmin*(1.0 - q) + xmax*q); f = 1.0 - beta2*deltaKinEnergy/tmax; if(f > grej) { G4cout << "G4BraggIonModel::SampleSecondary Warning! " << "Majorant " << grej << " < " << f << " for e= " << deltaKinEnergy << G4endl; } } while( grej*G4UniformRand() >= f ); G4double deltaMomentum = sqrt(deltaKinEnergy * (deltaKinEnergy + 2.0*electron_mass_c2)); G4double totMomentum = energy*sqrt(beta2); G4double cost = deltaKinEnergy * (energy + electron_mass_c2) / (deltaMomentum * totMomentum); if(cost > 1.0) cost = 1.0; G4double sint = sqrt((1.0 - cost)*(1.0 + cost)); G4double phi = twopi * G4UniformRand() ; G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost) ; deltaDirection.rotateUz(direction); // create G4DynamicParticle object for delta ray G4DynamicParticle* delta = new G4DynamicParticle(theElectron,deltaDirection, deltaKinEnergy); vdp->push_back(delta); // Change kinematics of primary particle kineticEnergy -= deltaKinEnergy; G4ThreeVector finalP = direction*totMomentum - deltaDirection*deltaMomentum; finalP = finalP.unit(); fParticleChange->SetProposedKineticEnergy(kineticEnergy); fParticleChange->SetProposedMomentumDirection(finalP); } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4double G4BraggIonModel::MaxSecondaryEnergy(const G4ParticleDefinition* pd, G4double kinEnergy) { if(pd != particle) SetParticle(pd); G4double tau = kinEnergy/mass; G4double tmax = 2.0*electron_mass_c2*tau*(tau + 2.) / (1. + 2.0*(tau + 1.)*ratio + ratio*ratio); return tmax; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4bool G4BraggIonModel::HasMaterial(const G4Material* material) { const size_t numberOfMolecula = 11 ; SetMoleculaNumber(numberOfMolecula) ; G4String chFormula = material->GetChemicalFormula() ; // ICRU Report N49, 1993. Ziegler model for He. static G4String molName[numberOfMolecula] = { "CaF_2", "Cellulose_Nitrate", "LiF", "Policarbonate", "(C_2H_4)_N-Polyethylene", "(C_2H_4)_N-Polymethly_Methacralate", "Polysterene", "SiO_2", "NaI", "H_2O", "Graphite" } ; // Search for the material in the table for (size_t i=0; i