Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/processes/hadronic/models/coherent_elastic/src/G4NeutronElectronElModel.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 
 32 #include "G4NeutronElectronElModel.hh"
 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 #include "G4PhysicsModelCatalog.hh"
 44 
 45 
 46 using namespace std;
 47 using namespace CLHEP;
 48 
 49 G4NeutronElectronElModel::G4NeutronElectronElModel(const G4String& name) 
 50   : G4HadronElastic(name)
 51 {
 52   secID = G4PhysicsModelCatalog::GetModelID( "model_" + name );
 53   
 54  // neutron magneton squared
 55 
 56   fM   = neutron_mass_c2; // neutron mass
 57   fM2  = fM*fM;
 58   fme  = electron_mass_c2;
 59   fme2 = fme*fme;
 60   fMv2 = 0.7056*GeV*GeV;
 61 
 62   SetMinEnergy( 0.001*GeV );
 63   SetMaxEnergy( 10.*TeV );
 64   SetLowestEnergyLimit(1.e-6*eV);  
 65 
 66   theElectron = G4Electron::Electron();
 67   // PDG2016: sin^2 theta Weinberg
 68 
 69   fEnergyBin = 200;
 70   fMinEnergy = 1.*MeV;
 71   fMaxEnergy = 10000.*GeV;
 72   fEnergyVector = new G4PhysicsLogVector(fMinEnergy, fMaxEnergy, fEnergyBin, false);
 73 
 74   fAngleBin = 500;
 75   fAngleTable = 0;
 76 
 77   fCutEnergy = 0.; // default value
 78 
 79   Initialise();
 80 }
 81 
 82 ////////////////////////////////////////////////
 83 
 84 G4NeutronElectronElModel::~G4NeutronElectronElModel()
 85 {
 86   if( fEnergyVector ) 
 87   {
 88     delete fEnergyVector;
 89     fEnergyVector = nullptr;
 90   }
 91   if( fAngleTable )
 92   {
 93     fAngleTable->clearAndDestroy();
 94     delete fAngleTable;
 95     fAngleTable = nullptr;
 96   }
 97 }
 98 
 99 /////////////////////////////////////////
