ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4NeutronElectronElModel.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4NeutronElectronElModel.cc
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 //
27 // Geant4 Header : G4NeutronElectronElModel
28 //
29 // 16.5.17: V.Grichine
30 //
31 
33 #include "G4SystemOfUnits.hh"
34 #include "G4ParticleTable.hh"
35 #include "G4ParticleDefinition.hh"
36 #include "G4IonTable.hh"
37 #include "Randomize.hh"
38 #include "G4Integrator.hh"
39 #include "G4Electron.hh"
40 #include "G4PhysicsTable.hh"
41 #include "G4PhysicsLogVector.hh"
42 #include "G4PhysicsFreeVector.hh"
43 
44 
45 using namespace std;
46 using namespace CLHEP;
47 
49  : G4HadronElastic(name)
50 {
51  // neutron magneton squared
52 
53  fM = neutron_mass_c2; // neutron mass
54  fM2 = fM*fM;
56  fme2 = fme*fme;
57  fMv2 = 0.7056*GeV*GeV;
58 
59  SetMinEnergy( 0.001*GeV );
60  SetMaxEnergy( 10.*TeV );
62 
64  // PDG2016: sin^2 theta Weinberg
65 
66  fEnergyBin = 200;
67  fMinEnergy = 1.*MeV;
68  fMaxEnergy = 10000.*GeV;
70 
71  fAngleBin = 500;
72  fAngleTable = 0;
73 
74  fCutEnergy = 0.; // default value
75 
76  Initialise();
77 }
78 
80 
82 {
83  if( fEnergyVector )
84  {
85  delete fEnergyVector;
86  fEnergyVector = 0;
87  }
88  if( fAngleTable )
89  {
91  delete fAngleTable;
92  fAngleTable = nullptr;
93  }
94 }
95 
97 
98 void G4NeutronElectronElModel::ModelDescription(std::ostream& outFile) const
99 {
100 
101  outFile << "G4NeutronElectronElModel is a neutrino-electron (neutral current) elastic scattering\n"
102  << "model which uses the standard model \n"
103  << "transfer parameterization. The model is fully relativistic\n";
104 
105 }
106 
108 
110  G4Nucleus & targetNucleus)
111 {
112  G4bool result = false;
113  G4String pName = aTrack.GetDefinition()->GetParticleName();
114  // G4double minEnergy = 0.;
115  G4double energy = aTrack.GetTotalEnergy();
116 
117  if( fCutEnergy > 0. ) // min detected recoil electron energy
118  {
119  // minEnergy = 0.5*(fCutEnergy+sqrt(fCutEnergy*(fCutEnergy+2.*electron_mass_c2)));
120  }
121  if( pName == "neutron" &&
122  energy >= fMinEnergy && energy <= fMaxEnergy )
123  {
124  result = true;
125  }
126  G4int Z = targetNucleus.GetZ_asInt();
127  Z *= 1;
128 
129  return result;
130 }
131 
133 
135 {
136  G4double result = 0., sum, Tkin, dt, t1, t2;
137  G4int iTkin, jTransfer;
139 
141 
142  for( iTkin = 0; iTkin < fEnergyBin; iTkin++)
143  {
144  Tkin = fEnergyVector->GetLowEdgeEnergy(iTkin);
145  fAm = CalculateAm(Tkin);
146  dt = 1./fAngleBin;
147 
149 
150  sum = 0.;
151 
152  for( jTransfer = 0; jTransfer < fAngleBin; jTransfer++)
153  {
154  t1 = dt*jTransfer;
155  t2 = t1 + dt;
156 
157  result = integral.Legendre96( this, &G4NeutronElectronElModel::XscIntegrand, t1, t2 );
158 
159  sum += result;
160  // G4cout<<sum<<", ";
161  vectorT->PutValue(jTransfer, t1, sum);
162  }
163  // G4cout<<G4endl;
164  fAngleTable->insertAt(iTkin,vectorT);
165  }
166  return;
167 }
168 
170 //
171 // sample recoil electron energy in lab frame
172 
174 {
175  G4double result = 0., position;
176  G4int iTkin, iTransfer;
177 
178  for( iTkin = 0; iTkin < fEnergyBin; iTkin++)
179  {
180  if( Tkin < fEnergyVector->GetLowEdgeEnergy(iTkin) ) break;
181  }
182  if ( iTkin >= fEnergyBin ) iTkin = fEnergyBin-1; // Tkin is more then theMaxEnergy
183  if ( iTkin < 0 ) iTkin = 0; // against negative index, Tkin < theMinEnergy
184 
185  position = (*(*fAngleTable)(iTkin))(fAngleBin-1)*G4UniformRand();
186 
187  // G4cout<<"position = "<<position<<G4endl;
188 
189  for( iTransfer = 0; iTransfer < fAngleBin; iTransfer++)
190  {
191  if( position <= (*(*fAngleTable)(iTkin))(iTransfer) ) break;
192  }
193  if (iTransfer >= fAngleBin-1) iTransfer = fAngleBin-1;
194 
195  // G4cout<<"iTransfer = "<<iTransfer<<G4endl;
196 
197  result = GetTransfer(iTkin, iTransfer, position);
198 
199  // G4cout<<"t = "<<t<<G4endl;
200 
201 
202  return result;
203 }
204 
206 
207 G4double
209 {
210  G4double x1, x2, y1, y2, randTransfer, delta, mean, epsilon = 1.e-6;
211 
212  if( iTransfer == 0 || iTransfer == fAngleBin-1 )
213  {
214  randTransfer = (*fAngleTable)(iTkin)->GetLowEdgeEnergy(iTransfer);
215  // iTransfer++;
216  }
217  else
218  {
219  if ( iTransfer >= G4int((*fAngleTable)(iTkin)->GetVectorLength()) )
220  {
221  iTransfer = (*fAngleTable)(iTkin)->GetVectorLength() - 1;
222  }
223  y1 = (*(*fAngleTable)(iTkin))(iTransfer-1);
224  y2 = (*(*fAngleTable)(iTkin))(iTransfer);
225 
226  x1 = (*fAngleTable)(iTkin)->GetLowEdgeEnergy(iTransfer-1);
227  x2 = (*fAngleTable)(iTkin)->GetLowEdgeEnergy(iTransfer);
228 
229  delta = y2 - y1;
230  mean = y2 + y1;
231 
232  if ( x1 == x2 ) randTransfer = x2;
233  else
234  {
235  // if ( y1 == y2 )
236 
237  if ( delta < epsilon*mean )
238  {
239  randTransfer = x1 + ( x2 - x1 )*G4UniformRand();
240  }
241  else
242  {
243  randTransfer = x1 + ( position - y1 )*( x2 - x1 )/delta; // ( y2 - y1 );
244  }
245  }
246  }
247  return randTransfer;
248 }
249 
251 //
252 // Rosenbluth relation (ultra-relativistic!) in the neutron rest frame,
253 // x = sin^2(theta/2), theta is the electron scattering angle
254 // Magnetic form factor in the dipole approximation.
255 
257 {
258  G4double result = 1., q2, znq2, znf, znf2, znf4;
259 
260  znq2 = 1. + 2.*fee*x/fM;
261 
262  q2 = 4.*fee2*x/znq2;
263 
264  znf = 1 + q2/fMv2;
265  znf2 = znf*znf;
266  znf4 = znf2*znf2;
267 
268  result /= ( x + fAm )*znq2*znq2*znf4;
269 
270  result *= ( 1 - x )/( 1 + q2/4./fM2 ) + 2.*x;
271 
272  return result;
273 }
274 
276 //
277 //
278 
280  const G4HadProjectile& aTrack, G4Nucleus& targetNucleus)
281 {
283 
284  const G4HadProjectile* aParticle = &aTrack;
285  G4double Tkin = aParticle->GetKineticEnergy();
286  fAm = CalculateAm( Tkin);
287  // G4double En = aParticle->GetTotalEnergy();
288 
289  if( Tkin <= LowestEnergyLimit() )
290  {
293  return &theParticleChange;
294  }
295  // sample e-scattering angle and make final state in lab frame
296 
297  G4double sin2ht = SampleSin2HalfTheta( Tkin); // in n-rrest frame
298 
299  // G4cout<<"sin2ht = "<<sin2ht<<G4endl;
300 
301  G4double eTkin = fee; // fM;
302 
303  eTkin /= 1.+2.*fee*sin2ht/fM; // fme/En + 2*sin2ht;
304 
305  eTkin -= fme;
306 
307  // G4cout<<"eTkin = "<<eTkin<<G4endl;
308 
309  if( eTkin > fCutEnergy )
310  {
311  G4double ePlab = sqrt( eTkin*(eTkin + 2.*fme) );
312 
313  // G4cout<<"ePlab = "<<ePlab<<G4endl;
314 
315  G4double cost = 1. - 2*sin2ht;
316 
317  if( cost > 1. ) cost = 1.;
318  if( cost < -1. ) cost = -1.;
319 
320  G4double sint = std::sqrt( (1.0 - cost)*(1.0 + cost) );
322 
323  G4ThreeVector eP( sint*std::cos(phi), sint*std::sin(phi), cost );
324  eP *= ePlab;
325  G4LorentzVector lvt2( eP, eTkin + electron_mass_c2 ); // recoil e- in n-rest frame
326 
327  G4LorentzVector lvp1 = aParticle->Get4Momentum();
328  G4LorentzVector lvt1(0.,0.,0.,electron_mass_c2);
329  G4LorentzVector lvsum = lvp1+lvt1;
330 
331  G4ThreeVector bst = lvp1.boostVector();
332  lvt2.boost(bst);
333 
334  // G4cout<<"lvt2 = "<<lvt2<<G4endl;
335 
336  G4DynamicParticle * aSec = new G4DynamicParticle( theElectron, lvt2 );
338 
339  G4LorentzVector lvp2 = lvsum-lvt2;
340 
341  // G4cout<<"lvp2 = "<<lvp2<<G4endl;
342 
343  G4double Tkin2 = lvp2.e()-aParticle->GetDefinition()->GetPDGMass();
346  }
347  else if( eTkin > 0.0 )
348  {
350  Tkin -= eTkin;
351 
352  if( Tkin > 0. )
353  {
356  }
357  }
358  else
359  {
362  }
363  G4int Z = targetNucleus.GetZ_asInt();
364  Z *= 1;
365 
366  return &theParticleChange;
367 }
368 
369 //
370 //