Import Geant4 9.2.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 15:58:43 +02:00
parent 96c8bcd0af
commit b79225fb37
7544 changed files with 245407 additions and 91099 deletions
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4DummyModel.cc,v 1.3 2007/05/22 17:31:58 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -0,0 +1,247 @@
//
// ********************************************************************
// * 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: G4ElectronIonPair.cc,v 1.2 2008/10/17 14:46:16 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4ElectronIonPair
//
// Author: Vladimir Ivanchenko
//
// Creation date: 08.07.2008
//
// Modifications:
//
// -------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4ElectronIonPair.hh"
#include "G4Gamma.hh"
#include "G4Material.hh"
#include "G4MaterialTable.hh"
#include "G4StepPoint.hh"
#include "G4VProcess.hh"
#include "G4ProcessType.hh"
#include "G4Track.hh"
#include "Randomize.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ElectronIonPair::G4ElectronIonPair()
{
verbose = 1;
curMaterial = 0;
curMeanEnergy = 0.0;
nMaterials = 0;
Initialise();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ElectronIonPair::~G4ElectronIonPair()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4ElectronIonPair::MeanNumberOfIonsAlongStep(
const G4ParticleDefinition* part,
const G4Material* material,
G4double edep,
G4double niel)
{
G4double nion = 0.0;
// NIEL does not provide ionisation clusters
if(edep > niel) {
// neutral particles do not produce ionisation along step
if(part->GetPDGCharge() != 0.0) {
// select material
if(material != curMaterial) {
curMaterial = material;
curMeanEnergy = material->GetIonisation()->GetMeanEnergyPerIonPair();
// if mean energy is not defined then look into G4 DB
if(0.0 == curMeanEnergy) {
curMeanEnergy = FindG4MeanEnergyPerIonPair(material);
}
}
if(curMeanEnergy > 0.0) nion = (edep - niel)/curMeanEnergy;
}
}
return nion;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
std::vector<G4ThreeVector>*
G4ElectronIonPair::SampleIonsAlongStep(const G4ThreeVector& prePos,
const G4ThreeVector& postPos,
G4double meanion)
{
std::vector<G4ThreeVector>* v = new std::vector<G4ThreeVector>;
G4double sig = 0.2*std::sqrt(meanion);
G4int nion = G4int(G4RandGauss::shoot(meanion,sig) + 0.5);
// sample ionisation along step
if(nion > 0) {
G4ThreeVector deltaPos = postPos - prePos;
for(G4int i=0; i<nion; i++) {
v->push_back( prePos + deltaPos*G4UniformRand() );
}
if(verbose > 1 ) {
G4cout << "### G4ElectronIonPair::SampleIonisationPoints: "
<< v->size() << " ion pairs are added" << G4endl;
}
}
return v;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4int G4ElectronIonPair::ResidualeChargePostStep(const G4ParticleDefinition*,
const G4TrackVector*,
G4int subType)
{
G4int nholes = 0;
if(2 == subType || 12 == subType || 13 == subType) nholes = 1;
return nholes;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4ElectronIonPair::FindG4MeanEnergyPerIonPair(const G4Material* mat)
{
G4String name = mat->GetName();
G4double res = 0.0;
// is this material in the vector?
for(G4int j=0; j<nMaterials; j++) {
if(name == g4MatNames[j]) {
res = g4MatData[j];
mat->GetIonisation()->SetMeanEnergyPerIonPair(res);
if(verbose > 0) {
G4cout << "### G4ElectronIonPair::FindG4MeanEnergyPerIonPair for "
<< name << " Epair= " << res/eV << " eV is set"
<< G4endl;
}
break;
}
}
return res;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4ElectronIonPair:: DumpMeanEnergyPerIonPair()
{
G4int nmat = G4Material::GetNumberOfMaterials();
const G4MaterialTable* mtable = G4Material::GetMaterialTable();
if(nmat > 0) {
G4cout << "### G4ElectronIonPair: mean energy per ion pair avalable:" << G4endl;
for(G4int i=0; i<nmat; i++) {
const G4Material* mat = (*mtable)[i];
G4double x = mat->GetIonisation()->GetMeanEnergyPerIonPair();
if(x > 0.0) {
G4cout << " " << mat->GetName() << " Epair= "
<< x/eV << " eV" << G4endl;
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4ElectronIonPair::DumpG4MeanEnergyPerIonPair()
{
if(nMaterials > 0) {
G4cout << "### G4ElectronIonPair: mean energy per ion pair "
<< " for Geant4 materials" << G4endl;
for(G4int i=0; i<nMaterials; i++) {
G4cout << " " << g4MatNames[i] << " Epair= "
<< g4MatData[i]/eV << " eV" << G4endl;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4ElectronIonPair::Initialise()
{
// ICRU Report 31, 1979
g4MatNames.push_back("G4_Si");
g4MatData.push_back(3.62*eV);
g4MatNames.push_back("G4_Ge");
g4MatData.push_back(2.97*eV);
g4MatNames.push_back("G4_He");
g4MatData.push_back(44.4*eV);
g4MatNames.push_back("G4_N");
g4MatData.push_back(36.4*eV);
g4MatNames.push_back("G4_O");
g4MatData.push_back(32.3*eV);
g4MatNames.push_back("G4_Ne");
g4MatData.push_back(36.8*eV);
g4MatNames.push_back("G4_Ar");
g4MatData.push_back(26.34*eV);
g4MatNames.push_back("G4_Kr");
g4MatData.push_back(24.1*eV);
g4MatNames.push_back("G4_Xe");
g4MatData.push_back(21.6*eV);
g4MatNames.push_back("G4_lAr");
g4MatData.push_back(23.6*eV);
g4MatNames.push_back("G4_lKr");
g4MatData.push_back(20.5*eV);
g4MatNames.push_back("G4_lXe");
g4MatData.push_back(15.6*eV);
g4MatNames.push_back("G4_AIR");
g4MatData.push_back(35.1*eV);
nMaterials = g4MatData.size();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4EmCalculator.cc,v 1.37 2007/08/16 15:55:42 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4EmCalculator.cc,v 1.44 2008/08/03 18:47:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -54,6 +54,7 @@
// 27.10.2006 Change test energy to access lowEnergy model from
// 10 keV to 1 keV (V. Ivanchenko)
// 15.03.2007 Add ComputeEnergyCutFromRangeCut methods (V.Ivanchenko)
// 21.04.2008 Updated computations for ions (V.Ivanchenko)
//
// Class Description:
//
@@ -125,6 +126,20 @@ G4double G4EmCalculator::GetDEDX(G4double kinEnergy, const G4ParticleDefinition*
const G4MaterialCutsCouple* couple = FindCouple(mat, region);
if(couple && UpdateParticle(p, kinEnergy) ) {
res = manager->GetDEDX(p, kinEnergy, couple);
if(isIon) {
G4double eth = 2.0*MeV/massRatio;
if(kinEnergy > eth) {
G4double x1 = corr->ComputeIonCorrections(p,mat,kinEnergy);
G4double x2 = corr->ComputeIonCorrections(p,mat,eth);
res += x1 - x2*eth/kinEnergy;
/*
G4cout << "### GetDEDX: E= " << kinEnergy << " res= " << res
<< " x1= " << x1 << " x2= " << x2
<< " del= " << x1 - x2*eth/kinEnergy << G4endl;;
*/
}
}
if(verbose>0) {
G4cout << "G4EmCalculator::GetDEDX: E(MeV)= " << kinEnergy/MeV
<< " DEDX(MeV/mm)= " << res*mm/MeV
@@ -405,31 +420,21 @@ G4double G4EmCalculator::ComputeDEDX(G4double kinEnergy,
if(baseParticle) {
res = currentModel->ComputeDEDXPerVolume(
mat, baseParticle, escaled, cut) * chargeSquare;
if(verbose > 1)
if(verbose > 1) {
G4cout << baseParticle->GetParticleName()
<< " Escaled(MeV)= " << escaled;
}
} else {
res = currentModel->ComputeDEDXPerVolume(mat, p, kinEnergy, cut);
if(verbose > 1) G4cout << " no basePart E(MeV)= " << kinEnergy;
}
if(verbose > 1)
if(verbose > 1) {
G4cout << " DEDX(MeV/mm)= " << res*mm/MeV
<< " DEDX(MeV*cm^2/g)= "
<< res*gram/(MeV*cm2*mat->GetDensity())
<< G4endl;
if(isIon) {
if(currentModel->HighEnergyLimit() > 100.*MeV)
res += corr->HighOrderCorrections(p,mat,kinEnergy);
else
res *= corr->EffectiveChargeCorrection(p,mat,kinEnergy);
if(verbose > 1)
G4cout << "After Corrections: DEDX(MeV/mm)= " << res*mm/MeV
<< " DEDX(MeV*cm^2/g)= " << res*gram/(MeV*cm2*mat->GetDensity())
<< G4endl;
}
// emulate boundary region for different parameterisations
G4double eth = currentModel->LowEnergyLimit();
// G4cout << "massRatio= " << massRatio << " eth= " << eth << G4endl;
@@ -446,15 +451,32 @@ G4double G4EmCalculator::ComputeDEDX(G4double kinEnergy,
res1 = currentModel->ComputeDEDXPerVolume(mat, p, eth, cut);
res0 = loweModel->ComputeDEDXPerVolume(mat, p, eth, cut);
}
if(verbose > 1)
if(verbose > 1) {
G4cout << "At boundary energy(MeV)= " << eth/MeV
<< " DEDX(MeV/mm)= " << res1*mm/MeV
<< G4endl;
if(isIon) res1 += corr->HighOrderCorrections(p,mat,eth/massRatio);
//G4cout << "eth= " << eth << " escaled= " << escaled
// << " res0= " << res0 << " res1= "
// << res1 << " q2= " << chargeSquare << G4endl;
}
/*
G4cout << "eth= " << eth << " escaled= " << escaled
<< " res0= " << res0 << " res1= "
<< res1 << " q2= " << chargeSquare << G4endl;
*/
res *= (1.0 + (res0/res1 - 1.0)*eth/escaled);
if(isIon) {
G4double ethscaled = eth/massRatio;
if(kinEnergy > ethscaled) {
G4double x1 = corr->ComputeIonCorrections(p,mat,kinEnergy);
G4double x2 = corr->ComputeIonCorrections(p,mat,ethscaled);
res += x1 - x2*ethscaled/kinEnergy;
}
if(verbose > 1) {
G4cout << "After Corrections: DEDX(MeV/mm)= " << res*mm/MeV
<< " DEDX(MeV*cm^2/g)= " << res*gram/(MeV*cm2*mat->GetDensity())
<< G4endl;
}
}
}
if(verbose > 0) {
@@ -506,8 +528,10 @@ G4double G4EmCalculator::ComputeElectronicDEDX(G4double kinEnergy, const G4Strin
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmCalculator::ComputeTotalDEDX(G4double kinEnergy, const G4ParticleDefinition* part,
const G4Material* mat, G4double cut)
G4double G4EmCalculator::ComputeTotalDEDX(G4double kinEnergy,
const G4ParticleDefinition* part,
const G4Material* mat,
G4double cut)
{
G4double dedx = ComputeElectronicDEDX(kinEnergy,part,mat,cut);
if(mass > 700.*MeV) dedx += ComputeNuclearDEDX(kinEnergy,part,mat);
@@ -516,8 +540,10 @@ G4double G4EmCalculator::ComputeTotalDEDX(G4double kinEnergy, const G4ParticleDe
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmCalculator::ComputeTotalDEDX(G4double kinEnergy, const G4String& part,
const G4String& mat, G4double cut)
G4double G4EmCalculator::ComputeTotalDEDX(G4double kinEnergy,
const G4String& part,
const G4String& mat,
G4double cut)
{
return ComputeTotalDEDX(kinEnergy,FindParticle(part),FindMaterial(mat),cut);
}
@@ -754,10 +780,12 @@ G4bool G4EmCalculator::UpdateParticle(const G4ParticleDefinition* p,
}
if(isIon) {
chargeSquare =
ionEffCharge->EffectiveChargeSquareRatio(p, currentMaterial, kinEnergy);
if(currentProcess)
ionEffCharge->EffectiveChargeSquareRatio(p, currentMaterial, kinEnergy)
* corr->EffectiveChargeCorrection(p,currentMaterial,kinEnergy);
if(currentProcess) {
currentProcess->SetDynamicMassCharge(massRatio,chargeSquare);
// G4cout << "massR= " << massRatio << " q2= " << chargeSquare << G4endl;
//G4cout << "NewP: massR= " << massRatio << " q2= " << chargeSquare << G4endl;
}
}
return true;
}
@@ -0,0 +1,274 @@
//
// ********************************************************************
// * 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: G4EmConfigurator.cc,v 1.3 2008/11/21 12:30:29 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class
//
// File name: G4EmConfigurator
//
// Author: Vladimir Ivanchenko
//
// Creation date: 14.07.2008
//
// Modifications:
//
// Class Description:
//
// This class provides configuration EM models for
// particles/processes/regions
//
// -------------------------------------------------------------------
//
#include "G4EmConfigurator.hh"
#include "G4ParticleTable.hh"
#include "G4ParticleDefinition.hh"
#include "G4ProcessManager.hh"
#include "G4VProcess.hh"
#include "G4ProcessVector.hh"
#include "G4RegionStore.hh"
#include "G4Region.hh"
#include "G4DummyModel.hh"
#include "G4VEnergyLossProcess.hh"
#include "G4VEmProcess.hh"
#include "G4VMultipleScattering.hh"
enum PType {unknown=0, eloss, discrete, msc};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4EmConfigurator::G4EmConfigurator()
{
index = 1;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4EmConfigurator::~G4EmConfigurator()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EmConfigurator::AddExtraEmModel(const G4String& particleName,
G4VEmModel* em,
G4VEmFluctuationModel* fm)
{
particleList.push_back(particleName);
modelList.push_back(em);
flucModelList.push_back(fm);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EmConfigurator::AddModelForRegion(const G4String& particleName,
const G4String& processName,
const G4String& modelName,
const G4String& regionName,
G4double emin, G4double emax,
const G4String& flucModelName)
{
particles.push_back(particleName);
processes.push_back(processName);
models.push_back(modelName);
regions.push_back(regionName);
flucModels.push_back(flucModelName);
lowEnergy.push_back(emin);
highEnergy.push_back(emax);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EmConfigurator::SetExtraEmModel(const G4String& particleName,
const G4String& processName,
G4VEmModel* mod,
const G4String& regionName,
G4double emin,
G4double emax,
G4VEmFluctuationModel* fm)
{
AddExtraEmModel(particleName, mod, fm);
G4String fname = "";
if(fm) fname = fm->GetName();
AddModelForRegion(particleName, processName, mod->GetName(), regionName,
emin, emax, fname);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EmConfigurator::AddModels()
{
size_t n = particles.size();
//G4cout << " G4EmConfigurator::AddModels n= " << n << G4endl;
if(n > 0) {
for(size_t i=0; i<n; i++) {
SetModelForRegion(particles[i],processes[i],models[i],regions[i],
flucModels[i],lowEnergy[i],highEnergy[i]);
}
}
particles.clear();
processes.clear();
models.clear();
flucModels.clear();
regions.clear();
lowEnergy.clear();
highEnergy.clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EmConfigurator::SetModelForRegion(const G4String& particleName,
const G4String& processName,
const G4String& modelName,
const G4String& regionName,
const G4String& flucModelName,
G4double emin, G4double emax)
{
//G4cout << " G4EmConfigurator::SetModelForRegion" << G4endl;
// new set
index--;
G4ParticleTable::G4PTblDicIterator* theParticleIterator =
G4ParticleTable::GetParticleTable()->GetIterator();
theParticleIterator->reset();
while( (*theParticleIterator)() ) {
const G4ParticleDefinition* part = theParticleIterator->value();
//G4cout << particleName << " " << part->GetParticleName() << G4endl;
if(particleName == part->GetParticleName() ||
(particleName == "charged" && part->GetPDGCharge() != 0.0) ) {
// search for process
G4ProcessManager* pmanager = part->GetProcessManager();
G4ProcessVector* plist = pmanager->GetProcessList();
G4int np = pmanager->GetProcessListLength();
//G4cout << processName << " in list of " << np << G4endl;
G4VProcess* proc = 0;
for(G4int i=0; i<np; i++) {
if(processName == (*plist)[i]->GetProcessName()) {
proc = (*plist)[i];
break;
}
}
if(!proc) {
G4cout << "### G4EmConfigurator WARNING: fails to find a process <"
<< processName << "> for " << particleName << G4endl;
} else {
// classify process
PType ptype = discrete;
G4int ii = proc->GetProcessSubType();
if(10 == ii) ptype = msc;
else if(2 <= ii && 4 >= ii) ptype = eloss;
// find out model
G4VEmModel* mod = 0;
G4VEmFluctuationModel* fluc = 0;
G4int nm = modelList.size();
//G4cout << "Search model " << modelName << " in " << nm << G4endl;
for(G4int i=0; i<nm; i++) {
if(modelName == modelList[i]->GetName() &&
(particleList[i] == "" || particleList[i] == particleName) ) {
mod = modelList[i];
fluc = flucModelList[i];
break;
}
}
if("dummy" == modelName) mod = new G4DummyModel();
if(!mod) {
G4cout << "### G4EmConfigurator WARNING: fails to find a model <"
<< modelName << "> for process <"
<< processName << "> and " << particleName
<< G4endl;
if(flucModelName != "")
G4cout << " fluctuation model <"
<< flucModelName << G4endl;
} else {
// search for region
G4Region* reg = 0;
G4RegionStore* regStore = G4RegionStore::GetInstance();
G4String r = regionName;
if(r == "" || r == "world" || r == "World") r = "DefaultRegionForTheWorld";
reg = regStore->GetRegion(r, true);
if(!reg) {
G4cout << "### G4EmConfigurator WARNING: fails to find a region <"
<< r << "> for model <" << modelName << "> of the process "
<< processName << " and " << particleName << G4endl;
return;
}
// energy limits
G4double e1 = std::max(emin,mod->LowEnergyLimit());
G4double e2 = std::min(emax,mod->HighEnergyLimit());
if(e2 < e1) e2 = e1;
mod->SetLowEnergyLimit(e1);
mod->SetHighEnergyLimit(e2);
//G4cout << "e1= " << e1 << " e2= " << e2 << G4endl;
// added model
if(ptype == eloss) {
G4VEnergyLossProcess* p = reinterpret_cast<G4VEnergyLossProcess*>(proc);
p->AddEmModel(index,mod,fluc,reg);
//G4cout << "### Added eloss model order= " << index << " for "
// << particleName << " and " << processName << " " << mod << G4endl;
} else if(ptype == discrete) {
G4VEmProcess* p = reinterpret_cast<G4VEmProcess*>(proc);
p->AddEmModel(index,mod,reg);
} else if(ptype == msc) {
G4VMultipleScattering* p = reinterpret_cast<G4VMultipleScattering*>(proc);
p->AddEmModel(index,mod,reg);
}
}
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4EmCorrections.cc,v 1.22 2007/05/18 18:39:55 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4EmCorrections.cc,v 1.51 2008/12/18 13:01:44 gunter Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -43,6 +43,9 @@
// 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:
@@ -55,30 +58,39 @@
#include "G4EmCorrections.hh"
#include "Randomize.hh"
#include "G4NistManager.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"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmCorrections::G4EmCorrections()
{
Initialise();
particle = 0;
curParticle= 0;
material = 0;
curMaterial= 0;
curVector = 0;
kinEnergy = 0.0;
ionModel = 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....
@@ -92,7 +104,7 @@ G4EmCorrections::~G4EmCorrections()
G4double G4EmCorrections::HighOrderCorrections(const G4ParticleDefinition* p,
const G4Material* mat,
G4double e)
G4double e, G4double)
{
// . Z^3 Barkas effect in the stopping power of matter for charged particles
// J.C Ashley and R.H.Ritchie
@@ -107,13 +119,12 @@ G4double G4EmCorrections::HighOrderCorrections(const G4ParticleDefinition* p,
G4double Barkas = BarkasCorrection (p, mat, e);
G4double Bloch = BlochCorrection (p, mat, e);
G4double Mott = MottCorrection (p, mat, e);
G4double FSize = FiniteSizeCorrection (p, mat, e);
G4double sum = (2.0*(Barkas + Bloch) + FSize + Mott);
G4double sum = (2.0*(Barkas + Bloch) + Mott);
if(verbose > 1)
G4cout << "EmCorrections: E(MeV)= " << e/MeV << " Barkas= " << Barkas
<< " Bloch= " << Bloch << " Mott= " << Mott << " Fsize= " << FSize
<< " Bloch= " << Bloch << " Mott= " << Mott
<< " Sum= " << sum << G4endl;
sum *= material->GetElectronDensity() * q2 * twopi_mc2_rcl2 /beta2;
@@ -122,6 +133,98 @@ G4double G4EmCorrections::HighOrderCorrections(const G4ParticleDefinition* p,
//....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<ncouples; i++) {
(thcorr[Z])[i] = ethscaled*ComputeIonCorrections(p, currmat[i], ethscaled);
//G4cout << i << ". ethscaled= " << ethscaled
//<< " corr= " << (thcorr[Z])[i]/ethscaled << G4endl;
}
}
G4double rest = (thcorr[Z])[couple->GetIndex()];
sum = ComputeIonCorrections(p,couple->GetMaterial(),e) - rest/e;
if(verbose > 1) G4cout << " Sum= " << sum << " dSum= " << rest/e << G4endl;
}
return sum;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmCorrections::Bethe(const G4ParticleDefinition* p,
const G4Material* mat,
G4double e)
@@ -225,7 +328,8 @@ G4double G4EmCorrections::KShell(G4double tet, G4double eta)
if(eta < Eta[0]) y = Eta[0];
G4int ieta = Index(y, Eta, nEtaK);
corr = Value2(x, y, TheK[itet], TheK[itet+1], Eta[ieta], Eta[ieta+1],
CK[itet][ieta], CK[itet+1][ieta], CK[itet][ieta+1], CK[itet+1][ieta+1]);
CK[itet][ieta], CK[itet+1][ieta],
CK[itet][ieta+1], CK[itet+1][ieta+1]);
//G4cout << " x= " <<x<<" y= "<<y<<" tet= " <<TheK[itet]
//<<" "<< TheK[itet+1]<<" eta= "<< Eta[ieta]<<" "<< Eta[ieta+1]
// <<" CK= " << CK[itet][ieta]<<" "<< CK[itet+1][ieta]
@@ -438,7 +542,8 @@ G4double G4EmCorrections::BarkasCorrection(const G4ParticleDefinition* p,
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]);
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;
@@ -474,111 +579,16 @@ G4double G4EmCorrections::BlochCorrection(const G4ParticleDefinition* p,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmCorrections::MottCorrection(const G4ParticleDefinition* p,
const G4Material* mat,
G4double e)
const G4Material* mat,
G4double e)
{
SetupKinematics(p, mat, e);
G4double mterm = pi*fine_structure_const*beta*charge;
/*
G4double mterm = 0.0;
if(beta > 0.0) {
// Estimation of mean square root of the ionisation potential
G4double Zeff = 0.0;
G4double norm = 0.0;
for (G4int i = 0; i<numberOfElements; i++) {
G4double Z = (*theElementVector)[i]->GetZ();
Zeff += Z*atomDensity[i];
norm += atomDensity[i];
}
Zeff *= (2.0/norm);
G4double ze1 = std::log(Zeff);
G4double eexc= material->GetIonisation()->GetMeanExcitationEnergy()*ze1*ze1/Zeff;
G4double invbeta = 1.0/beta;
G4double invbeta2= invbeta*invbeta;
G4double za = charge*fine_structure_const;
G4double za2 = za*za;
G4double za3 = za2*za;
G4double x = za*invbeta;
G4double cosx;
if(x < COSEB[13]) {
G4int i = Index(x,COSEB,14);
cosx = Value(x,COSEB[i], COSEB[i+1],COSXI[i],COSXI[i+1]);
} else {
cosx = COSXI[13]*COSEB[13]/x;
}
mterm =
za*beta*(1.725 + pi*cosx*(0.52 - 2.0*std::sqrt(eexc/(2.0*electron_mass_c2*bg2))));
+ za2*(3.246 - 0.451*beta2)
+ za3*(1.522*beta + 0.987*invbeta)
+ za2*za2*(4.569 - 0.494*beta2 - 2.696*invbeta2)
+ za3*za2*(1.254*beta + 0.222*invbeta - 1.17*invbeta*invbeta2);
}
*/
G4double mterm = CLHEP::pi*fine_structure_const*beta*charge;
return mterm;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmCorrections::FiniteSizeCorrection(const G4ParticleDefinition* p,
const G4Material* mat,
G4double e)
// Finite size corrections are parameterized according to
// J.D.Jackson Phys. Rev. D59 (1998) 017301
{
SetupKinematics(p, mat, e);
G4double term = 0.0;
//Leptons
if(p->GetLeptonNumber() != 0) {
G4double x = tmax/(e + mass);
term = x*x;
// Pions and Kaons
} else if(p->GetPDGSpin() == 0.0 && q2 < 1.5) {
G4double xpi = 0.736*GeV;
G4double x = 2.0*electron_mass_c2*tmax0/(xpi*xpi);
term = -std::log(1.0 + x);
// Protons and baryons
} else if(q2 < 1.5) {
G4double xp = 0.8426*GeV;
G4double x = 2.0*electron_mass_c2*tmax0/(xp*xp);
G4double ksi2 = 2.79285*2.79285;
term = -x*(1.0 + 5.0*x/6.0)/((1.0 + x)*(1 + x)) - std::log(1.0 + x);
G4double b = xp*0.5/mass;
G4double c = xp*mass/(electron_mass_c2*(mass + e));
G4double lb = b*b;
G4double lb2= lb*lb;
G4double nu = 0.5*c*c;
G4double x1 = 1.0 + x;
G4double x2 = x1*x1;
G4double l1 = 1.0 - lb;
G4double l2 = l1*l1;
G4double lx = 1.0 + lb*x;
G4double ia = lb2*(lx*std::log(lx/x1)/x + l1 -
0.5*x*l2/(lb*x1) +
x*(3.0 + 2.0*x)*l2*l1/(6.0*x2*lb2))/(l2*l2);
G4double ib = x*x*(3.0 + x)/(6.0*x2*x1);
term += lb*((ksi2 - 1.0)*ia + nu*ksi2*ib);
// G4cout << "Proton F= " << term << " ia= " << ia << " ib= " << ib << " lb= " << lb<< G4endl;
//ions
} else {
G4double xp = 0.8426*GeV/std::pow(mass/proton_mass_c2,-0.33333333);
G4double x = 2.0*electron_mass_c2*tmax0/(xp*xp);
term = -std::log(1.0 + x);
//G4cout << "Ion F= " << term << G4endl;
}
return term;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmCorrections::NuclearDEDX(const G4ParticleDefinition* p,
const G4Material* mat,
G4double e,
@@ -616,23 +626,29 @@ G4double G4EmCorrections::NuclearStoppingPower(G4double kineticEnergy,
G4double nloss = 0.0;
G4double rm;
if(z1 > 1.5) rm = (m1 + m2) * ( std::pow(z1, .23) + std::pow(z2, .23) ) ;
else rm = (m1 + m2) * std::pow(z2, 0.333333);
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
for (G4int i=1; i<104; i++)
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];
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*std::pow(er,-1.6991)+6.584*std::pow(er,-1.0494))) ;
(4.0 + 0.197/(er*er) + 6.584/er));
nloss *= G4RandGauss::shoot(1.0,sig) ;
}
@@ -646,56 +662,57 @@ G4double G4EmCorrections::NuclearStoppingPower(G4double kineticEnergy,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ionEffectiveCharge* G4EmCorrections::GetIonEffectiveCharge(G4VEmModel* m)
{
if(m) ionModel = m;
return &effCharge;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4int G4EmCorrections::GetNumberOfStoppingVectors()
{
return nIons;
}
//....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) return factor;
if(verbose > 1)
G4cout << "EffectiveChargeCorrection: " << p->GetParticleName() << " in " << mat->GetName()
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 = 0;
curMaterial = mat;
curVector = 0;
G4int Z = p->GetAtomicNumber();
G4int A = p->GetAtomicMass();
if(verbose > 1) G4cout << "Zion= " << Z << " Aion= " << A << G4endl;
massFactor = proton_mass_c2/ionTable->GetIonMass(Z,A);
idx = 0;
for(; idx<nIons; idx++) {
if(Z == Zion[idx] && A == Aion[idx]) {
if(materialList[idx] == mat) {
curMaterial = mat;
curVector = stopData[idx];
break;
} else if(materialList[idx] == 0) {
if(materialName[idx] == mat->GetName())
curVector = InitialiseMaterial(mat);
}
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;
G4int dz = 1000;
for(G4int i=0; i<nIons; i++) {
if(materialList[i] == mat) {
G4int delz = currentZ - Zion[i];
if(delz < 0) delz = -delz;
if(delz < dz) {
idx = i;
dz = delz;
if(0 == delz) break;
}
}
}
// G4cout << " idx= " << idx << " dz= " << dz << G4endl;
if(idx > 0) {
if(!ionList[idx]) BuildCorrectionVector();
if(ionList[idx]) curVector = stopData[idx];
}
}
if(curVector) {
G4bool b;
factor = curVector->GetValue(ekin*massFactor,b);
if(verbose > 1) {
G4cout << "E= " << ekin << " factor= " << factor << " massfactor= "
<< massFactor << G4endl;
}
}
if(verbose > 1) G4cout << " factor= " << factor << G4endl;
return factor;
}
@@ -703,69 +720,122 @@ G4double G4EmCorrections::EffectiveChargeCorrection(const G4ParticleDefinition*
void G4EmCorrections::AddStoppingData(G4int Z, G4int A,
const G4String& mname,
G4PhysicsVector& dVector)
G4PhysicsVector* dVector)
{
idx = 0;
for(; idx<nIons; idx++) {
if(Z == Zion[idx] && A == Aion[idx] && mname == materialName[idx])
break;
G4int i = 0;
for(; i<nIons; i++) {
if(Z == Zion[i] && A == Aion[i] && mname == materialName[i]) break;
}
if(idx == nIons) {
if(i == nIons) {
Zion.push_back(Z);
Aion.push_back(A);
materialName.push_back(mname);
materialList.push_back(0);
stopData.push_back(0);
ionList.push_back(0);
stopData.push_back(dVector);
nIons++;
} else {
if(stopData[idx]) delete stopData[idx];
if(verbose>1) {
G4cout << "AddStoppingData Z= " << Z << " A= " << A << " " << mname
<< " idx= " << i << G4endl;
}
}
size_t nbins = dVector.GetVectorLength();
size_t n = 0;
for(; n<nbins; n++) {
if(dVector.GetLowEdgeEnergy(n) > 2.0*MeV) break;
}
if(n < nbins) nbins = n + 1;
G4LPhysicsFreeVector* v =
new G4LPhysicsFreeVector(nbins,
dVector.GetLowEdgeEnergy(0),
dVector.GetLowEdgeEnergy(nbins-1));
G4bool b;
for(size_t i=0; i<nbins; i++) {
G4double e = dVector.GetLowEdgeEnergy(i);
G4double dedx = dVector.GetValue(e, b);
v->PutValues(i, e, dedx);
}
// G4cout << *v << G4endl;
stopData[idx] = v;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsVector* G4EmCorrections::InitialiseMaterial(const G4Material* mat)
void G4EmCorrections::BuildCorrectionVector()
{
G4PhysicsVector* v = 0;
const G4Material* m = nist->FindOrBuildMaterial(materialName[idx],false);
if(m) {
materialList[idx] = m;
curMaterial = mat;
v = stopData[idx];
size_t nbins = v->GetVectorLength();
const G4ParticleDefinition* p = G4Proton::Proton();
if(verbose>1) G4cout << "G4ionIonisation::InitialiseMaterial Stooping data for "
<< materialName[idx] << G4endl;
G4bool b;
for(size_t i=0; i<nbins; i++) {
G4double e = v->GetLowEdgeEnergy(i);
G4double dedx = v->GetValue(e, b);
G4double dedx1= ionModel->ComputeDEDXPerVolume(mat, p, e, e)*
effCharge.EffectiveChargeSquareRatio(curParticle,mat,e/massFactor);
v->PutValue(i, dedx/dedx1);
if(verbose>1) G4cout << " E(meV)= " << e/MeV << " Correction= " << dedx/dedx1
<< " " << dedx << " " << dedx1 << G4endl;
if(!ionLEModel || !ionHEModel) {
return;
}
const G4ParticleDefinition* ion = curParticle;
G4int Z = Zion[idx];
if(currentZ != Z) {
ion = G4ParticleTable::GetParticleTable()->FindIon(Z, Aion[idx], 0, Z);
}
//G4cout << "BuildCorrectionVector: idx= " << idx << " Z= " << Z
// << " curZ= " << currentZ << G4endl;
// G4double A = nist->GetAtomicMassAmu(Z);
G4double A = G4double(ion->GetBaryonNumber());
G4PhysicsVector* v = stopData[idx];
const G4ParticleDefinition* p = G4GenericIon::GenericIon();
G4double massRatio = proton_mass_c2/ion->GetPDGMass();
if(verbose>1) {
G4cout << "BuildCorrectionVector: Stopping for "
<< curParticle->GetParticleName() << " in "
<< materialName[idx] << " Ion Z= " << Z << " A= " << A
<< " massRatio= " << massRatio << G4endl;
}
G4bool b;
G4PhysicsLogVector* vv =
new G4PhysicsLogVector(eCorrMin,eCorrMax,nbinCorr);
vv->SetSpline(true);
G4double e, eion, dedx, dedx1;
G4double eth0 = v->GetLowEdgeEnergy(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)= "<<escal<<" dedxt0= " <<dedxt
// << " dedxt1= " << dedx1t << G4endl;
for(G4int i=0; i<nbinCorr; i++) {
e = vv->GetLowEdgeEnergy(i);
escal = e/massRatio;
eion = escal/A;
if(eion <= eth0) {
dedx = v->GetValue(eth0, b)*std::sqrt(eion/eth0);
} else {
dedx = v->GetValue(eion, b);
}
qe = effCharge.EffectiveChargeSquareRatio(curParticle,curMaterial,escal);
if(e <= eth) {
dedx1 = ionLEModel->ComputeDEDXPerVolume(curMaterial, p, e, e)*qe;
} else {
dedx1 = ionHEModel->ComputeDEDXPerVolume(curMaterial, p, e, e)*qe +
ComputeIonCorrections(curParticle, curMaterial, escal) + rest/escal;
}
vv->PutValue(i, dedx/dedx1);
if(verbose>1) {
G4cout << " E(meV)= " << e/MeV << " Correction= " << dedx/dedx1
<< " " << dedx << " " << dedx1
<< " massF= " << massFactor << G4endl;
}
}
delete v;
ionList[idx] = ion;
stopData[idx] = vv;
if(verbose>1) G4cout << "End data set " << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmCorrections::InitialiseForNewRun()
{
G4ProductionCutsTable* tb = G4ProductionCutsTable::GetProductionCutsTable();
ncouples = tb->GetTableSize();
if(currmat.size() != ncouples) {
currmat.resize(ncouples);
size_t i;
for(i=0; i<100; i++) {thcorr[i].clear();}
for(i=0; i<ncouples; i++) {
currmat[i] = tb->GetMaterialCutsCouple(i)->GetMaterial();
G4String nam = currmat[i]->GetName();
for(G4int j=0; j<nIons; j++) {
if(nam == materialName[j]) { materialList[j] = currmat[i]; }
}
}
}
return v;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -1412,6 +1482,10 @@ void G4EmCorrections::Initialise()
COSEB[i] = coseb[i];
COSXI[i] = cosxi[i];
}
for(i=1; i<100; i++) {
Z23[i] = std::pow(G4double(i),0.23);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,148 @@
//
// ********************************************************************
// * 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: G4EmElementSelector.cc,v 1.4 2008/08/21 18:53:32 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4EmElementSelector
//
// Author: Vladimir Ivanchenko
//
// Creation date: 29.05.2008
//
// Modifications:
//
// Class Description:
//
// Generic helper class for the random selection of an element
// -------------------------------------------------------------------
//
#include "G4EmElementSelector.hh"
#include "G4VEmModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4EmElementSelector::G4EmElementSelector(G4VEmModel* mod,
const G4Material* mat,
G4int bins,
G4double emin,
G4double emax,
G4bool spline):
model(mod), material(mat), nbins(bins), cutEnergy(-1.0),
lowEnergy(emin), highEnergy(emax)
{
G4int n = material->GetNumberOfElements();
nElmMinusOne = n - 1;
theElementVector = material->GetElementVector();
if(nElmMinusOne > 0) {
for(G4int i=0; i<nElmMinusOne; i++) {
G4PhysicsLogVector* v = new G4PhysicsLogVector(lowEnergy,highEnergy,nbins);
v->SetSpline(spline);
xSections.push_back(v);
}
}
//G4cout << "G4EmElementSelector for " << mat->GetName() << " n= " << n << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4EmElementSelector::~G4EmElementSelector()
{
if(nElmMinusOne > 0) {
for(G4int i=0; i<nElmMinusOne; i++) {
delete xSections[i];
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EmElementSelector::Initialise(const G4ParticleDefinition* part,
G4double cut)
{
//G4cout << "G4EmElementSelector initialise for " << material->GetName() << G4endl;
if(0 == nElmMinusOne || cut == cutEnergy) return;
cutEnergy = cut;
//G4cout << "cut(keV)= " << cut/keV << G4endl;
G4double cross;
const G4double* theAtomNumDensityVector = material->GetVecNbOfAtomsPerVolume();
G4int i;
G4int n = nElmMinusOne + 1;
G4double* xsec = new G4double[n];
// loop over bins
for(G4int j=0; j<nbins; j++) {
G4double e = (xSections[0])->GetLowEdgeEnergy(j);
model->SetupForMaterial(part, material, e);
cross = 0.0;
//G4cout << "j= " << j << " e(MeV)= " << e/MeV << G4endl;
for (i=0; i<n; i++) {
cross += theAtomNumDensityVector[i]*
model->ComputeCrossSectionPerAtom(part, (*theElementVector)[i], e,
cutEnergy, e);
xsec[i] = cross;
}
if(DBL_MIN >= cross) cross = 1.0;
// normalise cross section sum
for (i=0; i<nElmMinusOne; i++) {
xSections[i]->PutValue(j, xsec[i]/cross);
//G4cout << "i= " << i << " xs= " << xsec[i]/cross << G4endl;
}
}
delete [] xsec;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EmElementSelector::Dump(const G4ParticleDefinition* part)
{
G4cout << "======== G4EmElementSelector for the " << model->GetName();
if(part) G4cout << " and " << part->GetParticleName();
G4cout << " for " << material->GetName() << " ========" << G4endl;
if(0 < nElmMinusOne) {
for(G4int i=0; i<nElmMinusOne; i++) {
G4cout << " " << (*theElementVector)[i]->GetName() << " : " << G4endl;
G4cout << *(xSections[i]) << G4endl;
}
}
G4cout << "Last Element in element vector"
<< (*theElementVector)[nElmMinusOne]->GetName()
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4EmModelManager.cc,v 1.40 2007/11/09 11:35:54 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4EmModelManager.cc,v 1.46 2008/10/13 14:56:56 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -77,15 +77,18 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4RegionModels::G4RegionModels(G4int nMod, std::vector<G4int>& list, G4DataVector& lowE)
G4RegionModels::G4RegionModels(G4int nMod, std::vector<G4int>& indx,
G4DataVector& lowE, const G4Region* reg)
{
nModelsForRegion = nMod;
theListOfModelIndexes = new G4int [nModelsForRegion];
lowKineticEnergy = new G4double [nModelsForRegion];
lowKineticEnergy = new G4double [nModelsForRegion+1];
for (G4int i=0; i<nModelsForRegion; i++) {
theListOfModelIndexes[i] = list[i];
theListOfModelIndexes[i] = indx[i];
lowKineticEnergy[i] = lowE[i];
}
lowKineticEnergy[nModelsForRegion] = lowE[nModelsForRegion];
theRegion = reg;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -98,7 +101,6 @@ G4RegionModels::~G4RegionModels()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4LossTableManager.hh"
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4PhysicsVector.hh"
@@ -106,10 +108,10 @@ G4RegionModels::~G4RegionModels()
#include "G4Positron.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Region.hh"
#include "G4RegionStore.hh"
#include "G4Gamma.hh"
#include "G4Positron.hh"
#include "G4UnitsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -127,7 +129,6 @@ G4EmModelManager::G4EmModelManager():
flucModels.clear();
regions.clear();
orderOfModels.clear();
upperEkin.clear();
maxCutInRange = 12.*cm;
maxSubCutInRange = 0.7*mm;
theGamma = G4Gamma::Gamma();
@@ -138,41 +139,7 @@ G4EmModelManager::G4EmModelManager():
G4EmModelManager::~G4EmModelManager()
{
G4int i,j;
Clear();
if(1 < verboseLevel) {
G4cout << "G4EmModelManager:: delete models ";
if(particle) G4cout << " for " << particle->GetParticleName();
G4cout << " nModels=" << nEmModels <<G4endl;
}
for(i = 0; i<nEmModels; i++) {
orderOfModels[i] = 1;
}
for(i = 0; i<nEmModels; i++) {
if (orderOfModels[i]) {
orderOfModels[i] = 0;
for(j = i+1; j<nEmModels; j++) {
if(models[i] == models[j]) orderOfModels[j] = 0;
}
G4String nam = models[i]->GetName();
if(nam != "PAI" && nam != "PAIModel" ) delete models[i];
}
}
for(i = 0; i<nEmModels; i++) {
orderOfModels[i] = 1;
}
for(i = 0; i<nEmModels; i++) {
if (orderOfModels[i]) {
orderOfModels[i] = 0;
for(j = i+1; j<nEmModels; j++) {
if(flucModels[i] == flucModels[j]) orderOfModels[j] = 0;
}
delete flucModels[i];
}
}
if(1 < verboseLevel)
G4cout << "G4EmModelManager:: models are deleted!" << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -180,14 +147,11 @@ G4EmModelManager::~G4EmModelManager()
void G4EmModelManager::Clear()
{
if(1 < verboseLevel) {
G4cout << "G4EmModelManager::Clear()";
if(particle) G4cout << " for " << particle->GetParticleName();
G4cout << G4endl;
G4cout << "G4EmModelManager::Clear()" << G4endl;
}
theCuts.clear();
theSubCuts.clear();
upperEkin.clear();
if(idxOfRegionModels) delete [] idxOfRegionModels;
if(setOfRegionModels && nRegions) {
for(G4int i=0; i<nRegions; i++) {
@@ -214,21 +178,6 @@ void G4EmModelManager::AddEmModel(G4int num, G4VEmModel* p,
regions.push_back(r);
orderOfModels.push_back(num);
p->DefineForRegion(r);
if (nEmModels>0) {
G4int idx = nEmModels;
do {idx--;} while (idx && num < orderOfModels[idx]);
if (num >= orderOfModels[idx] && num <= orderOfModels[idx+1]) idx++;
if (idx < nEmModels) {
models[nEmModels] = models[idx];
flucModels[nEmModels] = flucModels[idx];
regions[nEmModels] = regions[idx];
orderOfModels[nEmModels] = orderOfModels[idx];
models[idx] = p;
flucModels[idx] = fm;
regions[idx] = r;
orderOfModels[idx] = num;
}
}
nEmModels++;
}
@@ -253,14 +202,17 @@ void G4EmModelManager::UpdateEmModel(const G4String& nam,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEmModel* G4EmModelManager::GetModel(G4int i)
G4VEmModel* G4EmModelManager::GetModel(G4int i, G4bool ver)
{
G4VEmModel* m = 0;
if(i >= 0 && i < nEmModels) m = models[i];
else if(verboseLevel > 0)
if(i >= 0 && i < nEmModels) {m = models[i];}
else if(verboseLevel > 0 && ver) {
G4cout << "G4EmModelManager::GetModel WARNING: "
<< "index " << i << " is wrong Nmodels= "
<< nEmModels << G4endl;
<< nEmModels;
if(particle) G4cout << " for " << particle->GetParticleName();
G4cout<< G4endl;
}
return m;
}
@@ -268,8 +220,8 @@ G4VEmModel* G4EmModelManager::GetModel(G4int i)
const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
const G4ParticleDefinition* sp,
G4double theMinSubRange,
G4int val)
G4double theMinSubRange,
G4int val)
{
verboseLevel = val;
if(1 < verboseLevel) {
@@ -292,8 +244,8 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
// Identify the list of regions with different set of models
nRegions = 1;
std::vector<const G4Region*> set;
set.push_back(world);
std::vector<const G4Region*> setr;
setr.push_back(world);
G4bool isWorld = false;
for (G4int ii=0; ii<nEmModels; ii++) {
@@ -305,11 +257,11 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
G4bool newRegion = true;
if (nRegions>1) {
for (G4int j=1; j<nRegions; j++) {
if ( r == set[j] ) newRegion = false;
if ( r == setr[j] ) newRegion = false;
}
}
if (newRegion) {
set.push_back(r);
setr.push_back(r);
nRegions++;
}
}
@@ -321,21 +273,18 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
idxOfRegionModels = new G4int[numOfCouples+1];
idxOfRegionModels[numOfCouples] = 0;
setOfRegionModels = new G4RegionModels*[nRegions];
upperEkin.resize(nEmModels);
std::vector<G4int> modelAtRegion(nEmModels);
std::vector<G4int> modelOrd(nEmModels);
G4DataVector eLow(nEmModels);
G4DataVector eHigh(nEmModels);
G4int nmax = nEmModels;
// Order models for regions
for (G4int reg=0; reg<nRegions; reg++) {
const G4Region* region = set[reg];
const G4Region* region = setr[reg];
G4int n = 0;
std::vector<G4int> modelAtRegion;
G4DataVector eLow;
G4DataVector eHigh;
modelAtRegion.clear();
eLow.clear();
eHigh.clear();
if(isWorld || 0 < reg) {
for (G4int ii=0; ii<nEmModels; ii++) {
@@ -345,7 +294,10 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
G4double tmin = model->LowEnergyLimit();
G4double tmax = model->HighEnergyLimit();
if (n>0) tmin = std::max(tmin, eHigh[n-1]);
G4int ord = orderOfModels[ii];
G4bool push = true;
G4bool insert = false;
G4int idx = n;
if(1 < verboseLevel) {
G4cout << "Model #" << ii
@@ -354,16 +306,104 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
G4cout << "> "
<< " tmin(MeV)= " << tmin/MeV
<< "; tmax(MeV)= " << tmax/MeV
<< "; order= " << orderOfModels[ii]
<< "; order= " << ord
<< G4endl;
}
if (n == 0) n++;
else {
tmin = std::min(tmin, eHigh[n-1]);
if(tmin >= tmax) push = false;
else {
if (tmin < tmax) {
modelAtRegion.push_back(ii);
eLow.push_back(tmin);
eHigh.push_back(tmax);
upperEkin[ii] = tmax;
n++;
// high energy model
if(tmin == eHigh[n-1] && tmax > eHigh[n-1]) n++;
else if (tmax > eHigh[n-1]) {
// compare order of models
for(G4int k = n-1; k>=0; k--) {
if (ord >= modelOrd[k]) {
tmin = std::max(tmin, eHigh[k]);
if(k < n-1) n = k + 2;
break;
} else if (tmin > eLow[k]) {
eHigh[k] = tmin;
n = k + 2;
break;
} else if (tmin == eLow[k]) {
n = k + 1;
break;
}
}
if(tmin < eLow[0]) n = 1;
idx = n - 1;
// low energy model
} else {
tmax = std::max(tmax, eLow[0]);
insert = true;
push = false;
idx = 0;
if(tmax <= eLow[0]) tmax = eLow[0];
else {
for(G4int k=0; k<n; k++) {
if (ord >= modelOrd[k]) {
if(k == 0) {
if(tmin < eLow[0]) tmax = eLow[0];
else insert = false;
break;
} else {
insert = false;
break;
}
} else if(tmax < eHigh[k]) {
idx = k;
if(k > 0) tmin = eLow[k];
eLow[k] = tmax;
break;
} else if(tmax == eHigh[k]) {
insert = false;
push = true;
idx = k;
if(k > 0) tmin = eLow[k];
else tmin = std::min(tmin,eLow[0]);
break;
} else {
modelAtRegion[k] = ii;
modelOrd[k] = ord;
if(k == 0) eLow[idx] = std::min(tmin,eLow[0]);
}
}
}
if(insert && idx < n) n++;
else insert = false;
}
}
}
if(n > nmax) {
nmax = n;
modelAtRegion.resize(nmax);
modelOrd.resize(nmax);
eLow.resize(nmax);
eHigh.resize(nmax);
}
if(insert) {
for(G4int k=n-2; k>=idx; k--) {
modelAtRegion[k+1] = modelAtRegion[k];
modelOrd[k+1] = modelOrd[k];
eLow[k+1] = eLow[k];
eHigh[k+1] = eHigh[k];
}
}
if (push || insert) {
modelAtRegion[idx] = ii;
modelOrd[idx] = ord;
eLow[idx] = tmin;
eHigh[idx] = tmax;
}
}
}
@@ -373,18 +413,19 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
modelAtRegion.push_back(nEmModels);
eLow.push_back(0.0);
eHigh.push_back(DBL_MAX);
upperEkin.push_back(DBL_MAX);
}
eLow[0] = 0.0;
if(n >= nmax) eLow.resize(nmax+1);
eLow[n] = eHigh[n-1];
if(1 < verboseLevel) {
G4cout << "New G4RegionModels set with " << n << " models for region <";
if (region) G4cout << region->GetName();
G4cout << "> Elow(MeV)= ";
for(G4int ii=0; ii<n; ii++) {G4cout << eLow[ii]/MeV << " ";}
for(G4int ii=0; ii<=n; ii++) {G4cout << eLow[ii]/MeV << " ";}
G4cout << G4endl;
}
G4RegionModels* rm = new G4RegionModels(n, modelAtRegion, eLow);
G4RegionModels* rm = new G4RegionModels(n, modelAtRegion, eLow, region);
setOfRegionModels[reg] = rm;
}
@@ -398,7 +439,7 @@ const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
const G4ProductionCuts* pcuts = couple->GetProductionCuts();
G4int reg = nRegions;
do {reg--;} while (reg>0 && pcuts != (set[reg]->GetProductionCuts()));
do {reg--;} while (reg>0 && pcuts != (setr[reg]->GetProductionCuts()));
idxOfRegionModels[i] = reg;
if(1 < verboseLevel) {
@@ -473,11 +514,6 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
G4EmTableType tType)
{
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector dedxLow;
G4DataVector dedxHigh;
G4double e;
size_t i = couple->GetIndex();
@@ -490,8 +526,8 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
if(1 < verboseLevel) {
G4cout << "G4EmModelManager::FillDEDXVector() for "
<< couple->GetMaterial()->GetName()
<< " Ecut(MeV)= " << cut
<< " Esubcut(MeV)= " << subcut
<< " cut(MeV)= " << cut
<< " subcut(MeV)= " << subcut
<< " Type " << tType
<< " for " << particle->GetParticleName()
<< G4endl;
@@ -500,9 +536,12 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
G4int reg = idxOfRegionModels[i];
const G4RegionModels* regModels = setOfRegionModels[reg];
G4int nmod = regModels->NumberOfModels();
factor.resize(nmod);
dedxLow.resize(nmod);
dedxHigh.resize(nmod);
// vectors to provide continues dE/dx
G4DataVector factor(nmod);
G4DataVector eLow(nmod+1);
G4DataVector dedxLow(nmod);
G4DataVector dedxHigh(nmod);
if(1 < verboseLevel) {
G4cout << "There are " << nmod << " models for "
@@ -511,44 +550,66 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
<< G4endl;
}
// calculate factors to provide continuity of energy loss
factor[0] = 1.0;
G4int j;
G4int totBinsLoss = aVector->GetVectorLength();
dedxLow[0] = 0.0;
dedxLow[0] = 0.0;
eLow[0] = 0.0;
e = upperEkin[regModels->ModelIndex(0)];
e = regModels->LowEdgeEnergy(1);
eLow[1] = e;
G4VEmModel* model = models[regModels->ModelIndex(0)];
dedxHigh[0] = 0.0;
if(model && cut > subcut) {
dedxHigh[0] = model->ComputeDEDX(couple,particle,e,cut);
if(subcut > 0.0)
if(subcut > 0.0) {
dedxHigh[0] -= model->ComputeDEDX(couple,particle,e,subcut);
}
}
if(nmod > 1) {
for(j=1; j<nmod; j++) {
e = upperEkin[regModels->ModelIndex(j-1)];
e = regModels->LowEdgeEnergy(j);
eLow[j] = e;
G4int idx = regModels->ModelIndex(j);
dedxLow[j] = models[idx]->ComputeDEDX(couple,particle,e,cut);
if(subcut > 0.0)
if(subcut > 0.0) {
dedxLow[j] -= models[idx]->ComputeDEDX(couple,particle,e,subcut);
}
if(subcut == cut) dedxLow[j] = 0.0;
e = upperEkin[idx];
e = regModels->LowEdgeEnergy(j+1);
eLow[j+1] = e;
dedxHigh[j] = models[idx]->ComputeDEDX(couple,particle,e,cut);
if(subcut > 0.0)
if(subcut > 0.0) {
dedxHigh[j] -= models[idx]->ComputeDEDX(couple,particle,e,subcut);
}
if(subcut == cut) dedxHigh[j] = 0.0;
}
if(1 < verboseLevel) {
G4cout << " model #0"
<< " dedx(" << eLow[0] << ")= " << dedxLow[0]
<< " dedx(" << eLow[1] << ")= " << dedxHigh[0]
<< G4endl;
}
for(j=1; j<nmod; j++) {
if(dedxLow[j] > 0.0) factor[j] = (dedxHigh[j-1]/dedxLow[j] - 1.0);
else factor[j] = 0.0;
if(dedxLow[j] > 0.0) {
factor[j] = (dedxHigh[j-1]/dedxLow[j] - 1.0)*eLow[j];
} else factor[j] = 0.0;
if(1 < verboseLevel) {
G4cout << " model #" << j
<< " dedx(" << eLow[j] << ")= " << dedxLow[j]
<< " dedx(" << eLow[j+1] << ")= " << dedxHigh[j]
<< " factor= " << factor[j]/eLow[j]
<< G4endl;
}
}
if(2 < verboseLevel) {
@@ -564,11 +625,11 @@ void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
// Choose a model of energy losses
G4int k = 0;
if (nmod > 1 && e > upperEkin[regModels->ModelIndex(0)]) {
if (nmod > 1 && e > eLow[1]) {
do {
k++;
fac *= (1.0 + factor[k]*upperEkin[regModels->ModelIndex(k-1)]/e);
} while (k<nmod-1 && e > upperEkin[regModels->ModelIndex(k)] );
fac *= (1.0 + factor[k]/e);
} while (k+1 < nmod && e > eLow[k+1]);
}
model = models[regModels->ModelIndex(k)];
@@ -601,11 +662,6 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
G4bool startFromNull,
G4EmTableType tType)
{
// vectors to provide continues cross section
G4DataVector factor;
G4DataVector sigmaLow;
G4DataVector sigmaHigh;
G4double e;
size_t i = couple->GetIndex();
@@ -629,9 +685,12 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
G4int reg = idxOfRegionModels[i];
const G4RegionModels* regModels = setOfRegionModels[reg];
G4int nmod = regModels->NumberOfModels();
factor.resize(nmod);
sigmaLow.resize(nmod);
sigmaHigh.resize(nmod);
// vectors to provide continues dE/dx
G4DataVector factor(nmod);
G4DataVector eLow(nmod+1);
G4DataVector sigmaLow(nmod);
G4DataVector sigmaHigh(nmod);
if(2 < verboseLevel) {
G4cout << "There are " << nmod << " models for "
@@ -643,9 +702,11 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
G4int j;
G4int totBinsLambda = aVector->GetVectorLength();
sigmaLow[0] = 0.0;
sigmaLow[0] = 0.0;
eLow[0] = 0.0;
e = upperEkin[regModels->ModelIndex(0)];
e = regModels->LowEdgeEnergy(1);
eLow[1] = e;
G4VEmModel* model = models[regModels->ModelIndex(0)];
sigmaHigh[0] = 0.0;
if(model) sigmaHigh[0] = model->CrossSection(couple,particle,e,cut,tmax);
@@ -667,22 +728,32 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
for(j=1; j<nmod; j++) {
e = upperEkin[regModels->ModelIndex(j-1)];
sigmaLow[j] =
models[regModels->ModelIndex(j)]->CrossSection(couple,particle,e,cut,tmax);
e = upperEkin[regModels->ModelIndex(j)];
sigmaHigh[j] =
models[regModels->ModelIndex(j)]->CrossSection(couple,particle,e,cut,tmax);
if(1 < verboseLevel) {
G4cout << " model #" << j << " eUp= " << e
<< " sigmaUp= " << sigmaHigh[j]
<< " sigmaDown= " << sigmaLow[j]
<< G4endl;
}
e = regModels->LowEdgeEnergy(j);
eLow[j] = e;
G4int idx = regModels->ModelIndex(j);
sigmaLow[j] = models[idx]->CrossSection(couple,particle,e,cut,tmax);
e = regModels->LowEdgeEnergy(j+1);
eLow[j+1] = e;
sigmaHigh[j] = models[idx]->CrossSection(couple,particle,e,cut,tmax);
}
if(1 < verboseLevel) {
G4cout << " model #0"
<< " sigma(" << eLow[0] << ")= " << sigmaLow[0]
<< " sigma(" << eLow[1] << ")= " << sigmaHigh[0]
<< G4endl;
}
for(j=1; j<nmod; j++) {
if(sigmaLow[j] > 0.0) factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0);
else factor[j] = 0.0;
if(sigmaLow[j] > 0.0) {
factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0)*eLow[j];
} else factor[j] = 0.0;
if(1 < verboseLevel) {
G4cout << " model #" << j
<< " sigma(" << eLow[j] << ")= " << sigmaLow[j]
<< " sigma(" << eLow[j+1] << ")= " << sigmaHigh[j]
<< " factor= " << factor[j]/eLow[j]
<< G4endl;
}
}
}
@@ -694,11 +765,11 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
// Choose a model of energy losses
G4int k = 0;
G4double fac = 1.0;
if (nmod > 1 && e > upperEkin[regModels->ModelIndex(0)]) {
if (nmod > 1 && e > eLow[1]) {
do {
k++;
fac *= (1.0 + factor[k]*upperEkin[regModels->ModelIndex(k-1)]/e);
} while (k<nmod-1 && e > upperEkin[regModels->ModelIndex(k)] );
fac *= (1.0 + factor[k]/e);
} while ( k+1 < nmod && e > eLow[k+1] );
}
model = models[regModels->ModelIndex(k)];
@@ -720,3 +791,30 @@ void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::DumpModelList(G4int verb)
{
if(verb == 0) return;
for(G4int i=0; i<nRegions; i++) {
G4RegionModels* r = setOfRegionModels[i];
const G4Region* reg = r->Region();
if(verb > 1 || nRegions > 1) {
}
G4int n = r->NumberOfModels();
if(verb > 1 || n > 0) {
G4cout << " ===== EM models for the G4Region " << reg->GetName()
<< " ======" << G4endl;;
for(G4int j=0; j<n; j++) {
const G4VEmModel* m = models[r->ModelIndex(j)];
G4cout << std::setw(20);
G4cout << m->GetName() << " : Emin= "
<< std::setw(10) << G4BestUnit(r->LowEdgeEnergy(j),"Energy")
<< " Emax= "
<< G4BestUnit(r->LowEdgeEnergy(j+1),"Energy")
<< G4endl;
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -24,7 +24,7 @@
// ********************************************************************
//
// $Id: G4EmMultiModel.cc,v 1.6 2007/05/22 17:31:58 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4EmProcessOptions.cc,v 1.22 2007/11/07 18:38:49 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4EmProcessOptions.cc,v 1.24 2008/04/17 10:33:27 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -476,6 +476,25 @@ void G4EmProcessOptions::SetMscGeomFactor(G4double val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmProcessOptions::SetPolarAngleLimit(G4double val)
{
const std::vector<G4VMultipleScattering*>& u =
theManager->GetMultipleScatteringVector();
std::vector<G4VMultipleScattering*>::const_iterator itm;
for(itm = u.begin(); itm != u.end(); itm++) {
if(*itm) (*itm)->SetPolarAngleLimit(val);
}
const std::vector<G4VEmProcess*>& w =
theManager->GetEmProcessVector();
std::vector<G4VEmProcess*>::const_iterator itp;
for(itp = w.begin(); itp != w.end(); itp++) {
G4VEmProcess* q = *itp;
if(q) q->SetPolarAngleLimit(val);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmProcessOptions::SetLPMFlag(G4bool val)
{
theManager->SetLPMFlag(val);
@@ -483,6 +502,13 @@ void G4EmProcessOptions::SetLPMFlag(G4bool val)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmProcessOptions::SetSplineFlag(G4bool val)
{
theManager->SetSplineFlag(val);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmProcessOptions::SetLinearLossLimit(G4double val)
{
theManager->SetLinearLossLimit(val);
@@ -0,0 +1,291 @@
//
// ********************************************************************
// * 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: G4EmSaturation.cc,v 1.9 2008/11/12 15:37:33 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4EmSaturation
//
// Author: Vladimir Ivanchenko
//
// Creation date: 18.02.2008
//
// Modifications:
//
// -------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4EmSaturation.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4Neutron.hh"
#include "G4Proton.hh"
#include "G4LossTableManager.hh"
#include "G4NistManager.hh"
#include "G4Material.hh"
#include "G4MaterialCutsCouple.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmSaturation::G4EmSaturation()
{
verbose = 1;
manager = 0;
curMaterial = 0;
curBirks = 0.0;
curRatio = 1.0;
curChargeSq = 1.0;
nMaterials = 0;
Initialise();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmSaturation::~G4EmSaturation()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmSaturation::VisibleEnergyDeposition(
const G4ParticleDefinition* p,
const G4MaterialCutsCouple* couple,
G4double length,
G4double edep,
G4double niel)
{
if(edep <= 0.0) return 0.0;
G4double evis = edep;
G4double bfactor = FindBirksCoefficient(couple->GetMaterial());
if(bfactor > 0.0) {
// atomic relaxations
if(p == gamma) {
evis /= (1.0 + bfactor*edep/manager->GetRange(electron,edep,couple));
// energy loss
} else {
// protections
G4double nloss = niel;
if(nloss < 0.0) nloss = 0.0;
G4double eloss = edep - nloss;
if(p == neutron || eloss < 0.0 || length <= 0.0) {
nloss = edep;
eloss = 0.0;
}
// continues energy loss
if(eloss > 0.0) eloss /= (1.0 + bfactor*eloss/length);
// non-ionizing energy loss
if(nloss > 0.0) {
G4double escaled = nloss*curRatio;
G4double s = manager->GetRange(proton,escaled,couple)/curChargeSq;
nloss /= (1.0 + bfactor*nloss/s);
}
evis = eloss + nloss;
}
}
return evis;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmSaturation::FindG4BirksCoefficient(const G4Material* mat)
{
G4String name = mat->GetName();
// is this material in the vector?
for(G4int j=0; j<nG4Birks; j++) {
if(name == g4MatNames[j]) {
if(verbose > 0)
G4cout << "### G4EmSaturation::FindG4BirksCoefficient for "
<< name << " is " << g4MatData[j]*MeV/mm << " mm/MeV "
<< G4endl;
return g4MatData[j];
}
}
return FindBirksCoefficient(mat);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4EmSaturation::FindBirksCoefficient(const G4Material* mat)
{
if(mat == curMaterial) return curBirks;
curMaterial = mat;
curBirks = 0.0;
curRatio = 1.0;
curChargeSq = 1.0;
// seach in the run-time list
for(G4int i=0; i<nMaterials; i++) {
if(mat == matPointers[i]) {
curBirks = mat->GetIonisation()->GetBirksConstant();
curRatio = massFactors[i];
curChargeSq = effCharges[i];
return curBirks;
}
}
if(!manager) {
manager = G4LossTableManager::Instance();
nist = G4NistManager::Instance();
gamma = G4Gamma::Gamma();
electron= G4Electron::Electron();
proton = G4Proton::Proton();
neutron = G4Neutron::Neutron();
}
G4String name = mat->GetName();
curBirks = mat->GetIonisation()->GetBirksConstant();
// material has no Birks coeffitient defined
// seach in the Geant4 list
if(curBirks == 0.0) {
for(G4int j=0; j<nG4Birks; j++) {
if(name == g4MatNames[j]) {
mat->GetIonisation()->SetBirksConstant(g4MatData[j]);
curBirks = g4MatData[j];
break;
}
}
}
if(curBirks == 0.0 && verbose > 0) {
G4cout << "### G4EmSaturation::FindBirksCoefficient fails "
" for material " << name << G4endl;
}
// compute mean mass ratio
curRatio = 0.0;
curChargeSq = 0.0;
G4double norm = 0.0;
const G4ElementVector* theElementVector = mat->GetElementVector();
const G4double* theAtomNumDensityVector = mat->GetVecNbOfAtomsPerVolume();
size_t nelm = mat->GetNumberOfElements();
for (size_t i=0; i<nelm; i++) {
const G4Element* elm = (*theElementVector)[i];
G4double Z = elm->GetZ();
G4double w = Z*Z*theAtomNumDensityVector[i];
curRatio += w/nist->GetAtomicMassAmu(G4int(Z));
curChargeSq = Z*Z*w;
norm += w;
}
curRatio *= proton_mass_c2/norm;
curChargeSq /= norm;
// store results
matPointers.push_back(mat);
matNames.push_back(name);
massFactors.push_back(curRatio);
effCharges.push_back(curChargeSq);
nMaterials++;
if(curBirks > 0.0 && verbose > 0) {
G4cout << "### G4EmSaturation::FindBirksCoefficient Birks coefficient for "
<< name << " " << curBirks*MeV/mm << " mm/MeV" << G4endl;
}
return curBirks;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmSaturation::DumpBirksCoefficients()
{
if(nMaterials > 0) {
G4cout << "### Birks coeffitients used in run time" << G4endl;
for(G4int i=0; i<nMaterials; i++) {
G4double br = matPointers[i]->GetIonisation()->GetBirksConstant();
G4cout << " " << matNames[i] << " "
<< br*MeV/mm << " mm/MeV" << " "
<< br*matPointers[i]->GetDensity()*MeV*cm2/g
<< " g/cm^2/MeV"
<< G4endl;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmSaturation::DumpG4BirksCoefficients()
{
if(nG4Birks > 0) {
G4cout << "### Birks coeffitients for Geant4 materials" << G4endl;
for(G4int i=0; i<nG4Birks; i++) {
G4cout << " " << g4MatNames[i] << " "
<< g4MatData[i]*MeV/mm << " mm/MeV" << G4endl;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmSaturation::Initialise()
{
// M.Hirschberg et al., IEEE Trans. Nuc. Sci. 39 (1992) 511
// SCSN-38 kB = 0.00842 g/cm^2/MeV; rho = 1.06 g/cm^3
g4MatNames.push_back("G4_POLYSTYRENE");
g4MatData.push_back(0.07943*mm/MeV);
// C.Fabjan (private communication)
// kB = 0.006 g/cm^2/MeV; rho = 7.13 g/cm^3
g4MatNames.push_back("G4_BGO");
g4MatData.push_back(0.008415*mm/MeV);
// A.Ribon analysis of publications
// Scallettar et al., Phys. Rev. A25 (1982) 2419.
// NIM A 523 (2004) 275.
// kB = 0.022 g/cm^2/MeV; rho = 1.396 g/cm^3;
// ATLAS Efield = 10 kV/cm provide the strongest effect
g4MatNames.push_back("G4_lAr");
g4MatData.push_back(0.1576*mm/MeV);
//G4_BARIUM_FLUORIDE
//G4_CESIUM_IODIDE
//G4_GEL_PHOTO_EMULSION
//G4_PHOTO_EMULSION
//G4_PLASTIC_SC_VINYLTOLUENE
//G4_SODIUM_IODIDE
//G4_STILBENE
//G4_lAr
//G4_PbWO4
//G4_Lucite
nG4Birks = g4MatData.size();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -24,8 +24,8 @@
// ********************************************************************
//
//
// $Id: G4EnergyLossMessenger.cc,v 1.29 2007/06/11 14:56:51 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4EnergyLossMessenger.cc,v 1.35 2008/10/20 13:27:45 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -48,6 +48,7 @@
// is needed after the command (V.Ivanchenko)
// 16-03-07 modify /process/eLoss/minsubsec command (V.Ivanchenko)
// 18-05-07 add /process/msc directory and commands (V.Ivanchenko)
// 11-03-08 add /process/em directory and commands (V.Ivanchenko)
//
// -------------------------------------------------------------------
//
@@ -83,6 +84,8 @@ G4EnergyLossMessenger::G4EnergyLossMessenger()
eLossDirectory->SetGuidance("Commands for EM processes.");
mscDirectory = new G4UIdirectory("/process/msc/");
mscDirectory->SetGuidance("Commands for EM scattering processes.");
emDirectory = new G4UIdirectory("/process/em/");
emDirectory->SetGuidance("General commands for EM processes.");
RndmStepCmd = new G4UIcmdWithABool("/process/eLoss/rndmStep",this);
RndmStepCmd->SetGuidance("Randomize the proposed step by eLoss.");
@@ -145,81 +148,104 @@ G4EnergyLossMessenger::G4EnergyLossMessenger()
MaxEnCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
IntegCmd = new G4UIcmdWithABool("/process/eLoss/integral",this);
IntegCmd->SetGuidance("Switch true/false the integration of cross section over step.");
IntegCmd->SetGuidance("Switch true/false the integral option");
IntegCmd->SetParameterName("integ",true);
IntegCmd->SetDefaultValue(true);
IntegCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
rangeCmd = new G4UIcmdWithABool("/process/eLoss/CSDARange",this);
rangeCmd->SetGuidance("Switch true/false the precise range calculation.");
rangeCmd->SetGuidance("Switch true/false the CSDA range calculation");
rangeCmd->SetParameterName("range",true);
rangeCmd->SetDefaultValue(true);
rangeCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
lpmCmd = new G4UIcmdWithABool("/process/eLoss/LPM",this);
lpmCmd->SetGuidance("Switch true/false the LPM effect calculation.");
lpmCmd->SetGuidance("The flag of the LPM effect calculation");
lpmCmd->SetParameterName("lpm",true);
lpmCmd->SetDefaultValue(true);
lpmCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
splCmd = new G4UIcmdWithABool("/process/em/spline",this);
splCmd->SetGuidance("The flag of usage spline for Physics Vectors");
splCmd->SetParameterName("spl",true);
splCmd->SetDefaultValue(false);
splCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
aplCmd = new G4UIcmdWithABool("/process/em/applyCuts",this);
aplCmd->SetGuidance("The flag to Apply Cuts for gamma processes");
aplCmd->SetParameterName("apl",true);
aplCmd->SetDefaultValue(false);
aplCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
dedxCmd = new G4UIcmdWithAnInteger("/process/eLoss/binsDEDX",this);
dedxCmd->SetGuidance("Set number of bins for DEDX tables.");
dedxCmd->SetGuidance("Set number of bins for DEDX tables");
dedxCmd->SetParameterName("binsDEDX",true);
dedxCmd->SetDefaultValue(120);
dedxCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
lamCmd = new G4UIcmdWithAnInteger("/process/eLoss/binsLambda",this);
lamCmd->SetGuidance("Set number of bins for Lambda tables.");
lamCmd->SetGuidance("Set number of bins for Lambda tables");
lamCmd->SetParameterName("binsL",true);
lamCmd->SetDefaultValue(120);
lamCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
verCmd = new G4UIcmdWithAnInteger("/process/eLoss/verbose",this);
verCmd->SetGuidance("Set verbose level for EM physics.");
verCmd->SetGuidance("Set verbose level for EM physics");
verCmd->SetParameterName("verb",true);
verCmd->SetDefaultValue(1);
verCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
ver1Cmd = new G4UIcmdWithAnInteger("/process/em/verbose",this);
ver1Cmd->SetGuidance("Set verbose level for EM physics");
ver1Cmd->SetParameterName("verb1",true);
ver1Cmd->SetDefaultValue(1);
ver1Cmd->AvailableForStates(G4State_PreInit,G4State_Idle);
lllCmd = new G4UIcmdWithADouble("/process/eLoss/linLossLimit",this);
lllCmd->SetGuidance("Set linearLossLimit parameter.");
lllCmd->SetGuidance("Set linearLossLimit parameter");
lllCmd->SetParameterName("linlim",true);
lllCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
labCmd = new G4UIcmdWithADouble("/process/eLoss/lambdaFactor",this);
labCmd->SetGuidance("Set lambdaFactor parameter.");
labCmd = new G4UIcmdWithADouble("/process/eLoss/LambdaFactor",this);
labCmd->SetGuidance("Set lambdaFactor parameter for integral option");
labCmd->SetParameterName("Fl",true);
labCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
mscCmd = new G4UIcmdWithAString("/process/msc/StepLimit",this);
mscCmd->SetGuidance("Set msc step limitation type.");
mscCmd->SetGuidance("Set msc step limitation type");
mscCmd->SetParameterName("StepLim",true);
mscCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
latCmd = new G4UIcmdWithABool("/process/msc/LateralDisplacement",this);
latCmd->SetGuidance("Switch true/false sampling of latra dislacent.");
latCmd->SetGuidance("Set flag of sampling of lateral displacement");
latCmd->SetParameterName("lat",true);
latCmd->SetDefaultValue(true);
latCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
frCmd = new G4UIcmdWithADouble("/process/msc/RangeFactor",this);
frCmd->SetGuidance("Set RangeFactor parameter for msc process.");
frCmd->SetGuidance("Set RangeFactor parameter for msc processes");
frCmd->SetParameterName("Fr",true);
frCmd->SetRange("Fr>0");
frCmd->SetDefaultValue(0.02);
frCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
fgCmd = new G4UIcmdWithADouble("/process/msc/GeomFactor",this);
fgCmd->SetGuidance("Set GeomFactor parameter for msc process.");
fgCmd->SetGuidance("Set GeomFactor parameter for msc processes");
fgCmd->SetParameterName("Fg",true);
fgCmd->SetRange("Fg>0");
fgCmd->SetDefaultValue(3.5);
fgCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
skinCmd = new G4UIcmdWithADouble("/process/msc/Skin",this);
skinCmd->SetGuidance("Set skin parameter for multiple scattering.");
skinCmd->SetGuidance("Set skin parameter for msc processes");
skinCmd->SetParameterName("skin",true);
skinCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
angCmd = new G4UIcmdWithADoubleAndUnit("/process/msc/ThetaLimit",this);
angCmd->SetGuidance("Set the limit on the polar angle");
angCmd->SetParameterName("theta",true);
angCmd->SetUnitCategory("Angle");
angCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -234,13 +260,17 @@ G4EnergyLossMessenger::~G4EnergyLossMessenger()
delete StepFuncCmd;
delete eLossDirectory;
delete mscDirectory;
delete emDirectory;
delete MinEnCmd;
delete MaxEnCmd;
delete IntegCmd;
delete rangeCmd;
delete lpmCmd;
delete splCmd;
delete aplCmd;
delete latCmd;
delete verCmd;
delete ver1Cmd;
delete mscCmd;
delete dedxCmd;
delete frCmd;
@@ -249,6 +279,7 @@ G4EnergyLossMessenger::~G4EnergyLossMessenger()
delete lamCmd;
delete labCmd;
delete skinCmd;
delete angCmd;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -316,9 +347,9 @@ void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
G4UImanager::GetUIpointer()->ApplyCommand("/run/physicsModified");
}
if (command == IntegCmd)
if (command == IntegCmd) {
opt->SetIntegral(IntegCmd->GetNewBoolValue(newValue));
}
if (command == rangeCmd) {
opt->SetBuildCSDARange(rangeCmd->GetNewBoolValue(newValue));
G4UImanager::GetUIpointer()->ApplyCommand("/run/physicsModified");
@@ -329,20 +360,32 @@ void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
G4UImanager::GetUIpointer()->ApplyCommand("/run/physicsModified");
}
if (command == splCmd) {
opt->SetSplineFlag(splCmd->GetNewBoolValue(newValue));
G4UImanager::GetUIpointer()->ApplyCommand("/run/physicsModified");
}
if (command == aplCmd) {
opt->SetApplyCuts(aplCmd->GetNewBoolValue(newValue));
}
if (command == latCmd) {
opt->SetMscLateralDisplacement(latCmd->GetNewBoolValue(newValue));
G4UImanager::GetUIpointer()->ApplyCommand("/run/physicsModified");
}
if (command == verCmd)
if (command == verCmd) {
opt->SetVerbose(verCmd->GetNewIntValue(newValue));
if (command == lllCmd)
}
if (command == ver1Cmd) {
opt->SetVerbose(ver1Cmd->GetNewIntValue(newValue));
}
if (command == lllCmd) {
opt->SetLinearLossLimit(lllCmd->GetNewDoubleValue(newValue));
if (command == labCmd)
}
if (command == labCmd) {
opt->SetLambdaFactor(labCmd->GetNewDoubleValue(newValue));
}
if (command == skinCmd) {
opt->SetSkin(skinCmd->GetNewDoubleValue(newValue));
G4UImanager::GetUIpointer()->ApplyCommand("/run/physicsModified");
@@ -363,6 +406,10 @@ void G4EnergyLossMessenger::SetNewValue(G4UIcommand* command,G4String newValue)
opt->SetMscGeomFactor(fgCmd->GetNewDoubleValue(newValue));
G4UImanager::GetUIpointer()->ApplyCommand("/run/physicsModified");
}
if (command == angCmd) {
opt->SetPolarAngleLimit(angCmd->GetNewDoubleValue(newValue));
G4UImanager::GetUIpointer()->ApplyCommand("/run/physicsModified");
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -24,8 +24,8 @@
// ********************************************************************
//
//
// $Id: G4EnergyLossTables.cc,v 1.33 2006/06/29 19:55:09 gunter Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4EnergyLossTables.cc,v 1.34 2008/07/08 10:57:22 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
// first version created by P.Urban , 06/04/1998
@@ -997,12 +997,13 @@ void G4EnergyLossTables::CPRWarning()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4EnergyLossTables::ParticleHaveNoLoss(const G4ParticleDefinition* aParticle, const G4String& q)
void G4EnergyLossTables::ParticleHaveNoLoss(const G4ParticleDefinition* aParticle,
const G4String& q)
{
G4String s = "G4EnergyLossTables:: " + q + " table not found for "
+ aParticle->GetParticleName() + "!";
G4Exception(s);
exit(1);
G4String s = " " + q + " table not found for "
+ aParticle->GetParticleName() + " !";
G4Exception("G4EnergyLossTables::ParticleHaveNoLoss", "EM01",
FatalException, s);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4LossTableBuilder.cc,v 1.24 2007/02/16 11:59:35 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4LossTableBuilder.cc,v 1.27 2008/07/22 15:55:15 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -63,7 +63,9 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LossTableBuilder::G4LossTableBuilder()
{}
{
splineFlag = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -72,8 +74,9 @@ G4LossTableBuilder::~G4LossTableBuilder()
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LossTableBuilder::BuildDEDXTable(G4PhysicsTable* dedxTable,
const std::vector<G4PhysicsTable*>& list)
void
G4LossTableBuilder::BuildDEDXTable(G4PhysicsTable* dedxTable,
const std::vector<G4PhysicsTable*>& list)
{
size_t n_processes = list.size();
if(1 >= n_processes) return;
@@ -90,6 +93,7 @@ void G4LossTableBuilder::BuildDEDXTable(G4PhysicsTable* dedxTable,
for (size_t i=0; i<n_vectors; i++) {
pv = new G4PhysicsLogVector(elow, ehigh, nbins);
pv->SetSpline(splineFlag);
for (size_t j=0; j<nbins; j++) {
G4double dedx = 0.0;
G4double energy = pv->GetLowEdgeEnergy(j);
@@ -127,6 +131,7 @@ void G4LossTableBuilder::BuildRangeTable(const G4PhysicsTable* dedxTable,
G4double ehigh = pv->GetLowEdgeEnergy(nbins);
G4double dedx1 = pv->GetValue(elow, b);
// protection for specific cases dedx=0
if(dedx1 == 0.0) {
for (size_t k=1; k<nbins; k++) {
bin0++;
@@ -137,39 +142,29 @@ void G4LossTableBuilder::BuildRangeTable(const G4PhysicsTable* dedxTable,
nbins -= bin0;
}
// initialisation of a new vector
G4PhysicsLogVector* v = new G4PhysicsLogVector(elow, ehigh, nbins);
v->SetSpline(splineFlag);
// assumed dedx proportional to beta
G4double range = 2.*elow/dedx1;
//G4double range = elow/dedx1;
v->PutValue(0,range);
G4double energy1 = elow;
for (size_t j=1; j<nbins; j++) {
G4double energy2 = pv->GetLowEdgeEnergy(j+bin0);
G4double dedx2 = pv->GetValue(energy2, b);
G4double de = (energy2 - energy1) * del;
G4double energy = energy1 - de*0.5;
G4bool yes = true;
//G4bool yes = false;
if(dedx1 < DBL_MIN || dedx2 < DBL_MIN) yes = false;
G4double fac, f;
if(yes) fac = std::log(dedx2/dedx1)/std::log(energy2/energy1);
else fac = (dedx2 - dedx1)/(energy2 - energy1);
G4double energy = energy2 + de*0.5;
for (size_t k=0; k<n; k++) {
energy += de;
if(yes) f = dedx1*std::exp(fac*std::log(energy/energy1));
else f = dedx1 + fac*(energy - energy1);
if(f > DBL_MIN) range += de/f;
}
energy -= de;
dedx1 = pv->GetValue(energy, b);
if(dedx1 > 0.0) range += de/dedx1;
}
// G4cout << "Range i= " <<i << " j= " << j << G4endl;
v->PutValue(j,range);
energy1 = energy2;
dedx1 = dedx2;
}
G4PhysicsTableHelper::SetPhysicsVector(rangeTable, i, v);
}
@@ -196,16 +191,16 @@ void G4LossTableBuilder::BuildInverseRangeTable(const G4PhysicsTable* rangeTable
G4double ehigh = pv->GetLowEdgeEnergy(nbins-1);
G4double rlow = pv->GetValue(elow, b);
G4double rhigh = pv->GetValue(ehigh, b);
rhigh *= std::exp(std::log(rhigh/rlow)/((G4double)(nbins-1)));
G4LPhysicsFreeVector* v = new G4LPhysicsFreeVector(nbins,rlow,rhigh);
v->SetSpline(splineFlag);
for (size_t j=0; j<nbins; j++) {
G4double e = pv->GetLowEdgeEnergy(j);
G4double r = pv->GetValue(e, b);
v->PutValues(j,r,e);
}
v->PutValues(nbins,rhigh+rlow,ehigh);
G4PhysicsTableHelper::SetPhysicsVector(invRangeTable, i, v);
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4LossTableManager.cc,v 1.84 2007/06/14 07:28:48 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4LossTableManager.cc,v 1.95 2008/11/13 18:23:39 schaelic Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -69,6 +69,7 @@
// left ionisation table for further usage (VI)
// 12-02-07 Add SetSkin, SetLinearLossLimit (V.Ivanchenko)
// 18-06-07 Move definition of msc parameters to G4EmProcessOptions (V.Ivanchenko)
// 21-02-08 Add G4EmSaturation (V.Ivanchenko)
//
// Class Description:
//
@@ -90,6 +91,7 @@
#include "G4ProductionCutsTable.hh"
#include "G4PhysicsTableHelper.hh"
#include "G4EmCorrections.hh"
#include "G4EmSaturation.hh"
#include "G4EmTableType.hh"
#include "G4LossTableBuilder.hh"
@@ -115,16 +117,25 @@ G4LossTableManager::~G4LossTableManager()
}
size_t msc = msc_vector.size();
for (size_t j=0; j<msc; j++) {
if(msc_vector[j] ) delete msc_vector[j];
if( msc_vector[j] ) delete msc_vector[j];
}
size_t emp = emp_vector.size();
for (size_t k=0; k<emp; k++) {
if(emp_vector[k] ) delete emp_vector[k];
if( emp_vector[k] ) delete emp_vector[k];
}
size_t mod = mod_vector.size();
for (size_t a=0; a<mod; a++) {
if( mod_vector[a] ) delete mod_vector[a];
}
size_t fmod = fmod_vector.size();
for (size_t b=0; b<fmod; b++) {
if( fmod_vector[b] ) delete fmod_vector[b];
}
Clear();
delete theMessenger;
delete tableBuilder;
delete emCorrections;
delete emSaturation;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
@@ -151,6 +162,7 @@ G4LossTableManager::G4LossTableManager()
theElectron = G4Electron::Electron();
tableBuilder = new G4LossTableBuilder();
emCorrections= new G4EmCorrections();
emSaturation = new G4EmSaturation();
integral = true;
integralActive = false;
buildCSDARange = false;
@@ -159,8 +171,10 @@ G4LossTableManager::G4LossTableManager()
maxEnergyForMuonsActive = false;
stepFunctionActive = false;
flagLPM = true;
splineFlag = true;
bremsTh = DBL_MAX;
verbose = 1;
tableBuilder->SetSplineFlag(splineFlag);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
@@ -225,9 +239,10 @@ void G4LossTableManager::DeRegister(G4VEnergyLossProcess* p)
void G4LossTableManager::Register(G4VMultipleScattering* p)
{
msc_vector.push_back(p);
if(verbose > 1)
if(verbose > 1) {
G4cout << "G4LossTableManager::Register G4VMultipleScattering : "
<< p->GetProcessName() << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
@@ -245,9 +260,10 @@ void G4LossTableManager::DeRegister(G4VMultipleScattering* p)
void G4LossTableManager::Register(G4VEmProcess* p)
{
emp_vector.push_back(p);
if(verbose > 1)
if(verbose > 1) {
G4cout << "G4LossTableManager::Register G4VEmProcess : "
<< p->GetProcessName() << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
@@ -262,6 +278,48 @@ void G4LossTableManager::DeRegister(G4VEmProcess* p)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::Register(G4VEmModel* p)
{
mod_vector.push_back(p);
if(verbose > 1) {
G4cout << "G4LossTableManager::Register G4VEmModel : "
<< p->GetName() << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::DeRegister(G4VEmModel* p)
{
size_t n = mod_vector.size();
for (size_t i=0; i<n; i++) {
if(mod_vector[i] == p) mod_vector[i] = 0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::Register(G4VEmFluctuationModel* p)
{
fmod_vector.push_back(p);
if(verbose > 1) {
G4cout << "G4LossTableManager::Register G4VEmFluctuationModel : "
<< p->GetName() << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::DeRegister(G4VEmFluctuationModel* p)
{
size_t n = fmod_vector.size();
for (size_t i=0; i<n; i++) {
if(fmod_vector[i] == p) fmod_vector[i] = 0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::RegisterIon(const G4ParticleDefinition* ion,
G4VEnergyLossProcess* p)
{
@@ -363,10 +421,11 @@ G4EnergyLossMessenger* G4LossTableManager::GetMessenger()
void G4LossTableManager::ParticleHaveNoLoss(
const G4ParticleDefinition* aParticle)
{
G4String s = "G4LossTableManager:: dE/dx table not found for "
+ aParticle->GetParticleName() + "!";
G4Exception(s);
exit(1);
G4String s = " dE/dx table not found for "
+ aParticle->GetParticleName() + " !";
G4Exception("G4LossTableManager::ParticleHaveNoLoss", "EM01",
FatalException, s);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
@@ -475,7 +534,8 @@ G4VEnergyLossProcess* G4LossTableManager::BuildTables(
for (i=0; i<n_loss; i++) {
p = loss_vector[i];
if (p && aParticle == part_vector[i] && !tables_are_built[i]) {
if (p->IsIonisationProcess() && isActive[i] || !em || (em && !isActive[iem]) ) {
if ((p->IsIonisationProcess() && isActive[i]) ||
!em || (em && !isActive[iem]) ) {
em = p;
iem= i;
}
@@ -508,7 +568,7 @@ G4VEnergyLossProcess* G4LossTableManager::BuildTables(
dedx = em->IonisationTable();
if (1 < n_dedx) {
em->SetDEDXTable(dedx, fIonisation);
em->SetDEDXTable(dedx, fIsIonisation);
dedx = 0;
dedx = G4PhysicsTableHelper::PreparePhysicsTable(dedx);
tableBuilder->BuildDEDXTable(dedx, t_list);
@@ -559,7 +619,7 @@ G4VEnergyLossProcess* G4LossTableManager::BuildTables(
if (0 < nSubRegions) {
G4PhysicsTable* dedxSub = em->IonisationTableForSubsec();
if (1 < listSub.size()) {
em->SetDEDXTable(dedxSub, fSubIonisation);
em->SetDEDXTable(dedxSub, fIsSubIonisation);
dedxSub = 0;
dedxSub = G4PhysicsTableHelper::PreparePhysicsTable(dedxSub);
tableBuilder->BuildDEDXTable(dedxSub, listSub);
@@ -828,6 +888,21 @@ G4bool G4LossTableManager::LPMFlag() const
return flagLPM;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
void G4LossTableManager::SetSplineFlag(G4bool val)
{
splineFlag = val;
tableBuilder->SetSplineFlag(splineFlag);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4bool G4LossTableManager::SplineFlag() const
{
return splineFlag;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LossTableManager::SetBremsstrahlungTh(G4double val)
@@ -842,4 +917,18 @@ G4double G4LossTableManager::BremsstrahlungTh() const
return bremsTh;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4EmCorrections* G4LossTableManager::EmCorrections()
{
return emCorrections;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4EmSaturation* G4LossTableManager::EmSaturation()
{
return emSaturation;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4VEmFluctuationModel.cc,v 1.2 2006/06/29 19:55:15 gunter Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4VEmFluctuationModel.cc,v 1.3 2008/07/15 16:56:39 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -48,16 +48,20 @@
//
#include "G4VEmFluctuationModel.hh"
#include "G4LossTableManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEmFluctuationModel::G4VEmFluctuationModel(const G4String& nam)
: name(nam)
{}
{
G4LossTableManager::Instance()->Register(this);
}
G4VEmFluctuationModel::~G4VEmFluctuationModel()
{}
{
G4LossTableManager::Instance()->DeRegister(this);
}
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4VEmModel.cc,v 1.8 2007/09/25 10:19:07 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4VEmModel.cc,v 1.20 2008/11/13 23:13:18 schaelic Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -50,35 +50,55 @@
//
#include "G4VEmModel.hh"
#include "G4LossTableManager.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VEmModel::G4VEmModel(const G4String& nam):
lowLimit(0.1*keV), highLimit(100.0*TeV), fluc(0), name(nam), pParticleChange(0)
{}
fluc(0), name(nam), lowLimit(0.1*keV), highLimit(100.0*TeV),
polarAngleLimit(0.0),secondaryThreshold(DBL_MAX),theLPMflag(false),
pParticleChange(0),nuclearStopping(false),nsec(5)
{
xsec.resize(nsec);
nSelectors = 0;
G4LossTableManager::Instance()->Register(this);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VEmModel::~G4VEmModel()
{}
{
G4LossTableManager::Instance()->DeRegister(this);
G4int n = elmSelectors.size();
if(n > 0) {
for(G4int i=0; i<n; i++) {
delete elmSelectors[i];
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4VEmModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* p,
G4double ekin,
G4double emin,
G4double emax)
G4double ekin,
G4double emin,
G4double emax)
{
SetupForMaterial(p, material, ekin);
G4double cross = 0.0;
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* theAtomNumDensityVector = material->GetVecNbOfAtomsPerVolume();
size_t nelm = material->GetNumberOfElements();
for (size_t i=0; i<nelm; i++) {
const G4Element* elm = (*theElementVector)[i];
G4int nelm = material->GetNumberOfElements();
if(nelm > nsec) {
xsec.resize(nelm);
nsec = nelm;
}
for (G4int i=0; i<nelm; i++) {
cross += theAtomNumDensityVector[i]*
ComputeCrossSectionPerAtom(p,ekin,elm->GetZ(),elm->GetN(),emin,emax);
ComputeCrossSectionPerAtom(p,(*theElementVector)[i],ekin,emin,emax);
xsec[i] = cross;
}
return cross;
@@ -87,10 +107,10 @@ G4double G4VEmModel::CrossSectionPerVolume(const G4Material* material,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4VEmModel::ComputeMeanFreePath(const G4ParticleDefinition* p,
G4double ekin,
G4double ekin,
const G4Material* material,
G4double emin,
G4double emax)
G4double emin,
G4double emax)
{
G4double mfp = DBL_MAX;
G4double cross = CrossSectionPerVolume(material,p,ekin,emin,emax);
@@ -100,4 +120,45 @@ G4double G4VEmModel::ComputeMeanFreePath(const G4ParticleDefinition* p,
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4VEmModel::InitialiseElementSelectors(const G4ParticleDefinition* p,
const G4DataVector& cuts)
{
G4int nbins = G4int(std::log10(highLimit/lowLimit) + 0.5);
if(nbins < 3) nbins = 3;
G4bool spline = G4LossTableManager::Instance()->SplineFlag();
G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
G4int numOfCouples = theCoupleTable->GetTableSize();
// prepare vector
if(numOfCouples > nSelectors) {
elmSelectors.resize(numOfCouples);
nSelectors = numOfCouples;
}
// initialise vector
for(G4int i=0; i<numOfCouples; i++) {
const G4MaterialCutsCouple* couple =
theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
G4int idx = couple->GetIndex();
// selector already exist check if should be deleted
G4bool create = true;
if(elmSelectors[i]) {
if(material == elmSelectors[i]->GetMaterial()) create = false;
else delete elmSelectors[i];
}
if(create) {
elmSelectors[i] = new G4EmElementSelector(this,material,nbins,
lowLimit,highLimit,spline);
}
elmSelectors[i]->Initialise(p, cuts[idx]);
//elmSelectors[i]->Dump(p);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4VEmProcess.cc,v 1.48 2007/10/29 08:38:58 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4VEmProcess.cc,v 1.60 2008/10/17 14:46:16 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -81,25 +81,34 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEmProcess::G4VEmProcess(const G4String& name, G4ProcessType type):
G4VDiscreteProcess(name, type),
selectedModel(0),
G4VDiscreteProcess(name, type),
secondaryParticle(0),
buildLambdaTable(true),
theLambdaTable(0),
theEnergyOfCrossSectionMax(0),
theCrossSectionMax(0),
particle(0),
secondaryParticle(0),
nLambdaBins(90),
lambdaFactor(0.8),
currentCouple(0),
integral(false),
buildLambdaTable(true),
applyCuts(false),
startFromNull(true),
nRegions(0)
nRegions(0),
selectedModel(0),
particle(0),
currentCouple(0)
{
SetVerboseLevel(1);
// Size of tables assuming spline
minKinEnergy = 0.1*keV;
maxKinEnergy = 100.0*GeV;
maxKinEnergy = 100.0*TeV;
nLambdaBins = 84;
// default lambda factor
lambdaFactor = 0.8;
// default limit on polar angle
polarAngleLimit = 0.0;
// particle types
theGamma = G4Gamma::Gamma();
theElectron = G4Electron::Electron();
thePositron = G4Positron::Positron();
@@ -372,7 +381,8 @@ G4VParticleChange* G4VEmProcess::PostStepDoIt(const G4Track& track,
if (e < (*theCutsElectron)[currentMaterialIndex]) good = false;
} else if (p == thePositron) {
if (e < (*theCutsPositron)[currentMaterialIndex]) {
if (electron_mass_c2 < (*theCutsGamma)[currentMaterialIndex] &&
e < (*theCutsPositron)[currentMaterialIndex]) {
good = false;
e += 2.0*electron_mass_c2;
}
@@ -396,42 +406,34 @@ G4VParticleChange* G4VEmProcess::PostStepDoIt(const G4Track& track,
void G4VEmProcess::PrintInfoDefinition()
{
if(verboseLevel > 0) {
G4cout << G4endl << GetProcessName() << ": " ;
G4cout << G4endl << GetProcessName() << ": for "
<< particle->GetParticleName();
if(integral) G4cout << ", integral: 1 ";
if(applyCuts) G4cout << ", applyCuts: 1 ";
G4cout << " SubType= " << GetProcessSubType() << G4endl;
if(buildLambdaTable) {
G4cout << " Lambda tables from "
<< G4BestUnit(minKinEnergy,"Energy")
<< " to "
<< G4BestUnit(maxKinEnergy,"Energy")
<< " in " << nLambdaBins << " bins, spline: "
<< (G4LossTableManager::Instance())->SplineFlag()
<< G4endl;
}
PrintInfo();
if(integral) {
G4cout << " Integral mode is used "<< G4endl;
}
modelManager->DumpModelList(verboseLevel);
}
if (!buildLambdaTable) return;
if(verboseLevel > 0) {
G4cout << " tables are built for "
<< particle->GetParticleName()
<< G4endl
<< " Lambda tables from "
<< G4BestUnit(minKinEnergy,"Energy")
<< " to "
<< G4BestUnit(maxKinEnergy,"Energy")
<< " in " << nLambdaBins << " bins."
<< G4endl;
}
if(verboseLevel > 1) {
G4cout << "Tables are built for " << particle->GetParticleName()
<< G4endl;
if(verboseLevel > 2) {
G4cout << "LambdaTable address= " << theLambdaTable << G4endl;
if(verboseLevel > 2 && buildLambdaTable) {
G4cout << " LambdaTable address= " << theLambdaTable << G4endl;
if(theLambdaTable) G4cout << (*theLambdaTable) << G4endl;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEmProcess::MicroscopicCrossSection(G4double kineticEnergy,
const G4MaterialCutsCouple* couple)
G4double G4VEmProcess::CrossSectionPerVolume(G4double kineticEnergy,
const G4MaterialCutsCouple* couple)
{
// Cross section per atom is calculated
DefineMaterial(couple);
@@ -440,8 +442,6 @@ G4double G4VEmProcess::MicroscopicCrossSection(G4double kineticEnergy,
if(theLambdaTable) {
cross = (((*theLambdaTable)[currentMaterialIndex])->
GetValue(kineticEnergy, b));
cross /= currentMaterial->GetTotNbOfAtomsPerVolume();
} else {
G4VEmModel* model = SelectModel(kineticEnergy);
cross =
@@ -507,6 +507,10 @@ G4bool G4VEmProcess::RetrievePhysicsTable(const G4ParticleDefinition* part,
<< filename << ">"
<< G4endl;
}
if((G4LossTableManager::Instance())->SplineFlag()) {
size_t n = theLambdaTable->length();
for(size_t i=0; i<n; i++) {(* theLambdaTable)[i]->SetSpline(true);}
}
} else {
if (1 < verboseLevel) {
G4cout << "Lambda table for " << particleName << " in file <"
@@ -567,6 +571,7 @@ G4PhysicsVector* G4VEmProcess::LambdaPhysicsVector(const G4MaterialCutsCouple*)
{
G4PhysicsVector* v =
new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nLambdaBins);
v->SetSpline((G4LossTableManager::Instance())->SplineFlag());
return v;
}
@@ -25,7 +25,7 @@
//
//
// $Id: G4VEnergyLoss.cc,v 1.46 2006/06/29 19:55:21 gunter Exp $
// GEANT4 tag $Name: geant4-09-01 $
// GEANT4 tag $Name: geant4-09-02 $
//
// --------------------------------------------------------------
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,73 @@
//
// ********************************************************************
// * 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: G4VMscModel.cc,v 1.4 2008/03/10 18:39:45 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4VMscModel
//
// Author: Vladimir Ivanchenko
//
// Creation date: 07.03.2008
//
// Modifications:
//
//
// Class Description:
//
// General interface to msc models
// -------------------------------------------------------------------
//
#include "G4VMscModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VMscModel::G4VMscModel(const G4String& nam):
G4VEmModel(nam),
facrange(0.02),
facgeom(2.5),
facsafety(0.25),
skin(3.0),
dtrl(0.05),
lambdalimit(mm),
steppingAlgorithm(fUseSafety),
samplez(false),
latDisplasment(true)
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4VMscModel::~G4VMscModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4VMultipleScattering.cc,v 1.47 2007/11/09 11:35:54 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4VMultipleScattering.cc,v 1.60 2008/11/20 20:32:40 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -54,6 +54,7 @@
// 27-10-05 introduce virtual function MscStepLimitation() (V.Ivanchenko)
// 12-04-07 Add verbosity at destruction (V.Ivanchenko)
// 27-10-07 Virtual functions moved to source (V.Ivanchenko)
// 11-03-08 Set skin value does not effect step limit type (V.Ivanchenko)
//
// Class Description:
//
@@ -84,23 +85,30 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VMultipleScattering::G4VMultipleScattering(const G4String& name, G4ProcessType type):
G4VContinuousDiscreteProcess(name, type),
G4VMultipleScattering::G4VMultipleScattering(const G4String& name,
G4ProcessType type):
G4VContinuousDiscreteProcess(name, type),
buildLambdaTable(true),
theLambdaTable(0),
firstParticle(0),
currentParticle(0),
currentCouple(0),
nBins(120),
stepLimit(fUseSafety),
skin(0.0),
skin(3.0),
facrange(0.02),
facgeom(2.5),
latDisplasment(true),
buildLambdaTable(true)
currentParticle(0),
currentCouple(0)
{
SetVerboseLevel(1);
SetProcessSubType(fMultipleScattering);
// Size of tables assuming spline
minKinEnergy = 0.1*keV;
maxKinEnergy = 100.0*TeV;
SetVerboseLevel(1);
nBins = 84;
// default limit on polar angle
polarAngleLimit = 0.0;
pParticleChange = &fParticleChange;
@@ -113,9 +121,10 @@ G4VMultipleScattering::G4VMultipleScattering(const G4String& name, G4ProcessType
G4VMultipleScattering::~G4VMultipleScattering()
{
if(1 < verboseLevel)
if(1 < verboseLevel) {
G4cout << "G4VMultipleScattering destruct " << GetProcessName()
<< G4endl;
}
delete modelManager;
if (theLambdaTable) {
theLambdaTable->clearAndDestroy();
@@ -130,7 +139,6 @@ void G4VMultipleScattering::BuildPhysicsTable(const G4ParticleDefinition& part)
{
G4String num = part.GetParticleName();
if(1 < verboseLevel) {
// G4cout << "========================================================" << G4endl;
G4cout << "### G4VMultipleScattering::BuildPhysicsTable() for "
<< GetProcessName()
<< " and particle " << num
@@ -147,7 +155,8 @@ void G4VMultipleScattering::BuildPhysicsTable(const G4ParticleDefinition& part)
if (theLambdaTable->GetFlag(i)) {
// create physics vector and fill it
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
const G4MaterialCutsCouple* couple =
theCoupleTable->GetMaterialCutsCouple(i);
G4PhysicsVector* aVector = PhysicsVector(couple);
modelManager->FillLambdaVector(aVector, couple, false);
G4PhysicsTableHelper::SetPhysicsVector(theLambdaTable, i, aVector);
@@ -161,7 +170,8 @@ void G4VMultipleScattering::BuildPhysicsTable(const G4ParticleDefinition& part)
}
}
if(verboseLevel>0 && ( num == "e-" || num == "mu+" ||
num == "proton" || num == "pi-" || num == "GenericIon")) {
num == "proton" || num == "pi-" ||
num == "GenericIon")) {
PrintInfoDefinition();
if(2 < verboseLevel && theLambdaTable) G4cout << *theLambdaTable << G4endl;
}
@@ -181,14 +191,16 @@ void G4VMultipleScattering::PreparePhysicsTable(const G4ParticleDefinition& part
if (!firstParticle) {
currentCouple = 0;
if(part.GetParticleType() == "nucleus" &&
part.GetParticleSubType() == "generic")
firstParticle = G4GenericIon::GenericIon();
else firstParticle = &part;
part.GetParticleSubType() == "generic") {
firstParticle = G4GenericIon::GenericIon();
} else {
firstParticle = &part;
}
currentParticle = &part;
}
if(1 < verboseLevel) {
// G4cout << "========================================================" << G4endl;
G4cout << "### G4VMultipleScattering::PrepearPhysicsTable() for "
<< GetProcessName()
<< " and particle " << part.GetParticleName()
@@ -216,20 +228,21 @@ void G4VMultipleScattering::PreparePhysicsTable(const G4ParticleDefinition& part
void G4VMultipleScattering::PrintInfoDefinition()
{
if (0 < verboseLevel) {
G4cout << G4endl << GetProcessName() << ": Model variant of multiple scattering "
<< "for " << firstParticle->GetParticleName()
G4cout << G4endl << GetProcessName()
<< ": for " << firstParticle->GetParticleName()
<< " SubType= " << GetProcessSubType()
<< G4endl;
if (theLambdaTable) {
G4cout << " Lambda tables from "
<< G4BestUnit(MinKinEnergy(),"Energy")
<< " to "
<< G4BestUnit(MaxKinEnergy(),"Energy")
<< " in " << nBins << " bins."
<< " in " << nBins << " bins, spline: "
<< (G4LossTableManager::Instance())->SplineFlag()
<< G4endl;
}
G4cout << " LateralDisplacementFlag= " << latDisplasment
<< " Skin= " << skin << G4endl;
PrintInfo();
modelManager->DumpModelList(verboseLevel);
if (2 < verboseLevel) {
G4cout << "LambdaTable address= " << theLambdaTable << G4endl;
if(theLambdaTable) G4cout << (*theLambdaTable) << G4endl;
@@ -241,15 +254,17 @@ void G4VMultipleScattering::PrintInfoDefinition()
G4double G4VMultipleScattering::AlongStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4double,
G4double currentMinimalStep,
G4double& currentSafety,
G4GPILSelection* selection)
{
// get Step limit proposed by the process
valueGPILSelectionMSC = NotCandidateForSelection;
G4double steplength = GetMscContinuousStepLimit(track,previousStepSize,
currentMinimalStep,currentSafety);
G4double steplength = GetMscContinuousStepLimit(track,
track.GetKineticEnergy(),
currentMinimalStep,
currentSafety);
// G4cout << "StepLimit= " << steplength << G4endl;
// set return value for G4GPILSelection
*selection = valueGPILSelectionMSC;
@@ -314,6 +329,7 @@ G4PhysicsVector* G4VMultipleScattering::PhysicsVector(const G4MaterialCutsCouple
G4int nbins = 3;
if( couple->IsUsed() ) nbins = nBins;
G4PhysicsVector* v = new G4PhysicsLogVector(minKinEnergy, maxKinEnergy, nbins);
v->SetSpline((G4LossTableManager::Instance())->SplineFlag());
return v;
}
@@ -371,6 +387,10 @@ G4bool G4VMultipleScattering::RetrievePhysicsTable(const G4ParticleDefinition* p
<< filename << ">"
<< G4endl;
}
if((G4LossTableManager::Instance())->SplineFlag()) {
size_t n = theLambdaTable->length();
for(size_t i=0; i<n; i++) {(* theLambdaTable)[i]->SetSpline(true);}
}
} else {
if (1 < verboseLevel) {
G4cout << "Lambda table for " << part->GetParticleName() << " in file <"
@@ -23,8 +23,8 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4ionEffectiveCharge.cc,v 1.17 2007/09/27 17:08:58 vnivanch Exp $
// GEANT4 tag $Name: geant4-09-01 $
// $Id: G4ionEffectiveCharge.cc,v 1.24 2008/12/18 13:01:46 gunter Exp $
// GEANT4 tag $Name: geant4-09-02 $
//
// -------------------------------------------------------------------
//
@@ -53,19 +53,24 @@
#include "G4ionEffectiveCharge.hh"
#include "G4UnitsTable.hh"
#include "G4ParticleDefinition.hh"
#include "G4Material.hh"
#include "G4NistManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4ionEffectiveCharge::G4ionEffectiveCharge()
{
chargeCorrection = 1.0;
energyHighLimit = 10.0*MeV;
energyHighLimit = 20.0*MeV;
energyLowLimit = 1.0*keV;
energyBohr = 25.*keV;
massFactor = amu_c2/(proton_mass_c2*keV);
minCharge = 0.1;
minCharge = 1.0;
lastPart = 0;
lastMat = 0;
lastKinEnergy = 0.0;
effCharge = eplus;
nist = G4NistManager::Instance();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -77,13 +82,21 @@ G4ionEffectiveCharge::~G4ionEffectiveCharge()
G4double G4ionEffectiveCharge::EffectiveCharge(const G4ParticleDefinition* p,
const G4Material* material,
G4double kineticEnergy)
G4double kineticEnergy)
{
if(p == lastPart && material == lastMat && kineticEnergy == lastKinEnergy)
return effCharge;
lastPart = p;
lastMat = material;
lastKinEnergy = kineticEnergy;
G4double mass = p->GetPDGMass();
G4double charge = p->GetPDGCharge();
G4double Zi = charge/eplus;
chargeCorrection = 1.0;
effCharge = charge;
// The aproximation of ion effective charge from:
// J.F.Ziegler, J.P. Biersack, U. Littmark
@@ -93,16 +106,15 @@ G4double G4ionEffectiveCharge::EffectiveCharge(const G4ParticleDefinition* p,
G4double reducedEnergy = kineticEnergy * proton_mass_c2/mass ;
if( reducedEnergy > Zi*energyHighLimit || Zi < 1.5 || !material) return charge;
static G4double c[6] = {0.2865, 0.1266, -0.001429,
0.02402,-0.01135, 0.001475} ;
G4double z = material->GetIonisation()->GetZeffective();
reducedEnergy = std::max(reducedEnergy,energyLowLimit);
G4double q;
// reducedEnergy = std::max(reducedEnergy,energyLowLimit);
// Helium ion case
if( Zi < 2.5 ) {
static G4double c[6] = {0.2865, 0.1266, -0.001429,
0.02402,-0.01135, 0.001475} ;
G4double Q = std::max(0.0,std::log(reducedEnergy*massFactor));
G4double x = c[0];
G4double y = 1.0;
@@ -119,23 +131,25 @@ G4double G4ionEffectiveCharge::EffectiveCharge(const G4ParticleDefinition* p,
G4double tt = ( 0.007 + 0.00005 * z );
if(tq2 < 0.2) tt *= (1.0 - tq2 + 0.5*tq2*tq2);
else tt *= std::exp(-tq2);
q = (1.0 + tt) * std::sqrt(ex);
effCharge = charge*(1.0 + tt) * std::sqrt(ex);
// Heavy ion case
} else {
G4double z23 = std::pow(z, 0.666666);
G4double zi13 = std::pow(Zi, 0.333333);
G4double y;
// = nist->GetZ13(z);
//G4double z23 = y*y;
G4double zi13 = nist->GetZ13(Zi);
G4double zi23 = zi13*zi13;
G4double e = std::max(reducedEnergy,energyBohr/z23);
// G4double e = std::max(reducedEnergy,energyBohr/z23);
//G4double e = reducedEnergy;
// v1 is ion velocity in vF unit
G4double eF = material->GetIonisation()->GetFermiEnergy();
G4double v1sq = e/eF;
G4double v1sq = reducedEnergy/eF;
G4double vFsq = eF/energyBohr;
G4double vF = std::sqrt(vFsq);
G4double y ;
G4double vF = std::sqrt(eF/energyBohr);
// Faster than Fermi velocity
if ( v1sq > 1.0 ) {
@@ -143,18 +157,33 @@ G4double G4ionEffectiveCharge::EffectiveCharge(const G4ParticleDefinition* p,
// Slower than Fermi velocity
} else {
y = 0.6923 * vF * (1.0 + 0.666666*v1sq + v1sq*v1sq/15.0) / zi23 ;
y = 0.692308 * vF * (1.0 + 0.666666*v1sq + v1sq*v1sq/15.0) / zi23 ;
}
G4double q;
G4double y3 = std::pow(y, 0.3) ;
// G4cout << "y= " << y << " y3= " << y3 << " v1= " << v1 << " vF= " << vF << G4endl;
// G4cout<<"y= "<<y<<" y3= "<<y3<<" v1= "<<v1<<" vF= "<<vF<<G4endl;
q = 1.0 - std::exp( 0.803*y3 - 1.3167*y3*y3 - 0.38157*y - 0.008983*y*y ) ;
//y *= 0.77;
//y *= (0.75 + 0.52/Zi);
// q = 1.0 - std::exp(-0.95*std::sqrt(reducedEnergy/energyBohr)/zi23);
//if( y < 0.2 ) q = y*(1.0 - 0.5*y);
//else q = 1.0 - std::exp(-y);
G4double qmin = minCharge/Zi;
if(q < qmin) q = qmin;
effCharge = q*charge;
/*
G4double x1 = 1.0*effCharge*(1.0 - 0.132*std::log(y))/(y*std::sqrt(z));
G4double x2 = 0.1*effCharge*effCharge*energyBohr/reducedEnergy;
chargeCorrection = 1.0 + x1 - x2;
G4cout << "x1= "<<x1<<" x2= "<< x2<<" corr= "<<chargeCorrection<<G4endl;
*/
G4double tq = 7.6 - std::log(reducedEnergy/keV);
G4double tq2= tq*tq;
@@ -169,7 +198,7 @@ G4double G4ionEffectiveCharge::EffectiveCharge(const G4ParticleDefinition* p,
// Nucl. Inst. & Meth. in Phys. Res. B35 (1988) 215-228.
G4double lambda = 10.0 * vF / (zi13 * (6.0 + q));
if(q < 0.2) lambda *= (1.0 - 0.666666*q - 0.444444*q*q);
if(q < 0.2) lambda *= (1.0 - 0.66666667*q - q*q/9.0);
else lambda *= std::pow(1.0-q, 0.666666);
G4double lambda2 = lambda*lambda;
@@ -179,11 +208,12 @@ G4double G4ionEffectiveCharge::EffectiveCharge(const G4ParticleDefinition* p,
else xx *= std::log(1.0 + lambda2);
chargeCorrection = sq * (1.0 + xx);
}
// G4cout << "G4ionEffectiveCharge: charge= " << charge << " q= " << q
// << " chargeCor= " << chargeCorrection
// << " e(MeV)= " << kineticEnergy/MeV << G4endl;
return q*charge;
return effCharge;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....