Files
geant4/source/processes/electromagnetic/utils/src/G4VEmProcess.cc
T
2024-06-28 13:08:51 +02:00

897 lines
30 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: G4VEmProcess
//
// Author: Vladimir Ivanchenko on base of Laszlo Urban code
//
// Creation date: 01.10.2003
//
// Modifications: by V.Ivanchenko
//
// Class Description: based class for discrete and rest/discrete EM processes
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4VEmProcess.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4ProcessManager.hh"
#include "G4LossTableManager.hh"
#include "G4LossTableBuilder.hh"
#include "G4Step.hh"
#include "G4ParticleDefinition.hh"
#include "G4VEmModel.hh"
#include "G4DataVector.hh"
#include "G4PhysicsTable.hh"
#include "G4EmDataHandler.hh"
#include "G4PhysicsLogVector.hh"
#include "G4VParticleChange.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Region.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4PhysicsTableHelper.hh"
#include "G4EmBiasingManager.hh"
#include "G4EmParameters.hh"
#include "G4EmProcessSubType.hh"
#include "G4EmTableUtil.hh"
#include "G4EmUtility.hh"
#include "G4DNAModelSubType.hh"
#include "G4GenericIon.hh"
#include "G4Log.hh"
#include <iostream>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEmProcess::G4VEmProcess(const G4String& name, G4ProcessType type):
G4VDiscreteProcess(name, type)
{
theParameters = G4EmParameters::Instance();
SetVerboseLevel(1);
// Size of tables
minKinEnergy = 0.1*CLHEP::keV;
maxKinEnergy = 100.0*CLHEP::TeV;
// default lambda factor
invLambdaFactor = 1.0/lambdaFactor;
// particle types
theGamma = G4Gamma::Gamma();
theElectron = G4Electron::Electron();
thePositron = G4Positron::Positron();
pParticleChange = &fParticleChange;
fParticleChange.SetSecondaryWeightByProcess(true);
secParticles.reserve(5);
modelManager = new G4EmModelManager();
lManager = G4LossTableManager::Instance();
lManager->Register(this);
isTheMaster = lManager->IsMaster();
G4LossTableBuilder* bld = lManager->GetTableBuilder();
theDensityFactor = bld->GetDensityFactors();
theDensityIdx = bld->GetCoupleIndexes();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEmProcess::~G4VEmProcess()
{
if(isTheMaster) {
delete theData;
delete theEnergyOfCrossSectionMax;
}
delete modelManager;
delete biasManager;
lManager->DeRegister(this);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::AddEmModel(G4int order, G4VEmModel* ptr,
const G4Region* region)
{
if(nullptr == ptr) { return; }
G4VEmFluctuationModel* fm = nullptr;
modelManager->AddEmModel(order, ptr, fm, region);
ptr->SetParticleChange(pParticleChange);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::SetEmModel(G4VEmModel* ptr, G4int)
{
if(nullptr == ptr) { return; }
if(!emModels.empty()) {
for(auto & em : emModels) { if(em == ptr) { return; } }
}
emModels.push_back(ptr);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::PreparePhysicsTable(const G4ParticleDefinition& part)
{
if(nullptr == particle) { SetParticle(&part); }
if(part.GetParticleType() == "nucleus" &&
part.GetParticleSubType() == "generic") {
G4String pname = part.GetParticleName();
if(pname != "deuteron" && pname != "triton" &&
pname != "He3" && pname != "alpha" && pname != "alpha+" &&
pname != "helium" && pname != "hydrogen") {
particle = G4GenericIon::GenericIon();
isIon = true;
}
}
if(particle != &part) { return; }
lManager->PreparePhysicsTable(&part, this);
// for new run
currentCouple = nullptr;
preStepLambda = 0.0;
fLambdaEnergy = 0.0;
InitialiseProcess(particle);
G4LossTableBuilder* bld = lManager->GetTableBuilder();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
theCutsGamma = theCoupleTable->GetEnergyCutsVector(idxG4GammaCut);
theCutsElectron = theCoupleTable->GetEnergyCutsVector(idxG4ElectronCut);
theCutsPositron = theCoupleTable->GetEnergyCutsVector(idxG4PositronCut);
// initialisation of the process
if(!actMinKinEnergy) { minKinEnergy = theParameters->MinKinEnergy(); }
if(!actMaxKinEnergy) { maxKinEnergy = theParameters->MaxKinEnergy(); }
applyCuts = theParameters->ApplyCuts();
lambdaFactor = theParameters->LambdaFactor();
invLambdaFactor = 1.0/lambdaFactor;
theParameters->DefineRegParamForEM(this);
// integral option may be disabled
if(!theParameters->Integral()) { fXSType = fEmNoIntegral; }
// prepare tables
if(isTheMaster) {
if(nullptr == theData) { theData = new G4EmDataHandler(2); }
if(buildLambdaTable) {
theLambdaTable = theData->MakeTable(0);
bld->InitialiseBaseMaterials(theLambdaTable);
}
// high energy table
if(minKinEnergyPrim < maxKinEnergy) {
theLambdaTablePrim = theData->MakeTable(1);
bld->InitialiseBaseMaterials(theLambdaTablePrim);
}
}
// models
baseMat = bld->GetBaseMaterialFlag();
numberOfModels = modelManager->NumberOfModels();
currentModel = modelManager->GetModel(0);
if(nullptr != lManager->AtomDeexcitation()) {
modelManager->SetFluoFlag(true);
}
// forced biasing
if(nullptr != biasManager) {
biasManager->Initialise(part, GetProcessName(), verboseLevel);
biasFlag = false;
}
theCuts =
G4EmTableUtil::PrepareEmProcess(this, particle, secondaryParticle,
modelManager, maxKinEnergy,
secID, tripletID, mainSecondaries,
verboseLevel, isTheMaster);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::BuildPhysicsTable(const G4ParticleDefinition& part)
{
if(nullptr == masterProc) {
if(isTheMaster) { masterProc = this; }
else { masterProc = static_cast<const G4VEmProcess*>(GetMasterProcess());}
}
G4int nModels = modelManager->NumberOfModels();
G4bool isLocked = theParameters->IsPrintLocked();
G4bool toBuild = (buildLambdaTable || minKinEnergyPrim < maxKinEnergy);
G4EmTableUtil::BuildEmProcess(this, masterProc, particle, &part,
nModels, verboseLevel, isTheMaster,
isLocked, toBuild, baseMat);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::BuildLambdaTable()
{
G4double scale = theParameters->MaxKinEnergy()/theParameters->MinKinEnergy();
G4int nbin =
theParameters->NumberOfBinsPerDecade()*G4lrint(std::log10(scale));
if(actBinning) { nbin = std::max(nbin, nLambdaBins); }
scale = nbin/G4Log(scale);
G4LossTableBuilder* bld = lManager->GetTableBuilder();
G4EmTableUtil::BuildLambdaTable(this, particle, modelManager,
bld, theLambdaTable, theLambdaTablePrim,
minKinEnergy, minKinEnergyPrim,
maxKinEnergy, scale, verboseLevel,
startFromNull, splineFlag);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::StreamInfo(std::ostream& out,
const G4ParticleDefinition& part, G4bool rst) const
{
G4String indent = (rst ? " " : "");
out << std::setprecision(6);
out << G4endl << indent << GetProcessName() << ": ";
if (!rst) {
out << " for " << part.GetParticleName();
}
if(fXSType != fEmNoIntegral) { out << " XStype:" << fXSType; }
if(applyCuts) { out << " applyCuts:1 "; }
G4int subtype = GetProcessSubType();
out << " SubType=" << subtype;
if (subtype == fAnnihilation) {
G4int mod = theParameters->PositronAtRestModelType();
const G4String namp[2] = {"Simple", "Allison"};
out << " AtRestModel:" << namp[mod];
}
if(biasFactor != 1.0) { out << " BiasingFactor=" << biasFactor; }
out << " BuildTable=" << buildLambdaTable << G4endl;
if(buildLambdaTable) {
if(particle == &part) {
for(auto & v : *theLambdaTable) {
if(nullptr != v) {
out << " Lambda table from ";
G4double emin = v->Energy(0);
G4double emax = v->GetMaxEnergy();
G4int nbin = G4int(v->GetVectorLength() - 1);
if(emin > minKinEnergy) { out << "threshold "; }
else { out << G4BestUnit(emin,"Energy"); }
out << " to "
<< G4BestUnit(emax,"Energy")
<< ", " << G4lrint(nbin/std::log10(emax/emin))
<< " bins/decade, spline: "
<< splineFlag << G4endl;
break;
}
}
} else {
out << " Used Lambda table of "
<< particle->GetParticleName() << G4endl;
}
}
if(minKinEnergyPrim < maxKinEnergy) {
if(particle == &part) {
for(auto & v : *theLambdaTablePrim) {
if(nullptr != v) {
out << " LambdaPrime table from "
<< G4BestUnit(v->Energy(0),"Energy")
<< " to "
<< G4BestUnit(v->GetMaxEnergy(),"Energy")
<< " in " << v->GetVectorLength()-1
<< " bins " << G4endl;
break;
}
}
} else {
out << " Used LambdaPrime table of "
<< particle->GetParticleName() << G4endl;
}
}
StreamProcessInfo(out);
modelManager->DumpModelList(out, verboseLevel);
if(verboseLevel > 2 && buildLambdaTable) {
out << " LambdaTable address= " << theLambdaTable << G4endl;
if(theLambdaTable && particle == &part) {
out << (*theLambdaTable) << G4endl;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::StartTracking(G4Track* track)
{
// reset parameters for the new track
currentParticle = track->GetParticleDefinition();
theNumberOfInteractionLengthLeft = -1.0;
mfpKinEnergy = DBL_MAX;
preStepLambda = 0.0;
if(isIon) { massRatio = proton_mass_c2/currentParticle->GetPDGMass(); }
// forced biasing only for primary particles
if(biasManager) {
if(0 == track->GetParentID()) {
// primary particle
biasFlag = true;
biasManager->ResetForcedInteraction();
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEmProcess::PostStepGetPhysicalInteractionLength(
const G4Track& track,
G4double previousStepSize,
G4ForceCondition* condition)
{
*condition = NotForced;
G4double x = DBL_MAX;
DefineMaterial(track.GetMaterialCutsCouple());
preStepKinEnergy = track.GetKineticEnergy();
const G4double scaledEnergy = preStepKinEnergy*massRatio;
SelectModel(scaledEnergy, currentCoupleIndex);
/*
G4cout << "PostStepGetPhysicalInteractionLength: idx= " << currentCoupleIndex
<< " couple: " << currentCouple << G4endl;
*/
if(!currentModel->IsActive(scaledEnergy)) {
theNumberOfInteractionLengthLeft = -1.0;
currentInteractionLength = DBL_MAX;
mfpKinEnergy = DBL_MAX;
preStepLambda = 0.0;
return x;
}
// forced biasing only for primary particles
if(biasManager) {
if(0 == track.GetParentID()) {
if(biasFlag &&
biasManager->ForcedInteractionRegion((G4int)currentCoupleIndex)) {
return biasManager->GetStepLimit((G4int)currentCoupleIndex, previousStepSize);
}
}
}
// compute mean free path
ComputeIntegralLambda(preStepKinEnergy, track);
// zero cross section
if(preStepLambda <= 0.0) {
theNumberOfInteractionLengthLeft = -1.0;
currentInteractionLength = DBL_MAX;
} else {
// non-zero cross section
if (theNumberOfInteractionLengthLeft < 0.0) {
// beggining of tracking (or just after DoIt of this process)
theNumberOfInteractionLengthLeft = -G4Log( G4UniformRand() );
theInitialNumberOfInteractionLength = theNumberOfInteractionLengthLeft;
} else {
theNumberOfInteractionLengthLeft -=
previousStepSize/currentInteractionLength;
theNumberOfInteractionLengthLeft =
std::max(theNumberOfInteractionLengthLeft, 0.0);
}
// new mean free path and step limit for the next step
currentInteractionLength = 1.0/preStepLambda;
x = theNumberOfInteractionLengthLeft * currentInteractionLength;
}
return x;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::ComputeIntegralLambda(G4double e, const G4Track& track)
{
if (fXSType == fEmNoIntegral) {
preStepLambda = GetCurrentLambda(e, LogEkin(track));
} else if (fXSType == fEmIncreasing) {
if(e*invLambdaFactor < mfpKinEnergy) {
preStepLambda = GetCurrentLambda(e, LogEkin(track));
mfpKinEnergy = (preStepLambda > 0.0) ? e : 0.0;
}
} else if(fXSType == fEmDecreasing) {
if(e < mfpKinEnergy) {
const G4double e1 = e*lambdaFactor;
preStepLambda = GetCurrentLambda(e1);
mfpKinEnergy = e1;
}
} else if(fXSType == fEmOnePeak) {
const G4double epeak = (*theEnergyOfCrossSectionMax)[currentCoupleIndex];
if(e <= epeak) {
if(e*invLambdaFactor < mfpKinEnergy) {
preStepLambda = GetCurrentLambda(e, LogEkin(track));
mfpKinEnergy = (preStepLambda > 0.0) ? e : 0.0;
}
} else if(e < mfpKinEnergy) {
const G4double e1 = std::max(epeak, e*lambdaFactor);
preStepLambda = GetCurrentLambda(e1);
mfpKinEnergy = e1;
}
} else {
preStepLambda = GetCurrentLambda(e, LogEkin(track));
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VParticleChange* G4VEmProcess::PostStepDoIt(const G4Track& track,
const G4Step& step)
{
// clear number of interaction lengths in any case
theNumberOfInteractionLengthLeft = -1.0;
mfpKinEnergy = DBL_MAX;
fParticleChange.InitializeForPostStep(track);
// Do not make anything if particle is stopped, the annihilation then
// should be performed by the AtRestDoIt!
if (track.GetTrackStatus() == fStopButAlive) { return &fParticleChange; }
const G4double finalT = track.GetKineticEnergy();
// forced process - should happen only once per track
if(biasFlag) {
if(biasManager->ForcedInteractionRegion((G4int)currentCoupleIndex)) {
biasFlag = false;
}
}
// check active and select model
const G4double scaledEnergy = finalT*massRatio;
SelectModel(scaledEnergy, currentCoupleIndex);
if(!currentModel->IsActive(scaledEnergy)) { return &fParticleChange; }
// Integral approach
if (fXSType != fEmNoIntegral) {
const G4double logFinalT =
track.GetDynamicParticle()->GetLogKineticEnergy();
const G4double lx = std::max(GetCurrentLambda(finalT, logFinalT), 0.0);
#ifdef G4VERBOSE
if(preStepLambda < lx && 1 < verboseLevel) {
G4cout << "WARNING: for " << currentParticle->GetParticleName()
<< " and " << GetProcessName() << " E(MeV)= " << finalT/MeV
<< " preLambda= " << preStepLambda
<< " < " << lx << " (postLambda) " << G4endl;
}
#endif
// if false interaction then use new cross section value
// if both values are zero - no interaction
if(preStepLambda*G4UniformRand() >= lx) {
return &fParticleChange;
}
}
// define new weight for primary and secondaries
G4double weight = fParticleChange.GetParentWeight();
if(weightFlag) {
weight /= biasFactor;
fParticleChange.ProposeWeight(weight);
}
#ifdef G4VERBOSE
if(1 < verboseLevel) {
G4cout << "G4VEmProcess::PostStepDoIt: Sample secondary; E= "
<< finalT/MeV
<< " MeV; model= (" << currentModel->LowEnergyLimit()
<< ", " << currentModel->HighEnergyLimit() << ")"
<< G4endl;
}
#endif
// sample secondaries
secParticles.clear();
currentModel->SampleSecondaries(&secParticles,
currentCouple,
track.GetDynamicParticle(),
(*theCuts)[currentCoupleIndex]);
G4int num0 = (G4int)secParticles.size();
// splitting or Russian roulette
if(biasManager) {
if(biasManager->SecondaryBiasingRegion((G4int)currentCoupleIndex)) {
G4double eloss = 0.0;
weight *= biasManager->ApplySecondaryBiasing(
secParticles, track, currentModel, &fParticleChange, eloss,
(G4int)currentCoupleIndex, (*theCuts)[currentCoupleIndex],
step.GetPostStepPoint()->GetSafety());
if(eloss > 0.0) {
eloss += fParticleChange.GetLocalEnergyDeposit();
fParticleChange.ProposeLocalEnergyDeposit(eloss);
}
}
}
// save secondaries
G4int num = (G4int)secParticles.size();
if(num > 0) {
fParticleChange.SetNumberOfSecondaries(num);
G4double edep = fParticleChange.GetLocalEnergyDeposit();
G4double time = track.GetGlobalTime();
G4int n1(0), n2(0);
if(num0 > mainSecondaries) {
currentModel->FillNumberOfSecondaries(n1, n2);
}
for (G4int i=0; i<num; ++i) {
G4DynamicParticle* dp = secParticles[i];
if (nullptr != dp) {
const G4ParticleDefinition* p = dp->GetParticleDefinition();
G4double e = dp->GetKineticEnergy();
G4bool good = true;
if(applyCuts) {
if (p == theGamma) {
if (e < (*theCutsGamma)[currentCoupleIndex]) { good = false; }
} else if (p == theElectron) {
if (e < (*theCutsElectron)[currentCoupleIndex]) { good = false; }
} else if (p == thePositron) {
if (electron_mass_c2 < (*theCutsGamma)[currentCoupleIndex] &&
e < (*theCutsPositron)[currentCoupleIndex]) {
good = false;
e += 2.0*electron_mass_c2;
}
}
// added secondary if it is good
}
if (good) {
G4Track* t = new G4Track(dp, time, track.GetPosition());
t->SetTouchableHandle(track.GetTouchableHandle());
if (biasManager) {
t->SetWeight(weight * biasManager->GetWeight(i));
} else {
t->SetWeight(weight);
}
pParticleChange->AddSecondary(t);
// define type of secondary
if(i < mainSecondaries) {
t->SetCreatorModelID(secID);
if(GetProcessSubType() == fComptonScattering && p == theGamma) {
t->SetCreatorModelID(_ComptonGamma);
}
} else if(i < mainSecondaries + n1) {
t->SetCreatorModelID(tripletID);
} else if(i < mainSecondaries + n1 + n2) {
t->SetCreatorModelID(_IonRecoil);
} else {
if(i < num0) {
if(p == theGamma) {
t->SetCreatorModelID(fluoID);
} else {
t->SetCreatorModelID(augerID);
}
} else {
t->SetCreatorModelID(biasID);
}
}
/*
G4cout << "Secondary(post step) has weight " << t->GetWeight()
<< ", Ekin= " << t->GetKineticEnergy()/MeV << " MeV "
<< GetProcessName() << " fluoID= " << fluoID
<< " augerID= " << augerID <<G4endl;
*/
} else {
delete dp;
edep += e;
}
}
}
fParticleChange.ProposeLocalEnergyDeposit(edep);
}
if(0.0 == fParticleChange.GetProposedKineticEnergy() &&
fAlive == fParticleChange.GetTrackStatus()) {
if(particle->GetProcessManager()->GetAtRestProcessVector()->size() > 0)
{ fParticleChange.ProposeTrackStatus(fStopButAlive); }
else { fParticleChange.ProposeTrackStatus(fStopAndKill); }
}
return &fParticleChange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4VEmProcess::StorePhysicsTable(const G4ParticleDefinition* part,
const G4String& directory,
G4bool ascii)
{
if(!isTheMaster || part != particle) { return true; }
if(G4EmTableUtil::StoreTable(this, part, theLambdaTable,
directory, "Lambda",
verboseLevel, ascii) &&
G4EmTableUtil::StoreTable(this, part, theLambdaTablePrim,
directory, "LambdaPrim",
verboseLevel, ascii)) {
return true;
}
return false;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
G4bool G4VEmProcess::RetrievePhysicsTable(const G4ParticleDefinition* part,
const G4String& dir,
G4bool ascii)
{
if(!isTheMaster || part != particle) { return true; }
G4bool yes = true;
if(buildLambdaTable) {
yes = G4EmTableUtil::RetrieveTable(this, part, theLambdaTable, dir,
"Lambda", verboseLevel,
ascii, splineFlag);
}
if(yes && minKinEnergyPrim < maxKinEnergy) {
yes = G4EmTableUtil::RetrieveTable(this, part, theLambdaTablePrim, dir,
"LambdaPrim", verboseLevel,
ascii, splineFlag);
}
return yes;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEmProcess::GetCrossSection(G4double kinEnergy,
const G4MaterialCutsCouple* couple)
{
CurrentSetup(couple, kinEnergy);
return GetCurrentLambda(kinEnergy, G4Log(kinEnergy));
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEmProcess::GetMeanFreePath(const G4Track& track,
G4double,
G4ForceCondition* condition)
{
*condition = NotForced;
return G4VEmProcess::MeanFreePath(track);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double
G4VEmProcess::ComputeCrossSectionPerAtom(G4double kinEnergy,
G4double Z, G4double A, G4double cut)
{
SelectModel(kinEnergy, currentCoupleIndex);
return (currentModel) ?
currentModel->ComputeCrossSectionPerAtom(currentParticle, kinEnergy,
Z, A, cut) : 0.0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4PhysicsVector*
G4VEmProcess::LambdaPhysicsVector(const G4MaterialCutsCouple* couple)
{
DefineMaterial(couple);
G4PhysicsVector* newv = new G4PhysicsLogVector(minKinEnergy, maxKinEnergy,
nLambdaBins, splineFlag);
return newv;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4Element* G4VEmProcess::GetCurrentElement() const
{
return (nullptr != currentModel) ?
currentModel->GetCurrentElement(currentMaterial) : nullptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4Element* G4VEmProcess::GetTargetElement() const
{
return (nullptr != currentModel) ?
currentModel->GetCurrentElement(currentMaterial) : nullptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
const G4Isotope* G4VEmProcess::GetTargetIsotope() const
{
return (nullptr != currentModel) ?
currentModel->GetCurrentIsotope(GetCurrentElement()) : nullptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::SetCrossSectionBiasingFactor(G4double f, G4bool flag)
{
if(f > 0.0) {
biasFactor = f;
weightFlag = flag;
if(1 < verboseLevel) {
G4cout << "### SetCrossSectionBiasingFactor: for "
<< particle->GetParticleName()
<< " and process " << GetProcessName()
<< " biasFactor= " << f << " weightFlag= " << flag
<< G4endl;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void
G4VEmProcess::ActivateForcedInteraction(G4double length, const G4String& r,
G4bool flag)
{
if(nullptr == biasManager) { biasManager = new G4EmBiasingManager(); }
if(1 < verboseLevel) {
G4cout << "### ActivateForcedInteraction: for "
<< particle->GetParticleName()
<< " and process " << GetProcessName()
<< " length(mm)= " << length/mm
<< " in G4Region <" << r
<< "> weightFlag= " << flag
<< G4endl;
}
weightFlag = flag;
biasManager->ActivateForcedInteraction(length, r);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void
G4VEmProcess::ActivateSecondaryBiasing(const G4String& region,
G4double factor,
G4double energyLimit)
{
if (0.0 <= factor) {
// Range cut can be applied only for e-
if(0.0 == factor && secondaryParticle != G4Electron::Electron())
{ return; }
if(!biasManager) { biasManager = new G4EmBiasingManager(); }
biasManager->ActivateSecondaryBiasing(region, factor, energyLimit);
if(1 < verboseLevel) {
G4cout << "### ActivateSecondaryBiasing: for "
<< " process " << GetProcessName()
<< " factor= " << factor
<< " in G4Region <" << region
<< "> energyLimit(MeV)= " << energyLimit/MeV
<< G4endl;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::SetLambdaBinning(G4int n)
{
if(5 < n && n < 10000000) {
nLambdaBins = n;
actBinning = true;
} else {
G4double e = (G4double)n;
PrintWarning("SetLambdaBinning", e);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::SetMinKinEnergy(G4double e)
{
if(1.e-3*eV < e && e < maxKinEnergy) {
nLambdaBins = G4lrint(nLambdaBins*G4Log(maxKinEnergy/e)
/G4Log(maxKinEnergy/minKinEnergy));
minKinEnergy = e;
actMinKinEnergy = true;
} else { PrintWarning("SetMinKinEnergy", e); }
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::SetMaxKinEnergy(G4double e)
{
if(minKinEnergy < e && e < 1.e+6*TeV) {
nLambdaBins = G4lrint(nLambdaBins*G4Log(e/minKinEnergy)
/G4Log(maxKinEnergy/minKinEnergy));
maxKinEnergy = e;
actMaxKinEnergy = true;
} else { PrintWarning("SetMaxKinEnergy", e); }
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::SetMinKinEnergyPrim(G4double e)
{
if(theParameters->MinKinEnergy() <= e &&
e <= theParameters->MaxKinEnergy()) { minKinEnergyPrim = e; }
else { PrintWarning("SetMinKinEnergyPrim", e); }
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4VEmProcess* G4VEmProcess::GetEmProcess(const G4String& nam)
{
return (nam == GetProcessName()) ? this : nullptr;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4VEmProcess::PolarAngleLimit() const
{
return theParameters->MscThetaLimit();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::PrintWarning(G4String tit, G4double val)
{
G4String ss = "G4VEmProcess::" + tit;
G4ExceptionDescription ed;
ed << "Parameter is out of range: " << val
<< " it will have no effect!\n" << " Process "
<< GetProcessName() << " nbins= " << theParameters->NumberOfBins()
<< " Emin(keV)= " << theParameters->MinKinEnergy()/keV
<< " Emax(GeV)= " << theParameters->MaxKinEnergy()/GeV;
G4Exception(ss, "em0044", JustWarning, ed);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4VEmProcess::ProcessDescription(std::ostream& out) const
{
if(nullptr != particle) {
StreamInfo(out, *particle, true);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....