CMS 3D CMS Logo

CMSmplIonisationWithDeltaModel.cc
Go to the documentation of this file.
1 //
2 // -------------------------------------------------------------------
3 //
4 //
5 // File name: CMSmplIonisationWithDeltaModel
6 //
7 // Author: Vladimir Ivanchenko
8 //
9 // Creation date: 02.03.2019 copied from Geant4 10.5p01
10 //
11 //
12 // -------------------------------------------------------------------
13 // References
14 // [1] Steven P. Ahlen: Energy loss of relativistic heavy ionizing particles,
15 // S.P. Ahlen, Rev. Mod. Phys 52(1980), p121
16 // [2] K.A. Milton arXiv:hep-ex/0602040
17 // [3] S.P. Ahlen and K. Kinoshita, Phys. Rev. D26 (1982) 2347
18 
19 
20 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
21 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
22 
24 #include "Randomize.hh"
25 #include "G4PhysicalConstants.hh"
26 #include "G4SystemOfUnits.hh"
27 #include "G4ParticleChangeForLoss.hh"
28 #include "G4Electron.hh"
29 #include "G4DynamicParticle.hh"
30 #include "G4ProductionCutsTable.hh"
31 #include "G4MaterialCutsCouple.hh"
32 #include "G4Log.hh"
33 #include "G4Pow.hh"
34 
35 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
36 
37 using namespace std;
38 
39 std::vector<G4double>* CMSmplIonisationWithDeltaModel::dedx0 = nullptr;
40 
42  const G4String& nam)
43  : G4VEmModel(nam),G4VEmFluctuationModel(nam),
44  magCharge(mCharge),
45  twoln10(std::log(100.0)),
46  betalow(0.01),
47  betalim(0.1),
48  beta2lim(betalim*betalim),
49  bg2lim(beta2lim*(1.0 + beta2lim))
50 {
51  nmpl = G4lrint(std::abs(magCharge) * 2 * fine_structure_const);
52  if(nmpl > 6) { nmpl = 6; }
53  else if(nmpl < 1) { nmpl = 1; }
54  pi_hbarc2_over_mc2 = pi * hbarc * hbarc / electron_mass_c2;
56  dedxlim = 45.*nmpl*nmpl*GeV*cm2/g;
57  fParticleChange = nullptr;
59  G4cout << "### Monopole ionisation model with d-electron production, Gmag= "
60  << magCharge/eplus << G4endl;
61  monopole = nullptr;
62  mass = 0.0;
63 }
64 
65 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
66 
68 {
69  if(IsMaster()) { delete dedx0; }
70 }
71 
72 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
73 
74 void CMSmplIonisationWithDeltaModel::SetParticle(const G4ParticleDefinition* p)
75 {
76  monopole = p;
77  mass = monopole->GetPDGMass();
78  G4double emin =
79  std::min(LowEnergyLimit(),0.1*mass*(1./sqrt(1. - betalow*betalow) - 1.));
80  G4double emax =
81  std::max(HighEnergyLimit(),10*mass*(1./sqrt(1. - beta2lim) - 1.));
82  SetLowEnergyLimit(emin);
83  SetHighEnergyLimit(emax);
84 }
85 
86 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
87 
88 void
89 CMSmplIonisationWithDeltaModel::Initialise(const G4ParticleDefinition* p,
90  const G4DataVector&)
91 {
92  if(!monopole) { SetParticle(p); }
93  if(!fParticleChange) { fParticleChange = GetParticleChangeForLoss(); }
94  if(IsMaster()) {
95  if(!dedx0) { dedx0 = new std::vector<G4double>; }
96  G4ProductionCutsTable* theCoupleTable=
97  G4ProductionCutsTable::GetProductionCutsTable();
98  G4int numOfCouples = theCoupleTable->GetTableSize();
99  G4int n = dedx0->size();
100  if(n < numOfCouples) { dedx0->resize(numOfCouples); }
101  G4Pow* g4calc = G4Pow::GetInstance();
102 
103  // initialise vector
104  for(G4int i=0; i<numOfCouples; ++i) {
105 
106  const G4Material* material =
107  theCoupleTable->GetMaterialCutsCouple(i)->GetMaterial();
108  G4double eDensity = material->GetElectronDensity();
109  G4double vF = electron_Compton_length*g4calc->A13(3.*pi*pi*eDensity);
110  (*dedx0)[i] = pi_hbarc2_over_mc2*eDensity*nmpl*nmpl*
111  (G4Log(2*vF/fine_structure_const) - 0.5)/vF;
112  }
113  }
114 }
115 
116 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
117 
118 G4double
120  const G4MaterialCutsCouple* couple)
121 {
122  return couple->GetMaterial()->GetIonisation()->GetMeanExcitationEnergy();
123 }
124 
125 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
126 
127 G4double
129  const G4ParticleDefinition* p,
130  G4double kineticEnergy,
131  G4double maxEnergy)
132 {
133  if(!monopole) { SetParticle(p); }
134  G4double tmax = MaxSecondaryEnergy(p,kineticEnergy);
135  G4double cutEnergy = std::min(tmax, maxEnergy);
136  cutEnergy = std::max(LowEnergyLimit(), cutEnergy);
137  G4double tau = kineticEnergy / mass;
138  G4double gam = tau + 1.0;
139  G4double bg2 = tau * (tau + 2.0);
140  G4double beta2 = bg2 / (gam * gam);
141  G4double beta = sqrt(beta2);
142 
143  // low-energy asymptotic formula
144  G4double dedx = (*dedx0)[CurrentCouple()->GetIndex()]*beta;
145 
146  // above asymptotic
147  if(beta > betalow) {
148 
149  // high energy
150  if(beta >= betalim) {
151  dedx = ComputeDEDXAhlen(material, bg2, cutEnergy);
152 
153  } else {
154  G4double dedx1 = (*dedx0)[CurrentCouple()->GetIndex()]*betalow;
155  G4double dedx2 = ComputeDEDXAhlen(material, bg2lim, cutEnergy);
156 
157  // extrapolation between two formula
158  G4double kapa2 = beta - betalow;
159  G4double kapa1 = betalim - beta;
160  dedx = (kapa1*dedx1 + kapa2*dedx2)/(kapa1 + kapa2);
161  }
162  }
163  return dedx;
164 }
165 
166 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
167 
168 G4double
170  G4double bg2,
171  G4double cutEnergy)
172 {
173  G4double eDensity = material->GetElectronDensity();
174  G4double eexc = material->GetIonisation()->GetMeanExcitationEnergy();
175 
176  // Ahlen's formula for nonconductors, [1]p157, f(5.7)
177  G4double dedx =
178  0.5*(G4Log(2.0*electron_mass_c2*bg2*cutEnergy/(eexc*eexc)) -1.0);
179 
180  // Kazama et al. cross-section correction
181  G4double k = 0.406;
182  if(nmpl > 1) { k = 0.346; }
183 
184  // Bloch correction
185  const G4double B[7] = { 0.0, 0.248, 0.672, 1.022, 1.243, 1.464, 1.685};
186 
187  dedx += 0.5 * k - B[nmpl];
188 
189  // density effect correction
190  G4double x = G4Log(bg2)/twoln10;
191  dedx -= material->GetIonisation()->DensityCorrection(x);
192 
193  // now compute the total ionization loss
194  dedx *= pi_hbarc2_over_mc2 * eDensity * nmpl * nmpl;
195 
196  dedx = std::max(dedx, 0.0);
197  return dedx;
198 }
199 
200 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
201 
202 G4double
204  const G4ParticleDefinition* p,
205  G4double kineticEnergy,
206  G4double cut,
207  G4double maxKinEnergy)
208 {
209  if(!monopole) { SetParticle(p); }
210  G4double tmax = MaxSecondaryEnergy(p, kineticEnergy);
211  G4double maxEnergy = std::min(tmax, maxKinEnergy);
212  G4double cutEnergy = std::max(LowEnergyLimit(), cut);
213  G4double cross = (cutEnergy < maxEnergy)
214  ? (0.5/cutEnergy - 0.5/maxEnergy)*pi_hbarc2_over_mc2 * nmpl * nmpl : 0.0;
215  return cross;
216 }
217 
218 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
219 
220 G4double
222  const G4ParticleDefinition* p,
223  G4double kineticEnergy,
224  G4double Z, G4double,
225  G4double cutEnergy,
226  G4double maxEnergy)
227 {
228  G4double cross =
229  Z*ComputeCrossSectionPerElectron(p,kineticEnergy,cutEnergy,maxEnergy);
230  return cross;
231 }
232 
233 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
234 
235 void
237  const G4MaterialCutsCouple*,
238  const G4DynamicParticle* dp,
239  G4double minKinEnergy,
240  G4double maxEnergy)
241 {
242  G4double kineticEnergy = dp->GetKineticEnergy();
243  G4double tmax = MaxSecondaryEnergy(dp->GetDefinition(),kineticEnergy);
244 
245  G4double maxKinEnergy = std::min(maxEnergy,tmax);
246  if(minKinEnergy >= maxKinEnergy) { return; }
247 
248  //G4cout << "CMSmplIonisationWithDeltaModel::SampleSecondaries: E(GeV)= "
249  // << kineticEnergy/GeV << " M(GeV)= " << mass/GeV
250  // << " tmin(MeV)= " << minKinEnergy/MeV << G4endl;
251 
252  G4double totEnergy = kineticEnergy + mass;
253  G4double etot2 = totEnergy*totEnergy;
254  G4double beta2 = kineticEnergy*(kineticEnergy + 2.0*mass)/etot2;
255 
256  // sampling without nuclear size effect
257  G4double q = G4UniformRand();
258  G4double deltaKinEnergy = minKinEnergy*maxKinEnergy
259  /(minKinEnergy*(1.0 - q) + maxKinEnergy*q);
260 
261  // delta-electron is produced
262  G4double totMomentum = totEnergy*sqrt(beta2);
263  G4double deltaMomentum =
264  sqrt(deltaKinEnergy * (deltaKinEnergy + 2.0*electron_mass_c2));
265  G4double cost = deltaKinEnergy * (totEnergy + electron_mass_c2) /
266  (deltaMomentum * totMomentum);
267  cost = std::min(cost, 1.0);
268 
269  G4double sint = sqrt((1.0 - cost)*(1.0 + cost));
270 
271  G4double phi = twopi * G4UniformRand() ;
272 
273  G4ThreeVector deltaDirection(sint*cos(phi),sint*sin(phi), cost);
274  const G4ThreeVector& direction = dp->GetMomentumDirection();
275  deltaDirection.rotateUz(direction);
276 
277  // create G4DynamicParticle object for delta ray
278  G4DynamicParticle* delta =
279  new G4DynamicParticle(theElectron,deltaDirection,deltaKinEnergy);
280 
281  vdp->push_back(delta);
282 
283  // Change kinematics of primary particle
284  kineticEnergy -= deltaKinEnergy;
285  G4ThreeVector finalP = direction*totMomentum - deltaDirection*deltaMomentum;
286  finalP = finalP.unit();
287 
288  fParticleChange->SetProposedKineticEnergy(kineticEnergy);
289  fParticleChange->SetProposedMomentumDirection(finalP);
290 }
291 
292 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
293 
295  const G4MaterialCutsCouple* couple,
296  const G4DynamicParticle* dp,
297  G4double tmax,
298  G4double length,
299  G4double meanLoss)
300 {
301  G4double siga = Dispersion(couple->GetMaterial(),dp,tmax,length);
302  G4double loss = meanLoss;
303  siga = sqrt(siga);
304  G4double twomeanLoss = meanLoss + meanLoss;
305 
306  if(twomeanLoss < siga) {
307  G4double x;
308  do {
309  loss = twomeanLoss*G4UniformRand();
310  x = (loss - meanLoss)/siga;
311  // Loop checking, 07-Aug-2015, Vladimir Ivanchenko
312  } while (1.0 - 0.5*x*x < G4UniformRand());
313  } else {
314  do {
315  loss = G4RandGauss::shoot(meanLoss,siga);
316  // Loop checking, 07-Aug-2015, Vladimir Ivanchenko
317  } while (0.0 > loss || loss > twomeanLoss);
318  }
319  return loss;
320 }
321 
322 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
323 
324 G4double
326  const G4DynamicParticle* dp,
327  G4double tmax,
328  G4double length)
329 {
330  G4double siga = 0.0;
331  G4double tau = dp->GetKineticEnergy()/mass;
332  if(tau > 0.0) {
333  G4double electronDensity = material->GetElectronDensity();
334  G4double gam = tau + 1.0;
335  G4double invbeta2 = (gam*gam)/(tau * (tau+2.0));
336  siga = (invbeta2 - 0.5) * twopi_mc2_rcl2 * tmax * length
337  * electronDensity * chargeSquare;
338  }
339  return siga;
340 }
341 
342 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
343 
344 G4double
346  G4double kinEnergy)
347 {
348  G4double tau = kinEnergy/mass;
349  return 2.0*electron_mass_c2*tau*(tau + 2.);
350 }
351 
352 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
virtual G4double ComputeCrossSectionPerElectron(const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy, G4double maxEnergy)
dbl * delta
Definition: mlp_gen.cc:36
const double GeV
Definition: MathUtil.h:16
const double hbarc
Definition: MathUtil.h:18
G4double ComputeDEDXAhlen(const G4Material *material, G4double bg2, G4double cut)
Sin< T >::type sin(const T &t)
Definition: Sin.h:22
CMSmplIonisationWithDeltaModel(G4double mCharge, const G4String &nam="mplIonisationWithDelta")
The Signals That Services Can Subscribe To This is based on ActivityRegistry and is current per Services can connect to the signals distributed by the ActivityRegistry in order to monitor the activity of the application Each possible callback has some defined which we here list in angle e g
Definition: Activities.doc:4
static std::vector< G4double > * dedx0
const Double_t pi
G4double ComputeDEDXPerVolume(const G4Material *, const G4ParticleDefinition *, G4double kineticEnergy, G4double cutEnergy) override
void SetParticle(const G4ParticleDefinition *p)
G4double SampleFluctuations(const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmax, G4double length, G4double meanLoss) override
T sqrt(T t)
Definition: SSEVec.h:18
Cos< T >::type cos(const T &t)
Definition: Cos.h:22
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
T min(T a, T b)
Definition: MathUtil.h:58
static const std::string B
int k[5][pyjets_maxn]
static const double tmax[3]
G4double MaxSecondaryEnergy(const G4ParticleDefinition *, G4double kinEnergy) override
G4double Dispersion(const G4Material *, const G4DynamicParticle *, G4double tmax, G4double length) override
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition *, G4double kineticEnergy, G4double Z, G4double A, G4double cutEnergy, G4double maxEnergy) override
G4double MinEnergyCut(const G4ParticleDefinition *, const G4MaterialCutsCouple *couple) override
Basic3DVector cross(const Basic3DVector &v) const
Vector product, or "cross" product, with a vector of same type.
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override