File indexing completed on 2026-07-17 08:31:34
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
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075 #ifndef G4VEmModel_h
0076 #define G4VEmModel_h 1
0077
0078 #include "globals.hh"
0079 #include "G4DynamicParticle.hh"
0080 #include "G4ParticleDefinition.hh"
0081 #include "G4MaterialCutsCouple.hh"
0082 #include "G4Material.hh"
0083 #include "G4Element.hh"
0084 #include "G4ElementVector.hh"
0085 #include "G4Isotope.hh"
0086 #include "G4DataVector.hh"
0087 #include "G4VEmFluctuationModel.hh"
0088 #include "G4VEmAngularDistribution.hh"
0089 #include "G4EmElementSelector.hh"
0090 #include <CLHEP/Random/RandomEngine.h>
0091 #include <vector>
0092
0093 class G4ElementData;
0094 class G4PhysicsTable;
0095 class G4Region;
0096 class G4VParticleChange;
0097 class G4ParticleChangeForLoss;
0098 class G4ParticleChangeForGamma;
0099 class G4Track;
0100 class G4LossTableManager;
0101
0102 class G4VEmModel
0103 {
0104
0105 public:
0106
0107 explicit G4VEmModel(const G4String& nam);
0108
0109 virtual ~G4VEmModel();
0110
0111
0112
0113
0114
0115 virtual void Initialise(const G4ParticleDefinition*, const G4DataVector&) = 0;
0116
0117 virtual void SampleSecondaries(std::vector<G4DynamicParticle*>*,
0118 const G4MaterialCutsCouple*,
0119 const G4DynamicParticle*,
0120 G4double tmin = 0.0,
0121 G4double tmax = DBL_MAX) = 0;
0122
0123
0124
0125
0126
0127
0128 virtual void InitialiseLocal(const G4ParticleDefinition*,
0129 G4VEmModel* masterModel);
0130
0131
0132 virtual void InitialiseForMaterial(const G4ParticleDefinition*,
0133 const G4Material*);
0134
0135
0136 virtual void InitialiseForElement(const G4ParticleDefinition*,
0137 G4int Z);
0138
0139
0140
0141
0142
0143
0144 virtual G4double ComputeDEDXPerVolume(const G4Material*,
0145 const G4ParticleDefinition*,
0146 G4double kineticEnergy,
0147 G4double cutEnergy = DBL_MAX);
0148
0149
0150 virtual G4double CrossSectionPerVolume(const G4Material*,
0151 const G4ParticleDefinition*,
0152 G4double kineticEnergy,
0153 G4double cutEnergy = 0.0,
0154 G4double maxEnergy = DBL_MAX);
0155
0156
0157 virtual G4double GetPartialCrossSection(const G4Material*,
0158 G4int level,
0159 const G4ParticleDefinition*,
0160 G4double kineticEnergy);
0161
0162
0163 virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
0164 G4double kinEnergy,
0165 G4double Z,
0166 G4double A = 0.,
0167 G4double cutEnergy = 0.0,
0168 G4double maxEnergy = DBL_MAX);
0169
0170
0171 virtual G4double ComputeCrossSectionPerShell(const G4ParticleDefinition*,
0172 G4int Z, G4int shellIdx,
0173 G4double kinEnergy,
0174 G4double cutEnergy = 0.0,
0175 G4double maxEnergy = DBL_MAX);
0176
0177
0178 virtual G4double ChargeSquareRatio(const G4Track&);
0179
0180
0181 virtual G4double GetChargeSquareRatio(const G4ParticleDefinition*,
0182 const G4Material*,
0183 G4double kineticEnergy);
0184
0185
0186 virtual G4double GetParticleCharge(const G4ParticleDefinition*,
0187 const G4Material*,
0188 G4double kineticEnergy);
0189
0190
0191 virtual void StartTracking(G4Track*);
0192
0193
0194 virtual void CorrectionsAlongStep(const G4Material*,
0195 const G4ParticleDefinition*,
0196 const G4double kinEnergy,
0197 const G4double cutEnergy,
0198 const G4double& length,
0199 G4double& eloss);
0200
0201
0202 virtual G4double Value(const G4MaterialCutsCouple*,
0203 const G4ParticleDefinition*,
0204 G4double kineticEnergy);
0205
0206
0207 virtual G4double MinPrimaryEnergy(const G4Material*,
0208 const G4ParticleDefinition*,
0209 G4double cut = 0.0);
0210
0211
0212 virtual G4double MinEnergyCut(const G4ParticleDefinition*,
0213 const G4MaterialCutsCouple*);
0214
0215
0216 virtual void SetupForMaterial(const G4ParticleDefinition*,
0217 const G4Material*,
0218 G4double kineticEnergy);
0219
0220
0221 virtual void DefineForRegion(const G4Region*);
0222
0223
0224 virtual void FillNumberOfSecondaries(G4int& numberOfTriplets,
0225 G4int& numberOfRecoil);
0226
0227
0228 virtual void ModelDescription(std::ostream& outFile) const;
0229
0230 protected:
0231
0232
0233 G4ParticleChangeForLoss* GetParticleChangeForLoss();
0234
0235
0236 G4ParticleChangeForGamma* GetParticleChangeForGamma();
0237
0238
0239 virtual G4double MaxSecondaryEnergy(const G4ParticleDefinition*,
0240 G4double kineticEnergy);
0241
0242 public:
0243
0244
0245
0246
0247
0248
0249 void InitialiseElementSelectors(const G4ParticleDefinition*,
0250 const G4DataVector&);
0251
0252
0253 inline std::vector<G4EmElementSelector*>* GetElementSelectors();
0254
0255
0256 inline void SetElementSelectors(std::vector<G4EmElementSelector*>*);
0257
0258
0259 inline G4double ComputeDEDX( const G4MaterialCutsCouple*,
0260 const G4ParticleDefinition*,
0261 G4double kineticEnergy,
0262 G4double cutEnergy = DBL_MAX);
0263
0264
0265 inline G4double CrossSection(const G4MaterialCutsCouple*,
0266 const G4ParticleDefinition*,
0267 G4double kineticEnergy,
0268 G4double cutEnergy = 0.0,
0269 G4double maxEnergy = DBL_MAX);
0270
0271
0272 inline G4double ComputeMeanFreePath(const G4ParticleDefinition*,
0273 G4double kineticEnergy,
0274 const G4Material*,
0275 G4double cutEnergy = 0.0,
0276 G4double maxEnergy = DBL_MAX);
0277
0278
0279 inline G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
0280 const G4Element*,
0281 G4double kinEnergy,
0282 G4double cutEnergy = 0.0,
0283 G4double maxEnergy = DBL_MAX);
0284
0285
0286 inline const G4Element* SelectRandomAtom(const G4MaterialCutsCouple*,
0287 const G4ParticleDefinition*,
0288 G4double kineticEnergy,
0289 G4double cutEnergy = 0.0,
0290 G4double maxEnergy = DBL_MAX);
0291
0292 inline const G4Element* SelectTargetAtom(const G4MaterialCutsCouple*,
0293 const G4ParticleDefinition*,
0294 G4double kineticEnergy,
0295 G4double logKineticEnergy,
0296 G4double cutEnergy = 0.0,
0297 G4double maxEnergy = DBL_MAX);
0298
0299
0300 const G4Element* SelectRandomAtom(const G4Material*,
0301 const G4ParticleDefinition*,
0302 G4double kineticEnergy,
0303 G4double cutEnergy = 0.0,
0304 G4double maxEnergy = DBL_MAX);
0305
0306
0307 const G4Element* GetCurrentElement(const G4Material* mat = nullptr) const;
0308 G4int SelectRandomAtomNumber(const G4Material*) const;
0309
0310
0311 const G4Isotope* GetCurrentIsotope(const G4Element* elm = nullptr) const;
0312 G4int SelectIsotopeNumber(const G4Element*) const;
0313
0314
0315
0316
0317
0318 void SetParticleChange(G4VParticleChange*, G4VEmFluctuationModel* f=nullptr);
0319
0320 void SetCrossSectionTable(G4PhysicsTable*, G4bool isLocal);
0321
0322 inline G4ElementData* GetElementData();
0323
0324 inline G4PhysicsTable* GetCrossSectionTable();
0325
0326 inline G4VEmFluctuationModel* GetModelOfFluctuations();
0327
0328 inline G4VEmAngularDistribution* GetAngularDistribution();
0329
0330 inline G4VEmModel* GetTripletModel();
0331
0332 inline void SetTripletModel(G4VEmModel*);
0333
0334 inline void SetAngularDistribution(G4VEmAngularDistribution*);
0335
0336 inline G4double HighEnergyLimit() const;
0337
0338 inline G4double LowEnergyLimit() const;
0339
0340 inline G4double HighEnergyActivationLimit() const;
0341
0342 inline G4double LowEnergyActivationLimit() const;
0343
0344 inline G4double PolarAngleLimit() const;
0345
0346 inline G4double SecondaryThreshold() const;
0347
0348 inline G4bool DeexcitationFlag() const;
0349
0350 inline G4bool ForceBuildTableFlag() const;
0351
0352 inline G4bool UseAngularGeneratorFlag() const;
0353
0354 inline void SetAngularGeneratorFlag(G4bool);
0355
0356 inline void SetHighEnergyLimit(G4double);
0357
0358 inline void SetLowEnergyLimit(G4double);
0359
0360 inline void SetActivationHighEnergyLimit(G4double);
0361
0362 inline void SetActivationLowEnergyLimit(G4double);
0363
0364 inline G4bool IsActive(G4double kinEnergy) const;
0365
0366 inline void SetPolarAngleLimit(G4double);
0367
0368 inline void SetSecondaryThreshold(G4double);
0369
0370 inline void SetDeexcitationFlag(G4bool val);
0371
0372 inline void SetForceBuildTable(G4bool val);
0373
0374 inline void SetFluctuationFlag(G4bool val);
0375
0376 inline G4bool IsMaster() const;
0377
0378 inline void SetUseBaseMaterials(G4bool val);
0379
0380 inline G4bool UseBaseMaterials() const;
0381
0382 inline G4double MaxSecondaryKinEnergy(const G4DynamicParticle* dynParticle);
0383
0384 inline const G4String& GetName() const;
0385
0386 inline void SetCurrentCouple(const G4MaterialCutsCouple*);
0387
0388 inline G4bool IsLocked() const;
0389
0390 inline void SetLocked(G4bool);
0391
0392
0393 [[deprecated("Use G4EmParameters::Instance()->SetLPM instead")]]
0394 void SetLPMFlag(G4bool);
0395
0396 void SetMasterThread(G4bool);
0397
0398
0399 G4VEmModel & operator=(const G4VEmModel &right) = delete;
0400 G4VEmModel(const G4VEmModel&) = delete;
0401
0402 protected:
0403
0404 inline const G4MaterialCutsCouple* CurrentCouple() const;
0405
0406 inline void SetCurrentElement(const G4Element*);
0407
0408 private:
0409
0410
0411
0412 G4VEmFluctuationModel* flucModel = nullptr;
0413 G4VEmAngularDistribution* anglModel = nullptr;
0414 G4VEmModel* fTripletModel = nullptr;
0415 const G4MaterialCutsCouple* fCurrentCouple = nullptr;
0416 const G4Element* fCurrentElement = nullptr;
0417 std::vector<G4EmElementSelector*>* elmSelectors = nullptr;
0418 G4LossTableManager* fEmManager;
0419
0420 protected:
0421
0422 G4ElementData* fElementData = nullptr;
0423 G4VParticleChange* pParticleChange = nullptr;
0424 G4PhysicsTable* xSectionTable = nullptr;
0425 const G4Material* pBaseMaterial = nullptr;
0426 const std::vector<G4double>* theDensityFactor = nullptr;
0427 const std::vector<G4int>* theDensityIdx = nullptr;
0428
0429 G4double inveplus;
0430 G4double pFactor = 1.0;
0431
0432 private:
0433
0434 G4double lowLimit;
0435 G4double highLimit;
0436 G4double eMinActive = 0.0;
0437 G4double eMaxActive = DBL_MAX;
0438 G4double secondaryThreshold = DBL_MAX;
0439 G4double polarAngleLimit;
0440
0441 G4int nSelectors = 0;
0442 G4int nsec = 5;
0443
0444 protected:
0445
0446 std::size_t currentCoupleIndex = 0;
0447 std::size_t basedCoupleIndex = 0;
0448 G4bool lossFlucFlag = true;
0449
0450 private:
0451
0452 G4bool flagDeexcitation = false;
0453 G4bool flagForceBuildTable = false;
0454 G4bool isMaster = true;
0455
0456 G4bool localTable = true;
0457 G4bool localElmSelectors = true;
0458 G4bool useAngularGenerator = false;
0459 G4bool useBaseMaterials = false;
0460 G4bool isLocked = false;
0461 G4bool localChange = false;
0462
0463 const G4String name;
0464 std::vector<G4double> xsec;
0465
0466 };
0467
0468
0469
0470 inline void G4VEmModel::SetCurrentCouple(const G4MaterialCutsCouple* ptr)
0471 {
0472 if(fCurrentCouple != ptr) {
0473 fCurrentCouple = ptr;
0474 basedCoupleIndex = currentCoupleIndex = ptr->GetIndex();
0475 pBaseMaterial = ptr->GetMaterial();
0476 pFactor = 1.0;
0477 if(useBaseMaterials) {
0478 basedCoupleIndex = (*theDensityIdx)[currentCoupleIndex];
0479 if(nullptr != pBaseMaterial->GetBaseMaterial())
0480 pBaseMaterial = pBaseMaterial->GetBaseMaterial();
0481 pFactor = (*theDensityFactor)[currentCoupleIndex];
0482 }
0483 }
0484 }
0485
0486
0487
0488 inline const G4MaterialCutsCouple* G4VEmModel::CurrentCouple() const
0489 {
0490 return fCurrentCouple;
0491 }
0492
0493
0494
0495 inline void G4VEmModel::SetCurrentElement(const G4Element* elm)
0496 {
0497 fCurrentElement = elm;
0498 }
0499
0500
0501
0502 inline
0503 G4double G4VEmModel::MaxSecondaryKinEnergy(const G4DynamicParticle* dynPart)
0504 {
0505 return MaxSecondaryEnergy(dynPart->GetParticleDefinition(),
0506 dynPart->GetKineticEnergy());
0507 }
0508
0509
0510
0511 inline G4double G4VEmModel::ComputeDEDX(const G4MaterialCutsCouple* couple,
0512 const G4ParticleDefinition* part,
0513 G4double kinEnergy,
0514 G4double cutEnergy)
0515 {
0516 SetCurrentCouple(couple);
0517 return pFactor*ComputeDEDXPerVolume(pBaseMaterial,part,kinEnergy,cutEnergy);
0518 }
0519
0520
0521
0522 inline G4double G4VEmModel::CrossSection(const G4MaterialCutsCouple* couple,
0523 const G4ParticleDefinition* part,
0524 G4double kinEnergy,
0525 G4double cutEnergy,
0526 G4double maxEnergy)
0527 {
0528 SetCurrentCouple(couple);
0529 return pFactor*CrossSectionPerVolume(pBaseMaterial,part,kinEnergy,
0530 cutEnergy,maxEnergy);
0531 }
0532
0533
0534
0535 inline
0536 G4double G4VEmModel::ComputeMeanFreePath(const G4ParticleDefinition* part,
0537 G4double ekin,
0538 const G4Material* material,
0539 G4double emin,
0540 G4double emax)
0541 {
0542 G4double cross = CrossSectionPerVolume(material,part,ekin,emin,emax);
0543 return (cross > 0.0) ? 1./cross : DBL_MAX;
0544 }
0545
0546
0547
0548 inline G4double
0549 G4VEmModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition* part,
0550 const G4Element* elm,
0551 G4double kinEnergy,
0552 G4double cutEnergy,
0553 G4double maxEnergy)
0554 {
0555 fCurrentElement = elm;
0556 return ComputeCrossSectionPerAtom(part,kinEnergy,elm->GetZ(),elm->GetN(),
0557 cutEnergy,maxEnergy);
0558 }
0559
0560
0561
0562 inline const G4Element*
0563 G4VEmModel::SelectRandomAtom(const G4MaterialCutsCouple* couple,
0564 const G4ParticleDefinition* part,
0565 G4double kinEnergy,
0566 G4double cutEnergy,
0567 G4double maxEnergy)
0568 {
0569 SetCurrentCouple(couple);
0570 fCurrentElement = (nSelectors > 0) ?
0571 ((*elmSelectors)[couple->GetIndex()])->SelectRandomAtom(kinEnergy) :
0572 SelectRandomAtom(pBaseMaterial,part,kinEnergy,cutEnergy,maxEnergy);
0573 return fCurrentElement;
0574 }
0575
0576
0577
0578 inline const G4Element*
0579 G4VEmModel::SelectTargetAtom(const G4MaterialCutsCouple* couple,
0580 const G4ParticleDefinition* part,
0581 G4double kinEnergy,
0582 G4double logKinE,
0583 G4double cutEnergy,
0584 G4double maxEnergy)
0585 {
0586 SetCurrentCouple(couple);
0587 fCurrentElement = (nSelectors > 0)
0588 ? ((*elmSelectors)[couple->GetIndex()])->SelectRandomAtom(kinEnergy,logKinE)
0589 : SelectRandomAtom(pBaseMaterial,part,kinEnergy,cutEnergy,maxEnergy);
0590 return fCurrentElement;
0591 }
0592
0593
0594
0595 inline G4VEmFluctuationModel* G4VEmModel::GetModelOfFluctuations()
0596 {
0597 return flucModel;
0598 }
0599
0600
0601
0602 inline G4VEmAngularDistribution* G4VEmModel::GetAngularDistribution()
0603 {
0604 return anglModel;
0605 }
0606
0607
0608
0609 inline void G4VEmModel::SetAngularDistribution(G4VEmAngularDistribution* p)
0610 {
0611 if(p != anglModel) {
0612 delete anglModel;
0613 anglModel = p;
0614 }
0615 }
0616
0617
0618
0619 inline G4VEmModel* G4VEmModel::GetTripletModel()
0620 {
0621 return fTripletModel;
0622 }
0623
0624
0625
0626 inline void G4VEmModel::SetTripletModel(G4VEmModel* p)
0627 {
0628 if(p != fTripletModel) {
0629 delete fTripletModel;
0630 fTripletModel = p;
0631 }
0632 }
0633
0634
0635
0636 inline G4double G4VEmModel::HighEnergyLimit() const
0637 {
0638 return highLimit;
0639 }
0640
0641
0642
0643 inline G4double G4VEmModel::LowEnergyLimit() const
0644 {
0645 return lowLimit;
0646 }
0647
0648
0649
0650 inline G4double G4VEmModel::HighEnergyActivationLimit() const
0651 {
0652 return eMaxActive;
0653 }
0654
0655
0656
0657 inline G4double G4VEmModel::LowEnergyActivationLimit() const
0658 {
0659 return eMinActive;
0660 }
0661
0662
0663
0664 inline G4double G4VEmModel::PolarAngleLimit() const
0665 {
0666 return polarAngleLimit;
0667 }
0668
0669
0670
0671 inline G4double G4VEmModel::SecondaryThreshold() const
0672 {
0673 return secondaryThreshold;
0674 }
0675
0676
0677
0678 inline G4bool G4VEmModel::DeexcitationFlag() const
0679 {
0680 return flagDeexcitation;
0681 }
0682
0683
0684
0685 inline G4bool G4VEmModel::ForceBuildTableFlag() const
0686 {
0687 return flagForceBuildTable;
0688 }
0689
0690
0691
0692 inline G4bool G4VEmModel::UseAngularGeneratorFlag() const
0693 {
0694 return useAngularGenerator;
0695 }
0696
0697
0698
0699 inline void G4VEmModel::SetAngularGeneratorFlag(G4bool val)
0700 {
0701 useAngularGenerator = val;
0702 }
0703
0704
0705
0706 inline void G4VEmModel::SetFluctuationFlag(G4bool val)
0707 {
0708 lossFlucFlag = val;
0709 }
0710
0711
0712
0713 inline G4bool G4VEmModel::IsMaster() const
0714 {
0715 return isMaster;
0716 }
0717
0718
0719
0720 inline void G4VEmModel::SetUseBaseMaterials(G4bool val)
0721 {
0722 useBaseMaterials = val;
0723 }
0724
0725
0726
0727 inline G4bool G4VEmModel::UseBaseMaterials() const
0728 {
0729 return useBaseMaterials;
0730 }
0731
0732
0733
0734 inline void G4VEmModel::SetHighEnergyLimit(G4double val)
0735 {
0736 highLimit = val;
0737 }
0738
0739
0740
0741 inline void G4VEmModel::SetLowEnergyLimit(G4double val)
0742 {
0743 lowLimit = val;
0744 }
0745
0746
0747
0748 inline void G4VEmModel::SetActivationHighEnergyLimit(G4double val)
0749 {
0750 eMaxActive = val;
0751 }
0752
0753
0754
0755 inline void G4VEmModel::SetActivationLowEnergyLimit(G4double val)
0756 {
0757 eMinActive = val;
0758 }
0759
0760
0761
0762 inline G4bool G4VEmModel::IsActive(G4double kinEnergy) const
0763 {
0764 return (kinEnergy >= eMinActive && kinEnergy <= eMaxActive);
0765 }
0766
0767
0768
0769 inline void G4VEmModel::SetPolarAngleLimit(G4double val)
0770 {
0771 if(!isLocked) { polarAngleLimit = val; }
0772 }
0773
0774
0775
0776 inline void G4VEmModel::SetSecondaryThreshold(G4double val)
0777 {
0778 secondaryThreshold = val;
0779 }
0780
0781
0782
0783 inline void G4VEmModel::SetDeexcitationFlag(G4bool val)
0784 {
0785 flagDeexcitation = val;
0786 }
0787
0788
0789
0790 inline void G4VEmModel::SetForceBuildTable(G4bool val)
0791 {
0792 flagForceBuildTable = val;
0793 }
0794
0795
0796
0797 inline const G4String& G4VEmModel::GetName() const
0798 {
0799 return name;
0800 }
0801
0802
0803
0804 inline std::vector<G4EmElementSelector*>* G4VEmModel::GetElementSelectors()
0805 {
0806 return elmSelectors;
0807 }
0808
0809
0810
0811 inline void
0812 G4VEmModel::SetElementSelectors(std::vector<G4EmElementSelector*>* p)
0813 {
0814 if(p != elmSelectors) {
0815 elmSelectors = p;
0816 nSelectors = (nullptr != elmSelectors) ? G4int(elmSelectors->size()) : 0;
0817 localElmSelectors = false;
0818 }
0819 }
0820
0821
0822
0823 inline G4ElementData* G4VEmModel::GetElementData()
0824 {
0825 return fElementData;
0826 }
0827
0828
0829
0830 inline G4PhysicsTable* G4VEmModel::GetCrossSectionTable()
0831 {
0832 return xSectionTable;
0833 }
0834
0835
0836
0837 inline G4bool G4VEmModel::IsLocked() const
0838 {
0839 return isLocked;
0840 }
0841
0842
0843
0844 inline void G4VEmModel::SetLocked(G4bool val)
0845 {
0846 isLocked = val;
0847 }
0848
0849
0850
0851 #endif