Import Geant4 5.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-08 16:57:27 +02:00
parent 330b82b769
commit 37fff30d2e
5733 changed files with 263867 additions and 74574 deletions
@@ -0,0 +1,585 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * 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. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4EmModelManager
//
// Author: Vladimir Ivanchenko
//
// Creation date: 07.05.2002
//
// Modifications:
//
// Class Description:
//
// It is the unified energy loss process it calculates the continuous
// energy loss for charged particles using a set of Energy Loss
// models valid for different energy regions. There are a possibility
// to create and access to dE/dx and range tables, or to calculate
// that information on fly.
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4EmModelManager.hh"
#include "G4LossTableManager.hh"
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4VEmModel.hh"
#include "G4DataVector.hh"
#include "G4PhysicsVector.hh"
#include "G4VParticleChange.hh"
#include "G4Positron.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmModelManager::G4EmModelManager():
nEmModels(0),
nmax(4),
orderIsChanged(false),
minSubRange(0.1),
particle(0)
{
verboseLevel = 0;
for(G4int i = 0; i<nmax; i++) {
emModels[i] = 0;
order[i] = 0;
upperEkin[i] = 0.0;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmModelManager::~G4EmModelManager()
{
Clear();
for(G4int i = 0; i<nmax; i++) {
if(emModels[i]) delete emModels[i];
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::Clear()
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::Clear()" << G4endl;
}
theCuts.clear();
theSubCuts.clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4DataVector* G4EmModelManager::Initialise(const G4ParticleDefinition* p,
const G4ParticleDefinition* sp,
G4double theMinSubRange,
G4int val)
{
// Are models defined?
if(!nEmModels) {
G4Exception("G4EmModelManager::Initialise without any model defined");
}
particle = p;
secondaryParticle = sp;
minSubRange = theMinSubRange;
verboseLevel = val;
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::Initialise() for "
<< p->GetParticleName()
<< G4endl;
}
// Ordering
if(orderIsChanged) {
G4int oldOrder[5];
G4VEmModel* oldEmModels[5];
for(G4int k = 0; k<nmax; k++) {
oldEmModels[k] = emModels[k];
oldOrder[k] = order[k];
}
for(G4int ik=0; ik<nEmModels; ik++) {
G4int low = INT_MAX;
G4int index = 0;
for(G4int kk=0; kk<nEmModels; kk++) {
if(oldEmModels[kk]) {
if(oldOrder[kk] < low) {
low = oldOrder[kk];
index = kk;
}
}
}
emModels[ik] = oldEmModels[index];
order[ik] = ik;
oldEmModels[index] = 0;
}
orderIsChanged = false;
}
G4DataVector eLow;
eLow.clear();
G4int n = 0;
for(G4int j=0; j<nEmModels; j++) {
G4double ep = 0.0;
if(0 < n) ep = upperEkin[n-1];
G4VEmModel* model = emModels[j];
G4bool accepted = false;
if(model->IsInCharge(particle, 0)) {
G4double tmin = model->LowEnergyLimit(particle, 0);
G4double tmax = model->HighEnergyLimit(particle, 0);
if(1 < verboseLevel) {
G4cout << "New model for tmin(MeV)= " << tmin/MeV
<< "; tmax(MeV)= " << tmax/MeV
<< "; tlast(MeV)= " << ep/MeV
<< G4endl;
}
if(tmax > tmin) {
if(n == 0 || tmax > upperEkin[n-1]) {
// First model or next model for more high energy range;
upperEkin[n] = (tmax);
if(0 < n) tmin = G4std::max(tmin, upperEkin[n-1]);
eLow.push_back(tmin);
n++;
accepted = true;
} else {
G4cout << "The model number #" << j
<< " has no active range "
<< "; tmax(MeV)= " << tmax/MeV
<< "; tlast(MeV)= " << ep/MeV
<< G4endl;
}
} else {
G4cout << "The model number #" << j
<< " has no active range "
<< "; tmin(MeV)= " << tmin/MeV
<< "; tmax(MeV)= " << tmax/MeV
<< G4endl;
}
}
if(!accepted) {
upperEkin[n] = ep;
eLow.push_back(ep);
n++;
}
}
// Access to materials and build cuts
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
size_t nMaterials = G4Material::GetNumberOfMaterials();
for(size_t i=0; i<nMaterials; i++) {
const G4Material* material = (*theMaterialTable)[i];
if(1 < verboseLevel) {
G4cout << "G4EmModelManager::Initialise() for "
<< material->GetName() << G4endl;
}
G4double cut = 0.0;
G4double subcut = 0.0;
if(secondaryParticle) {
cut = secondaryParticle->GetEnergyThreshold(material);
subcut = minSubRange*cut;
}
for(G4int j=0; j<nEmModels; j++) {
G4VEmModel* model = emModels[j];
if(upperEkin[j] > eLow[j]) {
G4double tcutmin = model->MinEnergyCut(particle, material);
if(1 < verboseLevel) {
G4cout << "The model # " << j
<< "; tcutmin(MeV)= " << tcutmin/MeV
<< G4endl;
}
cut = G4std::max(cut, tcutmin);
subcut = G4std::max(subcut, tcutmin);
}
}
theCuts.push_back(cut);
theSubCuts.push_back(subcut);
}
if(1 < verboseLevel) {
G4cout << "G4EmModelManager is initialised "
<< G4endl;
}
return &theCuts;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::AddEmModel(G4VEmModel* p, G4int num)
{
if(nEmModels) {
for(G4int i=0; i<nEmModels; i++) {
if(num < order[i]) orderIsChanged = true;
}
}
if(nEmModels == nmax) {
G4cout << "G4EmModelManager::AddEmModel WARNING: cannot accept model #"
<< nEmModels << " - the list is closed"
<< G4endl;
} else {
emModels[nEmModels] = p;
order[nEmModels] = num;
currentModel = p;
nEmModels++;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
const G4Material* material)
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::FillDEDXVector() for "
<< material->GetName()
<< G4endl;
}
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector dedxLow;
G4DataVector dedxHigh;
G4double e;
G4int i = material->GetIndex();
G4double cut = theCuts[i];
factor.resize(nEmModels);
dedxLow.resize(nEmModels);
dedxHigh.resize(nEmModels);
if(0 < verboseLevel) {
G4cout << "There are " << nEmModels << " models for "
<< material->GetName() << G4endl;
}
// calculate factors to provide continuity of energy loss
factor[0] = 1.0;
G4int j;
G4int totBinsLoss = aVector->GetVectorLength();
dedxLow[0] = 0.0;
e = upperEkin[0];
dedxHigh[0] = emModels[0]->ComputeDEDX(material,particle,e,cut);
if(nEmModels > 1) {
for(j=1; j<nEmModels; j++) {
e = upperEkin[j-1];
dedxLow[j] = emModels[j]->ComputeDEDX(material,particle,e,cut);
e = upperEkin[j];
dedxHigh[j] = emModels[j]->ComputeDEDX(material,particle,e,cut);
}
for(j=1; j<nEmModels; j++) {
if(dedxLow[j] > 0.0) factor[j] = (dedxHigh[j-1]/dedxLow[j] - 1.0);
else factor[j] = 0.0;
}
if(0 < verboseLevel) {
G4cout << "Loop over " << totBinsLoss << " bins start " << G4endl;
}
}
// Calculate energy losses vector
for(j=0; j<totBinsLoss; j++) {
G4double e = aVector->GetLowEdgeEnergy(j);
G4double fac = 1.0;
// Choose a model of energy losses
G4int k = 0;
if(nEmModels > 1) {
if (e >= upperEkin[0]) {
for(k=1; k<nEmModels; k++) {
fac *= (1.0 + factor[k]*upperEkin[k-1]/e);
if(e <= upperEkin[k]) break;
}
}
}
G4double dedx = emModels[k]->ComputeDEDX(material,particle,e,cut)*fac;
if(dedx < 0.0) dedx = 0.0;
if(0 < verboseLevel) {
G4cout << "Material= " << material->GetName()
<< " E(MeV)= " << e/MeV
<< " dEdx(MeV/mm)= " << dedx*mm/MeV
<< G4endl;
}
aVector->PutValue(j, dedx);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
const G4Material* material)
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::FillLambdaVector() for particle "
<< particle->GetParticleName() << G4endl;
}
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector sigmaLow;
G4DataVector sigmaHigh;
G4double e;
G4int i = material->GetIndex();
G4double cut = theCuts[i];
factor.resize(nEmModels);
sigmaLow.resize(nEmModels);
sigmaHigh.resize(nEmModels);
if(0 < verboseLevel) {
G4cout << "There are " << nEmModels << " models for "
<< material->GetName() << G4endl;
}
// calculate factors to provide continuity of energy loss
factor[0] = 1.0;
G4int j;
G4int totBinsLambda = aVector->GetVectorLength();
sigmaLow[0] = 0.0;
e = upperEkin[0];
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " " << nEmModels
<< " models"
<< " Ecut(MeV)= " << cut/MeV
<< " Emax(MeV)= " << e/MeV
<< " nbins= " << totBinsLambda
<< G4endl;
}
sigmaHigh[0] = emModels[0]->CrossSection(material,particle,e,cut,e);
if(nEmModels > 1) {
for(j=1; j<nEmModels; j++) {
e = upperEkin[j-1];
sigmaLow[j] = emModels[j]->CrossSection(material,particle,e,cut,e);
e = upperEkin[j];
sigmaHigh[j] = emModels[j]->CrossSection(material,particle,e,cut,e);
}
for(j=1; j<nEmModels; j++) {
if(sigmaLow[j] > 0.0) factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0);
else factor[j] = 0.0;
}
}
// Calculate lambda vector
for(j=0; j<totBinsLambda; j++) {
e = aVector->GetLowEdgeEnergy(j);
// Choose a model of energy losses
G4int k = 0;
G4double fac = 1.0;
if(nEmModels > 1) {
if(e >= upperEkin[0]) {
for(k=1; k<nEmModels; k++) {
fac *= (1.0 + factor[k]*upperEkin[k-1]/e);
if(e <= upperEkin[k]) break;
}
}
}
// Cross section interpolation should start from zero
G4double cross = 0.0;
if(j > 0) {
cross = emModels[k]->CrossSection(material,particle,e,cut,e)*fac;
}
if(1 < verboseLevel) {
G4cout << "BuildLambdaTable: e(MeV)= " << e/MeV
<< " cross(1/mm)= " << cross*mm
<< " fac= " << fac
<< G4endl;
}
if(cross <= 0.0) cross = 0.0;
// if(cross <= 0.0) cross = DBL_MAX;
// else cross = 1.0/cross;
aVector->PutValue(j, cross);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillSubLambdaVector(G4PhysicsVector* aVector,
const G4Material* material)
{
if(0 < verboseLevel) {
G4cout << "G4EmModelManager::BuildLambdaSubTable() for particle "
<< particle->GetParticleName() << G4endl;
}
// vectors to provide continues dE/dx
G4DataVector factor;
G4DataVector sigmaLow;
G4DataVector sigmaHigh;
G4double e;
G4int i = material->GetIndex();
G4double cut = theCuts[i];
G4double subcut = theSubCuts[i];
factor.resize(nEmModels);
sigmaLow.resize(nEmModels);
sigmaHigh.resize(nEmModels);
if(0 < verboseLevel) {
G4cout << "There are " << nEmModels << " models for "
<< material->GetName() << G4endl;
}
// calculate factors to provide continuity of energy loss
factor[0] = 1.0;
G4int j;
G4int totBinsLambda = aVector->GetVectorLength();
sigmaLow[0] = 0.0;
e = upperEkin[0];
if(1 < verboseLevel) {
G4cout << "### For material " << material->GetName()
<< " are available " << nEmModels
<< " models"
<< " Ecut(MeV)= " << cut/MeV
<< " nbins= " << totBinsLambda
<< G4endl;
}
sigmaHigh[0] = emModels[0]->CrossSection(material,particle,e,subcut,cut);
if(nEmModels > 1) {
for(j=1; j<nEmModels; j++) {
e = upperEkin[j-1];
sigmaLow[j] = emModels[j]->CrossSection(material,particle,e,subcut,cut);
e = upperEkin[j];
sigmaHigh[j] = emModels[j]->CrossSection(material,particle,e,subcut,cut);
}
for(j=1; j<nEmModels; j++) {
if(sigmaLow[j] > 0.0) factor[j] = (sigmaHigh[j-1]/sigmaLow[j] - 1.0);
else factor[j] = 0.0;
}
}
// Calculate energy losses vector
for(j=0; j<totBinsLambda; j++) {
e = aVector->GetLowEdgeEnergy(j);
// Choose a model of energy losses
G4int k = 0;
G4double fac = 1.0;
if(nEmModels > 1) {
if(e >= upperEkin[0]) {
for(k=1; k<nEmModels; k++) {
fac *= (1.0 + factor[k]*upperEkin[k-1]/e);
if(e <= upperEkin[k]) break;
}
}
}
G4double cross = 0.0;
// Cross section interpolation should start from zero
if (j > 0) {
cross = emModels[k]->CrossSection(material,particle,e,subcut,cut)*fac;
}
if(1 < verboseLevel) {
G4cout << "BuildLambdaTable: e(MeV)= " << e/MeV
<< " cross(1/mm)= " << cross*mm
<< " fac= " << fac
<< G4endl;
}
if(cross <= 0.0) cross = 0.0;
aVector->PutValue(j, cross);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....