65 :
G4VEmModel(nam),fParticleChange(nullptr),fParticle(nullptr),
66 fPenelopeFSHelper(nullptr),fPenelopeAngular(nullptr),fEnergyGrid(nullptr),
67 fXSTableElectron(nullptr),fXSTablePositron(nullptr),
68 fIsInitialised(false),fLocalTable(false)
71 fIntrinsicLowEnergyLimit = 100.0*eV;
72 fIntrinsicHighEnergyLimit = 100.0*GeV;
102 if (fPenelopeFSHelper)
103 delete fPenelopeFSHelper;
106 if (fPenelopeAngular)
107 delete fPenelopeAngular;
115 if (fVerboseLevel > 3)
116 G4cout <<
"Calling G4PenelopeBremsstrahlungModel::Initialise()" <<
G4endl;
122 if (!fPenelopeFSHelper)
124 if (!fPenelopeAngular)
130 if (fPenelopeAngular)
135 nBins = std::max(nBins,(std::size_t)100);
140 fXSTableElectron =
new
142 fXSTablePositron =
new
156 BuildXSTable(theMat,theCuts.at(i));
160 if (fVerboseLevel > 2) {
161 G4cout <<
"Penelope Bremsstrahlung model v2008 is initialized " <<
G4endl
169 if(fIsInitialised)
return;
171 fIsInitialised =
true;
179 if (fVerboseLevel > 3)
180 G4cout <<
"Calling G4PenelopeBremsstrahlungModel::InitialiseLocal()" <<
G4endl;
192 fEnergyGrid = theModel->fEnergyGrid;
193 fXSTableElectron = theModel->fXSTableElectron;
194 fXSTablePositron = theModel->fXSTablePositron;
195 fPenelopeFSHelper = theModel->fPenelopeFSHelper;
198 if (!fPenelopeAngular)
201 if (fPenelopeAngular)
215 nBins = theModel->nBins;
218 fVerboseLevel = theModel->fVerboseLevel;
232 if (fVerboseLevel > 3)
233 G4cout <<
"Calling CrossSectionPerVolume() of G4PenelopeBremsstrahlungModel" <<
G4endl;
246 if (fVerboseLevel > 3)
247 G4cout <<
"Material " << material->
GetName() <<
" has " << atPerMol <<
248 "atoms per molecule" <<
G4endl;
252 moleculeDensity = atomDensity/atPerMol;
254 G4double crossPerVolume = crossPerMolecule*moleculeDensity;
256 if (fVerboseLevel > 2)
259 G4cout <<
"Mean free path for gamma emission > " << cutEnergy/keV <<
" keV at " <<
260 energy/keV <<
" keV = " << (1./crossPerVolume)/mm <<
" mm" <<
G4endl;
263 return crossPerVolume;
278 G4cout <<
"*** G4PenelopeBremsstrahlungModel -- WARNING ***" <<
G4endl;
279 G4cout <<
"Penelope Bremsstrahlung model v2008 does not calculate cross section _per atom_ " <<
G4endl;
280 G4cout <<
"so the result is always zero. For physics values, please invoke " <<
G4endl;
281 G4cout <<
"GetCrossSectionPerVolume() or GetMeanFreePath() via the G4EmCalculator" <<
G4endl;
292 if (fVerboseLevel > 3)
293 G4cout <<
"Calling ComputeDEDX() of G4PenelopeBremsstrahlungModel" <<
G4endl;
306 moleculeDensity = atomDensity/atPerMol;
308 G4double sPowerPerVolume = sPowerPerMolecule*moleculeDensity;
310 if (fVerboseLevel > 2)
313 G4cout <<
"Stopping power < " << cutEnergy/keV <<
" keV at " <<
314 kineticEnergy/keV <<
" keV = " <<
315 sPowerPerVolume/(keV/mm) <<
" keV/mm" <<
G4endl;
317 return sPowerPerVolume;
328 if (fVerboseLevel > 3)
329 G4cout <<
"Calling SampleSecondaries() of G4PenelopeBremsstrahlungModel" <<
G4endl;
334 if (kineticEnergy <= fIntrinsicLowEnergyLimit)
346 if (kineticEnergy < cutG)
349 if (fVerboseLevel > 3)
350 G4cout <<
"Going to sample gamma energy for: " <<material->
GetName() <<
" " <<
351 "energy = " << kineticEnergy/keV <<
", cut = " << cutG/keV <<
G4endl;
357 if (fVerboseLevel > 3)
358 G4cout <<
"Sampled gamma energy: " << gammaEnergy/keV <<
" keV" <<
G4endl;
363 fPenelopeAngular->
SampleDirection(aDynamicParticle,gammaEnergy,0,material);
365 if (fVerboseLevel > 3)
368 G4double residualPrimaryEnergy = kineticEnergy-gammaEnergy;
369 if (residualPrimaryEnergy < 0)
372 gammaEnergy += residualPrimaryEnergy;
373 residualPrimaryEnergy = 0.0;
377 G4ThreeVector particleDirection1 = initialMomentum - gammaEnergy*gammaDirection1;
378 particleDirection1 = particleDirection1.
unit();
381 if (residualPrimaryEnergy > 0.)
395 fvect->push_back(theGamma);
397 if (fVerboseLevel > 1)
399 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
400 G4cout <<
"Energy balance from G4PenelopeBremsstrahlung" <<
G4endl;
401 G4cout <<
"Incoming primary energy: " << kineticEnergy/keV <<
" keV" <<
G4endl;
402 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
403 G4cout <<
"Outgoing primary energy: " << residualPrimaryEnergy/keV <<
" keV" <<
G4endl;
404 G4cout <<
"Bremsstrahlung photon " << gammaEnergy/keV <<
" keV" <<
G4endl;
405 G4cout <<
"Total final state: " << (residualPrimaryEnergy+gammaEnergy)/keV
407 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
410 if (fVerboseLevel > 0)
412 G4double energyDiff = std::fabs(residualPrimaryEnergy+gammaEnergy-kineticEnergy);
413 if (energyDiff > 0.05*keV)
414 G4cout <<
"Warning from G4PenelopeBremsstrahlung: problem with energy conservation: "
416 (residualPrimaryEnergy+gammaEnergy)/keV <<
417 " keV (final) vs. " <<
418 kineticEnergy/keV <<
" keV (initial)" <<
G4endl;
425void G4PenelopeBremsstrahlungModel::ClearTables()
429 G4Exception(
"G4PenelopeBremsstrahlungModel::ClearTables()",
432 if (fXSTableElectron)
434 for (
auto& item : (*fXSTableElectron))
436 delete fXSTableElectron;
437 fXSTableElectron =
nullptr;
439 if (fXSTablePositron)
441 for (
auto& item : (*fXSTablePositron))
443 delete fXSTablePositron;
444 fXSTablePositron =
nullptr;
450 if (fPenelopeFSHelper)
453 if (fVerboseLevel > 2)
454 G4cout <<
"G4PenelopeBremsstrahlungModel: cleared tables" <<
G4endl;
464 return fIntrinsicLowEnergyLimit;
473 G4Exception(
"G4PenelopeBremsstrahlungModel::BuildXSTable()",
477 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
480 if (fXSTableElectron->count(theKey) && fXSTablePositron->count(theKey))
488 if (fVerboseLevel > 2)
490 G4cout <<
"G4PenelopeBremsstrahlungModel: going to build cross section table " <<
G4endl;
491 G4cout <<
"for e+/e- in " << mat->
GetName() <<
" for Ecut(gamma)= " <<
492 cut/keV <<
" keV " <<
G4endl;
499 ed <<
"Energy Grid looks not initialized" <<
G4endl;
501 G4Exception(
"G4PenelopeBremsstrahlungModel::BuildXSTable()",
510 for (std::size_t bin=0;bin<nBins;++bin)
518 ((
energy+electron_mass_c2)*(energy+electron_mass_c2)/
525 std::size_t nBinsX = fPenelopeFSHelper->
GetNBinsX();
528 for (std::size_t ix=0;ix<nBinsX;++ix)
531 G4double val = (*table)[ix]->Value(logene);
532 tempData[ix] =
G4Exp(val);
536 if (restrictedCut <= 1)
544 if (restrictedCut <=1)
562 G4double posCorrection = GetPositronXSCorrection(mat,energy);
572 fXSTableElectron->insert(std::make_pair(theKey,XSEntry));
573 fXSTablePositron->insert(std::make_pair(theKey,XSEntry2));
590 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
599 if (!fXSTableElectron)
603 G4String excep =
"The Cross Section Table for e- was not initialized correctly!";
604 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
607 fXSTableElectron =
new
613 if (!fPenelopeFSHelper)
616 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
617 if (fXSTableElectron->count(theKey))
618 return fXSTableElectron->find(theKey)->second;
623 if (fVerboseLevel > 0)
627 ed <<
"Unable to find e- table for " << mat->
GetName() <<
" at Ecut(gamma)= "
628 << cut/keV <<
" keV " <<
G4endl;
629 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
630 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
634 G4AutoLock lock(&PenelopeBremsstrahlungModelMutex);
636 BuildXSTable(mat,cut);
639 return fXSTableElectron->find(theKey)->second;
646 if (!fXSTablePositron)
648 G4String excep =
"The Cross Section Table for e+ was not initialized correctly!";
649 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
652 fXSTablePositron =
new
658 if (!fPenelopeFSHelper)
661 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
662 if (fXSTablePositron->count(theKey))
663 return fXSTablePositron->find(theKey)->second;
668 if (fVerboseLevel > 0)
672 ed <<
"Unable to find e+ table for " << mat->
GetName() <<
" at Ecut(gamma)= "
673 << cut/keV <<
" keV " <<
G4endl;
674 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
675 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
679 G4AutoLock lock(&PenelopeBremsstrahlungModelMutex);
681 BuildXSTable(mat,cut);
684 return fXSTablePositron->find(theKey)->second;
703 (3.1516e-2-t*(7.7446e-3-t*(1.0595e-3-t*
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
G4double G4Log(G4double x)
#define G4MUTEX_INITIALIZER
G4GLOB_DLL std::ostream G4cout
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
G4ThreeVector GetMomentum() const
static G4Electron * Electron()
const G4Material * GetMaterial() const
G4double GetTotNbOfAtomsPerVolume() const
const G4String & GetName() const
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
void SetProposedKineticEnergy(G4double proposedKinEnergy)
const G4String & GetParticleName() const
G4ThreeVector & SampleDirection(const G4DynamicParticle *dp, G4double out_energy, G4int Z, const G4Material *mat=nullptr) override
Samples the direction of the outgoing photon (in global coordinates).
void PrepareTables(const G4Material *material, G4bool isMaster)
Reserved for Master Model.
void BuildScaledXSTable(const G4Material *material, G4double cut, G4bool isMaster)
G4double GetEffectiveZSquared(const G4Material *mat) const
const G4PhysicsTable * GetScaledXSTable(const G4Material *, const G4double cut) const
void ClearTables(G4bool isMaster=true)
Reserved for the master model: they build and handle tables.
G4double SampleGammaEnergy(G4double energy, const G4Material *, const G4double cut) const
G4double GetMomentumIntegral(G4double *y, G4double up, G4int momOrder) const
G4double CrossSectionPerVolume(const G4Material *material, const G4ParticleDefinition *theParticle, G4double kineticEnergy, G4double cutEnergy, G4double maxEnergy=DBL_MAX) override
G4PenelopeBremsstrahlungModel(const G4ParticleDefinition *p=nullptr, const G4String &processName="PenBrem")
void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *) override
const G4ParticleDefinition * fParticle
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *theParticle, G4double kinEnergy, G4double Z, G4double A=0, G4double cut=0, G4double emax=DBL_MAX) override
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
G4double MinEnergyCut(const G4ParticleDefinition *, const G4MaterialCutsCouple *) override
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
G4ParticleChangeForLoss * fParticleChange
G4double ComputeDEDXPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy) override
virtual ~G4PenelopeBremsstrahlungModel()
G4double GetSoftStoppingPower(G4double energy) const
Returns the total stopping power due to soft collisions.
G4double GetHardCrossSection(G4double energy) const
Returns hard cross section at the given energy.
void AddCrossSectionPoint(size_t binNumber, G4double energy, G4double XH0, G4double XH1, G4double XH2, G4double XS0, G4double XS1, G4double XS2)
G4double GetAtomsPerMolecule(const G4Material *)
Returns the total number of atoms per molecule.
static G4PenelopeOscillatorManager * GetOscillatorManager()
G4double GetLowEdgeEnergy(const std::size_t index) const
std::size_t GetVectorLength() const
static G4Positron * Positron()
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
static G4ProductionCutsTable * GetProductionCutsTable()
void SetHighEnergyLimit(G4double)
G4double LowEnergyLimit() const
G4double HighEnergyLimit() const
virtual void SetupForMaterial(const G4ParticleDefinition *, const G4Material *, G4double kineticEnergy)
void SetDeexcitationFlag(G4bool val)
G4ParticleChangeForLoss * GetParticleChangeForLoss()
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
G4double energy(const ThreeVector &p, const G4double m)