Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4AdjointForcedInteractionForGamma.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26//
28#include "G4SystemOfUnits.hh"
29#include "G4AdjointCSManager.hh"
30#include "G4AdjointCSMatrix.hh"
31#include "G4VEmAdjointModel.hh"
33#include "G4ParticleChange.hh"
34#include "G4AdjointGamma.hh"
35
36
39 G4VContinuousDiscreteProcess(process_name),theAdjointComptonModel(0),theAdjointBremModel(0)
40{ theAdjointCSManager = G4AdjointCSManager::GetAdjointCSManager();
41 fParticleChange=new G4ParticleChange();
42 lastAdjCS=0.;
43 trackid = nstep = 0;
44 is_free_flight_gamma = false;
45 copy_gamma_for_forced_interaction = false;
46 last_free_flight_trackid=1000;
47
48 theAdjointComptonModel =0;
49 theAdjointBremModel=0;
50
51 acc_track_length=0.;
52 acc_nb_adj_interaction_length=0.;
53 acc_nb_fwd_interaction_length=0.;
54 total_acc_nb_adj_interaction_length=0.;
55 total_acc_nb_fwd_interaction_length=0.;
56 continue_gamma_as_new_free_flight =false;
57
58
59
60}
61//////////////////////////////////////////////////////////////////////////////
62//
65{ if (fParticleChange) delete fParticleChange;
66}
67//////////////////////////////////////////////////////////////////////////////
68//
70{;
71}
72//////////////////////////////////////////////////////////////////////////////
73//
75{
76 theAdjointCSManager->BuildCrossSectionMatrices(); //do not worry it will be done just once
77 theAdjointCSManager->BuildTotalSigmaTables();
78}
79//Note on weight correction for forced interaction
80//For the forced interaction applied here we do use a truncated exponential law for the probability of survival
81//over a fixed total length. This is done by using a linear transformation of the non biased probability survival
82//In mathematic this writes
83//P'(x)=C1P(x)+C2
84//With P(x)=exp(-sum(sigma_ixi)) x and L can cross different volumes with different cross section sigma.
85//For forced interaction we get the following limit conditions
86//P'(L)=0 P'(0)=1 (L can be used over different volumes)
87//From simple solving of linear equation we get
88//C1=1/(1-P(L)) et C2=-P(L)/(1-P(L))
89//P'(x)=(P(x)-P(L))/(1-P(L))
90//For the probability over a step x1 to x2
91//P'(x1->x2)=P'(x2)/P'(x1)
92//The effective cross section is defined -d(P'(x))/dx/P'(x)
93//We get therefore
94//sigma_eff=C1sigmaP(x)/(C1P(x)+C2)=sigmaP(x)/(P(x)+C2/C1)=sigmaP(x)/(P(x)-P(L))=sigma/(1-P(L)/P(x))
95//////////////////////////////////////////////////////////////////////////////
96//
98{ fParticleChange->Initialize(track);
99 //For the free flight gamma no interaction occur but a gamma with same property is
100 //produces for further forced interaction
101 //It is done at the very beginning of the track such that the weight can be the same
102 if (copy_gamma_for_forced_interaction) {
103 G4ThreeVector theGammaMomentum = track.GetMomentum();
104 fParticleChange->AddSecondary(new G4DynamicParticle(G4AdjointGamma::AdjointGamma(),theGammaMomentum));
105 fParticleChange->SetParentWeightByProcess(false);
106 fParticleChange->SetSecondaryWeightByProcess(false);
107 }
108 else { //Occurrence of forced interaction
109
110 //Selection of the model to be called
111 G4VEmAdjointModel* theSelectedModel =0;
112 G4bool is_scat_proj_to_proj_case=false;
113 if (!theAdjointComptonModel && !theAdjointBremModel) return fParticleChange;
114 if (!theAdjointComptonModel) {
115 theSelectedModel = theAdjointBremModel;
116 is_scat_proj_to_proj_case=false;
117 //This is needed because the results of it will be used in the post step do it weight correction inside the model
118 theAdjointBremModel->AdjointCrossSection(
119 track.GetMaterialCutsCouple(),track.GetKineticEnergy(), false);
120
121 }
122 else if (!theAdjointBremModel) {
123 theSelectedModel = theAdjointComptonModel;
124 is_scat_proj_to_proj_case=true;
125 }
126 else { //Choose the model according to cross sections
127
128 G4double bremAdjCS = theAdjointBremModel->AdjointCrossSection(
129 track.GetMaterialCutsCouple(),track.GetKineticEnergy(), false);
130 if (G4UniformRand()*lastAdjCS<bremAdjCS) {
131 theSelectedModel = theAdjointBremModel;
132 is_scat_proj_to_proj_case=false;
133 }
134 else {
135 theSelectedModel = theAdjointComptonModel;
136 is_scat_proj_to_proj_case=true;
137 }
138 }
139
140 //Compute the weight correction factor
141 G4double one_over_effectiveAdjointCS= (1.-std::exp(acc_nb_adj_interaction_length-total_acc_nb_adj_interaction_length))/lastAdjCS;
142 G4double weight_correction_factor = lastAdjCS*one_over_effectiveAdjointCS;
143 //G4cout<<"Weight correction factor start "<<weight_correction_factor<<std::endl;
144 //Call the selected model without correction of the weight in the model
145 theSelectedModel->SetCorrectWeightForPostStepInModel(false);
146 theSelectedModel->SetAdditionalWeightCorrectionFactorForPostStepOutsideModel(weight_correction_factor);
147 theSelectedModel->SampleSecondaries(track,is_scat_proj_to_proj_case,fParticleChange);
148 theSelectedModel->SetCorrectWeightForPostStepInModel(true);
149
150 continue_gamma_as_new_free_flight =true;
151 }
152 return fParticleChange;
153}
154//////////////////////////////////////////////////////////////////////////////
155//
157{ fParticleChange->Initialize(track);
158 //Compute nb of interactions length over step length
160 G4double stepLength = track.GetStep()->GetStepLength();
161 G4double ekin = track.GetKineticEnergy();
162 G4double nb_fwd_interaction_length_over_step=0.;
163 G4double nb_adj_interaction_length_over_step=0.;
166 ekin,track.GetMaterialCutsCouple());
167 nb_fwd_interaction_length_over_step = stepLength*lastFwdCS;
168 nb_adj_interaction_length_over_step = stepLength*lastAdjCS;
169 G4double fwd_survival_probability=std::exp(-nb_fwd_interaction_length_over_step);
170 G4double mc_induced_survival_probability=1.;
171
172 if (is_free_flight_gamma) { //for free_flight survival probability stays 1
173 //Accumulate the number of interaction lengths during free flight of gamma
174 total_acc_nb_fwd_interaction_length+=nb_fwd_interaction_length_over_step;
175 total_acc_nb_adj_interaction_length+=nb_adj_interaction_length_over_step;
176 acc_track_length+=stepLength;
177 }
178 else {
179 G4double previous_acc_nb_adj_interaction_length =acc_nb_adj_interaction_length;
180 acc_nb_fwd_interaction_length+=nb_fwd_interaction_length_over_step;
181 acc_nb_adj_interaction_length+=nb_adj_interaction_length_over_step;
182 theNumberOfInteractionLengthLeft-=nb_adj_interaction_length_over_step;
183
184 //Following condition to remove very rare FPE issue
185 //if (total_acc_nb_adj_interaction_length <= 1.e-50 && theNumberOfInteractionLengthLeft<=1.e-50) { //condition added to avoid FPE issue
186 // VI 06.11.2017 - new condition
187 if (std::abs(total_acc_nb_adj_interaction_length - previous_acc_nb_adj_interaction_length) <= 1.e-15) {
188 mc_induced_survival_probability = 1.e50;
189 /*
190 G4cout << "FPE protection: " << total_acc_nb_adj_interaction_length << " "
191 << previous_acc_nb_adj_interaction_length << " "
192 << acc_nb_fwd_interaction_length << " "
193 << acc_nb_adj_interaction_length << " "
194 << theNumberOfInteractionLengthLeft
195 << G4endl;
196 */
197 }
198 else {
199 mc_induced_survival_probability= std::exp(-acc_nb_adj_interaction_length)-std::exp(-total_acc_nb_adj_interaction_length);
200 mc_induced_survival_probability=mc_induced_survival_probability/(std::exp(-previous_acc_nb_adj_interaction_length)-std::exp(-total_acc_nb_adj_interaction_length));
201 }
202 }
203 G4double weight_correction = fwd_survival_probability/mc_induced_survival_probability;
204
205 //weight_correction = 1.;
206 //Caution!!!
207 // It is important to select the weight of the post_step_point
208 // as the current weight and not the weight of the track, as t
209 // the weight of the track is changed after having applied all
210 // the along_step_do_it.
211 G4double new_weight=weight_correction*track.GetStep()->GetPostStepPoint()->GetWeight();
212/*
213 G4cout<<"New weight "<<new_weight<<std::endl;
214 G4cout<<"Weight correction "<<weight_correction<<std::endl;
215 */
216
217 fParticleChange->SetParentWeightByProcess(false);
218 fParticleChange->SetSecondaryWeightByProcess(false);
219 fParticleChange->ProposeParentWeight(new_weight);
220
221 return fParticleChange;
222}
223//////////////////////////////////////////////////////////////////////////////
224//
226 const G4Track& track,
227 G4double ,
229{ G4int step_id = track.GetCurrentStepNumber();
231 copy_gamma_for_forced_interaction = false;
232 G4int track_id=track.GetTrackID();
233 is_free_flight_gamma = (track_id != last_free_flight_trackid+1 || continue_gamma_as_new_free_flight);
234 if (is_free_flight_gamma) {
235 if (step_id == 1 || continue_gamma_as_new_free_flight) {
237 //A gamma with same conditions will be generate at next post_step do it for the forced interaction
238 copy_gamma_for_forced_interaction = true;
239 last_free_flight_trackid = track_id;
240 acc_track_length=0.;
241 total_acc_nb_adj_interaction_length=0.;
242 total_acc_nb_fwd_interaction_length=0.;
243 continue_gamma_as_new_free_flight=false;
244 return 1.e-90;
245 }
246 else {
247 //Computation of accumulated length for
248 return DBL_MAX;
249 }
250 }
251 else { //compute the interaction length for forced interaction
252 if (step_id ==1) {
253 G4double min_val= std::exp(-total_acc_nb_adj_interaction_length);
254 theNumberOfInteractionLengthLeft = -std::log( min_val+G4UniformRand()*(1.-min_val));
256 acc_nb_adj_interaction_length=0.;
257 acc_nb_fwd_interaction_length=0.;
258 }
259 G4VPhysicalVolume* thePostPhysVolume = track.GetStep()->GetPreStepPoint()->GetPhysicalVolume();
260 G4double ekin =track.GetKineticEnergy();
261 G4double postCS=0.;
262 if (thePostPhysVolume){
264 ekin,thePostPhysVolume->GetLogicalVolume()->GetMaterialCutsCouple());
265 }
266 if (postCS>0.) return theNumberOfInteractionLengthLeft/postCS;
267 else return DBL_MAX;
268 }
269}
270////////////////////////////////////////////////////////////////////////////////
271//
273 G4double ,
274 G4double ,
275 G4double& )
276{return DBL_MAX;
277}
278////////////////////////////////////////////////////////////////////////////////
279//Not used in this process but should be implemented as virtual method
281 G4double ,
283{ return 0.;
284}
285
286
G4double condition(const G4ErrorSymMatrix &m)
G4ForceCondition
@ NotForced
@ Forced
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4UniformRand()
Definition: Randomize.hh:52
G4double GetTotalForwardCS(G4ParticleDefinition *aPartDef, G4double Ekin, const G4MaterialCutsCouple *aCouple)
static G4AdjointCSManager * GetAdjointCSManager()
G4double GetTotalAdjointCS(G4ParticleDefinition *aPartDef, G4double Ekin, const G4MaterialCutsCouple *aCouple)
virtual G4double GetContinuousStepLimit(const G4Track &aTrack, G4double previousStepSize, G4double currentMinimumStep, G4double &currentSafety)
virtual G4VParticleChange * PostStepDoIt(const G4Track &, const G4Step &)
virtual G4double GetMeanFreePath(const G4Track &track, G4double previousStepSize, G4ForceCondition *condition)
void PreparePhysicsTable(const G4ParticleDefinition &)
virtual G4double PostStepGetPhysicalInteractionLength(const G4Track &track, G4double previousStepSize, G4ForceCondition *condition)
virtual G4VParticleChange * AlongStepDoIt(const G4Track &track, const G4Step &step)
void BuildPhysicsTable(const G4ParticleDefinition &)
static G4AdjointGamma * AdjointGamma()
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
void AddSecondary(G4Track *aSecondary)
virtual void Initialize(const G4Track &)
G4VPhysicalVolume * GetPhysicalVolume() const
G4double GetWeight() const
Definition: G4Step.hh:62
G4StepPoint * GetPreStepPoint() const
G4double GetStepLength() const
G4StepPoint * GetPostStepPoint() const
G4int GetTrackID() const
const G4ThreeVector & GetPosition() const
G4int GetCurrentStepNumber() const
G4ThreeVector GetMomentum() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
const G4Step * GetStep() const
virtual void SampleSecondaries(const G4Track &aTrack, G4bool IsScatProjToProjCase, G4ParticleChange *fParticleChange)=0
void SetAdditionalWeightCorrectionFactorForPostStepOutsideModel(G4double factor)
void SetCorrectWeightForPostStepInModel(G4bool aBool)
virtual G4double AdjointCrossSection(const G4MaterialCutsCouple *aCouple, G4double primEnergy, G4bool IsScatProjToProjCase)
void SetSecondaryWeightByProcess(G4bool)
void SetParentWeightByProcess(G4bool)
void ProposeParentWeight(G4double finalWeight)
G4LogicalVolume * GetLogicalVolume() const
G4double theInitialNumberOfInteractionLength
Definition: G4VProcess.hh:338
G4double theNumberOfInteractionLengthLeft
Definition: G4VProcess.hh:331
#define DBL_MAX
Definition: templates.hh:62