100 
101 void G4NeutronElectronElModel::ModelDescription(std::ostream& outFile) const
102 {
103   outFile << "G4NeutronElectronElModel is a neutrino-electron (neutral current) elastic scattering\n"
104     << "model which uses the standard model \n"
105     << "transfer parameterization.  The model is fully relativistic\n";
106 }
107 
108 /////////////////////////////////////////////////////////
109 
110 G4bool G4NeutronElectronElModel::IsApplicable(const G4HadProjectile & aTrack, G4Nucleus&)
111 {
112   G4String pName = aTrack.GetDefinition()->GetParticleName();
113   G4double energy = aTrack.GetTotalEnergy();
114 
115   return (pName == "neutron" && energy >= fMinEnergy && energy <= fMaxEnergy);                            
116 }
117 
118 ////////////////////////////////////////////////////
119 
120 void  G4NeutronElectronElModel::Initialise()
121 {
122   G4double result = 0., sum, Tkin, dt, t1, t2;
123   G4int iTkin, jTransfer;
124   G4Integrator<G4NeutronElectronElModel, G4double(G4NeutronElectronElModel::*)(G4double)> integral;
125 
126   fAngleTable = new G4PhysicsTable(fEnergyBin);
127 
128   for( iTkin = 0; iTkin < fEnergyBin; iTkin++)
129   {
130     Tkin  = fEnergyVector->GetLowEdgeEnergy(iTkin);
131     fAm      = CalculateAm(Tkin);
132     dt = 1./fAngleBin;
133 
134     G4PhysicsFreeVector* vectorT = new G4PhysicsFreeVector(fAngleBin);
135 
136     sum = 0.;
137 
138     for( jTransfer = 0; jTransfer < fAngleBin; jTransfer++)
139     {
140       t1 = dt*jTransfer;
141       t2 = t1 + dt;
142 
143       result = integral.Legendre96( this, &G4NeutronElectronElModel::XscIntegrand, t1, t2 );
144 
145       sum += result;
146       // G4cout<<sum<<", ";
147       vectorT->PutValue(jTransfer, t1, sum);
148     }
149     // G4cout<<G4endl;   
150     fAngleTable->insertAt(iTkin,vectorT);
151   }
152   return;
153 }
154 
155 //////////////////////////////////////////////////////
156 //
157 // sample recoil electron energy in lab frame
158 
159 G4double G4NeutronElectronElModel::SampleSin2HalfTheta(G4double Tkin)
160 {
161   G4double result = 0., position; 
162   G4int iTkin, iTransfer;
163 
164   for( iTkin = 0; iTkin < fEnergyBin; iTkin++)
165   {
166     if( Tkin < fEnergyVector->Energy(iTkin) ) break;
167   }  
168   if ( iTkin >= fEnergyBin ) iTkin = fEnergyBin-1;   // Tkin is more then theMaxEnergy
169   if ( iTkin < 0 )           iTkin = 0; // against negative index, Tkin < theMinEnergy
170 
171     position = (*(*fAngleTable)(iTkin))(fAngleBin-1)*G4UniformRand();
172 
173     // G4cout<<"position = "<<position<<G4endl;
174 
175     for( iTransfer = 0; iTransfer < fAngleBin; iTransfer++)
176     {
177       if( position <= (*(*fAngleTable)(iTkin))(iTransfer) ) break;
178     }
179     if (iTransfer >= fAngleBin-1) iTransfer = fAngleBin-1;
180 
181     // G4cout<<"iTransfer = "<<iTransfer<<G4endl;
182 
183     result = GetTransfer(iTkin, iTransfer, position);
184 
185     // G4cout<<"t = "<<t<<G4endl;
186   
187 
188   return result;
189 }
190 
191 /////////////////////////////////////////////////
192 
193 G4double 
194 G4NeutronElectronElModel:: GetTransfer( G4int iTkin, G4int iTransfer, G4double position )
195 {
196   G4double x1, x2, y1, y2, randTransfer, delta, mean, epsilon = 1.e-6;
197 
198   if( iTransfer == 0 ||  iTransfer == fAngleBin-1 )
199   {
200     randTransfer = (*fAngleTable)(iTkin)->Energy(iTransfer);
201   }
202   else
203   {
204     if ( iTransfer >= G4int((*fAngleTable)(iTkin)->GetVectorLength()) )
205     {
206       iTransfer = G4int((*fAngleTable)(iTkin)->GetVectorLength() - 1);
207     }
208     y1 = (*(*fAngleTable)(iTkin))(iTransfer-1);
209     y2 = (*(*fAngleTable)(iTkin))(iTransfer);
210 
211     x1 = (*fAngleTable)(iTkin)->Energy(iTransfer-1);
212     x2 = (*fAngleTable)(iTkin)->Energy(iTransfer);
213 
214     delta = y2 - y1;
215     mean  = y2 + y1;
216 
217     if ( x1 == x2 ) randTransfer = x2;
218     else
219     {
220       if ( delta < epsilon*mean ) 
221       {
222         randTransfer = x1 + ( x2 - x1 )*G4UniformRand();
223       }
224       else 
225       {
226         randTransfer = x1 + ( position - y1 )*( x2 - x1 )/delta; // ( y2 - y1 );
227       }
228     }
229   }
230   return randTransfer;
231 }
232 
233 //////////////////////////////////////////////////////////////
234 //
235 // Rosenbluth relation (ultra-relativistic!) in the neutron rest frame, 
236 // x = sin^2(theta/2), theta is the electron scattering angle
237 // Magnetic form factor in the dipole approximation.
238 
239 G4double G4NeutronElectronElModel::XscIntegrand(G4double x)
240 {
241   G4double result = 1., q2, znq2, znf, znf2, znf4;
242 
243   znq2 = 1. + 2.*fee*x/fM;
244 
245   q2 = 4.*fee2*x/znq2;
246 
247   znf  = 1 + q2/fMv2;
248   znf2 = znf*znf;
249   znf4 = znf2*znf2;
250 
251   result /= ( x + fAm )*znq2*znq2*znf4; 
252 
253   result *= ( 1 - x )/( 1 + q2/4./fM2 ) + 2.*x;
254 
255   return result;
256 }
257 
258 ////////////////////////////////////////////////
259 //
260 //
261 
262 G4HadFinalState* G4NeutronElectronElModel::ApplyYourself(
263      const G4HadProjectile& aTrack, G4Nucleus&)
264 {
265   theParticleChange.Clear();
266 
267   const G4HadProjectile* aParticle = &aTrack;
268   G4double Tkin = aParticle->GetKineticEnergy();
269   fAm = CalculateAm( Tkin);
270   //   G4double En = aParticle->GetTotalEnergy();
271 
272   if( Tkin <= LowestEnergyLimit() ) 
273   {
274     theParticleChange.SetEnergyChange(Tkin);
275     theParticleChange.SetMomentumChange(aTrack.Get4Momentum().vect().unit());
276     return &theParticleChange;
277   }
278   // sample e-scattering angle and make final state in lab frame
279 
280   G4double sin2ht = SampleSin2HalfTheta( Tkin); // in n-rrest frame
281 
282   // G4cout<<"sin2ht = "<<sin2ht<<G4endl;
283 
284   G4double eTkin = fee; // fM;
285 
286   eTkin /= 1.+2.*fee*sin2ht/fM; // fme/En + 2*sin2ht;
287 
288   eTkin -= fme;
289 
290   // G4cout<<"eTkin = "<<eTkin<<G4endl;
291 
292   if( eTkin > fCutEnergy )
293   {
294     G4double ePlab = sqrt( eTkin*(eTkin + 2.*fme) );
295 
296     // G4cout<<"ePlab = "<<ePlab<<G4endl;
297 
298     G4double cost = 1. - 2*sin2ht;
299 
300     if( cost >  1. ) cost = 1.;
301     if( cost < -1. ) cost = -1.;
302 
303     G4double sint = std::sqrt( (1.0 - cost)*(1.0 + cost) );
304     G4double phi  = G4UniformRand()*CLHEP::twopi;
305 
306     G4ThreeVector eP( sint*std::cos(phi), sint*std::sin(phi), cost );
307     eP *= ePlab;
308     G4LorentzVector lvt2( eP, eTkin + electron_mass_c2 ); // recoil e- in n-rest frame
309 
310     G4LorentzVector lvp1 = aParticle->Get4Momentum();
311     G4LorentzVector lvt1(0.,0.,0.,electron_mass_c2);
312     G4LorentzVector lvsum = lvp1+lvt1;
313 
314     G4ThreeVector bst = lvp1.boostVector();
315     lvt2.boost(bst);
316 
317     // G4cout<<"lvt2 = "<<lvt2<<G4endl;
318 
319     G4DynamicParticle * aSec = new G4DynamicParticle( theElectron, lvt2 );
320     theParticleChange.AddSecondary( aSec, secID );
321 
322     G4LorentzVector lvp2 = lvsum-lvt2;
323 
324     // G4cout<<"lvp2 = "<<lvp2<<G4endl;
325 
326     G4double Tkin2 = lvp2.e()-aParticle->GetDefinition()->GetPDGMass();
327     theParticleChange.SetEnergyChange(Tkin2);
328     theParticleChange.SetMomentumChange(lvp2.vect().unit());
329   }
330   else if( eTkin > 0.0 ) 
331   {
332     theParticleChange.SetLocalEnergyDeposit( eTkin );
333     Tkin -= eTkin;
334 
335     if( Tkin > 0. )
336     {
337       theParticleChange.SetEnergyChange( Tkin );
338       theParticleChange.SetMomentumChange( aTrack.Get4Momentum().vect().unit() );
339     }
340   }
341   else 
342   {
343     theParticleChange.SetEnergyChange( Tkin );
344     theParticleChange.SetMomentumChange( aTrack.Get4Momentum().vect().unit() );
345   }
346   return &theParticleChange;
347 }
348 
349 //
350 //
351 ///////////////////////////
352