42 #include "G4PenelopeBremsstrahlungModel.hh" 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;
79 SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
93 SetDeexcitationFlag(
true);
99 G4PenelopeBremsstrahlungModel::~G4PenelopeBremsstrahlungModel()
101 if (IsMaster() || fLocalTable)
104 if (fPenelopeFSHelper)
105 delete fPenelopeFSHelper;
108 if (fPenelopeAngular)
109 delete fPenelopeAngular;
117 if (verboseLevel > 3)
118 G4cout <<
"Calling G4PenelopeBremsstrahlungModel::Initialise()" <<
G4endl;
122 if (IsMaster() && part == fParticle)
125 if (!fPenelopeFSHelper)
127 if (!fPenelopeAngular)
133 if (fPenelopeAngular)
134 fPenelopeAngular->Initialize();
137 nBins = (size_t) (20*std::log10(HighEnergyLimit()/LowEnergyLimit()));
138 nBins =
std::max(nBins,(
size_t)100);
144 XSTableElectron =
new 146 XSTablePositron =
new 147 std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>;
158 fPenelopeFSHelper->BuildScaledXSTable(theMat,theCuts.at(i),IsMaster());
159 fPenelopeAngular->PrepareTables(theMat,IsMaster());
160 BuildXSTable(theMat,theCuts.at(i));
165 if (verboseLevel > 2) {
166 G4cout <<
"Penelope Bremsstrahlung model v2008 is initialized " << G4endl
168 << LowEnergyLimit() /
keV <<
" keV - " 169 << HighEnergyLimit() /
GeV <<
" GeV." 174 if(isInitialised)
return;
175 fParticleChange = GetParticleChangeForLoss();
176 isInitialised =
true;
183 if (verboseLevel > 3)
184 G4cout <<
"Calling G4PenelopeBremsstrahlungModel::InitialiseLocal()" <<
G4endl;
190 if (part == fParticle)
193 const G4PenelopeBremsstrahlungModel* theModel =
194 static_cast<G4PenelopeBremsstrahlungModel*
> (masterModel);
197 energyGrid = theModel->energyGrid;
198 XSTableElectron = theModel->XSTableElectron;
199 XSTablePositron = theModel->XSTablePositron;
200 fPenelopeFSHelper = theModel->fPenelopeFSHelper;
205 if (!fPenelopeAngular)
208 if (fPenelopeAngular)
209 fPenelopeAngular->Initialize();
218 fPenelopeAngular->PrepareTables(theMat,IsMaster());
223 nBins = theModel->nBins;
226 verboseLevel = theModel->verboseLevel;
241 if (verboseLevel > 3)
242 G4cout <<
"Calling CrossSectionPerVolume() of G4PenelopeBremsstrahlungModel" <<
G4endl;
244 SetupForMaterial(theParticle, material, energy);
248 G4PenelopeCrossSection* theXS = GetCrossSectionTableForCouple(theParticle,material,
255 G4double atPerMol = oscManager->GetAtomsPerMolecule(material);
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;
298 G4double G4PenelopeBremsstrahlungModel::ComputeDEDXPerVolume(
const G4Material* material,
303 if (verboseLevel > 3)
304 G4cout <<
"Calling ComputeDEDX() of G4PenelopeBremsstrahlungModel" <<
G4endl;
306 G4PenelopeCrossSection* theXS = GetCrossSectionTableForCouple(theParticle,material,
314 G4double atPerMol = oscManager->GetAtomsPerMolecule(material);
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;
334 void G4PenelopeBremsstrahlungModel::SampleSecondaries(std::vector<G4DynamicParticle*>*fvect,
340 if (verboseLevel > 3)
341 G4cout <<
"Calling SampleSecondaries() of G4PenelopeBremsstrahlungModel" <<
G4endl;
346 if (kineticEnergy <= fIntrinsicLowEnergyLimit)
348 fParticleChange->SetProposedKineticEnergy(0.);
349 fParticleChange->ProposeLocalEnergyDeposit(kineticEnergy);
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;
367 fPenelopeFSHelper->SampleGammaEnergy(kineticEnergy,material,cutG);
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.)
395 fParticleChange->ProposeMomentumDirection(particleDirection1);
396 fParticleChange->SetProposedKineticEnergy(residualPrimaryEnergy);
400 fParticleChange->SetProposedKineticEnergy(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()
439 if (!IsMaster() && !fLocalTable)
441 G4Exception(
"G4PenelopeBremsstrahlungModel::ClearTables()",
444 std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>::iterator i;
447 for (i=XSTableElectron->begin(); i != XSTableElectron->end(); i++)
449 G4PenelopeCrossSection*
tab = i->second;
452 delete XSTableElectron;
457 for (i=XSTablePositron->begin(); i != XSTablePositron->end(); i++)
459 G4PenelopeCrossSection*
tab = i->second;
462 delete XSTablePositron;
469 if (fPenelopeFSHelper)
470 fPenelopeFSHelper->ClearTables(IsMaster());
472 if (verboseLevel > 2)
473 G4cout <<
"G4PenelopeBremsstrahlungModel: cleared tables" <<
G4endl;
483 return fIntrinsicLowEnergyLimit;
490 if (!IsMaster() && !fLocalTable)
492 G4Exception(
"G4PenelopeBremsstrahlungModel::BuildXSTable()",
496 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
499 if (XSTableElectron->count(theKey) && XSTablePositron->count(theKey))
507 if (verboseLevel > 2)
509 G4cout <<
"G4PenelopeBremsstrahlungModel: going to build cross section table " <<
G4endl;
510 G4cout <<
"for e+/e- in " << mat->
GetName() <<
" for Ecut(gamma)= " <<
515 if (energyGrid->GetVectorLength() != nBins)
518 ed <<
"Energy Grid looks not initialized" <<
G4endl;
519 ed << nBins <<
" " << energyGrid->GetVectorLength() <<
G4endl;
520 G4Exception(
"G4PenelopeBremsstrahlungModel::BuildXSTable()",
524 G4PenelopeCrossSection* XSEntry =
new G4PenelopeCrossSection(nBins);
525 G4PenelopeCrossSection* XSEntry2 =
new G4PenelopeCrossSection(nBins);
527 const G4PhysicsTable* table = fPenelopeFSHelper->GetScaledXSTable(mat,cut);
533 G4double energy = energyGrid->GetLowEdgeEnergy(
bin);
538 G4double fact = fPenelopeFSHelper->GetEffectiveZSquared(mat)*
546 size_t nBinsX = fPenelopeFSHelper->GetNBinsX();
549 for (
size_t ix=0;ix<
nBinsX;ix++)
552 G4double val = (*table)[ix]->Value(logene);
553 tempData[ix] =
G4Exp(val);
557 if (restrictedCut <= 1)
558 XH0A = fPenelopeFSHelper->GetMomentumIntegral(tempData,1.0,-1) -
559 fPenelopeFSHelper->GetMomentumIntegral(tempData,restrictedCut,-1);
560 G4double XS1A = fPenelopeFSHelper->GetMomentumIntegral(tempData,
562 G4double XS2A = fPenelopeFSHelper->GetMomentumIntegral(tempData,
565 if (restrictedCut <=1)
567 XH1A = fPenelopeFSHelper->GetMomentumIntegral(tempData,1.0,0) -
569 XH2A = fPenelopeFSHelper->GetMomentumIntegral(tempData,1.0,1) -
577 XS2 = XS2A*fact*energy*
energy;
578 XH2 = XH2A*fact*energy*
energy;
583 G4double posCorrection = GetPositronXSCorrection(mat,energy);
593 XSTableElectron->insert(std::make_pair(theKey,XSEntry));
594 XSTablePositron->insert(std::make_pair(theKey,XSEntry2));
602 G4PenelopeCrossSection*
611 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
620 if (!XSTableElectron)
624 G4String excep =
"The Cross Section Table for e- was not initialized correctly!";
625 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
628 XSTableElectron =
new 629 std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>;
634 if (!fPenelopeFSHelper)
637 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
638 if (XSTableElectron->count(theKey))
639 return XSTableElectron->find(theKey)->second;
644 if (verboseLevel > 0)
648 ed <<
"Unable to find e- table for " << mat->
GetName() <<
" at Ecut(gamma)= " 650 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
651 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
655 G4AutoLock lock(&PenelopeBremsstrahlungModelMutex);
656 fPenelopeFSHelper->BuildScaledXSTable(mat,cut,
true);
657 BuildXSTable(mat,cut);
660 return XSTableElectron->find(theKey)->second;
668 if (!XSTablePositron)
670 G4String excep =
"The Cross Section Table for e+ was not initialized correctly!";
671 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
674 XSTablePositron =
new 675 std::map< std::pair<const G4Material*,G4double>, G4PenelopeCrossSection*>;
680 if (!fPenelopeFSHelper)
683 std::pair<const G4Material*,G4double> theKey = std::make_pair(mat,cut);
684 if (XSTablePositron->count(theKey))
685 return XSTablePositron->find(theKey)->second;
690 if (verboseLevel > 0)
694 ed <<
"Unable to find e+ table for " << mat->
GetName() <<
" at Ecut(gamma)= " 696 ed <<
"This can happen only in Unit Tests or via G4EmCalculator" <<
G4endl;
697 G4Exception(
"G4PenelopeBremsstrahlungModel::GetCrossSectionTableForCouple()",
701 G4AutoLock lock(&PenelopeBremsstrahlungModelMutex);
702 fPenelopeFSHelper->BuildScaledXSTable(mat,cut,
true);
703 BuildXSTable(mat,cut);
706 return XSTablePositron->find(theKey)->second;
716 G4double G4PenelopeBremsstrahlungModel::GetPositronXSCorrection(
const G4Material* mat,
727 (3.1516
e-2-t*(7.7446
e-3-t*(1.0595
e-3-t*
std::ostringstream G4ExceptionDescription
const G4Material * GetMaterial() const
static const size_t nBinsX
G4double GetTotNbOfAtomsPerVolume() const
#define G4MUTEX_INITIALIZER
void AddCrossSectionPoint(size_t binNumber, G4double energy, G4double XH0, G4double XH1, G4double XH2, G4double XS0, G4double XS1, G4double XS2)
G4double GetSoftStoppingPower(G4double energy) const
Returns the total stopping power due to soft collisions.
G4double GetKineticEnergy() const
G4ThreeVector GetMomentum() const
const G4String & GetParticleName() const
G4GLOB_DLL std::ostream G4cout
void ClearTables(G4bool isMaster=true)
Reserved for the master model: they build and handle tables.
std::ostream & tab(std::ostream &)
static G4PenelopeOscillatorManager * GetOscillatorManager()
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
ComputeCrossSectionPerAtom
static G4ProductionCutsTable * GetProductionCutsTable()
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
static G4Positron * Positron()
G4PenelopeBremsstrahlungFS(G4int verbosity=0)
Only master models are supposed to create instances.
const G4ThreeVector & GetMomentumDirection() const
G4double GetHardCrossSection(G4double energy) const
Returns hard cross section at the given energy.
size_t GetTableSize() const
static G4Electron * Electron()
const G4String & GetName() const