Files
geant4/source/processes/electromagnetic/utils/src/G4EmModelManager.cc
T
2020-12-04 12:30:43 +01:00

829 lines
26 KiB
C++

//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4EmModelManager
//
// Author: Vladimir Ivanchenko
//
// Creation date: 07.05.2002
//
// Modifications: V.Ivanchenko
//
// 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 "G4SystemOfUnits.hh"
#include "G4PhysicsTable.hh"
#include "G4PhysicsVector.hh"
#include "G4VMscModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4RegionModels::G4RegionModels(G4int nMod, std::vector<G4int>& indx,
G4DataVector& lowE, const G4Region* reg)
{
nModelsForRegion = nMod;
theListOfModelIndexes = new G4int [nModelsForRegion];
lowKineticEnergy = new G4double [nModelsForRegion+1];
for (G4int i=0; i<nModelsForRegion; ++i) {
theListOfModelIndexes[i] = indx[i];
lowKineticEnergy[i] = lowE[i];
}
lowKineticEnergy[nModelsForRegion] = lowE[nModelsForRegion];
theRegion = reg;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4RegionModels::~G4RegionModels()
{
delete [] theListOfModelIndexes;
delete [] lowKineticEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4PhysicsVector.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ProductionCutsTable.hh"
#include "G4RegionStore.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4UnitsTable.hh"
#include "G4DataVector.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmModelManager::G4EmModelManager():
nEmModels(0),
nRegions(0),
particle(0),
verboseLevel(0)
{
maxSubCutInRange = 0.7*mm;
models.reserve(4);
flucModels.reserve(4);
regions.reserve(4);
orderOfModels.reserve(4);
isUsed.reserve(4);
severalModels = true;
fluoFlag = false;
currRegionModel = nullptr;
currModel = nullptr;
theCuts = nullptr;
theCutsNew = nullptr;
theSubCuts = nullptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4EmModelManager::~G4EmModelManager()
{
verboseLevel = 0; // no verbosity at destruction
Clear();
delete theCutsNew;
delete theSubCuts;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::Clear()
{
if(1 < verboseLevel) {
G4cout << "G4EmModelManager::Clear()" << G4endl;
}
size_t n = setOfRegionModels.size();
if(n > 0) {
for(size_t i=0; i<n; ++i) {
delete setOfRegionModels[i];
setOfRegionModels[i] = nullptr;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::AddEmModel(G4int num, G4VEmModel* p,
G4VEmFluctuationModel* fm, const G4Region* r)
{
if(!p) {
G4cout << "G4EmModelManager::AddEmModel WARNING: no model defined."
<< G4endl;
return;
}
models.push_back(p);
flucModels.push_back(fm);
regions.push_back(r);
orderOfModels.push_back(num);
isUsed.push_back(0);
p->DefineForRegion(r);
++nEmModels;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::UpdateEmModel(const G4String& nam,
G4double emin, G4double emax)
{
if (nEmModels > 0) {
for(G4int i=0; i<nEmModels; ++i) {
if(nam == models[i]->GetName()) {
models[i]->SetLowEnergyLimit(emin);
models[i]->SetHighEnergyLimit(emax);
break;
}
}
}
G4cout << "G4EmModelManager::UpdateEmModel WARNING: no model <"
<< nam << "> is found out"
<< G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEmModel* G4EmModelManager::GetModel(G4int i, G4bool ver)
{
G4VEmModel* model = nullptr;
if(i < nEmModels) { model = models[i]; }
else if(verboseLevel > 0 && ver) {
G4cout << "G4EmModelManager::GetModel WARNING: "
<< "index " << i << " is wrong Nmodels= "
<< nEmModels;
if(particle) { G4cout << " for " << particle->GetParticleName(); }
G4cout<< G4endl;
}
return model;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEmModel* G4EmModelManager::GetRegionModel(G4int k, size_t idx)
{
G4RegionModels* rm = setOfRegionModels[idxOfRegionModels[idx]];
G4VEmModel* mod = models[rm->ModelIndex(k)];
return mod;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4int G4EmModelManager::NumberOfRegionModels(size_t idx) const
{
G4RegionModels* rm = setOfRegionModels[idxOfRegionModels[idx]];
return rm->NumberOfModels();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4DataVector*
G4EmModelManager::Initialise(const G4ParticleDefinition* p,
const G4ParticleDefinition* secondaryParticle,
G4double minSubRange,
G4int val)
{
verboseLevel = val;
G4String partname = p->GetParticleName();
if(1 < verboseLevel) {
G4cout << "G4EmModelManager::Initialise() for "
<< partname << " Nmodels= " << nEmModels << G4endl;
}
// Are models defined?
if(nEmModels < 1) {
G4ExceptionDescription ed;
ed << "No models found out for " << p->GetParticleName()
<< " !";
G4Exception("G4EmModelManager::Initialise","em0002",
FatalException, ed);
}
particle = p;
Clear(); // needed if run is not first
G4RegionStore* regionStore = G4RegionStore::GetInstance();
const G4Region* world =
regionStore->GetRegion("DefaultRegionForTheWorld", false);
// Identify the list of regions with different set of models
nRegions = 1;
std::vector<const G4Region*> setr;
setr.push_back(world);
G4bool isWorld = false;
for (G4int ii=0; ii<nEmModels; ++ii) {
const G4Region* r = regions[ii];
if ( r == 0 || r == world) {
isWorld = true;
regions[ii] = world;
} else {
G4bool newRegion = true;
if (nRegions>1) {
for (G4int j=1; j<nRegions; ++j) {
if ( r == setr[j] ) { newRegion = false; }
}
}
if (newRegion) {
setr.push_back(r);
nRegions++;
}
}
}
// Are models defined?
if(!isWorld) {
G4ExceptionDescription ed;
ed << "No models defined for the World volume for "
<< p->GetParticleName() << " !";
G4Exception("G4EmModelManager::Initialise","em0002",
FatalException, ed);
}
G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
// prepare vectors, shortcut for the case of only 1 model
// or only one region
if(nRegions > 1 && nEmModels > 1) {
idxOfRegionModels.resize(numOfCouples,0);
setOfRegionModels.resize((size_t)nRegions,0);
} else {
idxOfRegionModels.resize(1,0);
setOfRegionModels.resize(1,0);
}
std::vector<G4int> modelAtRegion(nEmModels);
std::vector<G4int> modelOrd(nEmModels);
G4DataVector eLow(nEmModels+1);
G4DataVector eHigh(nEmModels);
if(1 < verboseLevel) {
G4cout << " Nregions= " << nRegions
<< " Nmodels= " << nEmModels << G4endl;
}
// Order models for regions
for (G4int reg=0; reg<nRegions; ++reg) {
const G4Region* region = setr[reg];
G4int n = 0;
for (G4int ii=0; ii<nEmModels; ++ii) {
G4VEmModel* model = models[ii];
if ( region == regions[ii] ) {
G4double tmin = model->LowEnergyLimit();
G4double tmax = model->HighEnergyLimit();
G4int ord = orderOfModels[ii];
G4bool push = true;
G4bool insert = false;
G4int idx = n;
if(1 < verboseLevel) {
G4cout << "Model #" << ii
<< " <" << model->GetName() << "> for region <";
if (region) G4cout << region->GetName();
G4cout << "> "
<< " tmin(MeV)= " << tmin/MeV
<< "; tmax(MeV)= " << tmax/MeV
<< "; order= " << ord
<< "; tminAct= " << model->LowEnergyActivationLimit()/MeV
<< "; tmaxAct= " << model->HighEnergyActivationLimit()/MeV
<< G4endl;
}
static const G4double limitdelta = 0.01*eV;
if(n > 0) {
// extend energy range to previous models
tmin = std::min(tmin, eHigh[n-1]);
tmax = std::max(tmax, eLow[0]);
//G4cout << "tmin= " << tmin << " tmax= "
// << tmax << " ord= " << ord <<G4endl;
// empty energy range
if( tmax - tmin <= limitdelta) { push = false; }
// low-energy model
else if (tmax == eLow[0]) {
push = false;
insert = true;
idx = 0;
// resolve intersections
} else if(tmin < eHigh[n-1]) {
// compare order
for(G4int k=0; k<n; ++k) {
// new model has higher order parameter,
// so, its application area may be reduced
// to avoid intersections
if(ord >= modelOrd[k]) {
if(tmin < eHigh[k] && tmin >= eLow[k]) { tmin = eHigh[k]; }
if(tmax <= eHigh[k] && tmax > eLow[k]) { tmax = eLow[k]; }
if(tmax > eHigh[k] && tmin < eLow[k]) {
if(tmax - eHigh[k] > eLow[k] - tmin) { tmin = eHigh[k]; }
else { tmax = eLow[k]; }
}
if( tmax - tmin <= limitdelta) {
push = false;
break;
}
}
}
// this model has lower order parameter than possible
// other models, with which there may be intersections
// so, appliction area of such models may be reduced
// insert below the first model
if (tmax <= eLow[0]) {
push = false;
insert = true;
idx = 0;
// resolve intersections
} else if(tmin < eHigh[n-1]) {
// last energy interval
if(tmin > eLow[n-1] && tmax >= eHigh[n-1]) {
eHigh[n-1] = tmin;
// first energy interval
} else if(tmin <= eLow[0] && tmax < eHigh[0]) {
eLow[0] = tmax;
push = false;
insert = true;
idx = 0;
// loop over all models
} else {
for(G4int k=n-1; k>=0; --k) {
if(tmin <= eLow[k] && tmax >= eHigh[k]) {
// full overlap exclude previous model
isUsed[modelAtRegion[k]] = 0;
idx = k;
if(k < n-1) {
// shift upper models and change index
for(G4int kk=k; kk<n-1; ++kk) {
modelAtRegion[kk] = modelAtRegion[kk+1];
modelOrd[kk] = modelOrd[kk+1];
eLow[kk] = eLow[kk+1];
eHigh[kk] = eHigh[kk+1];
}
++k;
}
--n;
} else {
// partially reduce previous model area
if(tmin <= eLow[k] && tmax > eLow[k]) {
eLow[k] = tmax;
idx = k;
insert = true;
push = false;
} else if(tmin < eHigh[k] && tmax >= eHigh[k]) {
eHigh[k] = tmin;
idx = k + 1;
if(idx < n) {
insert = true;
push = false;
}
} else if(tmin > eLow[k] && tmax < eHigh[k]) {
if(eHigh[k] - tmax > tmin - eLow[k]) {
eLow[k] = tmax;
idx = k;
insert = true;
push = false;
} else {
eHigh[k] = tmin;
idx = k + 1;
if(idx < n) {
insert = true;
push = false;
}
}
}
}
}
}
}
}
}
// provide space for the new model
if(insert) {
for(G4int k=n-1; k>=idx; --k) {
modelAtRegion[k+1] = modelAtRegion[k];
modelOrd[k+1] = modelOrd[k];
eLow[k+1] = eLow[k];
eHigh[k+1] = eHigh[k];
}
}
//G4cout << "push= " << push << " insert= " << insert
// << " idx= " << idx <<G4endl;
// the model is added
if (push || insert) {
++n;
modelAtRegion[idx] = ii;
modelOrd[idx] = ord;
eLow[idx] = tmin;
eHigh[idx] = tmax;
isUsed[ii] = 1;
}
// exclude models with zero energy range
for(G4int k=n-1; k>=0; --k) {
if(eHigh[k] - eLow[k] <= limitdelta) {
isUsed[modelAtRegion[k]] = 0;
if(k < n-1) {
for(G4int kk=k; kk<n-1; ++kk) {
modelAtRegion[kk] = modelAtRegion[kk+1];
modelOrd[kk] = modelOrd[kk+1];
eLow[kk] = eLow[kk+1];
eHigh[kk] = eHigh[kk+1];
}
}
--n;
}
}
}
}
eLow[0] = 0.0;
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 iii=0; iii<=n; ++iii) {G4cout << eLow[iii]/MeV << " ";}
G4cout << G4endl;
}
G4RegionModels* rm = new G4RegionModels(n, modelAtRegion, eLow, region);
setOfRegionModels[reg] = rm;
// shortcut
if(1 == nEmModels) { break; }
}
currRegionModel = setOfRegionModels[0];
currModel = models[0];
// Access to materials and build cuts
size_t idx = 1;
if(secondaryParticle) {
if( secondaryParticle == G4Gamma::Gamma() ) { idx = 0; }
else if( secondaryParticle == G4Electron::Electron()) { idx = 1; }
else if( secondaryParticle == G4Positron::Positron()) { idx = 2; }
else { idx = 3; }
}
theCuts =
static_cast<const G4DataVector*>(theCoupleTable->GetEnergyCutsVector(idx));
// for the second run the check on cuts should be repeated
if(theCutsNew) { *theCutsNew = *theCuts; }
if(minSubRange < 1.0) {
if( !theSubCuts ) { theSubCuts = new G4DataVector(); }
theSubCuts->resize(numOfCouples,DBL_MAX);
}
// G4cout << "========Start define cuts" << G4endl;
// define cut values
for(size_t i=0; i<numOfCouples; ++i) {
const G4MaterialCutsCouple* couple =
theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
const G4ProductionCuts* pcuts = couple->GetProductionCuts();
G4int reg = 0;
if(nRegions > 1 && nEmModels > 1) {
reg = nRegions;
// Loop checking, 03-Aug-2015, Vladimir Ivanchenko
do {--reg;} while (reg>0 && pcuts != (setr[reg]->GetProductionCuts()));
idxOfRegionModels[i] = reg;
}
if(1 < verboseLevel) {
G4cout << "G4EmModelManager::Initialise() for "
<< material->GetName()
<< " indexOfCouple= " << i
<< " indexOfRegion= " << reg
<< G4endl;
}
G4double cut = (*theCuts)[i];
if(secondaryParticle) {
// compute subcut
if( cut < DBL_MAX && minSubRange < 1.0) {
G4double subcut = minSubRange*cut;
G4double rcut = std::min(minSubRange*pcuts->GetProductionCut(idx),
maxSubCutInRange);
G4double tcutmax =
theCoupleTable->ConvertRangeToEnergy(secondaryParticle,
material,rcut);
if(tcutmax < subcut) { subcut = tcutmax; }
(*theSubCuts)[i] = subcut;
}
// note that idxOfRegionModels[] not always filled
G4int inn = 0;
G4int nnm = 1;
if(nRegions > 1 && nEmModels > 1) {
inn = idxOfRegionModels[i];
}
// check cuts and introduce upper limits
//G4cout << "idx= " << i << " cut(keV)= " << cut/keV << G4endl;
currRegionModel = setOfRegionModels[inn];
nnm = currRegionModel->NumberOfModels();
//G4cout << "idx= " << i << " Nmod= " << nnm << G4endl;
for(G4int jj=0; jj<nnm; ++jj) {
//G4cout << "jj= " << jj << " modidx= "
// << currRegionModel->ModelIndex(jj) << G4endl;
currModel = models[currRegionModel->ModelIndex(jj)];
G4double cutlim = currModel->MinEnergyCut(particle,couple);
if(cutlim > cut) {
if(!theCutsNew) { theCutsNew = new G4DataVector(*theCuts); }
(*theCutsNew)[i] = cutlim;
/*
G4cout << "### " << partname << " energy loss model in "
<< material->GetName()
<< " Cut was changed from " << cut/keV << " keV to "
<< cutlim/keV << " keV " << " due to "
<< currModel->GetName() << G4endl;
*/
}
}
}
}
if(theCutsNew) { theCuts = theCutsNew; }
// initialize models
G4int nn = 0;
severalModels = true;
for(G4int jj=0; jj<nEmModels; ++jj) {
if(1 == isUsed[jj]) {
++nn;
currModel = models[jj];
currModel->Initialise(particle, *theCuts);
if(flucModels[jj]) { flucModels[jj]->InitialiseMe(particle); }
}
}
if(1 == nn) { severalModels = false; }
if(1 < verboseLevel) {
G4cout << "G4EmModelManager for " << partname
<< " is initialised; nRegions= " << nRegions
<< " severalModels: " << severalModels
<< G4endl;
}
return theCuts;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillDEDXVector(G4PhysicsVector* aVector,
const G4MaterialCutsCouple* couple,
G4EmTableType tType)
{
size_t i = couple->GetIndex();
G4double cut = (*theCuts)[i];
G4double emin = 0.0;
if(fTotal == tType) { cut = DBL_MAX; }
else if(fSubRestricted == tType) {
emin = cut;
if(theSubCuts) { emin = (*theSubCuts)[i]; }
}
if(1 < verboseLevel) {
G4cout << "G4EmModelManager::FillDEDXVector() for "
<< couple->GetMaterial()->GetName()
<< " cut(MeV)= " << cut
<< " emin(MeV)= " << emin
<< " Type " << tType
<< " for " << particle->GetParticleName()
<< G4endl;
}
G4int reg = 0;
if(nRegions > 1 && nEmModels > 1) { reg = idxOfRegionModels[i]; }
const G4RegionModels* regModels = setOfRegionModels[reg];
G4int nmod = regModels->NumberOfModels();
// Calculate energy losses vector
//G4cout << "nmod= " << nmod << G4endl;
size_t totBinsLoss = aVector->GetVectorLength();
G4double del = 0.0;
G4int k0 = 0;
for(size_t j=0; j<totBinsLoss; ++j) {
G4double e = aVector->Energy(j);
// Choose a model of energy losses
G4int k = 0;
if (nmod > 1) {
k = nmod;
// Loop checking, 03-Aug-2015, Vladimir Ivanchenko
do {--k;} while (k>0 && e <= regModels->LowEdgeEnergy(k));
//G4cout << "k= " << k << G4endl;
if(k > 0 && k != k0) {
k0 = k;
G4double elow = regModels->LowEdgeEnergy(k);
G4double dedx1 = ComputeDEDX(models[regModels->ModelIndex(k-1)],
couple,elow,cut,emin);
G4double dedx2 = ComputeDEDX(models[regModels->ModelIndex(k)],
couple,elow,cut,emin);
del = 0.0;
if(dedx2 > 0.0) { del = (dedx1/dedx2 - 1.0)*elow; }
//G4cout << "elow= " << elow
// << " dedx1= " << dedx1 << " dedx2= " << dedx2 << G4endl;
}
}
G4double dedx =
ComputeDEDX(models[regModels->ModelIndex(k)],couple,e,cut,emin);
dedx *= (1.0 + del/e);
if(2 < verboseLevel) {
G4cout << "Material= " << couple->GetMaterial()->GetName()
<< " E(MeV)= " << e/MeV
<< " dEdx(MeV/mm)= " << dedx*mm/MeV
<< " del= " << del*mm/MeV<< " k= " << k
<< " modelIdx= " << regModels->ModelIndex(k)
<< G4endl;
}
if(dedx < 0.0) { dedx = 0.0; }
aVector->PutValue(j, dedx);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::FillLambdaVector(G4PhysicsVector* aVector,
const G4MaterialCutsCouple* couple,
G4bool startFromNull,
G4EmTableType tType)
{
size_t i = couple->GetIndex();
G4double cut = (*theCuts)[i];
G4double tmax = DBL_MAX;
if (fSubRestricted == tType) {
tmax = cut;
if(theSubCuts) { cut = (*theSubCuts)[i]; }
}
G4int reg = 0;
if(nRegions > 1 && nEmModels > 1) { reg = idxOfRegionModels[i]; }
const G4RegionModels* regModels = setOfRegionModels[reg];
G4int nmod = regModels->NumberOfModels();
if(1 < verboseLevel) {
G4cout << "G4EmModelManager::FillLambdaVector() for "
<< particle->GetParticleName()
<< " in " << couple->GetMaterial()->GetName()
<< " Emin(MeV)= " << aVector->Energy(0)
<< " Emax(MeV)= " << aVector->GetMaxEnergy()
<< " cut= " << cut
<< " Type " << tType
<< " nmod= " << nmod
<< " theSubCuts " << theSubCuts
<< G4endl;
}
// Calculate lambda vector
size_t totBinsLambda = aVector->GetVectorLength();
G4double del = 0.0;
G4int k0 = 0;
G4int k = 0;
G4VEmModel* mod = models[regModels->ModelIndex(0)];
for(size_t j=0; j<totBinsLambda; ++j) {
G4double e = aVector->Energy(j);
// Choose a model
if (nmod > 1) {
k = nmod;
// Loop checking, 03-Aug-2015, Vladimir Ivanchenko
do {--k;} while (k>0 && e <= regModels->LowEdgeEnergy(k));
if(k > 0 && k != k0) {
k0 = k;
G4double elow = regModels->LowEdgeEnergy(k);
G4VEmModel* mod1 = models[regModels->ModelIndex(k-1)];
G4double xs1 = mod1->CrossSection(couple,particle,elow,cut,tmax);
mod = models[regModels->ModelIndex(k)];
G4double xs2 = mod->CrossSection(couple,particle,elow,cut,tmax);
del = 0.0;
if(xs2 > 0.0) { del = (xs1/xs2 - 1.0)*elow; }
//G4cout << "New model k=" << k << " E(MeV)= " << e/MeV
// << " Elow(MeV)= " << elow/MeV << " del= " << del << G4endl;
}
}
G4double cross = mod->CrossSection(couple,particle,e,cut,tmax);
cross *= (1.0 + del/e);
if(fIsCrossSectionPrim == tType) { cross *= e; }
if(j==0 && startFromNull) { cross = 0.0; }
if(2 < verboseLevel) {
G4cout << "FillLambdaVector: " << j << ". e(MeV)= " << e/MeV
<< " cross(1/mm)= " << cross*mm
<< " del= " << del*mm << " k= " << k
<< " modelIdx= " << regModels->ModelIndex(k)
<< G4endl;
}
cross = std::max(cross, 0.0);
aVector->PutValue(j, cross);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4EmModelManager::DumpModelList(std::ostream& out, G4int verb)
{
if(verb == 0) { return; }
for(G4int i=0; i<nRegions; ++i) {
G4RegionModels* r = setOfRegionModels[i];
const G4Region* reg = r->Region();
G4int n = r->NumberOfModels();
if(n > 0) {
out << " ===== EM models for the G4Region " << reg->GetName()
<< " ======" << G4endl;
for(G4int j=0; j<n; ++j) {
G4VEmModel* model = models[r->ModelIndex(j)];
G4double emin =
std::max(r->LowEdgeEnergy(j),model->LowEnergyActivationLimit());
G4double emax =
std::min(r->LowEdgeEnergy(j+1),model->HighEnergyActivationLimit());
if(emax > emin) {
out << std::setw(20);
out << model->GetName() << " : Emin="
<< std::setw(5) << G4BestUnit(emin,"Energy")
<< " Emax="
<< std::setw(5) << G4BestUnit(emax,"Energy");
G4PhysicsTable* table = model->GetCrossSectionTable();
if(table) {
size_t kk = table->size();
for(size_t k=0; k<kk; ++k) {
const G4PhysicsVector* v = (*table)[k];
if(v) {
G4int nn = v->GetVectorLength() - 1;
out << " Nbins=" << nn << " "
<< std::setw(3) << G4BestUnit(v->Energy(0),"Energy")
<< " - "
<< std::setw(3) << G4BestUnit(v->Energy(nn),"Energy");
break;
}
}
}
G4VEmAngularDistribution* an = model->GetAngularDistribution();
if(an) { out << " " << an->GetName(); }
if(fluoFlag && model->DeexcitationFlag()) {
out << " Fluo";
}
out << G4endl;
G4VMscModel* msc = dynamic_cast<G4VMscModel*>(model);
if(msc != nullptr) msc->DumpParameters(out);
}
}
}
if(1 == nEmModels) { break; }
}
if(theCutsNew) {
out << " ===== Limit on energy threshold has been applied " << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....