Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4PenelopeRayleighModelMI Class Reference

#include <G4PenelopeRayleighModelMI.hh>

+ Inheritance diagram for G4PenelopeRayleighModelMI:

Public Member Functions

 G4PenelopeRayleighModelMI (const G4ParticleDefinition *p=nullptr, const G4String &processName="PenRayleighMI")
 
virtual ~G4PenelopeRayleighModelMI ()
 
void Initialise (const G4ParticleDefinition *, const G4DataVector &) override
 
void InitialiseLocal (const G4ParticleDefinition *, G4VEmModel *masterModel) override
 
G4double ComputeCrossSectionPerAtom (const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0, G4double cut=0, G4double emax=DBL_MAX) override
 
G4double CrossSectionPerVolume (const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0., G4double maxEnergy=DBL_MAX) override
 
void SampleSecondaries (std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
 
void SetVerbosityLevel (G4int lev)
 
G4int GetVerbosityLevel ()
 
void DumpFormFactorTable (const G4Material *)
 
void SetMIActive (G4bool val)
 
G4bool IsMIActive ()
 
G4PenelopeRayleighModelMIoperator= (const G4PenelopeRayleighModelMI &right)=delete
 
 G4PenelopeRayleighModelMI (const G4PenelopeRayleighModelMI &)=delete
 
- Public Member Functions inherited from G4VEmModel
 G4VEmModel (const G4String &nam)
 
virtual ~G4VEmModel ()
 
virtual void InitialiseForMaterial (const G4ParticleDefinition *, const G4Material *)
 
virtual void InitialiseForElement (const G4ParticleDefinition *, G4int Z)
 
virtual G4double ComputeDEDXPerVolume (const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=DBL_MAX)
 
virtual G4double GetPartialCrossSection (const G4Material *, G4int level, const G4ParticleDefinition *, G4double kineticEnergy)
 
virtual G4double ComputeCrossSectionPerShell (const G4ParticleDefinition *, G4int Z, G4int shellIdx, G4double kinEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
 
virtual G4double ChargeSquareRatio (const G4Track &)
 
virtual G4double GetChargeSquareRatio (const G4ParticleDefinition *, const G4Material *, G4double kineticEnergy)
 
virtual G4double GetParticleCharge (const G4ParticleDefinition *, const G4Material *, G4double kineticEnergy)
 
virtual void StartTracking (G4Track *)
 
virtual void CorrectionsAlongStep (const G4MaterialCutsCouple *, const G4DynamicParticle *, const G4double &length, G4double &eloss)
 
virtual G4double Value (const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy)
 
virtual G4double MinPrimaryEnergy (const G4Material *, const G4ParticleDefinition *, G4double cut=0.0)
 
virtual G4double MinEnergyCut (const G4ParticleDefinition *, const G4MaterialCutsCouple *)
 
virtual void SetupForMaterial (const G4ParticleDefinition *, const G4Material *, G4double kineticEnergy)
 
virtual void DefineForRegion (const G4Region *)
 
virtual void FillNumberOfSecondaries (G4int &numberOfTriplets, G4int &numberOfRecoil)
 
virtual void ModelDescription (std::ostream &outFile) const
 
void InitialiseElementSelectors (const G4ParticleDefinition *, const G4DataVector &)
 
std::vector< G4EmElementSelector * > * GetElementSelectors ()
 
void SetElementSelectors (std::vector< G4EmElementSelector * > *)
 
G4double ComputeDEDX (const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=DBL_MAX)
 
G4double CrossSection (const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
 
G4double ComputeMeanFreePath (const G4ParticleDefinition *, G4double kineticEnergy, const G4Material *, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
 
G4double ComputeCrossSectionPerAtom (const G4ParticleDefinition *, const G4Element *, G4double kinEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
 
const G4ElementSelectRandomAtom (const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
 
const G4ElementSelectTargetAtom (const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double logKineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
 
const G4ElementSelectRandomAtom (const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
 
const G4ElementGetCurrentElement (const G4Material *mat=nullptr) const
 
G4int SelectRandomAtomNumber (const G4Material *) const
 
const G4IsotopeGetCurrentIsotope (const G4Element *elm=nullptr) const
 
G4int SelectIsotopeNumber (const G4Element *) const
 
void SetParticleChange (G4VParticleChange *, G4VEmFluctuationModel *f=nullptr)
 
void SetCrossSectionTable (G4PhysicsTable *, G4bool isLocal)
 
G4ElementDataGetElementData ()
 
G4PhysicsTableGetCrossSectionTable ()
 
G4VEmFluctuationModelGetModelOfFluctuations ()
 
G4VEmAngularDistributionGetAngularDistribution ()
 
G4VEmModelGetTripletModel ()
 
void SetTripletModel (G4VEmModel *)
 
void SetAngularDistribution (G4VEmAngularDistribution *)
 
G4double HighEnergyLimit () const
 
G4double LowEnergyLimit () const
 
G4double HighEnergyActivationLimit () const
 
G4double LowEnergyActivationLimit () const
 
G4double PolarAngleLimit () const
 
G4double SecondaryThreshold () const
 
G4bool DeexcitationFlag () const
 
G4bool ForceBuildTableFlag () const
 
G4bool UseAngularGeneratorFlag () const
 
void SetAngularGeneratorFlag (G4bool)
 
void SetHighEnergyLimit (G4double)
 
void SetLowEnergyLimit (G4double)
 
void SetActivationHighEnergyLimit (G4double)
 
void SetActivationLowEnergyLimit (G4double)
 
G4bool IsActive (G4double kinEnergy) const
 
void SetPolarAngleLimit (G4double)
 
void SetSecondaryThreshold (G4double)
 
void SetDeexcitationFlag (G4bool val)
 
void SetForceBuildTable (G4bool val)
 
void SetFluctuationFlag (G4bool val)
 
void SetMasterThread (G4bool val)
 
G4bool IsMaster () const
 
void SetUseBaseMaterials (G4bool val)
 
G4bool UseBaseMaterials () const
 
G4double MaxSecondaryKinEnergy (const G4DynamicParticle *dynParticle)
 
const G4StringGetName () const
 
void SetCurrentCouple (const G4MaterialCutsCouple *)
 
G4bool IsLocked () const
 
void SetLocked (G4bool)
 
void SetLPMFlag (G4bool)
 
G4VEmModeloperator= (const G4VEmModel &right)=delete
 
 G4VEmModel (const G4VEmModel &)=delete
 

Additional Inherited Members

- Protected Member Functions inherited from G4VEmModel
G4ParticleChangeForLossGetParticleChangeForLoss ()
 
G4ParticleChangeForGammaGetParticleChangeForGamma ()
 
virtual G4double MaxSecondaryEnergy (const G4ParticleDefinition *, G4double kineticEnergy)
 
const G4MaterialCutsCoupleCurrentCouple () const
 
void SetCurrentElement (const G4Element *)
 
- Protected Attributes inherited from G4VEmModel
G4ElementDatafElementData = nullptr
 
G4VParticleChangepParticleChange = nullptr
 
G4PhysicsTablexSectionTable = nullptr
 
const G4MaterialpBaseMaterial = nullptr
 
const std::vector< G4double > * theDensityFactor = nullptr
 
const std::vector< G4int > * theDensityIdx = nullptr
 
G4double inveplus
 
G4double pFactor = 1.0
 
std::size_t currentCoupleIndex = 0
 
std::size_t basedCoupleIndex = 0
 
G4bool lossFlucFlag = true
 

Detailed Description

Definition at line 71 of file G4PenelopeRayleighModelMI.hh.

Constructor & Destructor Documentation

◆ G4PenelopeRayleighModelMI() [1/2]

G4PenelopeRayleighModelMI::G4PenelopeRayleighModelMI ( const G4ParticleDefinition * p = nullptr,
const G4String & processName = "PenRayleighMI" )
explicit

Definition at line 72 of file G4PenelopeRayleighModelMI.cc.

73 :
74 G4VEmModel(nam),
75 fParticleChange(nullptr),fParticle(nullptr),fLogFormFactorTable(nullptr),fPMaxTable(nullptr),
76 fSamplingTable(nullptr),fMolInterferenceData(nullptr),fAngularFunction(nullptr), fKnownMaterials(nullptr),
77 fIsInitialised(false),fLocalTable(false),fIsMIActive(true)
78{
79 fIntrinsicLowEnergyLimit = 100.0*eV;
80 fIntrinsicHighEnergyLimit = 100.0*GeV;
81 //SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
82 SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
83
84 if (part) SetParticle(part);
85
86 fVerboseLevel = 0;
87 // Verbosity scale:
88 // 0 = nothing
89 // 1 = warning for energy non-conservation
90 // 2 = details of energy budget
91 // 3 = calculation of FF and CS, file openings, sampling of atoms
92 // 4 = entering in methods
93
94 //build the energy grid. It is the same for all materials
95 G4double logenergy = G4Log(fIntrinsicLowEnergyLimit/2.);
96 G4double logmaxenergy = G4Log(1.5*fIntrinsicHighEnergyLimit);
97 //finer grid below 160 keV
98 G4double logtransitionenergy = G4Log(160*keV);
99 G4double logfactor1 = G4Log(10.)/250.;
100 G4double logfactor2 = logfactor1*10;
101 fLogEnergyGridPMax.push_back(logenergy);
102 do {
103 if (logenergy < logtransitionenergy)
104 logenergy += logfactor1;
105 else
106 logenergy += logfactor2;
107 fLogEnergyGridPMax.push_back(logenergy);
108 } while (logenergy < logmaxenergy);
109}
G4double G4Log(G4double x)
Definition G4Log.hh:227
double G4double
Definition G4Types.hh:83
void SetHighEnergyLimit(G4double)
G4VEmModel(const G4String &nam)
Definition G4VEmModel.cc:67

◆ ~G4PenelopeRayleighModelMI()

G4PenelopeRayleighModelMI::~G4PenelopeRayleighModelMI ( )
virtual

Definition at line 113 of file G4PenelopeRayleighModelMI.cc.

114{
115 if (IsMaster() || fLocalTable) {
116
117 for(G4int i=0; i<=fMaxZ; ++i)
118 {
119 if(fLogAtomicCrossSection[i])
120 {
121 delete fLogAtomicCrossSection[i];
122 fLogAtomicCrossSection[i] = nullptr;
123 }
124 if(fAtomicFormFactor[i])
125 {
126 delete fAtomicFormFactor[i];
127 fAtomicFormFactor[i] = nullptr;
128 }
129 }
130 if (fMolInterferenceData) {
131 for (auto& item : (*fMolInterferenceData))
132 if (item.second) delete item.second;
133 delete fMolInterferenceData;
134 fMolInterferenceData = nullptr;
135 }
136 if (fKnownMaterials)
137 {
138 delete fKnownMaterials;
139 fKnownMaterials = nullptr;
140 }
141 if (fAngularFunction)
142 {
143 delete fAngularFunction;
144 fAngularFunction = nullptr;
145 }
146 ClearTables();
147 }
148}
int G4int
Definition G4Types.hh:85
G4bool IsMaster() const

◆ G4PenelopeRayleighModelMI() [2/2]

G4PenelopeRayleighModelMI::G4PenelopeRayleighModelMI ( const G4PenelopeRayleighModelMI & )
delete

Member Function Documentation

◆ ComputeCrossSectionPerAtom()

G4double G4PenelopeRayleighModelMI::ComputeCrossSectionPerAtom ( const G4ParticleDefinition * ,
G4double kinEnergy,
G4double Z,
G4double A = 0,
G4double cut = 0,
G4double emax = DBL_MAX )
overridevirtual

Reimplemented from G4VEmModel.

Definition at line 319 of file G4PenelopeRayleighModelMI.cc.

325{
326 //Cross section of Rayleigh scattering in Penelope v2008 is calculated by the EPDL97
327 //tabulation, Cuellen et al. (1997), with non-relativistic form factors from Hubbel
328 //et al. J. Phys. Chem. Ref. Data 4 (1975) 471; Erratum ibid. 6 (1977) 615.
329
330 if (fVerboseLevel > 3)
331 G4cout << "Calling CrossSectionPerAtom() of G4PenelopeRayleighModelMI" << G4endl;
332
333 G4int iZ = G4int(Z);
334 if (!fLogAtomicCrossSection[iZ]) {
335 //If we are here, it means that Initialize() was inkoved, but the MaterialTable was
336 //not filled up. This can happen in a UnitTest or via G4EmCalculator
337 if (fVerboseLevel > 0) {
338 //Issue a G4Exception (warning) only in verbose mode
340 ed << "Unable to retrieve the cross section table for Z=" << iZ << G4endl;
341 ed << "This can happen only in Unit Tests or via G4EmCalculator" << G4endl;
342 G4Exception("G4PenelopeRayleighModelMI::ComputeCrossSectionPerAtom()",
343 "em2040",JustWarning,ed);
344 }
345
346 //protect file reading via autolock
347 G4AutoLock lock(&PenelopeRayleighModelMutex);
348 ReadDataFile(iZ);
349 lock.unlock();
350 }
351
352 G4double cross = 0;
353 G4PhysicsFreeVector* atom = fLogAtomicCrossSection[iZ];
354 if (!atom) {
356 ed << "Unable to find Z=" << iZ << " in the atomic cross section table" << G4endl;
357 G4Exception("G4PenelopeRayleighModelMI::ComputeCrossSectionPerAtom()",
358 "em2041",FatalException,ed);
359 return 0;
360 }
361
362 G4double logene = G4Log(energy);
363 G4double logXS = atom->Value(logene);
364 cross = G4Exp(logXS);
365
366 if (fVerboseLevel > 2) {
367 G4cout << "Rayleigh cross section at " << energy/keV << " keV for Z="
368 << Z << " = " << cross/barn << " barn" << G4endl;
369 }
370 return cross;
371}
@ JustWarning
@ FatalException
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.
Definition G4Exp.hh:180
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
G4double Value(const G4double energy, std::size_t &lastidx) const
G4double energy(const ThreeVector &p, const G4double m)

◆ CrossSectionPerVolume()

G4double G4PenelopeRayleighModelMI::CrossSectionPerVolume ( const G4Material * material,
const G4ParticleDefinition * p,
G4double kineticEnergy,
G4double cutEnergy = 0.,
G4double maxEnergy = DBL_MAX )
overridevirtual

Reimplemented from G4VEmModel.

Definition at line 409 of file G4PenelopeRayleighModelMI.cc.

414{
415 //check if we are in a Unit Test (only for the first time)
416 static G4bool amInAUnitTest = false;
417 if (G4ProductionCutsTable::GetProductionCutsTable()->GetTableSize() == 0 && !amInAUnitTest)
418 {
419 amInAUnitTest = true;
421 ed << "The ProductionCuts table is empty " << G4endl;
422 ed << "This should happen only in Unit Tests" << G4endl;
423 G4Exception("G4PenelopeRayleighModelMI::CrossSectionPerVolume()",
424 "em2019",JustWarning,ed);
425 }
426 //If the material does not have a MIFF, continue with the old-style calculation
427 G4String matname = material->GetName();
428 if (amInAUnitTest)
429 {
430 //No need to lock, as this is always called in a master
431 const G4ElementVector* theElementVector = material->GetElementVector();
432 //protect file reading via autolock
433 for (std::size_t j=0;j<material->GetNumberOfElements();++j) {
434 G4int iZ = theElementVector->at(j)->GetZasInt();
435 if (!fLogAtomicCrossSection[iZ]) {
436 ReadDataFile(iZ);
437 }
438 }
439 if (fIsMIActive)
440 ReadMolInterferenceData(matname);
441 if (!fLogFormFactorTable->count(material))
442 BuildFormFactorTable(material);
443 if (!(fSamplingTable->count(material)))
444 InitializeSamplingAlgorithm(material);
445 if (!fPMaxTable->count(material))
446 GetPMaxTable(material);
447 }
448 G4bool useMIFF = fIsMIActive && (fMolInterferenceData->count(matname) || matname.find("MedMat") != std::string::npos);
449 if (!useMIFF)
450 {
451 if (fVerboseLevel > 2)
452 G4cout << "Rayleigh CS of: " << matname << " calculated through CSperAtom!" << G4endl;
453 return G4VEmModel::CrossSectionPerVolume(material,p,energy);
454 }
455
456 // If we are here, it means that we have to integrate the cross section
457 if (fVerboseLevel > 2)
458 G4cout << "Rayleigh CS of: " << matname
459 << " calculated through integration of the DCS" << G4endl;
460
461 G4double cs = 0;
462
463 //force null cross-section if below the low-energy edge of the table
464 if (energy < LowEnergyLimit())
465 return cs;
466
467 //if the material is a CRYSTAL, forbid this process
468 if (material->IsExtended() && material->GetName() != "CustomMat") {
469 G4ExtendedMaterial* extendedmaterial = (G4ExtendedMaterial*)material;
470 G4CrystalExtension* crystalExtension = (G4CrystalExtension*)extendedmaterial->RetrieveExtension("crystal");
471 if (crystalExtension != 0) {
472 G4cout << "The material has a crystalline structure, a dedicated diffraction model is used!" << G4endl;
473 return 0;
474 }
475 }
476
477 //GET MATERIAL INFORMATION
478 G4double atomDensity = material->GetTotNbOfAtomsPerVolume();
479 std::size_t nElements = material->GetNumberOfElements();
480 const G4ElementVector* elementVector = material->GetElementVector();
481 const G4double* fractionVector = material->GetFractionVector();
482
483 //Stoichiometric factors
484 std::vector<G4double> *StoichiometricFactors = new std::vector<G4double>;
485 for (std::size_t i=0;i<nElements;++i) {
486 G4double fraction = fractionVector[i];
487 G4double atomicWeigth = (*elementVector)[i]->GetA()/(g/mole);
488 StoichiometricFactors->push_back(fraction/atomicWeigth);
489 }
490 G4double MaxStoichiometricFactor = 0.;
491 for (std::size_t i=0;i<nElements;++i) {
492 if ((*StoichiometricFactors)[i] > MaxStoichiometricFactor)
493 MaxStoichiometricFactor = (*StoichiometricFactors)[i];
494 }
495 for (std::size_t i=0;i<nElements;++i) {
496 (*StoichiometricFactors)[i] /= MaxStoichiometricFactor;
497 }
498
499 //Equivalent atoms per molecule
500 G4double atPerMol = 0;
501 for (std::size_t i=0;i<nElements;++i)
502 atPerMol += (*StoichiometricFactors)[i];
503 G4double moleculeDensity = 0.;
504 if (atPerMol) moleculeDensity = atomDensity/atPerMol;
505
506 if (fVerboseLevel > 2)
507 G4cout << "Material " << material->GetName() << " has " << atPerMol << " atoms "
508 << "per molecule and " << moleculeDensity/(cm*cm*cm) << " molecule/cm3" << G4endl;
509
510 //Equivalent molecular weight (dimensionless)
511 G4double MolWeight = 0.;
512 for (std::size_t i=0;i<nElements;++i)
513 MolWeight += (*StoichiometricFactors)[i]*(*elementVector)[i]->GetA()/(g/mole);
514
515 if (fVerboseLevel > 2)
516 G4cout << "Molecular weight of " << matname << ": " << MolWeight << " g/mol" << G4endl;
517
518 G4double IntegrandFun[fNtheta];
519 for (G4int k=0; k<fNtheta; k++) {
520 G4double theta = fAngularFunction->Energy(k); //the x-value is called "Energy", but is an angle
521 G4double F2 = GetFSquared(material,CalculateQSquared(theta,energy));
522 IntegrandFun[k] = (*fAngularFunction)[k]*F2;
523 }
524
525 G4double constant = pi*classic_electr_radius*classic_electr_radius;
526 cs = constant*IntegrateFun(IntegrandFun,fNtheta,fDTheta);
527
528 //Now cs is the cross section per molecule, let's calculate the cross section per volume
529 G4double csvolume = cs*moleculeDensity;
530
531 //print CS and mfp
532 if (fVerboseLevel > 2)
533 G4cout << "Rayleigh CS of " << matname << " at " << energy/keV
534 << " keV: " << cs/barn << " barn"
535 << ", mean free path: " << 1./csvolume/mm << " mm" << G4endl;
536
537 delete StoichiometricFactors;
538 //return CS
539 return csvolume;
540}
std::vector< const G4Element * > G4ElementVector
bool G4bool
Definition G4Types.hh:86
G4VMaterialExtension * RetrieveExtension(const G4String &name)
const G4ElementVector * GetElementVector() const
G4double GetTotNbOfAtomsPerVolume() const
virtual G4bool IsExtended() const
const G4double * GetFractionVector() const
std::size_t GetNumberOfElements() const
const G4String & GetName() const
G4double Energy(const std::size_t index) const
static G4ProductionCutsTable * GetProductionCutsTable()
G4double LowEnergyLimit() const
virtual G4double CrossSectionPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)

◆ DumpFormFactorTable()

void G4PenelopeRayleighModelMI::DumpFormFactorTable ( const G4Material * mat)

Definition at line 1674 of file G4PenelopeRayleighModelMI.cc.

1675{
1676 G4cout << "*****************************************************************" << G4endl;
1677 G4cout << "G4PenelopeRayleighModelMI: Form Factor Table for " << mat->GetName() << G4endl;
1678 //try to use the same format as Penelope-Fortran, namely Q (/m_e*c) and F
1679 G4cout << "Q/(m_e*c) F(Q) " << G4endl;
1680 G4cout << "*****************************************************************" << G4endl;
1681 if (!fLogFormFactorTable->count(mat))
1682 BuildFormFactorTable(mat);
1683
1684 G4PhysicsFreeVector* theVec = fLogFormFactorTable->find(mat)->second;
1685 for (std::size_t i=0;i<theVec->GetVectorLength();++i)
1686 {
1687 G4double logQ2 = theVec->GetLowEdgeEnergy(i);
1688 G4double Q = G4Exp(0.5*logQ2);
1689 G4double logF2 = (*theVec)[i];
1690 G4double F = G4Exp(0.5*logF2);
1691 G4cout << Q << " " << F << G4endl;
1692 }
1693 //DONE
1694 return;
1695}
G4double GetLowEdgeEnergy(const std::size_t index) const
std::size_t GetVectorLength() const

◆ GetVerbosityLevel()

G4int G4PenelopeRayleighModelMI::GetVerbosityLevel ( )
inline

Definition at line 105 of file G4PenelopeRayleighModelMI.hh.

105{return fVerboseLevel;};

◆ Initialise()

void G4PenelopeRayleighModelMI::Initialise ( const G4ParticleDefinition * part,
const G4DataVector &  )
overridevirtual

Implements G4VEmModel.

Definition at line 180 of file G4PenelopeRayleighModelMI.cc.

182{
183 if (fVerboseLevel > 3)
184 G4cout << "Calling G4PenelopeRayleighModelMI::Initialise()" << G4endl;
185
186 SetParticle(part);
187
188 if (fVerboseLevel)
189 G4cout << "# Molecular Interference is " << (fIsMIActive ? "ON" : "OFF") << " #" << G4endl;
190
191 //Only the master model creates/fills/destroys the tables
192 if (IsMaster() && part == fParticle) {
193 //clear tables depending on materials, not the atomic ones
194 ClearTables();
195
196 //Use here the highest verbosity, from G4EmParameter or local
197 G4int globVerb = G4EmParameters::Instance()->Verbose();
198 if (globVerb > fVerboseLevel)
199 {
200 fVerboseLevel = globVerb;
201 if (fVerboseLevel)
202 G4cout << "Verbosity level of G4PenelopeRayleighModelMI set to " << fVerboseLevel <<
203 " from G4EmParameters()" << G4endl;
204 }
205 if (fVerboseLevel > 3)
206 G4cout << "Calling G4PenelopeRayleighModelMI::Initialise() [master]" << G4endl;
207
208 //Load the list of known materials and the DCS integration grid
209 if (fIsMIActive)
210 {
211 if (!fKnownMaterials)
212 fKnownMaterials = new std::map<G4String,G4String>;
213 if (!fKnownMaterials->size())
214 LoadKnownMIFFMaterials();
215 if (!fAngularFunction)
216 {
217 //Create and fill once
218 fAngularFunction = new G4PhysicsFreeVector(fNtheta);
219 CalculateThetaAndAngFun(); //angular funtion for DCS integration
220 }
221 }
222 if (fIsMIActive && !fMolInterferenceData)
223 fMolInterferenceData = new std::map<G4String,G4PhysicsFreeVector*>;
224 if (!fLogFormFactorTable)
225 fLogFormFactorTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
226 if (!fPMaxTable)
227 fPMaxTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
228 if (!fSamplingTable)
229 fSamplingTable = new std::map<const G4Material*,G4PenelopeSamplingData*>;
230
231 //loop on the used materials
233
234 for (G4int i=0;i<(G4int)theCoupleTable->GetTableSize();++i) {
235 const G4Material* material =
236 theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial();
237 const G4ElementVector* theElementVector = material->GetElementVector();
238
239 for (std::size_t j=0;j<material->GetNumberOfElements();++j) {
240 G4int iZ = theElementVector->at(j)->GetZasInt();
241 //read data files only in the master
242 if (!fLogAtomicCrossSection[iZ])
243 ReadDataFile(iZ);
244 }
245
246 //1) Read MI form factors
247 if (fIsMIActive && !fMolInterferenceData->count(material->GetName()))
248 ReadMolInterferenceData(material->GetName());
249
250 //2) If the table has not been built for the material, do it!
251 if (!fLogFormFactorTable->count(material))
252 BuildFormFactorTable(material);
253
254 //3) retrieve or build the sampling table
255 if (!(fSamplingTable->count(material)))
256 InitializeSamplingAlgorithm(material);
257
258 //4) retrieve or build the pMax data
259 if (!fPMaxTable->count(material))
260 GetPMaxTable(material);
261 }
262
263 if (fVerboseLevel > 1) {
264 G4cout << G4endl << "Penelope Rayleigh model v2008 is initialized" << G4endl
265 << "Energy range: "
266 << LowEnergyLimit() / keV << " keV - "
267 << HighEnergyLimit() / GeV << " GeV"
268 << G4endl;
269 }
270 }
271
272 if (fIsInitialised)
273 return;
274 fParticleChange = GetParticleChangeForGamma();
275 fIsInitialised = true;
276}
static G4EmParameters * Instance()
G4int Verbose() const
const G4Material * GetMaterial() const
const G4MaterialCutsCouple * GetMaterialCutsCouple(G4int i) const
std::size_t GetTableSize() const
G4ParticleChangeForGamma * GetParticleChangeForGamma()
G4double HighEnergyLimit() const

◆ InitialiseLocal()

void G4PenelopeRayleighModelMI::InitialiseLocal ( const G4ParticleDefinition * part,
G4VEmModel * masterModel )
overridevirtual

Reimplemented from G4VEmModel.

Definition at line 280 of file G4PenelopeRayleighModelMI.cc.

282{
283 if (fVerboseLevel > 3)
284 G4cout << "Calling G4PenelopeRayleighModelMI::InitialiseLocal()" << G4endl;
285
286 //Check that particle matches: one might have multiple master models
287 //(e.g. for e+ and e-)
288 if (part == fParticle) {
289
290 //Get the const table pointers from the master to the workers
291 const G4PenelopeRayleighModelMI* theModel =
292 static_cast<G4PenelopeRayleighModelMI*> (masterModel);
293
294 //Copy pointers to the data tables
295 for(G4int i=0; i<=fMaxZ; ++i)
296 {
297 fLogAtomicCrossSection[i] = theModel->fLogAtomicCrossSection[i];
298 fAtomicFormFactor[i] = theModel->fAtomicFormFactor[i];
299 }
300 fMolInterferenceData = theModel->fMolInterferenceData;
301 fLogFormFactorTable = theModel->fLogFormFactorTable;
302 fPMaxTable = theModel->fPMaxTable;
303 fSamplingTable = theModel->fSamplingTable;
304 fKnownMaterials = theModel->fKnownMaterials;
305 fAngularFunction = theModel->fAngularFunction;
306
307 //Copy the G4DataVector with the grid
308 fLogQSquareGrid = theModel->fLogQSquareGrid;
309
310 //Same verbosity for all workers, as the master
311 fVerboseLevel = theModel->fVerboseLevel;
312 }
313 return;
314}

◆ IsMIActive()

G4bool G4PenelopeRayleighModelMI::IsMIActive ( )
inline

Definition at line 112 of file G4PenelopeRayleighModelMI.hh.

112{return fIsMIActive;};

◆ operator=()

G4PenelopeRayleighModelMI & G4PenelopeRayleighModelMI::operator= ( const G4PenelopeRayleighModelMI & right)
delete

◆ SampleSecondaries()

void G4PenelopeRayleighModelMI::SampleSecondaries ( std::vector< G4DynamicParticle * > * ,
const G4MaterialCutsCouple * couple,
const G4DynamicParticle * aDynamicGamma,
G4double tmin,
G4double maxEnergy )
overridevirtual

Implements G4VEmModel.

Definition at line 710 of file G4PenelopeRayleighModelMI.cc.

715{
716 // Sampling of the Rayleigh final state (namely, scattering angle of the photon)
717 // from the Penelope2008 model. The scattering angle is sampled from the atomic
718 // cross section dOmega/d(cosTheta) from Born ("Atomic Phyisics", 1969), disregarding
719 // anomalous scattering effects. The Form Factor F(Q) function which appears in the
720 // analytical cross section is retrieved via the method GetFSquared(); atomic data
721 // are tabulated for F(Q). Form factor for compounds is calculated according to
722 // the additivity rule. The sampling from the F(Q) is made via a Rational Inverse
723 // Transform with Aliasing (RITA) algorithm; RITA parameters are calculated once
724 // for each material and managed by G4PenelopeSamplingData objects.
725 // The sampling algorithm (rejection method) has efficiency 67% at low energy, and
726 // increases with energy. For E=100 keV the efficiency is 100% and 86% for
727 // hydrogen and uranium, respectively.
728
729 if (fVerboseLevel > 3)
730 G4cout << "Calling SamplingSecondaries() of G4PenelopeRayleighModelMI" << G4endl;
731
732 G4double photonEnergy0 = aDynamicGamma->GetKineticEnergy();
733
734 if (photonEnergy0 <= fIntrinsicLowEnergyLimit) {
735 fParticleChange->ProposeTrackStatus(fStopAndKill);
736 fParticleChange->SetProposedKineticEnergy(0.);
737 fParticleChange->ProposeLocalEnergyDeposit(photonEnergy0);
738 return;
739 }
740
741 G4ParticleMomentum photonDirection0 = aDynamicGamma->GetMomentumDirection();
742 const G4Material* theMat = couple->GetMaterial();
743
744 //1) Verify if tables are ready
745 //Either Initialize() was not called, or we are in a slave and InitializeLocal() was
746 //not invoked
747 if (!fPMaxTable || !fSamplingTable || !fLogFormFactorTable) {
748 //create a **thread-local** version of the table. Used only for G4EmCalculator and
749 //Unit Tests
750 fLocalTable = true;
751 if (!fLogFormFactorTable)
752 fLogFormFactorTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
753 if (!fPMaxTable)
754 fPMaxTable = new std::map<const G4Material*,G4PhysicsFreeVector*>;
755 if (!fSamplingTable)
756 fSamplingTable = new std::map<const G4Material*,G4PenelopeSamplingData*>;
757 if (fIsMIActive && !fMolInterferenceData)
758 fMolInterferenceData = new std::map<G4String,G4PhysicsFreeVector*>;
759 }
760
761 if (!fSamplingTable->count(theMat)) {
762 //If we are here, it means that Initialize() was inkoved, but the MaterialTable was
763 //not filled up. This can happen in a UnitTest
764 if (fVerboseLevel > 0) {
765 //Issue a G4Exception (warning) only in verbose mode
767 ed << "Unable to find the fSamplingTable data for " <<
768 theMat->GetName() << G4endl;
769 ed << "This can happen only in Unit Tests" << G4endl;
770 G4Exception("G4PenelopeRayleighModelMI::SampleSecondaries()",
771 "em2019",JustWarning,ed);
772 }
773 const G4ElementVector* theElementVector = theMat->GetElementVector();
774 //protect file reading via autolock
775 G4AutoLock lock(&PenelopeRayleighModelMutex);
776 for (std::size_t j=0;j<theMat->GetNumberOfElements();++j) {
777 G4int iZ = theElementVector->at(j)->GetZasInt();
778 if (!fLogAtomicCrossSection[iZ]) {
779 lock.lock();
780 ReadDataFile(iZ);
781 lock.unlock();
782 }
783 }
784 lock.lock();
785
786 //1) If the table has not been built for the material, do it!
787 if (!fLogFormFactorTable->count(theMat))
788 BuildFormFactorTable(theMat);
789
790 //2) retrieve or build the sampling table
791 if (!(fSamplingTable->count(theMat)))
792 InitializeSamplingAlgorithm(theMat);
793
794 //3) retrieve or build the pMax data
795 if (!fPMaxTable->count(theMat))
796 GetPMaxTable(theMat);
797
798 lock.unlock();
799 }
800
801 //Ok, restart the job
802 G4PenelopeSamplingData* theDataTable = fSamplingTable->find(theMat)->second;
803 G4PhysicsFreeVector* thePMax = fPMaxTable->find(theMat)->second;
804 G4double cosTheta = 1.0;
805
806 //OK, ready to go!
807 G4double qmax = 2.0*photonEnergy0/electron_mass_c2; //this is non-dimensional now
808
809 if (qmax < 1e-10) { //very low momentum transfer
810 G4bool loopAgain=false;
811 do {
812 loopAgain = false;
813 cosTheta = 1.0-2.0*G4UniformRand();
814 G4double G = 0.5*(1+cosTheta*cosTheta);
815 if (G4UniformRand()>G)
816 loopAgain = true;
817 } while(loopAgain);
818 }
819 else { //larger momentum transfer
820 std::size_t nData = theDataTable->GetNumberOfStoredPoints();
821 G4double LastQ2inTheTable = theDataTable->GetX(nData-1);
822 G4double q2max = std::min(qmax*qmax,LastQ2inTheTable);
823
824 G4bool loopAgain = false;
825 G4double MaxPValue = thePMax->Value(photonEnergy0);
826 G4double xx=0;
827
828 //Sampling by rejection method. The rejection function is
829 //G = 0.5*(1+cos^2(theta))
830 do {
831 loopAgain = false;
832 G4double RandomMax = G4UniformRand()*MaxPValue;
833 xx = theDataTable->SampleValue(RandomMax);
834
835 //xx is a random value of q^2 in (0,q2max),sampled according to
836 //F(Q^2) via the RITA algorithm
837 if (xx > q2max)
838 loopAgain = true;
839 cosTheta = 1.0-2.0*xx/q2max;
840 G4double G = 0.5*(1+cosTheta*cosTheta);
841 if (G4UniformRand()>G)
842 loopAgain = true;
843 } while(loopAgain);
844 }
845
846 G4double sinTheta = std::sqrt(1-cosTheta*cosTheta);
847
848 //Scattered photon angles. ( Z - axis along the parent photon)
849 G4double phi = twopi * G4UniformRand() ;
850 G4double dirX = sinTheta*std::cos(phi);
851 G4double dirY = sinTheta*std::sin(phi);
852 G4double dirZ = cosTheta;
853
854 //Update G4VParticleChange for the scattered photon
855 G4ThreeVector photonDirection1(dirX, dirY, dirZ);
856
857 photonDirection1.rotateUz(photonDirection0);
858 fParticleChange->ProposeMomentumDirection(photonDirection1) ;
859 fParticleChange->SetProposedKineticEnergy(photonEnergy0) ;
860
861 return;
862}
@ fStopAndKill
#define G4UniformRand()
Definition Randomize.hh:52
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
G4double GetX(size_t index)
G4double SampleValue(G4double rndm)
void ProposeTrackStatus(G4TrackStatus status)
void ProposeLocalEnergyDeposit(G4double anEnergyPart)

◆ SetMIActive()

void G4PenelopeRayleighModelMI::SetMIActive ( G4bool val)
inline

Definition at line 111 of file G4PenelopeRayleighModelMI.hh.

111{fIsMIActive = val;};

◆ SetVerbosityLevel()

void G4PenelopeRayleighModelMI::SetVerbosityLevel ( G4int lev)
inline

Definition at line 104 of file G4PenelopeRayleighModelMI.hh.

104{fVerboseLevel = lev;};

The documentation for this class was generated from the following files: