File indexing completed on 2025-01-31 09:22:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 #include "G4LowEnergyPhotoElectric.hh"
0066
0067 #include "G4RDVPhotoElectricAngularDistribution.hh"
0068 #include "G4RDPhotoElectricAngularGeneratorSimple.hh"
0069 #include "G4RDPhotoElectricAngularGeneratorSauterGavrila.hh"
0070 #include "G4RDPhotoElectricAngularGeneratorPolarized.hh"
0071
0072 #include "G4PhysicalConstants.hh"
0073 #include "G4SystemOfUnits.hh"
0074 #include "G4ParticleDefinition.hh"
0075 #include "G4Track.hh"
0076 #include "G4Step.hh"
0077 #include "G4ForceCondition.hh"
0078 #include "G4Gamma.hh"
0079 #include "G4Electron.hh"
0080 #include "G4DynamicParticle.hh"
0081 #include "G4VParticleChange.hh"
0082 #include "G4ThreeVector.hh"
0083 #include "G4RDVCrossSectionHandler.hh"
0084 #include "G4RDCrossSectionHandler.hh"
0085 #include "G4RDVEMDataSet.hh"
0086 #include "G4RDCompositeEMDataSet.hh"
0087 #include "G4RDVDataSetAlgorithm.hh"
0088 #include "G4RDLogLogInterpolation.hh"
0089 #include "G4RDVRangeTest.hh"
0090 #include "G4RDRangeNoTest.hh"
0091 #include "G4RDAtomicTransitionManager.hh"
0092 #include "G4RDAtomicShell.hh"
0093 #include "G4ProductionCutsTable.hh"
0094
0095 G4LowEnergyPhotoElectric::G4LowEnergyPhotoElectric(const G4String& processName)
0096 : G4VDiscreteProcess(processName), lowEnergyLimit(250*eV), highEnergyLimit(100*GeV),
0097 intrinsicLowEnergyLimit(10*eV),
0098 intrinsicHighEnergyLimit(100*GeV),
0099 cutForLowEnergySecondaryPhotons(250.*eV),
0100 cutForLowEnergySecondaryElectrons(250.*eV)
0101 {
0102 if (lowEnergyLimit < intrinsicLowEnergyLimit ||
0103 highEnergyLimit > intrinsicHighEnergyLimit)
0104 {
0105 G4Exception("G4LowEnergyPhotoElectric::G4LowEnergyPhotoElectric()",
0106 "OutOfRange", FatalException,
0107 "Energy limit outside intrinsic process validity range!");
0108 }
0109
0110 crossSectionHandler = new G4RDCrossSectionHandler();
0111 shellCrossSectionHandler = new G4RDCrossSectionHandler();
0112 meanFreePathTable = 0;
0113 rangeTest = new G4RDRangeNoTest;
0114 generatorName = "geant4.6.2";
0115 ElectronAngularGenerator = new G4RDPhotoElectricAngularGeneratorSimple("GEANTSimpleGenerator");
0116
0117
0118 if (verboseLevel > 0)
0119 {
0120 G4cout << GetProcessName() << " is created " << G4endl
0121 << "Energy range: "
0122 << lowEnergyLimit / keV << " keV - "
0123 << highEnergyLimit / GeV << " GeV"
0124 << G4endl;
0125 }
0126 }
0127
0128 G4LowEnergyPhotoElectric::~G4LowEnergyPhotoElectric()
0129 {
0130 delete crossSectionHandler;
0131 delete shellCrossSectionHandler;
0132 delete meanFreePathTable;
0133 delete rangeTest;
0134 delete ElectronAngularGenerator;
0135 }
0136
0137 void G4LowEnergyPhotoElectric::BuildPhysicsTable(const G4ParticleDefinition& )
0138 {
0139
0140 crossSectionHandler->Clear();
0141 G4String crossSectionFile = "phot/pe-cs-";
0142 crossSectionHandler->LoadData(crossSectionFile);
0143
0144 shellCrossSectionHandler->Clear();
0145 G4String shellCrossSectionFile = "phot/pe-ss-cs-";
0146 shellCrossSectionHandler->LoadShellData(shellCrossSectionFile);
0147
0148 delete meanFreePathTable;
0149 meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
0150 }
0151
0152 G4VParticleChange* G4LowEnergyPhotoElectric::PostStepDoIt(const G4Track& aTrack,
0153 const G4Step& aStep)
0154 {
0155
0156
0157
0158
0159
0160 aParticleChange.Initialize(aTrack);
0161
0162 const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
0163 G4double photonEnergy = incidentPhoton->GetKineticEnergy();
0164 if (photonEnergy <= lowEnergyLimit)
0165 {
0166 aParticleChange.ProposeTrackStatus(fStopAndKill);
0167 aParticleChange.ProposeEnergy(0.);
0168 aParticleChange.ProposeLocalEnergyDeposit(photonEnergy);
0169 return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
0170 }
0171
0172 G4ThreeVector photonDirection = incidentPhoton->GetMomentumDirection();
0173
0174
0175 const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
0176 G4int Z = crossSectionHandler->SelectRandomAtom(couple,photonEnergy);
0177
0178
0179 size_t shellIndex = shellCrossSectionHandler->SelectRandomShell(Z,photonEnergy);
0180
0181
0182 const G4RDAtomicTransitionManager* transitionManager = G4RDAtomicTransitionManager::Instance();
0183 const G4RDAtomicShell* shell = transitionManager->Shell(Z,shellIndex);
0184 G4double bindingEnergy = shell->BindingEnergy();
0185 G4int shellId = shell->ShellId();
0186
0187
0188
0189 std::vector<G4DynamicParticle*>* photonVector = 0;
0190 std::vector<G4DynamicParticle*> electronVector;
0191
0192 G4double energyDeposit = 0.0;
0193
0194
0195 G4double eKineticEnergy = photonEnergy - bindingEnergy;
0196
0197
0198
0199 if (eKineticEnergy > 0.)
0200 {
0201
0202 G4double safety = aStep.GetPostStepPoint()->GetSafety();
0203
0204 if (rangeTest->Escape(G4Electron::Electron(),couple,eKineticEnergy,safety))
0205 {
0206
0207
0208 G4ThreeVector gammaPolarization = incidentPhoton->GetPolarization();
0209 G4ThreeVector electronDirection = ElectronAngularGenerator->GetPhotoElectronDirection(photonDirection,eKineticEnergy,gammaPolarization,shellId);
0210
0211
0212 G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),
0213 electronDirection,
0214 eKineticEnergy);
0215 electronVector.push_back(electron);
0216 }
0217 else
0218 {
0219 energyDeposit += eKineticEnergy;
0220 }
0221 }
0222 else
0223 {
0224 bindingEnergy = photonEnergy;
0225 }
0226
0227 G4int nElectrons = electronVector.size();
0228 size_t nTotPhotons = 0;
0229 G4int nPhotons=0;
0230 const G4ProductionCutsTable* theCoupleTable=
0231 G4ProductionCutsTable::GetProductionCutsTable();
0232
0233 size_t index = couple->GetIndex();
0234 G4double cutg = (*(theCoupleTable->GetEnergyCutsVector(0)))[index];
0235 cutg = std::min(cutForLowEnergySecondaryPhotons,cutg);
0236
0237 G4double cute = (*(theCoupleTable->GetEnergyCutsVector(1)))[index];
0238 cute = std::min(cutForLowEnergySecondaryPhotons,cute);
0239
0240 G4DynamicParticle* aPhoton;
0241
0242
0243
0244
0245
0246 if (Z > 5 && (bindingEnergy > cutg || bindingEnergy > cute))
0247 {
0248 photonVector = deexcitationManager.GenerateParticles(Z,shellId);
0249 nTotPhotons = photonVector->size();
0250 for (size_t k=0; k<nTotPhotons; k++)
0251 {
0252 aPhoton = (*photonVector)[k];
0253 if (aPhoton)
0254 {
0255 G4double itsCut = cutg;
0256 if(aPhoton->GetDefinition() == G4Electron::Electron()) itsCut = cute;
0257 G4double itsEnergy = aPhoton->GetKineticEnergy();
0258
0259 if (itsEnergy > itsCut && itsEnergy <= bindingEnergy)
0260 {
0261 nPhotons++;
0262
0263
0264
0265 bindingEnergy -= itsEnergy;
0266
0267 }
0268 else
0269 {
0270 delete aPhoton;
0271 (*photonVector)[k] = 0;
0272 }
0273 }
0274 }
0275 }
0276
0277 energyDeposit += bindingEnergy;
0278
0279 G4int nSecondaries = nElectrons + nPhotons;
0280 aParticleChange.SetNumberOfSecondaries(nSecondaries);
0281
0282 for (G4int l = 0; l<nElectrons; l++ )
0283 {
0284 aPhoton = electronVector[l];
0285 if(aPhoton) {
0286 aParticleChange.AddSecondary(aPhoton);
0287 }
0288 }
0289 for ( size_t ll = 0; ll < nTotPhotons; ll++)
0290 {
0291 aPhoton = (*photonVector)[ll];
0292 if(aPhoton) {
0293 aParticleChange.AddSecondary(aPhoton);
0294 }
0295 }
0296
0297 delete photonVector;
0298
0299 if (energyDeposit < 0)
0300 {
0301 G4cout << "WARNING - "
0302 << "G4LowEnergyPhotoElectric::PostStepDoIt - Negative energy deposit"
0303 << G4endl;
0304 energyDeposit = 0;
0305 }
0306
0307
0308 aParticleChange.ProposeMomentumDirection( 0., 0., 0. );
0309 aParticleChange.ProposeEnergy( 0. );
0310
0311 aParticleChange.ProposeLocalEnergyDeposit(energyDeposit);
0312 aParticleChange.ProposeTrackStatus( fStopAndKill );
0313
0314
0315 return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep );
0316 }
0317
0318 G4bool G4LowEnergyPhotoElectric::IsApplicable(const G4ParticleDefinition& particle)
0319 {
0320 return ( &particle == G4Gamma::Gamma() );
0321 }
0322
0323 G4double G4LowEnergyPhotoElectric::GetMeanFreePath(const G4Track& track,
0324 G4double,
0325 G4ForceCondition*)
0326 {
0327 const G4DynamicParticle* photon = track.GetDynamicParticle();
0328 G4double energy = photon->GetKineticEnergy();
0329 G4Material* material = track.GetMaterial();
0330
0331
0332 G4double meanFreePath = DBL_MAX;
0333
0334
0335
0336
0337
0338
0339 G4double cross = shellCrossSectionHandler->ValueForMaterial(material,energy);
0340 if(cross > 0.0) meanFreePath = 1.0/cross;
0341
0342 return meanFreePath;
0343 }
0344
0345 void G4LowEnergyPhotoElectric::SetCutForLowEnSecPhotons(G4double cut)
0346 {
0347 cutForLowEnergySecondaryPhotons = cut;
0348 deexcitationManager.SetCutForSecondaryPhotons(cut);
0349 }
0350
0351 void G4LowEnergyPhotoElectric::SetCutForLowEnSecElectrons(G4double cut)
0352 {
0353 cutForLowEnergySecondaryElectrons = cut;
0354 deexcitationManager.SetCutForAugerElectrons(cut);
0355 }
0356
0357 void G4LowEnergyPhotoElectric::ActivateAuger(G4bool val)
0358 {
0359 deexcitationManager.ActivateAugerElectronProduction(val);
0360 }
0361
0362 void G4LowEnergyPhotoElectric::SetAngularGenerator(G4RDVPhotoElectricAngularDistribution* distribution)
0363 {
0364 ElectronAngularGenerator = distribution;
0365 ElectronAngularGenerator->PrintGeneratorInformation();
0366 }
0367
0368 void G4LowEnergyPhotoElectric::SetAngularGenerator(const G4String& name)
0369 {
0370 if (name == "default")
0371 {
0372 delete ElectronAngularGenerator;
0373 ElectronAngularGenerator = new G4RDPhotoElectricAngularGeneratorSimple("GEANT4LowEnergySimpleGenerator");
0374 generatorName = name;
0375 }
0376 else if (name == "standard")
0377 {
0378 delete ElectronAngularGenerator;
0379 ElectronAngularGenerator = new G4RDPhotoElectricAngularGeneratorSauterGavrila("GEANT4SauterGavrilaGenerator");
0380 generatorName = name;
0381 }
0382 else if (name == "polarized")
0383 {
0384 delete ElectronAngularGenerator;
0385 ElectronAngularGenerator = new G4RDPhotoElectricAngularGeneratorPolarized("GEANT4LowEnergyPolarizedGenerator");
0386 generatorName = name;
0387 }
0388 else
0389 {
0390 G4Exception("G4LowEnergyPhotoElectric::SetAngularGenerator()",
0391 "InvalidSetup", FatalException,
0392 "Generator does not exist!");
0393 }
0394
0395 ElectronAngularGenerator->PrintGeneratorInformation();
0396 }