19#include "BDSPhysicsVectorLinear.hh"
20#include "BDSWrapperMuonSplitting.hh"
22#include "G4ParticleDefinition.hh"
25#include "G4VParticleChange.hh"
26#include "G4VProcess.hh"
34BDSWrapperMuonSplitting::BDSWrapperMuonSplitting(G4VProcess* originalProcess,
35 G4int splittingFactorIn,
36 G4double splittingThresholdEKIn,
37 G4int splittingFactor2In,
38 G4double splittingThresholdEK2In,
39 G4bool excludeWeight1ParticlesIn,
40 G4double muonSplittingExclusionWeightIn):
42 splittingFactor(splittingFactorIn),
43 splittingThresholdEK(splittingThresholdEKIn),
44 splittingFactor2(splittingFactor2In),
45 splittingThresholdEK2(splittingThresholdEK2In),
46 excludeWeight1Particles(excludeWeight1ParticlesIn),
47 muonSplittingExclusionWeight(muonSplittingExclusionWeightIn),
50 RegisterProcess(originalProcess);
51 theProcessSubType = originalProcess->GetProcessSubType();
52 theProcessName =
"MuonSplittingWrapper("+originalProcess->GetProcessName()+
")";
53 if (splittingFactor2 < splittingFactor)
54 {splittingFactor2 = splittingFactor;}
55 if (splittingThresholdEK2 < splittingThresholdEK)
56 {splittingThresholdEK2 = splittingThresholdEK;}
58 std::vector<G4double> eK = {0.8*splittingThresholdEK, splittingThresholdEK};
59 std::vector<G4double> va = {2.0,
static_cast<G4double
>(splittingFactorIn)};
60 if (splittingThresholdEK2 > splittingThresholdEK)
62 eK.push_back(splittingThresholdEK2);
63 va.push_back((G4double)splittingFactor2In);
68BDSWrapperMuonSplitting::~BDSWrapperMuonSplitting()
76 G4VParticleChange* particleChange = pRegProcess->PostStepDoIt(track, step);
78 if (splittingFactor == 1)
79 {
return particleChange;}
81 G4double parentEk = track.GetKineticEnergy();
82 if (parentEk < 0.8*splittingThresholdEK)
83 {
return particleChange;}
85 G4int nSecondaries = particleChange->GetNumberOfSecondaries();
86 if (nSecondaries == 0)
87 {
return particleChange;}
90 if (excludeWeight1Particles && std::abs(track.GetWeight() - 1.0) > std::numeric_limits<double>::epsilon())
91 {
return particleChange;}
93 if (track.GetWeight() > muonSplittingExclusionWeight)
94 {
return particleChange;}
96 G4bool muonPresent =
false;
97 std::vector<G4int> secondaryPDGIDs;
98 for (G4int i = 0; i < nSecondaries; i++)
100 G4int secondaryPDGID = particleChange->GetSecondary(i)->GetDefinition()->GetPDGEncoding();
101 muonPresent = std::abs(secondaryPDGID) == 13 || muonPresent;
104 {
return particleChange;}
107 std::vector<G4Track*> originalSecondaries;
108 std::vector<G4Track*> originalMuons;
109 for (G4int i = 0; i < nSecondaries; i++)
111 G4Track* secondary = particleChange->GetSecondary(i);
112 if (std::abs(secondary->GetDefinition()->GetPDGEncoding()) != 13)
113 {originalSecondaries.push_back(secondary);}
115 {originalMuons.push_back(secondary);}
118 G4int nOriginalSecondaries = nSecondaries;
120 particleChange->Clear();
122 G4double spf2 = splitting->
Value(parentEk);
123 G4int thisTimeSplittingFactor =
static_cast<G4int
>(std::round(spf2));
127 G4int maxTrials = 10 * thisTimeSplittingFactor;
128 G4int nSuccessfulMuonSplits = 0;
130 std::vector<G4Track*> newMuons;
131 while (iTry < maxTrials && nSuccessfulMuonSplits < thisTimeSplittingFactor-1)
134 particleChange->Clear();
135 particleChange = pRegProcess->PostStepDoIt(track, step);
136 G4bool success =
false;
137 for (G4int i = 0; i < particleChange->GetNumberOfSecondaries(); i++)
139 G4Track* sec = particleChange->GetSecondary(i);
140 if (std::abs(sec->GetDefinition()->GetPDGEncoding()) == 13)
142 newMuons.push_back(sec);
148 particleChange->Clear();
150 {nSuccessfulMuonSplits++;}
153 particleChange->Clear();
154 particleChange->SetNumberOfSecondaries(nOriginalSecondaries +
static_cast<G4int
>(newMuons.size()));
155 particleChange->SetSecondaryWeightByProcess(
true);
156 if (nSuccessfulMuonSplits == 0)
158 for (
auto secondary : originalSecondaries)
159 {particleChange->AddSecondary(secondary);}
160 for (
auto muon : originalMuons)
161 {particleChange->AddSecondary(muon);}
162 return particleChange;
166 G4double weightFactor = 1.0 / (
static_cast<G4double
>(nSuccessfulMuonSplits) + 1.0);
168 for (
auto aSecondary : originalSecondaries)
169 {particleChange->AddSecondary(aSecondary);}
170 for (
auto originalMuon : originalMuons)
172 G4double existingWeight = originalMuon->GetWeight();
173 G4double newWeight = existingWeight * weightFactor;
174 originalMuon->SetWeight(newWeight);
175 particleChange->AddSecondary(originalMuon);
177 for (
auto newMuon : newMuons)
179 G4double existingWeight = newMuon->GetWeight();
180 G4double newWeight = existingWeight * weightFactor;
181 newMuon->SetWeight(newWeight);
182 particleChange->AddSecondary(newMuon);
185 return particleChange;
A vector of some values vs Ek that are linearly interpolated.
G4double Value(G4double eK) const
Get the linearly interpolated value for a given kinetic energy.
static G4int nCallsThisEvent
Counter for understanding occurence.
virtual G4VParticleChange * PostStepDoIt(const G4Track &track, const G4Step &step)
Do the splitting operation.