Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4AdjointhIonisationModel.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
30#include "G4SystemOfUnits.hh"
31#include "G4AdjointCSManager.hh"
32#include "G4Integrator.hh"
33#include "G4TrackStatus.hh"
34#include "G4ParticleChange.hh"
35#include "G4AdjointElectron.hh"
36#include "G4AdjointProton.hh"
38#include "G4BetheBlochModel.hh"
39#include "G4BraggModel.hh"
40#include "G4Proton.hh"
41#include "G4NistManager.hh"
42
43////////////////////////////////////////////////////////////////////////////////
44//
46 G4VEmAdjointModel("Adjoint_hIonisation")
47{
48
49
50
51 UseMatrix =true;
53 ApplyCutInRange = true;
57
58 //The direct EM Modfel is taken has BetheBloch it is only used for the computation
59 // of the differential cross section.
60 //The Bragg model could be used as an alternative as it offers the same differential cross section
61
62 theDirectEMModel = new G4BetheBlochModel(projectileDefinition);
63 theBraggDirectEMModel = new G4BraggModel(projectileDefinition);
65
66 theDirectPrimaryPartDef = projectileDefinition;
68 if (projectileDefinition == G4Proton::Proton()) {
70
71 }
72
73 DefineProjectileProperty();
74}
75////////////////////////////////////////////////////////////////////////////////
76//
78{;}
79
80
81////////////////////////////////////////////////////////////////////////////////
82//
84 G4bool IsScatProjToProjCase,
85 G4ParticleChange* fParticleChange)
86{
87 if (!UseMatrix) return RapidSampleSecondaries(aTrack,IsScatProjToProjCase,fParticleChange);
88
89 const G4DynamicParticle* theAdjointPrimary =aTrack.GetDynamicParticle();
90
91 //Elastic inverse scattering
92 //---------------------------------------------------------
93 G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
94 G4double adjointPrimP =theAdjointPrimary->GetTotalMomentum();
95
96 if (adjointPrimKinEnergy>HighEnergyLimit*0.999){
97 return;
98 }
99
100 //Sample secondary energy
101 //-----------------------
102 G4double projectileKinEnergy = SampleAdjSecEnergyFromCSMatrix(adjointPrimKinEnergy, IsScatProjToProjCase);
103 CorrectPostStepWeight(fParticleChange,
104 aTrack.GetWeight(),
105 adjointPrimKinEnergy,
106 projectileKinEnergy,
107 IsScatProjToProjCase); //Caution !!!this weight correction should be always applied
108
109
110 //Kinematic:
111 //we consider a two body elastic scattering for the forward processes where the projectile knock on an e- at rest and gives
112 // him part of its energy
113 //----------------------------------------------------------------------------------------
114
116 G4double projectileTotalEnergy = projectileM0+projectileKinEnergy;
117 G4double projectileP2 = projectileTotalEnergy*projectileTotalEnergy - projectileM0*projectileM0;
118
119
120
121 //Companion
122 //-----------
124 if (IsScatProjToProjCase) {
126 }
127 G4double companionTotalEnergy =companionM0+ projectileKinEnergy-adjointPrimKinEnergy;
128 G4double companionP2 = companionTotalEnergy*companionTotalEnergy - companionM0*companionM0;
129
130
131 //Projectile momentum
132 //--------------------
133 G4double P_parallel = (adjointPrimP*adjointPrimP + projectileP2 - companionP2)/(2.*adjointPrimP);
134 G4double P_perp = std::sqrt( projectileP2 - P_parallel*P_parallel);
135 G4ThreeVector dir_parallel=theAdjointPrimary->GetMomentumDirection();
136 G4double phi =G4UniformRand()*2.*3.1415926;
137 G4ThreeVector projectileMomentum = G4ThreeVector(P_perp*std::cos(phi),P_perp*std::sin(phi),P_parallel);
138 projectileMomentum.rotateUz(dir_parallel);
139
140
141
142 if (!IsScatProjToProjCase ){ //kill the primary and add a secondary
143 fParticleChange->ProposeTrackStatus(fStopAndKill);
144 fParticleChange->AddSecondary(new G4DynamicParticle(theAdjEquivOfDirectPrimPartDef,projectileMomentum));
145 //G4cout<<"projectileMomentum "<<projectileMomentum<<G4endl;
146 }
147 else {
148 fParticleChange->ProposeEnergy(projectileKinEnergy);
149 fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
150 }
151
152
153
154
155}
156
157////////////////////////////////////////////////////////////////////////////////
158//
160 G4bool IsScatProjToProjCase,
161 G4ParticleChange* fParticleChange)
162{
163
164 const G4DynamicParticle* theAdjointPrimary =aTrack.GetDynamicParticle();
166
167
168 G4double adjointPrimKinEnergy = theAdjointPrimary->GetKineticEnergy();
169 G4double adjointPrimP =theAdjointPrimary->GetTotalMomentum();
170
171 if (adjointPrimKinEnergy>HighEnergyLimit*0.999){
172 return;
173 }
174
175 G4double projectileKinEnergy =0.;
176 G4double eEnergy=0.;
177 G4double newCS=currentMaterial->GetElectronDensity()*twopi_mc2_rcl2*mass;
178 if (!IsScatProjToProjCase){//1/E^2 distribution
179
180 eEnergy=adjointPrimKinEnergy;
181 G4double Emax = GetSecondAdjEnergyMaxForProdToProjCase(adjointPrimKinEnergy);
182 G4double Emin= GetSecondAdjEnergyMinForProdToProjCase(adjointPrimKinEnergy);
183 if (Emin>=Emax) return;
184 G4double a=1./Emax;
185 G4double b=1./Emin;
186 newCS=newCS*(b-a)/eEnergy;
187
188 projectileKinEnergy =1./(b- (b-a)*G4UniformRand());
189
190
191 }
192 else { G4double Emax = GetSecondAdjEnergyMaxForScatProjToProjCase(adjointPrimKinEnergy);
194 if (Emin>=Emax) return;
195 G4double diff1=Emin-adjointPrimKinEnergy;
196 G4double diff2=Emax-adjointPrimKinEnergy;
197
198 G4double t1=adjointPrimKinEnergy*(1./diff1-1./diff2);
199 G4double t2=adjointPrimKinEnergy*(1./Emin-1./Emax);
200 /*G4double f31=diff1/Emin;
201 G4double f32=diff2/Emax/f31;*/
202 G4double t3=2.*std::log(Emax/Emin);
203 G4double sum_t=t1+t2+t3;
204 newCS=newCS*sum_t/adjointPrimKinEnergy/adjointPrimKinEnergy;
205 G4double t=G4UniformRand()*sum_t;
206 if (t <=t1 ){
207 G4double q= G4UniformRand()*t1/adjointPrimKinEnergy ;
208 projectileKinEnergy =adjointPrimKinEnergy +1./(1./diff1-q);
209
210 }
211 else if (t <=t2 ) {
212 G4double q= G4UniformRand()*t2/adjointPrimKinEnergy;
213 projectileKinEnergy =1./(1./Emin-q);
214 }
215 else {
216 projectileKinEnergy=Emin*std::pow(Emax/Emin,G4UniformRand());
217
218 }
219 eEnergy=projectileKinEnergy-adjointPrimKinEnergy;
220
221
222 }
223
224
225
226 G4double diffCS_perAtom_Used=twopi_mc2_rcl2*mass*adjointPrimKinEnergy/projectileKinEnergy/projectileKinEnergy/eEnergy/eEnergy;
227
228
229
230 //Weight correction
231 //-----------------------
232 //First w_corr is set to the ratio between adjoint total CS and fwd total CS
234
235 //G4cout<<w_corr<<G4endl;
236 w_corr*=newCS/lastCS;
237 //G4cout<<w_corr<<G4endl;
238 //Then another correction is needed due to the fact that a biaised differential CS has been used rather than the one consistent with the direct model
239 //Here we consider the true diffCS as the one obtained by the numerical differentiation over Tcut of the direct CS
240
241 G4double diffCS = DiffCrossSectionPerAtomPrimToSecond(projectileKinEnergy, eEnergy,1,1);
242 w_corr*=diffCS/diffCS_perAtom_Used;
243 //G4cout<<w_corr<<G4endl;
244
245 G4double new_weight = aTrack.GetWeight()*w_corr;
246 fParticleChange->SetParentWeightByProcess(false);
247 fParticleChange->SetSecondaryWeightByProcess(false);
248 fParticleChange->ProposeParentWeight(new_weight);
249
250
251
252
253 //Kinematic:
254 //we consider a two body elastic scattering for the forward processes where the projectile knock on an e- at rest and gives
255 // him part of its energy
256 //----------------------------------------------------------------------------------------
257
259 G4double projectileTotalEnergy = projectileM0+projectileKinEnergy;
260 G4double projectileP2 = projectileTotalEnergy*projectileTotalEnergy - projectileM0*projectileM0;
261
262
263
264 //Companion
265 //-----------
267 if (IsScatProjToProjCase) {
269 }
270 G4double companionTotalEnergy =companionM0+ projectileKinEnergy-adjointPrimKinEnergy;
271 G4double companionP2 = companionTotalEnergy*companionTotalEnergy - companionM0*companionM0;
272
273
274 //Projectile momentum
275 //--------------------
276 G4double P_parallel = (adjointPrimP*adjointPrimP + projectileP2 - companionP2)/(2.*adjointPrimP);
277 G4double P_perp = std::sqrt( projectileP2 - P_parallel*P_parallel);
278 G4ThreeVector dir_parallel=theAdjointPrimary->GetMomentumDirection();
279 G4double phi =G4UniformRand()*2.*3.1415926;
280 G4ThreeVector projectileMomentum = G4ThreeVector(P_perp*std::cos(phi),P_perp*std::sin(phi),P_parallel);
281 projectileMomentum.rotateUz(dir_parallel);
282
283
284
285 if (!IsScatProjToProjCase ){ //kill the primary and add a secondary
286 fParticleChange->ProposeTrackStatus(fStopAndKill);
287 fParticleChange->AddSecondary(new G4DynamicParticle(theAdjEquivOfDirectPrimPartDef,projectileMomentum));
288 //G4cout<<"projectileMomentum "<<projectileMomentum<<G4endl;
289 }
290 else {
291 fParticleChange->ProposeEnergy(projectileKinEnergy);
292 fParticleChange->ProposeMomentumDirection(projectileMomentum.unit());
293 }
294
295
296
297
298
299
300
301}
302
303////////////////////////////////////////////////////////////////////////////////
304//
306 G4double kinEnergyProj,
307 G4double kinEnergyProd,
308 G4double Z,
309 G4double A)
310{//Probably that here the Bragg Model should be also used for kinEnergyProj/nuc<2MeV
311
312
313
314 G4double dSigmadEprod=0;
315 G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProjCase(kinEnergyProd);
316 G4double Emin_proj = GetSecondAdjEnergyMinForProdToProjCase(kinEnergyProd);
317
318
319 if (kinEnergyProj>Emin_proj && kinEnergyProj<=Emax_proj){ //the produced particle should have a kinetic energy smaller than the projectile
320 G4double Tmax=kinEnergyProj;
321
322 G4double E1=kinEnergyProd;
323 G4double E2=kinEnergyProd*1.000001;
324 G4double dE=(E2-E1);
325 G4double sigma1,sigma2;
326 if (kinEnergyProj >2.*MeV){
327 sigma1=theDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,Z,A ,E1,1.e20);
328 sigma2=theDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,Z,A ,E2,1.e20);
329 }
330 else {
331 sigma1=theBraggDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,Z,A ,E1,1.e20);
332 sigma2=theBraggDirectEMModel->ComputeCrossSectionPerAtom(theDirectPrimaryPartDef,kinEnergyProj,Z,A ,E2,1.e20);
333 }
334
335
336 dSigmadEprod=(sigma1-sigma2)/dE;
337 if (dSigmadEprod>1.) {
338 G4cout<<"sigma1 "<<kinEnergyProj/MeV<<'\t'<<kinEnergyProd/MeV<<'\t'<<sigma1<<G4endl;
339 G4cout<<"sigma2 "<<kinEnergyProj/MeV<<'\t'<<kinEnergyProd/MeV<<'\t'<<sigma2<<G4endl;
340 G4cout<<"dsigma "<<kinEnergyProj/MeV<<'\t'<<kinEnergyProd/MeV<<'\t'<<dSigmadEprod<<G4endl;
341
342 }
343
344
345
346 //correction of differential cross section at high energy to correct for the suppression of particle at secondary at high
347 //energy used in the Bethe Bloch Model. This correction consist to multiply by g the probability function used
348 //to test the rejection of a secondary
349 //-------------------------
350
351 //Source code taken from G4BetheBlochModel::SampleSecondaries
352
353 G4double deltaKinEnergy = kinEnergyProd;
354
355 //Part of the taken code
356 //----------------------
357
358
359
360 // projectile formfactor - suppresion of high energy
361 // delta-electron production at high energy
362 G4double x = formfact*deltaKinEnergy;
363 if(x > 1.e-6) {
364
365
366 G4double totEnergy = kinEnergyProj + mass;
367 G4double etot2 = totEnergy*totEnergy;
368 G4double beta2 = kinEnergyProj*(kinEnergyProj + 2.0*mass)/etot2;
369 G4double f;
370 G4double f1 = 0.0;
371 f = 1.0 - beta2*deltaKinEnergy/Tmax;
372 if( 0.5 == spin ) {
373 f1 = 0.5*deltaKinEnergy*deltaKinEnergy/etot2;
374 f += f1;
375 }
376 G4double x1 = 1.0 + x;
377 G4double gg = 1.0/(x1*x1);
378 if( 0.5 == spin ) {
379 G4double x2 = 0.5*electron_mass_c2*deltaKinEnergy/(mass*mass);
380 gg *= (1.0 + magMoment2*(x2 - f1/f)/(1.0 + x2));
381 }
382 if(gg > 1.0) {
383 G4cout << "### G4BetheBlochModel in Adjoint Sim WARNING: g= " << g
384 << G4endl;
385 gg=1.;
386 }
387 //G4cout<<"gg"<<gg<<G4endl;
388 dSigmadEprod*=gg;
389 }
390
391 }
392
393 return dSigmadEprod;
394}
395
396
397
398//////////////////////////////////////////////////////////////////////////////////////////////
399//
400void G4AdjointhIonisationModel::DefineProjectileProperty()
401{
402 //Slightly modified code taken from G4BetheBlochModel::SetParticle
403 //------------------------------------------------
405 if (theDirectPrimaryPartDef->GetParticleType() == "nucleus" &&
406 pname != "deuteron" && pname != "triton") {
407 isIon = true;
408 }
409
414 chargeSquare = q*q;
415 ratio = electron_mass_c2/mass;
416 ratio2 = ratio*ratio;
417 one_plus_ratio_2=(1+ratio)*(1+ratio);
418 one_minus_ratio_2=(1-ratio)*(1-ratio);
420 *mass/(0.5*eplus*hbar_Planck*c_squared);
421 magMoment2 = magmom*magmom - 1.0;
422 formfact = 0.0;
424 G4double x = 0.8426*GeV;
425 if(spin == 0.0 && mass < GeV) {x = 0.736*GeV;}
426 else if(mass > GeV) {
427 x /= G4NistManager::Instance()->GetZ13(mass/proton_mass_c2);
428 // tlimit = 51.2*GeV*A13[iz]*A13[iz];
429 }
430 formfact = 2.0*electron_mass_c2/(x*x);
431 tlimit = 2.0/formfact;
432 }
433}
434
435////////////////////////////////////////////////////////////////////////////////
436//
438 G4double primEnergy,
439 G4bool IsScatProjToProjCase)
440{
441 if (UseMatrix) return G4VEmAdjointModel::AdjointCrossSection(aCouple,primEnergy,IsScatProjToProjCase);
442 DefineCurrentMaterial(aCouple);
443
444
445 G4double Cross=currentMaterial->GetElectronDensity()*twopi_mc2_rcl2*mass;
446
447 if (!IsScatProjToProjCase ){
448 G4double Emax_proj = GetSecondAdjEnergyMaxForProdToProjCase(primEnergy);
449 G4double Emin_proj = GetSecondAdjEnergyMinForProdToProjCase(primEnergy);
450 if (Emax_proj>Emin_proj && primEnergy > currentTcutForDirectSecond) {
451 Cross*=(1./Emin_proj -1./Emax_proj)/primEnergy;
452 }
453 else Cross=0.;
454
455
456
457
458
459
460 }
461 else {
464 G4double diff1=Emin_proj-primEnergy;
465 G4double diff2=Emax_proj-primEnergy;
466 G4double t1=(1./diff1+1./Emin_proj-1./diff2-1./Emax_proj)/primEnergy;
467 //G4double t2=2.*std::log(diff2*Emin_proj/Emax_proj/diff1)/primEnergy/primEnergy;
468 G4double t2=2.*std::log(Emax_proj/Emin_proj)/primEnergy/primEnergy;
469 Cross*=(t1+t2);
470
471
472 }
473 lastCS =Cross;
474 return Cross;
475}
476//////////////////////////////////////////////////////////////////////////////
477//
479{
480 G4double Tmax=PrimAdjEnergy*one_plus_ratio_2/(one_minus_ratio_2-2.*ratio*PrimAdjEnergy/mass);
481 return Tmax;
482}
483//////////////////////////////////////////////////////////////////////////////
484//
486{ return PrimAdjEnergy+Tcut;
487}
488//////////////////////////////////////////////////////////////////////////////
489//
491{ return HighEnergyLimit;
492}
493//////////////////////////////////////////////////////////////////////////////
494//
496{ G4double Tmin= (2*PrimAdjEnergy-4*mass + std::sqrt(4.*PrimAdjEnergy*PrimAdjEnergy +16.*mass*mass + 8.*PrimAdjEnergy*mass*(1/ratio +ratio)))/4.;
497 return Tmin;
498}
double A(double temperature)
CLHEP::Hep3Vector G4ThreeVector
@ fStopAndKill
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
Hep3Vector unit() const
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:33
G4double GetPostStepWeightCorrection()
static G4AdjointCSManager * GetAdjointCSManager()
static G4AdjointElectron * AdjointElectron()
static G4AdjointProton * AdjointProton()
virtual G4double GetSecondAdjEnergyMaxForScatProjToProjCase(G4double PrimAdjEnergy)
G4AdjointhIonisationModel(G4ParticleDefinition *projectileDefinition)
virtual G4double GetSecondAdjEnergyMinForProdToProjCase(G4double PrimAdjEnergy)
virtual G4double GetSecondAdjEnergyMinForScatProjToProjCase(G4double PrimAdjEnergy, G4double Tcut=0)
virtual G4double AdjointCrossSection(const G4MaterialCutsCouple *aCouple, G4double primEnergy, G4bool IsScatProjToProjCase)
virtual G4double DiffCrossSectionPerAtomPrimToSecond(G4double kinEnergyProj, G4double kinEnergyProd, G4double Z, G4double A=0.)
virtual void SampleSecondaries(const G4Track &aTrack, G4bool IsScatProjToProjCase, G4ParticleChange *fParticleChange)
virtual G4double GetSecondAdjEnergyMaxForProdToProjCase(G4double PrimAdjEnergy)
void RapidSampleSecondaries(const G4Track &aTrack, G4bool IsScatProjToProjCase, G4ParticleChange *fParticleChange)
const G4ThreeVector & GetMomentumDirection() const
G4double GetKineticEnergy() const
G4double GetTotalMomentum() const
G4double GetElectronDensity() const
Definition: G4Material.hh:215
G4double GetZ13(G4double Z) const
static G4NistManager * Instance()
void AddSecondary(G4Track *aSecondary)
void ProposeEnergy(G4double finalEnergy)
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
G4double GetPDGMagneticMoment() const
const G4String & GetParticleType() const
G4double GetPDGCharge() const
const G4String & GetParticleName() const
static G4Proton * Proton()
Definition: G4Proton.cc:92
G4double GetWeight() const
const G4DynamicParticle * GetDynamicParticle() const
const G4MaterialCutsCouple * GetMaterialCutsCouple() const
G4VEmModel * theDirectEMModel
virtual void CorrectPostStepWeight(G4ParticleChange *fParticleChange, G4double old_weight, G4double adjointPrimKinEnergy, G4double projectileKinEnergy, G4bool IsScatProjToProjCase)
void DefineCurrentMaterial(const G4MaterialCutsCouple *couple)
G4ParticleDefinition * theDirectPrimaryPartDef
G4double SampleAdjSecEnergyFromCSMatrix(size_t MatrixIndex, G4double prim_energy, G4bool IsScatProjToProjCase)
G4Material * currentMaterial
G4bool UseOnlyOneMatrixForAllElements
G4double currentTcutForDirectSecond
virtual G4double AdjointCrossSection(const G4MaterialCutsCouple *aCouple, G4double primEnergy, G4bool IsScatProjToProjCase)
G4ParticleDefinition * theAdjEquivOfDirectSecondPartDef
G4ParticleDefinition * theAdjEquivOfDirectPrimPartDef
virtual G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kinEnergy, G4double Z, G4double A=0., G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
Definition: G4VEmModel.cc:359
void ProposeTrackStatus(G4TrackStatus status)
void SetSecondaryWeightByProcess(G4bool)
void SetParentWeightByProcess(G4bool)
void ProposeParentWeight(G4double finalWeight)