47{
48
50
51
52 if ( wrappedProcessParticleChange->GetNumberOfSecondaries() == 0 ) return wrappedProcessParticleChange;
53 if ( wrappedProcessParticleChange->GetTrackStatus() ==
fKillTrackAndSecondaries )
return wrappedProcessParticleChange;
54
55 std::vector < G4Track* > secondariesAndPrimary;
56 for ( auto i = 0 ; i < wrappedProcessParticleChange->GetNumberOfSecondaries() ; i++ ) secondariesAndPrimary.push_back( wrappedProcessParticleChange->GetSecondary( i ) );
57
58
59
60
61
62
63
64
65
67 G4Track* finalStatePrimary (
nullptr );
68 if ( ( wrappedProcessParticleChange->GetTrackStatus() !=
fStopAndKill ) )
69 {
70
71
72
73
74 castParticleChange =
dynamic_cast< G4ParticleChange*
>( wrappedProcessParticleChange );
75 if ( castParticleChange == nullptr )
76 {
77 G4cout <<
" **** G4BOptnLeadingParticle::ApplyFinalStateBiasing(...) : can not bias for " << callingProcess->
GetProcessName() <<
", this is just a warning." <<
G4endl;
78 return wrappedProcessParticleChange;
79 }
80 finalStatePrimary =
new G4Track( *track );
81 finalStatePrimary->SetKineticEnergy ( castParticleChange->GetEnergy() );
82 finalStatePrimary->SetWeight ( castParticleChange->GetWeight() );
83 finalStatePrimary->SetMomentumDirection( *(castParticleChange->GetMomentumDirection()) );
84
85 secondariesAndPrimary.push_back( finalStatePrimary );
86 }
87
88
89
91 if ( finalStatePrimary ) primaryWeight = finalStatePrimary->GetWeight();
93
94 for ( auto i = 0 ; i < wrappedProcessParticleChange->GetNumberOfSecondaries() ; i++ ) secondariesAndPrimary[ i ]->SetWeight( primaryWeight );
95
96
97
98 size_t leadingIDX = 0;
100 std::map< G4Track*, G4bool > survivingMap;
101 for ( size_t idx = 0; idx < secondariesAndPrimary.size(); idx++ )
102 {
103 survivingMap[ secondariesAndPrimary[idx] ] = false;
104 if ( secondariesAndPrimary[idx]->GetKineticEnergy() > leadingEnergy )
105 {
106 leadingEnergy = secondariesAndPrimary[idx]->GetKineticEnergy();
107 leadingIDX = idx;
108 }
109 }
110 survivingMap[ secondariesAndPrimary[leadingIDX] ] = true;
111
112
113
114 std::map < G4int, std::vector< G4Track* > > typesAndTracks;
115 for ( size_t idx = 0; idx < secondariesAndPrimary.size(); idx++ )
116 {
117 if ( idx == leadingIDX ) continue;
118 auto currentTrack = secondariesAndPrimary[idx];
119 auto GROUP = std::abs( currentTrack->GetDefinition()->GetPDGEncoding() );
120 if ( currentTrack->GetDefinition()->GetBaryonNumber() >= 2 ) GROUP = -1000;
121
122 if ( typesAndTracks.find( GROUP ) == typesAndTracks.end() )
123 {
124 std::vector< G4Track* > v;
125 v.push_back( currentTrack );
126 typesAndTracks[ GROUP ] = v;
127 }
128 else
129 {
130 typesAndTracks[ GROUP ].push_back( currentTrack );
131 }
132 }
133
134
135
136 G4int nSecondaries = 0;
137 for ( auto& typeAndTrack : typesAndTracks )
138 {
139 size_t nTracks = (typeAndTrack.second).size();
141
142 if ( nTracks > 1 )
143 {
144 auto keptTrackIDX = G4RandFlat::shootInt( nTracks );
145 keptTrack = (typeAndTrack.second)[keptTrackIDX];
147 }
148 else
149 {
150 keptTrack = (typeAndTrack.second)[0];
151 }
152
154 if ( fRussianRouletteKillingProbability > 0.0 )
155 {
157 {
158 keptTrack->
SetWeight( keptTrack->
GetWeight() / (1. - fRussianRouletteKillingProbability) );
159 keepTrack = true;
160 }
161 }
162 else keepTrack = true;
163 if ( keepTrack )
164 {
165 survivingMap[ keptTrack ] = true;
166 if ( keptTrack != finalStatePrimary ) nSecondaries++;
167 }
168 }
169
170 if ( secondariesAndPrimary[leadingIDX] != finalStatePrimary ) nSecondaries++;
171
172
173 G4bool primarySurvived =
false;
174 if ( finalStatePrimary ) primarySurvived = survivingMap[ finalStatePrimary ];
175
176
177
178
180 if ( primarySurvived )
181 {
182 fParticleChange.
ProposeTrackStatus ( wrappedProcessParticleChange->GetTrackStatus() );
184 fParticleChange.
ProposeEnergy ( finalStatePrimary->GetKineticEnergy() );
186 }
187 else
188 {
192 }
193
196
197
198 for ( auto idx = 0 ; idx < wrappedProcessParticleChange->GetNumberOfSecondaries() ; idx++ )
199 {
200 G4Track* secondary = secondariesAndPrimary[idx];
201
202
203
204
205
206
207
208 if ( survivingMap[ secondary ] ) fParticleChange.
AddSecondary( secondary );
209 else delete secondary;
210 }
211
212
213
214 wrappedProcessParticleChange->Clear();
215
216 if ( finalStatePrimary ) delete finalStatePrimary;
217
218
219 return &fParticleChange;
220
221}
@ fKillTrackAndSecondaries
G4GLOB_DLL std::ostream G4cout
G4VProcess * GetWrappedProcess() const
void AddSecondary(G4Track *aSecondary)
void Initialize(const G4Track &) override
void ProposeEnergy(G4double finalEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
G4double GetWeight() const
void SetWeight(G4double aValue)
void ProposeTrackStatus(G4TrackStatus status)
void SetSecondaryWeightByProcess(G4bool)
void SetNumberOfSecondaries(G4int totSecondaries)
void ProposeParentWeight(G4double finalWeight)
virtual G4VParticleChange * PostStepDoIt(const G4Track &track, const G4Step &stepData)=0
const G4String & GetProcessName() const