66 :
G4VEmModel(nam),fParticleChange(0),fParticle(0),
67 isInitialised(false),energyGrid(0),
68 XSTableElectron(0),XSTablePositron(0),fPenelopeFSHelper(0),
69 fPenelopeAngular(0),fLocalTable(false)
72 fIntrinsicLowEnergyLimit = 100.0*
eV;
73 fIntrinsicHighEnergyLimit = 100.0*
GeV;
104 if (fPenelopeFSHelper)
105 delete fPenelopeFSHelper;
108 if (fPenelopeAngular)
109 delete fPenelopeAngular;
117 if (verboseLevel > 3)
118 G4cout <<
"Calling G4PenelopeBremsstrahlungModel::Initialise()" <<
G4endl;
125 if (!fPenelopeFSHelper)
127 if (!fPenelopeAngular)
133 if (fPenelopeAngular)
138 nBins =
std::max(nBins,(
size_t)100);
144 XSTableElectron =
new
146 XSTablePositron =
new
147 std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>;
160 BuildXSTable(theMat,theCuts.at(i));
165 if (verboseLevel > 2) {
166 G4cout <<
"Penelope Bremsstrahlung model v2008 is initialized " << G4endl
174 if(isInitialised)
return;
176 isInitialised =
true;
183 if (verboseLevel > 3)
184 G4cout <<
"Calling G4PenelopeBremsstrahlungModel::InitialiseLocal()" <<
G4endl;
197 energyGrid = theModel->energyGrid;
198 XSTableElectron = theModel->XSTableElectron;
199 XSTablePositron = theModel->XSTablePositron;
200 fPenelopeFSHelper = theModel->fPenelopeFSHelper;
205 if (!fPenelopeAngular)
208 if (fPenelopeAngular)
223 nBins = theModel->nBins;
226 verboseLevel = theModel->verboseLevel;
241 if (verboseLevel > 3)
242 G4cout <<
"Calling CrossSectionPerVolume() of G4PenelopeBremsstrahlungModel" <<
G4endl;
257 if (verboseLevel > 3)
258 G4cout <<
"Material " << material->
GetName() <<
" has " << atPerMol <<
259 "atoms per molecule" <<
G4endl;
263 moleculeDensity = atomDensity/atPerMol;
265 G4double crossPerVolume = crossPerMolecule*moleculeDensity;
267 if (verboseLevel > 2)
270 G4cout <<
"Mean free path for gamma emission > " << cutEnergy/
keV <<
" keV at " <<
271 energy/
keV <<
" keV = " << (1./crossPerVolume)/
mm <<
" mm" << G4endl;
274 return crossPerVolume;
289 G4cout <<
"*** G4PenelopeBremsstrahlungModel -- WARNING ***" <<
G4endl;
290 G4cout <<
"Penelope Bremsstrahlung model v2008 does not calculate cross section _per atom_ " <<
G4endl;
291 G4cout <<
"so the result is always zero. For physics values, please invoke " <<
G4endl;
292 G4cout <<
"GetCrossSectionPerVolume() or GetMeanFreePath() via the G4EmCalculator" <<
G4endl;
303 if (verboseLevel > 3)
304 G4cout <<
"Calling ComputeDEDX() of G4PenelopeBremsstrahlungModel" <<
G4endl;
318 moleculeDensity = atomDensity/atPerMol;
320 G4double sPowerPerVolume = sPowerPerMolecule*moleculeDensity;
322 if (verboseLevel > 2)
325 G4cout <<
"Stopping power < " << cutEnergy/
keV <<
" keV at " <<
326 kineticEnergy/
keV <<
" keV = " <<
327 sPowerPerVolume/(
keV/
mm) <<
" keV/mm" << G4endl;
329 return sPowerPerVolume;
340 if (verboseLevel > 3)
341 G4cout <<
"Calling SampleSecondaries() of G4PenelopeBremsstrahlungModel" <<
G4endl;
346 if (kineticEnergy <= fIntrinsicLowEnergyLimit)
358 if (kineticEnergy < cutG)
361 if (verboseLevel > 3)
362 G4cout <<
"Going to sample gamma energy for: " <<material->
GetName() <<
" " <<
363 "energy = " << kineticEnergy/
keV <<
", cut = " << cutG/
keV <<
G4endl;
369 if (verboseLevel > 3)
370 G4cout <<
"Sampled gamma energy: " << gammaEnergy/
keV <<
" keV" <<
G4endl;
375 fPenelopeAngular->
SampleDirection(aDynamicParticle,gammaEnergy,0,material);
377 if (verboseLevel > 3)
380 G4double residualPrimaryEnergy = kineticEnergy-gammaEnergy;
381 if (residualPrimaryEnergy < 0)
384 gammaEnergy += residualPrimaryEnergy;
385 residualPrimaryEnergy = 0.0;
389 G4ThreeVector particleDirection1 = initialMomentum - gammaEnergy*gammaDirection1;
390 particleDirection1 = particleDirection1.
unit();
393 if (residualPrimaryEnergy > 0.)
407 fvect->push_back(theGamma);
409 if (verboseLevel > 1)
411 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
412 G4cout <<
"Energy balance from G4PenelopeBremsstrahlung" <<
G4endl;
413 G4cout <<
"Incoming primary energy: " << kineticEnergy/
keV <<
" keV" <<
G4endl;
414 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
415 G4cout <<
"Outgoing primary energy: " << residualPrimaryEnergy/
keV <<
" keV" <<
G4endl;
416 G4cout <<
"Bremsstrahlung photon " << gammaEnergy/
keV <<
" keV" <<
G4endl;
417 G4cout <<
"Total final state: " << (residualPrimaryEnergy+gammaEnergy)/
keV
419 G4cout <<
"-----------------------------------------------------------" <<
G4endl;
422 if (verboseLevel > 0)
424 G4double energyDiff = std::fabs(residualPrimaryEnergy+gammaEnergy-kineticEnergy);
425 if (energyDiff > 0.05*
keV)
426 G4cout <<
"Warning from G4PenelopeBremsstrahlung: problem with energy conservation: "
428 (residualPrimaryEnergy+gammaEnergy)/
keV <<
429 " keV (final) vs. " <<
430 kineticEnergy/
keV <<
" keV (initial)" << G4endl;
437 void G4PenelopeBremsstrahlungModel::ClearTables()
441 G4Exception(
"G4PenelopeBremsstrahlungModel::ClearTables()",
446 for (
auto& item : (*XSTableElectron))
448 delete XSTableElectron;
449 XSTableElectron =
nullptr;
453 for (
auto& item : (*XSTablePositron))
455 delete XSTablePositron;
456 XSTablePositron =
nullptr;
462 if (fPenelopeFSHelper)
465 if (verboseLevel > 2)
466 G4cout <<
"G4PenelopeBremsstrahlungModel: cleared tables" <<
G4endl;
476 return fIntrinsicLowEnergyLimit;
485 G4Exception(
"G4PenelopeBremsstrahlungModel::BuildXSTable()",
489 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
492 if (XSTableElectron->count(theKey) && XSTablePositron->count(theKey))
500 if (verboseLevel > 2)
502 G4cout <<
"G4PenelopeBremsstrahlungModel: going to build cross section table " <<
G4endl;
503 G4cout <<
"for e+/e- in " << mat->
GetName() <<
" for Ecut(gamma)= " <<
511 ed <<
"Energy Grid looks not initialized" <<
G4endl;
513 G4Exception(
"G4PenelopeBremsstrahlungModel::BuildXSTable()",
539 size_t nBinsX = fPenelopeFSHelper->
GetNBinsX();
542 for (
size_t ix=0;ix<nBinsX;ix++)
545 G4double val = (*table)[ix]->Value(logene);
546 tempData[ix] =
G4Exp(val);
550 if (restrictedCut <= 1)
558 if (restrictedCut <=1)
570 XS2 = XS2A*fact*energy*
energy;
571 XH2 = XH2A*fact*energy*
energy;
576 G4double posCorrection = GetPositronXSCorrection(mat,energy);
586 XSTableElectron->insert(std::make_pair(theKey,XSEntry));
587 XSTablePositron->insert(std::make_pair(theKey,XSEntry2));
604 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
613 if (!XSTableElectron)
617 G4String excep =
"The Cross Section Table for e- was not initialized correctly!";
618 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
621 XSTableElectron =
new
627 if (!fPenelopeFSHelper)
630 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
631 if (XSTableElectron->count(theKey))
632 return XSTableElectron->find(theKey)->second;
637 if (verboseLevel > 0)
641 ed <<
"Unable to find e- table for " << mat->
GetName() <<
" at Ecut(gamma)= "
643 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
644 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
648 G4AutoLock lock(&PenelopeBremsstrahlungModelMutex);
650 BuildXSTable(mat,cut);
653 return XSTableElectron->find(theKey)->second;
661 if (!XSTablePositron)
663 G4String excep =
"The Cross Section Table for e+ was not initialized correctly!";
664 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
667 XSTablePositron =
new
668 std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>;
673 if (!fPenelopeFSHelper)
676 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
677 if (XSTablePositron->count(theKey))
678 return XSTablePositron->find(theKey)->second;
683 if (verboseLevel > 0)
687 ed <<
"Unable to find e+ table for " << mat->
GetName() <<
" at Ecut(gamma)= "
689 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
690 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
694 G4AutoLock lock(&PenelopeBremsstrahlungModelMutex);
696 BuildXSTable(mat,cut);
699 return XSTablePositron->find(theKey)->second;
709 G4double G4PenelopeBremsstrahlungModel::GetPositronXSCorrection(
const G4Material* mat,
720 (3.1516e-2-t*(7.7446e-3-t*(1.0595e-3-t*
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
G4double LowEnergyLimit() const
G4double GetEffectiveZSquared(const G4Material *mat) const
G4double GetMomentumIntegral(G4double *y, G4double up, G4int momOrder) const
G4ParticleChangeForLoss * GetParticleChangeForLoss()
static constexpr double mm
G4double GetSoftStoppingPower(G4double energy) const
Returns the total stopping power due to soft collisions.
std::ostringstream G4ExceptionDescription
G4double GetKineticEnergy() const
G4double HighEnergyLimit() const
const G4String & GetName() const
const G4ParticleDefinition * fParticle
virtual void SetupForMaterial(const G4ParticleDefinition *, const G4Material *, G4double kineticEnergy)
G4double SampleGammaEnergy(G4double energy, const G4Material *, const G4double cut) const
G4double GetHardCrossSection(G4double energy) const
Returns hard cross section at the given energy.
void PrepareTables(const G4Material *material, G4bool isMaster)
Reserved for Master Model.
size_t GetVectorLength() const
G4double GetLowEdgeEnergy(size_t binNumber) const
G4ThreeVector & SampleDirection(const G4DynamicParticle *dp, G4double out_energy, G4int Z, const G4Material *mat=0)
Samples the direction of the outgoing photon (in global coordinates).
#define G4MUTEX_INITIALIZER
const G4String & GetParticleName() const
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
void AddCrossSectionPoint(size_t binNumber, G4double energy, G4double XH0, G4double XH1, G4double XH2, G4double XS0, G4double XS1, G4double XS2)
void SetHighEnergyLimit(G4double)
virtual void InitialiseLocal(const G4ParticleDefinition *, G4VEmModel *)
G4GLOB_DLL std::ostream G4cout
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *theParticle, G4double kinEnergy, G4double Z, G4double A=0, G4double cut=0, G4double emax=DBL_MAX)
size_t GetTableSize() const
void BuildScaledXSTable(const G4Material *material, G4double cut, G4bool isMaster)
void ClearTables(G4bool isMaster=true)
Reserved for the master model: they build and handle tables.
G4PenelopeBremsstrahlungModel(const G4ParticleDefinition *p=0, const G4String &processName="PenBrem")
const G4ThreeVector & GetMomentumDirection() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
virtual G4double CrossSectionPerVolume(const G4Material *material, const G4ParticleDefinition *theParticle, G4double kineticEnergy, G4double cutEnergy, G4double maxEnergy=DBL_MAX)
static constexpr double eV
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &)
static G4PenelopeOscillatorManager * GetOscillatorManager()
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
virtual ~G4PenelopeBremsstrahlungModel()
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
G4double GetTotNbOfAtomsPerVolume() const
static G4ProductionCutsTable * GetProductionCutsTable()
static G4Positron * Positron()
virtual G4double MinEnergyCut(const G4ParticleDefinition *, const G4MaterialCutsCouple *)
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
T max(const T t1, const T t2)
brief Return the largest of the two arguments
G4double energy(const ThreeVector &p, const G4double m)
static constexpr double GeV
virtual G4double ComputeDEDXPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy)
static G4Electron * Electron()
G4ParticleChangeForLoss * fParticleChange
void SetDeexcitationFlag(G4bool val)
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy)
G4double GetAtomsPerMolecule(const G4Material *)
Returns the total number of atoms per molecule.
const G4PhysicsTable * GetScaledXSTable(const G4Material *, const G4double cut) const
static constexpr double keV
G4ThreeVector GetMomentum() const
const G4Material * GetMaterial() const