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)
131 fPenelopeAngular->Initialize();
135 nBins = std::max(nBins,(std::size_t)100);
140 fXSTableElectron =
new
142 fXSTablePositron =
new
154 fPenelopeFSHelper->BuildScaledXSTable(theMat,theCuts.at(i),
IsMaster());
155 fPenelopeAngular->PrepareTables(theMat,
IsMaster());
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)
202 fPenelopeAngular->Initialize();
211 fPenelopeAngular->PrepareTables(theMat,
IsMaster());
215 nBins = theModel->nBins;
218 fVerboseLevel = theModel->fVerboseLevel;
232 if (fVerboseLevel > 3)
233 G4cout <<
"Calling CrossSectionPerVolume() of G4PenelopeBremsstrahlungModel" <<
G4endl;
244 G4double atPerMol = fOscManager->GetAtomsPerMolecule(material);
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 = " <<
261 (crossPerVolume? (1./crossPerVolume)/mm :
DBL_MAX) <<
" mm" <<
G4endl;
264 return crossPerVolume;
279 G4cout <<
"*** G4PenelopeBremsstrahlungModel -- WARNING ***" <<
G4endl;
280 G4cout <<
"Penelope Bremsstrahlung model v2008 does not calculate cross section _per atom_ " <<
G4endl;
281 G4cout <<
"so the result is always zero. For physics values, please invoke " <<
G4endl;
282 G4cout <<
"GetCrossSectionPerVolume() or GetMeanFreePath() via the G4EmCalculator" <<
G4endl;
293 if (fVerboseLevel > 3)
294 G4cout <<
"Calling ComputeDEDX() of G4PenelopeBremsstrahlungModel" <<
G4endl;
303 G4double atPerMol = fOscManager->GetAtomsPerMolecule(material);
307 moleculeDensity = atomDensity/atPerMol;
309 G4double sPowerPerVolume = sPowerPerMolecule*moleculeDensity;
311 if (fVerboseLevel > 2)
314 G4cout <<
"Stopping power < " << cutEnergy/keV <<
" keV at " <<
315 kineticEnergy/keV <<
" keV = " <<
316 sPowerPerVolume/(keV/mm) <<
" keV/mm" <<
G4endl;
318 return sPowerPerVolume;
329 if (fVerboseLevel > 3)
330 G4cout <<
"Calling SampleSecondaries() of G4PenelopeBremsstrahlungModel" <<
G4endl;
335 if (kineticEnergy <= fIntrinsicLowEnergyLimit)
347 if (kineticEnergy < cutG)
350 if (fVerboseLevel > 3)
351 G4cout <<
"Going to sample gamma energy for: " <<material->
GetName() <<
" " <<
352 "energy = " << kineticEnergy/keV <<
", cut = " << cutG/keV <<
G4endl;
356 fPenelopeFSHelper->SampleGammaEnergy(kineticEnergy,material,cutG);
358 if (fVerboseLevel > 3)
359 G4cout <<
"Sampled gamma energy: " << gammaEnergy/keV <<
" keV" <<
G4endl;
364 fPenelopeAngular->SampleDirection(aDynamicParticle,gammaEnergy,0,material);
366 if (fVerboseLevel > 3)
369 G4double residualPrimaryEnergy = kineticEnergy-gammaEnergy;
370 if (residualPrimaryEnergy < 0)
373 gammaEnergy += residualPrimaryEnergy;
374 residualPrimaryEnergy = 0.0;
378 G4ThreeVector particleDirection1 = initialMomentum - gammaEnergy*gammaDirection1;
379 particleDirection1 = particleDirection1.
unit();
382 if (residualPrimaryEnergy > 0.)
396 fvect->push_back(theGamma);
398 if (fVerboseLevel > 1)
400 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
401 G4cout <<
"Energy balance from G4PenelopeBremsstrahlung" <<
G4endl;
402 G4cout <<
"Incoming primary energy: " << kineticEnergy/keV <<
" keV" <<
G4endl;
403 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
404 G4cout <<
"Outgoing primary energy: " << residualPrimaryEnergy/keV <<
" keV" <<
G4endl;
405 G4cout <<
"Bremsstrahlung photon " << gammaEnergy/keV <<
" keV" <<
G4endl;
406 G4cout <<
"Total final state: " << (residualPrimaryEnergy+gammaEnergy)/keV
408 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
411 if (fVerboseLevel > 0)
413 G4double energyDiff = std::fabs(residualPrimaryEnergy+gammaEnergy-kineticEnergy);
414 if (energyDiff > 0.05*keV)
415 G4cout <<
"Warning from G4PenelopeBremsstrahlung: problem with energy conservation: "
417 (residualPrimaryEnergy+gammaEnergy)/keV <<
418 " keV (final) vs. " <<
419 kineticEnergy/keV <<
" keV (initial)" <<
G4endl;
426void G4PenelopeBremsstrahlungModel::ClearTables()
430 G4Exception(
"G4PenelopeBremsstrahlungModel::ClearTables()",
433 if (fXSTableElectron)
435 for (
auto& item : (*fXSTableElectron))
437 delete fXSTableElectron;
438 fXSTableElectron =
nullptr;
440 if (fXSTablePositron)
442 for (
auto& item : (*fXSTablePositron))
444 delete fXSTablePositron;
445 fXSTablePositron =
nullptr;
451 if (fPenelopeFSHelper)
452 fPenelopeFSHelper->ClearTables(
IsMaster());
454 if (fVerboseLevel > 2)
455 G4cout <<
"G4PenelopeBremsstrahlungModel: cleared tables" <<
G4endl;
465 return fIntrinsicLowEnergyLimit;
474 G4Exception(
"G4PenelopeBremsstrahlungModel::BuildXSTable()",
478 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
481 if (fXSTableElectron->count(theKey) && fXSTablePositron->count(theKey))
489 if (fVerboseLevel > 2)
491 G4cout <<
"G4PenelopeBremsstrahlungModel: going to build cross section table " <<
G4endl;
492 G4cout <<
"for e+/e- in " << mat->
GetName() <<
" for Ecut(gamma)= " <<
493 cut/keV <<
" keV " <<
G4endl;
497 if (fEnergyGrid->GetVectorLength() != nBins)
500 ed <<
"Energy Grid looks not initialized" <<
G4endl;
501 ed << nBins <<
" " << fEnergyGrid->GetVectorLength() <<
G4endl;
502 G4Exception(
"G4PenelopeBremsstrahlungModel::BuildXSTable()",
506 G4PenelopeCrossSection* XSEntry =
new G4PenelopeCrossSection(nBins);
507 G4PenelopeCrossSection* XSEntry2 =
new G4PenelopeCrossSection(nBins);
508 const G4PhysicsTable*
table = fPenelopeFSHelper->GetScaledXSTable(mat,cut);
511 for (std::size_t bin=0;bin<nBins;++bin)
518 G4double fact = fPenelopeFSHelper->GetEffectiveZSquared(mat)*
526 std::size_t nBinsX = fPenelopeFSHelper->GetNBinsX();
529 for (std::size_t ix=0;ix<nBinsX;++ix)
532 G4double val = (*table)[ix]->Value(logene);
533 tempData[ix] =
G4Exp(val);
537 if (restrictedCut <= 1)
538 XH0A = fPenelopeFSHelper->GetMomentumIntegral(tempData,1.0,-1) -
539 fPenelopeFSHelper->GetMomentumIntegral(tempData,restrictedCut,-1);
540 G4double XS1A = fPenelopeFSHelper->GetMomentumIntegral(tempData,
542 G4double XS2A = fPenelopeFSHelper->GetMomentumIntegral(tempData,
545 if (restrictedCut <=1)
547 XH1A = fPenelopeFSHelper->GetMomentumIntegral(tempData,1.0,0) -
549 XH2A = fPenelopeFSHelper->GetMomentumIntegral(tempData,1.0,1) -
563 G4double posCorrection = GetPositronXSCorrection(mat,energy);
573 fXSTableElectron->insert(std::make_pair(theKey,XSEntry));
574 fXSTablePositron->insert(std::make_pair(theKey,XSEntry2));
591 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
600 if (!fXSTableElectron)
604 G4String excep =
"The Cross Section Table for e- was not initialized correctly!";
605 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
608 fXSTableElectron =
new
609 std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>;
614 if (!fPenelopeFSHelper)
615 fPenelopeFSHelper =
new G4PenelopeBremsstrahlungFS(fVerboseLevel);
617 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
618 if (fXSTableElectron->count(theKey))
619 return fXSTableElectron->find(theKey)->second;
624 if (fVerboseLevel > 0)
628 ed <<
"Unable to find e- table for " << mat->
GetName() <<
" at Ecut(gamma)= "
629 << cut/keV <<
" keV " <<
G4endl;
630 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
631 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
635 G4AutoLock lock(&PenelopeBremsstrahlungModelMutex);
636 fPenelopeFSHelper->BuildScaledXSTable(mat,cut,
true);
637 BuildXSTable(mat,cut);
640 return fXSTableElectron->find(theKey)->second;
647 if (!fXSTablePositron)
649 G4String excep =
"The Cross Section Table for e+ was not initialized correctly!";
650 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
653 fXSTablePositron =
new
654 std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>;
659 if (!fPenelopeFSHelper)
660 fPenelopeFSHelper =
new G4PenelopeBremsstrahlungFS(fVerboseLevel);
662 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
663 if (fXSTablePositron->count(theKey))
664 return fXSTablePositron->find(theKey)->second;
669 if (fVerboseLevel > 0)
673 ed <<
"Unable to find e+ table for " << mat->
GetName() <<
" at Ecut(gamma)= "
674 << cut/keV <<
" keV " <<
G4endl;
675 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
676 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
680 G4AutoLock lock(&PenelopeBremsstrahlungModelMutex);
681 fPenelopeFSHelper->BuildScaledXSTable(mat,cut,
true);
682 BuildXSTable(mat,cut);
685 return fXSTablePositron->find(theKey)->second;
702 (electron_mass_c2*fPenelopeFSHelper->GetEffectiveZSquared(mat)));
704 (3.1516e-2-t*(7.7446e-3-t*(1.0595e-3-t*
G4TemplateAutoLock< G4Mutex > G4AutoLock
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)
G4ThreeVector G4ParticleMomentum
#define G4MUTEX_INITIALIZER
CLHEP::Hep3Vector G4ThreeVector
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
const G4String & GetParticleName() 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)
static G4PenelopeOscillatorManager * GetOscillatorManager()
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)
G4VEmModel(const G4String &nam)
G4ParticleChangeForLoss * GetParticleChangeForLoss()
G4double energy(const ThreeVector &p, const G4double m)