Geant4  10.01.p03
G4DNARuddIonisationModel.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 // $Id: G4DNARuddIonisationModel.cc 81552 2014-06-03 08:28:18Z gcosmo $
27 // GEANT4 tag $Name: $
28 //
29 
31 #include "G4PhysicalConstants.hh"
32 #include "G4SystemOfUnits.hh"
33 #include "G4UAtomicDeexcitation.hh"
34 #include "G4LossTableManager.hh"
35 #include "G4DNAChemistryManager.hh"
37 #include "G4DNARuddAngle.hh"
38 #include "G4DeltaAngle.hh"
39 
40 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
41 
42 using namespace std;
43 
44 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
45 
47  const G4String& nam)
48  :G4VEmModel(nam),isInitialised(false)
49 {
50  // nistwater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
51  fpWaterDensity = 0;
52 
56  sCoefficient[0]=0.;
57  sCoefficient[1]=0.;
58  sCoefficient[2]=0.;
59 
60  lowEnergyLimitForZ1 = 0 * eV;
61  lowEnergyLimitForZ2 = 0 * eV;
66 
67  verboseLevel= 0;
68  // Verbosity scale:
69  // 0 = nothing
70  // 1 = warning for energy non-conservation
71  // 2 = details of energy budget
72  // 3 = calculation of cross sections, file openings, sampling of atoms
73  // 4 = entering in methods
74 
75  if( verboseLevel>0 )
76  {
77  G4cout << "Rudd ionisation model is constructed " << G4endl;
78  }
79 
80  // define default angular generator
82 
83  //Mark this model as "applicable" for atomic deexcitation
84  SetDeexcitationFlag(true);
87 }
88 
89 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
90 
92 {
93  // Cross section
94 
95  std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
96  for (pos = tableData.begin(); pos != tableData.end(); ++pos)
97  {
98  G4DNACrossSectionDataSet* table = pos->second;
99  delete table;
100  }
101 
102 
103  // The following removal is forbidden since G4VEnergyLossmodel takes care of deletion
104  // Coverity however will signal this as an error
105  //if (fAtomDeexcitation) {delete fAtomDeexcitation;}
106 
107 }
108 
109 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
110 
112  const G4DataVector& /*cuts*/)
113 {
114 
115  if (verboseLevel > 3)
116  G4cout << "Calling G4DNARuddIonisationModel::Initialise()" << G4endl;
117 
118  // Energy limits
119 
120  G4String fileProton("dna/sigma_ionisation_p_rudd");
121  G4String fileHydrogen("dna/sigma_ionisation_h_rudd");
122  G4String fileAlphaPlusPlus("dna/sigma_ionisation_alphaplusplus_rudd");
123  G4String fileAlphaPlus("dna/sigma_ionisation_alphaplus_rudd");
124  G4String fileHelium("dna/sigma_ionisation_he_rudd");
125 
129  G4ParticleDefinition* hydrogenDef = instance->GetIon("hydrogen");
130  G4ParticleDefinition* alphaPlusPlusDef = instance->GetIon("alpha++");
131  G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
132  G4ParticleDefinition* heliumDef = instance->GetIon("helium");
133 
135  G4String hydrogen;
136  G4String alphaPlusPlus;
137  G4String alphaPlus;
138  G4String helium;
139 
140  G4double scaleFactor = 1 * m*m;
141 
142  // LIMITS AND DATA
143 
144  // ********************************************************
145 
146  proton = protonDef->GetParticleName();
147  tableFile[proton] = fileProton;
148 
150  highEnergyLimit[proton] = 500. * keV;
151 
152  // Cross section
153 
155  eV,
156  scaleFactor );
157  tableProton->LoadData(fileProton);
158  tableData[proton] = tableProton;
159 
160  // ********************************************************
161 
162  hydrogen = hydrogenDef->GetParticleName();
163  tableFile[hydrogen] = fileHydrogen;
164 
166  highEnergyLimit[hydrogen] = 100. * MeV;
167 
168  // Cross section
169 
171  eV,
172  scaleFactor );
173  tableHydrogen->LoadData(fileHydrogen);
174 
175  tableData[hydrogen] = tableHydrogen;
176 
177  // ********************************************************
178 
179  alphaPlusPlus = alphaPlusPlusDef->GetParticleName();
180  tableFile[alphaPlusPlus] = fileAlphaPlusPlus;
181 
182  lowEnergyLimit[alphaPlusPlus] = lowEnergyLimitForZ2;
183  highEnergyLimit[alphaPlusPlus] = 400. * MeV;
184 
185  // Cross section
186 
188  eV,
189  scaleFactor );
190  tableAlphaPlusPlus->LoadData(fileAlphaPlusPlus);
191 
192  tableData[alphaPlusPlus] = tableAlphaPlusPlus;
193 
194  // ********************************************************
195 
196  alphaPlus = alphaPlusDef->GetParticleName();
197  tableFile[alphaPlus] = fileAlphaPlus;
198 
199  lowEnergyLimit[alphaPlus] = lowEnergyLimitForZ2;
200  highEnergyLimit[alphaPlus] = 400. * MeV;
201 
202  // Cross section
203 
205  eV,
206  scaleFactor );
207  tableAlphaPlus->LoadData(fileAlphaPlus);
208  tableData[alphaPlus] = tableAlphaPlus;
209 
210  // ********************************************************
211 
212  helium = heliumDef->GetParticleName();
213  tableFile[helium] = fileHelium;
214 
216  highEnergyLimit[helium] = 400. * MeV;
217 
218  // Cross section
219 
221  eV,
222  scaleFactor );
223  tableHelium->LoadData(fileHelium);
224  tableData[helium] = tableHelium;
225 
226  //
227 
228  if (particle==protonDef)
229  {
232  }
233 
234  if (particle==hydrogenDef)
235  {
238  }
239 
240  if (particle==heliumDef)
241  {
244  }
245 
246  if (particle==alphaPlusDef)
247  {
248  SetLowEnergyLimit(lowEnergyLimit[alphaPlus]);
250  }
251 
252  if (particle==alphaPlusPlusDef)
253  {
254  SetLowEnergyLimit(lowEnergyLimit[alphaPlusPlus]);
255  SetHighEnergyLimit(highEnergyLimit[alphaPlusPlus]);
256  }
257 
258  if( verboseLevel>0 )
259  {
260  G4cout << "Rudd ionisation model is initialized " << G4endl
261  << "Energy range: "
262  << LowEnergyLimit() / eV << " eV - "
263  << HighEnergyLimit() / keV << " keV for "
264  << particle->GetParticleName()
265  << G4endl;
266  }
267 
268  // Initialize water density pointer
270 
271  //
272 
274 
275  if (isInitialised) { return; }
277  isInitialised = true;
278 
279 }
280 
281 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
282 
284  const G4ParticleDefinition* particleDefinition,
285  G4double k,
286  G4double,
287  G4double)
288 {
289  if (verboseLevel > 3)
290  G4cout << "Calling CrossSectionPerVolume() of G4DNARuddIonisationModel" << G4endl;
291 
292  // Calculate total cross section for model
293 
296 
297  if (
298  particleDefinition != G4Proton::ProtonDefinition()
299  &&
300  particleDefinition != instance->GetIon("hydrogen")
301  &&
302  particleDefinition != instance->GetIon("alpha++")
303  &&
304  particleDefinition != instance->GetIon("alpha+")
305  &&
306  particleDefinition != instance->GetIon("helium")
307  )
308 
309  return 0;
310 
311  G4double lowLim = 0;
312 
313  if ( particleDefinition == G4Proton::ProtonDefinition()
314  || particleDefinition == instance->GetIon("hydrogen")
315  )
316 
318 
319  if ( particleDefinition == instance->GetIon("alpha++")
320  || particleDefinition == instance->GetIon("alpha+")
321  || particleDefinition == instance->GetIon("helium")
322  )
323 
325 
326  G4double highLim = 0;
327  G4double sigma=0;
328 
329  G4double waterDensity = (*fpWaterDensity)[material->GetIndex()];
330 
331  if(waterDensity!= 0.0)
332  // if (material == nistwater || material->GetBaseMaterial() == nistwater)
333  {
334  const G4String& particleName = particleDefinition->GetParticleName();
335 
336  // SI - the following is useless since lowLim is already defined
337 /*
338  std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
339  pos1 = lowEnergyLimit.find(particleName);
340 
341  if (pos1 != lowEnergyLimit.end())
342  {
343  lowLim = pos1->second;
344  }
345 */
346 
347  std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
348  pos2 = highEnergyLimit.find(particleName);
349 
350  if (pos2 != highEnergyLimit.end())
351  {
352  highLim = pos2->second;
353  }
354 
355  if (k <= highLim)
356  {
357  //SI : XS must not be zero otherwise sampling of secondaries method ignored
358 
359  if (k < lowLim) k = lowLim;
360 
361  //
362 
363  std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
364  pos = tableData.find(particleName);
365 
366  if (pos != tableData.end())
367  {
368  G4DNACrossSectionDataSet* table = pos->second;
369  if (table != 0)
370  {
371  sigma = table->FindValue(k);
372  }
373  }
374  else
375  {
376  G4Exception("G4DNARuddIonisationModel::CrossSectionPerVolume","em0002",
377  FatalException,"Model not applicable to particle type.");
378  }
379 
380  } // if (k >= lowLim && k < highLim)
381 
382  if (verboseLevel > 2)
383  {
384  G4cout << "__________________________________" << G4endl;
385  G4cout << "°°° G4DNARuddIonisationModel - XS INFO START" << G4endl;
386  G4cout << "°°° Kinetic energy(eV)=" << k/eV << " particle : " << particleDefinition->GetParticleName() << G4endl;
387  G4cout << "°°° Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
388  G4cout << "°°° Cross section per water molecule (cm^-1)=" << sigma*waterDensity/(1./cm) << G4endl;
389  // G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
390  G4cout << "°°° G4DNARuddIonisationModel - XS INFO END" << G4endl;
391  }
392 
393  } // if (waterMaterial)
394  else
395  {
396  if (verboseLevel > 2)
397  {
398  G4cout << "Warning : RuddIonisationModel: WATER DENSITY IS NULL" << G4endl;
399  }
400  }
401 
402  return sigma*waterDensity;
403  // return sigma*material->GetAtomicNumDensityVector()[1];
404 
405 }
406 
407 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
408 
409 void G4DNARuddIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
410  const G4MaterialCutsCouple* couple,
411  const G4DynamicParticle* particle,
412  G4double,
413  G4double)
414 {
415  if (verboseLevel > 3)
416  G4cout << "Calling SampleSecondaries() of G4DNARuddIonisationModel" << G4endl;
417 
418  G4double lowLim = 0;
419  G4double highLim = 0;
420 
423 
424  if ( particle->GetDefinition() == G4Proton::ProtonDefinition()
425  || particle->GetDefinition() == instance->GetIon("hydrogen")
426  )
427 
428  lowLim = killBelowEnergyForZ1;
429 
430  if ( particle->GetDefinition() == instance->GetIon("alpha++")
431  || particle->GetDefinition() == instance->GetIon("alpha+")
432  || particle->GetDefinition() == instance->GetIon("helium")
433  )
434 
435  lowLim = killBelowEnergyForZ2;
436 
437  G4double k = particle->GetKineticEnergy();
438 
439  const G4String& particleName = particle->GetDefinition()->GetParticleName();
440 
441  // SI - the following is useless since lowLim is already defined
442  /*
443  std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
444  pos1 = lowEnergyLimit.find(particleName);
445 
446  if (pos1 != lowEnergyLimit.end())
447  {
448  lowLim = pos1->second;
449  }
450  */
451 
452  std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
453  pos2 = highEnergyLimit.find(particleName);
454 
455  if (pos2 != highEnergyLimit.end())
456  {
457  highLim = pos2->second;
458  }
459 
460  if (k >= lowLim && k <= highLim)
461  {
462  G4ParticleDefinition* definition = particle->GetDefinition();
463  G4ParticleMomentum primaryDirection = particle->GetMomentumDirection();
464  /*
465  G4double particleMass = definition->GetPDGMass();
466  G4double totalEnergy = k + particleMass;
467  G4double pSquare = k*(totalEnergy+particleMass);
468  G4double totalMomentum = std::sqrt(pSquare);
469  */
470 
471  G4int ionizationShell = RandomSelect(k,particleName);
472 
473  // sample deexcitation
474  // here we assume that H_{2}O electronic levels are the same of Oxigen.
475  // this can be considered true with a rough 10% error in energy on K-shell,
476 
477  G4int secNumberInit = 0; // need to know at a certain point the enrgy of secondaries
478  G4int secNumberFinal = 0; // So I'll make the diference and then sum the energies
479 
481  bindingEnergy = waterStructure.IonisationEnergy(ionizationShell);
482 
483  G4int Z = 8;
484  if(fAtomDeexcitation) {
486 
487  if (ionizationShell <5 && ionizationShell >1)
488  {
489  as = G4AtomicShellEnumerator(4-ionizationShell);
490  }
491  else if (ionizationShell <2)
492  {
493  as = G4AtomicShellEnumerator(3);
494  }
495 
496 
497 
498  // DEBUG
499  // if (ionizationShell == 4) {
500  //
501  // G4cout << "Z: " << Z << " as: " << as
502  // << " ionizationShell: " << ionizationShell << " bindingEnergy: "<< bindingEnergy/eV << G4endl;
503  // G4cout << "Press <Enter> key to continue..." << G4endl;
504  // G4cin.ignore();
505  // }
506 
507  const G4AtomicShell* shell = fAtomDeexcitation->GetAtomicShell(Z, as);
508  secNumberInit = fvect->size();
509  fAtomDeexcitation->GenerateParticles(fvect, shell, Z, 0, 0);
510  secNumberFinal = fvect->size();
511  }
512 
513 
514  G4double secondaryKinetic = RandomizeEjectedElectronEnergy(definition,k,ionizationShell);
515 
516  G4ThreeVector deltaDirection =
517  GetAngularDistribution()->SampleDirectionForShell(particle, secondaryKinetic,
518  Z, ionizationShell,
519  couple->GetMaterial());
520 
521  // Ignored for ions on electrons
522  /*
523  G4double deltaTotalMomentum = std::sqrt(secondaryKinetic*(secondaryKinetic + 2.*electron_mass_c2 ));
524 
525  G4double finalPx = totalMomentum*primaryDirection.x() - deltaTotalMomentum*deltaDirection.x();
526  G4double finalPy = totalMomentum*primaryDirection.y() - deltaTotalMomentum*deltaDirection.y();
527  G4double finalPz = totalMomentum*primaryDirection.z() - deltaTotalMomentum*deltaDirection.z();
528  G4double finalMomentum = std::sqrt(finalPx*finalPx+finalPy*finalPy+finalPz*finalPz);
529  finalPx /= finalMomentum;
530  finalPy /= finalMomentum;
531  finalPz /= finalMomentum;
532 
533  G4ThreeVector direction;
534  direction.set(finalPx,finalPy,finalPz);
535 
536  fParticleChangeForGamma->ProposeMomentumDirection(direction.unit()) ;
537  */
539 
540  G4double scatteredEnergy = k-bindingEnergy-secondaryKinetic;
541  G4double deexSecEnergy = 0;
542  for (G4int j=secNumberInit; j < secNumberFinal; j++) {
543 
544  deexSecEnergy = deexSecEnergy + (*fvect)[j]->GetKineticEnergy();
545 
546  }
547 
549  fParticleChangeForGamma->ProposeLocalEnergyDeposit(k-scatteredEnergy-secondaryKinetic-deexSecEnergy);
550 
551  // debug
552  // k-scatteredEnergy-secondaryKinetic-deexSecEnergy = k-(k-bindingEnergy-secondaryKinetic)-secondaryKinetic-deexSecEnergy =
553  // = k-k+bindingEnergy+secondaryKinetic-secondaryKinetic-deexSecEnergy=
554  // = bindingEnergy-deexSecEnergy
555  // SO deexSecEnergy=0 => LocalEnergyDeposit = bindingEnergy
556 
557  G4DynamicParticle* dp = new G4DynamicParticle (G4Electron::Electron(),deltaDirection,secondaryKinetic) ;
558  fvect->push_back(dp);
559 
560  const G4Track * theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack();
562  ionizationShell,
563  theIncomingTrack);
564  }
565 
566  // SI - not useful since low energy of model is 0 eV
567 
568  if (k < lowLim)
569  {
573  }
574 
575 }
576 
577 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
578 
580  G4double k,
581  G4int shell)
582 {
583  G4double maximumKineticEnergyTransfer = 0.;
584 
587 
588  if (particleDefinition == G4Proton::ProtonDefinition()
589  || particleDefinition == instance->GetIon("hydrogen"))
590  {
591  maximumKineticEnergyTransfer= 4.* (electron_mass_c2 / proton_mass_c2) * k;
592  }
593 
594  else if (particleDefinition == instance->GetIon("helium")
595  || particleDefinition == instance->GetIon("alpha+")
596  || particleDefinition == instance->GetIon("alpha++"))
597  {
598  maximumKineticEnergyTransfer= 4.* (0.511 / 3728) * k;
599  }
600 
601  G4double crossSectionMaximum = 0.;
602 
603  for(G4double value=waterStructure.IonisationEnergy(shell); value<=5.*waterStructure.IonisationEnergy(shell) && k>=value ; value+=0.1*eV)
604  {
605  G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k, value, shell);
606  if(differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
607  }
608 
609 
610  G4double secElecKinetic = 0.;
611 
612  do
613  {
614  secElecKinetic = G4UniformRand() * maximumKineticEnergyTransfer;
615  } while(G4UniformRand()*crossSectionMaximum > DifferentialCrossSection(particleDefinition,
616  k,
617  secElecKinetic+waterStructure.IonisationEnergy(shell),
618  shell));
619 
620  return(secElecKinetic);
621 }
622 
623 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
624 
625 // The following section is not used anymore but is kept for memory
626 // GetAngularDistribution()->SampleDirectionForShell is used instead
627 
628 /*
629 void G4DNARuddIonisationModel::RandomizeEjectedElectronDirection(G4ParticleDefinition* particleDefinition,
630  G4double k,
631  G4double secKinetic,
632  G4double & cosTheta,
633  G4double & phi )
634 {
635  G4DNAGenericIonsManager *instance;
636  instance = G4DNAGenericIonsManager::Instance();
637 
638  G4double maxSecKinetic = 0.;
639 
640  if (particleDefinition == G4Proton::ProtonDefinition()
641  || particleDefinition == instance->GetIon("hydrogen"))
642  {
643  maxSecKinetic = 4.* (electron_mass_c2 / proton_mass_c2) * k;
644  }
645 
646  else if (particleDefinition == instance->GetIon("helium")
647  || particleDefinition == instance->GetIon("alpha+")
648  || particleDefinition == instance->GetIon("alpha++"))
649  {
650  maxSecKinetic = 4.* (0.511 / 3728) * k;
651  }
652 
653  phi = twopi * G4UniformRand();
654 
655  // cosTheta = std::sqrt(secKinetic / maxSecKinetic);
656 
657  // Restriction below 100 eV from Emfietzoglou (2000)
658 
659  if (secKinetic>100*eV) cosTheta = std::sqrt(secKinetic / maxSecKinetic);
660  else cosTheta = (2.*G4UniformRand())-1.;
661 
662 }
663 */
664 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
665 
666 
668  G4double k,
669  G4double energyTransfer,
670  G4int ionizationLevelIndex)
671 {
672  // Shells ids are 0 1 2 3 4 (4 is k shell)
673  // !!Attention, "energyTransfer" here is the energy transfered to the electron which means
674  // that the secondary kinetic energy is w = energyTransfer - bindingEnergy
675  //
676  // ds S F1(nu) + w * F2(nu)
677  // ---- = G(k) * ---- -------------------------------------------
678  // dw Bj (1+w)^3 * [1 + exp{alpha * (w - wc) / nu}]
679  //
680  // w is the secondary electron kinetic Energy in eV
681  //
682  // All the other parameters can be found in Rudd's Papers
683  //
684  // M.Eugene Rudd, 1988, User-Friendly model for the energy distribution of
685  // electrons from protons or electron collisions. Nucl. Tracks Rad. Meas.Vol 16 N0 2/3 pp 219-218
686  //
687 
688  const G4int j=ionizationLevelIndex;
689 
690  G4double A1 ;
691  G4double B1 ;
692  G4double C1 ;
693  G4double D1 ;
694  G4double E1 ;
695  G4double A2 ;
696  G4double B2 ;
697  G4double C2 ;
698  G4double D2 ;
699  G4double alphaConst ;
700 
701  // const G4double Bj[5] = {12.61*eV, 14.73*eV, 18.55*eV, 32.20*eV, 539.7*eV};
702  // The following values are provided by M. dingfelder (priv. comm)
703  const G4double Bj[5] = {12.60*eV, 14.70*eV, 18.40*eV, 32.20*eV, 540*eV};
704 
705  if (j == 4)
706  {
707  //Data For Liquid Water K SHELL from Dingfelder (Protons in Water)
708  A1 = 1.25;
709  B1 = 0.5;
710  C1 = 1.00;
711  D1 = 1.00;
712  E1 = 3.00;
713  A2 = 1.10;
714  B2 = 1.30;
715  C2 = 1.00;
716  D2 = 0.00;
717  alphaConst = 0.66;
718  }
719  else
720  {
721  //Data For Liquid Water from Dingfelder (Protons in Water)
722  A1 = 1.02;
723  B1 = 82.0;
724  C1 = 0.45;
725  D1 = -0.80;
726  E1 = 0.38;
727  A2 = 1.07;
728  // Value provided by M. Dingfelder (priv. comm)
729  B2 = 11.6;
730  //
731  C2 = 0.60;
732  D2 = 0.04;
733  alphaConst = 0.64;
734  }
735 
736  const G4double n = 2.;
737  const G4double Gj[5] = {0.99, 1.11, 1.11, 0.52, 1.};
738 
741 
742  G4double wBig = (energyTransfer - waterStructure.IonisationEnergy(ionizationLevelIndex));
743  if (wBig<0) return 0.;
744 
745  G4double w = wBig / Bj[ionizationLevelIndex];
746  // Note that the following (j==4) cases are provided by M. Dingfelder (priv. comm)
747  if (j==4) w = wBig / waterStructure.IonisationEnergy(ionizationLevelIndex);
748 
749  G4double Ry = 13.6*eV;
750 
751  G4double tau = 0.;
752 
753  G4bool isProtonOrHydrogen = false;
754  G4bool isHelium = false;
755 
756  if (particleDefinition == G4Proton::ProtonDefinition()
757  || particleDefinition == instance->GetIon("hydrogen"))
758  {
759  isProtonOrHydrogen = true;
760  tau = (electron_mass_c2/proton_mass_c2) * k ;
761  }
762 
763  else if ( particleDefinition == instance->GetIon("helium")
764  || particleDefinition == instance->GetIon("alpha+")
765  || particleDefinition == instance->GetIon("alpha++"))
766  {
767  isHelium = true;
768  tau = (0.511/3728.) * k ;
769  }
770 
771  G4double S = 4.*pi * Bohr_radius*Bohr_radius * n * std::pow((Ry/Bj[ionizationLevelIndex]),2);
772  if (j==4) S = 4.*pi * Bohr_radius*Bohr_radius * n * std::pow((Ry/waterStructure.IonisationEnergy(ionizationLevelIndex)),2);
773 
774  G4double v2 = tau / Bj[ionizationLevelIndex];
775  if (j==4) v2 = tau / waterStructure.IonisationEnergy(ionizationLevelIndex);
776 
777  G4double v = std::sqrt(v2);
778  G4double wc = 4.*v2 - 2.*v - (Ry/(4.*Bj[ionizationLevelIndex]));
779  if (j==4) wc = 4.*v2 - 2.*v - (Ry/(4.*waterStructure.IonisationEnergy(ionizationLevelIndex)));
780 
781  G4double L1 = (C1* std::pow(v,(D1))) / (1.+ E1*std::pow(v, (D1+4.)));
782  G4double L2 = C2*std::pow(v,(D2));
783  G4double H1 = (A1*std::log(1.+v2)) / (v2+(B1/v2));
784  G4double H2 = (A2/v2) + (B2/(v2*v2));
785 
786  G4double F1 = L1+H1;
787  G4double F2 = (L2*H2)/(L2+H2);
788 
789  G4double sigma = CorrectionFactor(particleDefinition, k)
790  * Gj[j] * (S/Bj[ionizationLevelIndex])
791  * ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
792 
793  if (j==4) sigma = CorrectionFactor(particleDefinition, k)
794  * Gj[j] * (S/waterStructure.IonisationEnergy(ionizationLevelIndex))
795  * ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
796 
797  if ( (particleDefinition == instance->GetIon("hydrogen")) && (ionizationLevelIndex==4))
798  {
799  // sigma = Gj[j] * (S/Bj[ionizationLevelIndex])
800  sigma = Gj[j] * (S/waterStructure.IonisationEnergy(ionizationLevelIndex))
801  * ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
802  }
803 // if ( particleDefinition == G4Proton::ProtonDefinition()
804 // || particleDefinition == instance->GetIon("hydrogen")
805 // )
806  if(isProtonOrHydrogen)
807  {
808  return(sigma);
809  }
810 
811  if (particleDefinition == instance->GetIon("alpha++") )
812  {
813  slaterEffectiveCharge[0]=0.;
814  slaterEffectiveCharge[1]=0.;
815  slaterEffectiveCharge[2]=0.;
816  sCoefficient[0]=0.;
817  sCoefficient[1]=0.;
818  sCoefficient[2]=0.;
819  }
820 
821  else if (particleDefinition == instance->GetIon("alpha+") )
822  {
823  slaterEffectiveCharge[0]=2.0;
824  // The following values are provided by M. Dingfelder (priv. comm)
825  slaterEffectiveCharge[1]=2.0;
826  slaterEffectiveCharge[2]=2.0;
827  //
828  sCoefficient[0]=0.7;
829  sCoefficient[1]=0.15;
830  sCoefficient[2]=0.15;
831  }
832 
833  else if (particleDefinition == instance->GetIon("helium") )
834  {
835  slaterEffectiveCharge[0]=1.7;
836  slaterEffectiveCharge[1]=1.15;
837  slaterEffectiveCharge[2]=1.15;
838  sCoefficient[0]=0.5;
839  sCoefficient[1]=0.25;
840  sCoefficient[2]=0.25;
841  }
842 
843 // if ( particleDefinition == instance->GetIon("helium")
844 // || particleDefinition == instance->GetIon("alpha+")
845 // || particleDefinition == instance->GetIon("alpha++")
846 // )
847  if(isHelium)
848  {
849  sigma = Gj[j] * (S/Bj[ionizationLevelIndex]) * ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
850 
851  if (j==4) sigma = Gj[j] * (S/waterStructure.IonisationEnergy(ionizationLevelIndex))
852  * ( (F1+w*F2) / ( std::pow((1.+w),3) * ( 1.+std::exp(alphaConst*(w-wc)/v))) );
853 
854  G4double zEff = particleDefinition->GetPDGCharge() / eplus + particleDefinition->GetLeptonNumber();
855 
856  zEff -= ( sCoefficient[0] * S_1s(k, energyTransfer, slaterEffectiveCharge[0], 1.) +
857  sCoefficient[1] * S_2s(k, energyTransfer, slaterEffectiveCharge[1], 2.) +
858  sCoefficient[2] * S_2p(k, energyTransfer, slaterEffectiveCharge[2], 2.) );
859 
860  return zEff * zEff * sigma ;
861  }
862 
863  return 0;
864 }
865 
866 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
867 
869  G4double energyTransferred,
870  G4double slaterEffectiveChg,
871  G4double shellNumber)
872 {
873  // 1 - e^(-2r) * ( 1 + 2 r + 2 r^2)
874  // Dingfelder, in Chattanooga 2005 proceedings, formula (7)
875 
876  G4double r = R(t, energyTransferred, slaterEffectiveChg, shellNumber);
877  G4double value = 1. - std::exp(-2 * r) * ( ( 2. * r + 2. ) * r + 1. );
878 
879  return value;
880 }
881 
882 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
883 
885  G4double energyTransferred,
886  G4double slaterEffectiveChg,
887  G4double shellNumber)
888 {
889  // 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 2 r^4)
890  // Dingfelder, in Chattanooga 2005 proceedings, formula (8)
891 
892  G4double r = R(t, energyTransferred, slaterEffectiveChg, shellNumber);
893  G4double value = 1. - std::exp(-2 * r) * (((2. * r * r + 2.) * r + 2.) * r + 1.);
894 
895  return value;
896 
897 }
898 
899 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
900 
902  G4double energyTransferred,
903  G4double slaterEffectiveChg,
904  G4double shellNumber)
905 {
906  // 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 4/3 r^3 + 2/3 r^4)
907  // Dingfelder, in Chattanooga 2005 proceedings, formula (9)
908 
909  G4double r = R(t, energyTransferred, slaterEffectiveChg, shellNumber);
910  G4double value = 1. - std::exp(-2 * r) * (((( 2./3. * r + 4./3.) * r + 2.) * r + 2.) * r + 1.);
911 
912  return value;
913 }
914 
915 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
916 
918  G4double energyTransferred,
919  G4double slaterEffectiveChg,
920  G4double shellNumber)
921 {
922  // tElectron = m_electron / m_alpha * t
923  // Dingfelder, in Chattanooga 2005 proceedings, p 4
924 
925  G4double tElectron = 0.511/3728. * t;
926  // The following values are provided by M. Dingfelder (priv. comm)
927  G4double H = 2.*13.60569172 * eV;
928  G4double value = std::sqrt ( 2. * tElectron / H ) / ( energyTransferred / H ) * (slaterEffectiveChg/shellNumber);
929 
930  return value;
931 }
932 
933 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
934 
936 {
939 
940  if (particleDefinition == G4Proton::Proton())
941  {
942  return(1.);
943  }
944  else
945  if (particleDefinition == instance->GetIon("hydrogen"))
946  {
947  G4double value = (std::log10(k/eV)-4.2)/0.5;
948  // The following values are provided by M. Dingfelder (priv. comm)
949  return((0.6/(1+std::exp(value))) + 0.9);
950  }
951  else
952  {
953  return(1.);
954  }
955 }
956 
957 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
958 
960 {
961 
962  // BEGIN PART 1/2 OF ELECTRON CORRECTION
963 
964  // add ONE or TWO electron-water ionisation for alpha+ and helium
965 
966  G4int level = 0;
967 
968  // Retrieve data table corresponding to the current particle type
969 
970  std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
971  pos = tableData.find(particle);
972 
973  if (pos != tableData.end())
974  {
975  G4DNACrossSectionDataSet* table = pos->second;
976 
977  if (table != 0)
978  {
979  G4double* valuesBuffer = new G4double[table->NumberOfComponents()];
980 
981  const size_t n(table->NumberOfComponents());
982  size_t i(n);
983  G4double value = 0.;
984 
985  while (i>0)
986  {
987  i--;
988  valuesBuffer[i] = table->GetComponent(i)->FindValue(k);
989  value += valuesBuffer[i];
990  }
991 
992  value *= G4UniformRand();
993 
994  i = n;
995 
996  while (i > 0)
997  {
998  i--;
999 
1000 
1001  if (valuesBuffer[i] > value)
1002  {
1003  delete[] valuesBuffer;
1004  return i;
1005  }
1006  value -= valuesBuffer[i];
1007  }
1008 
1009  if (valuesBuffer) delete[] valuesBuffer;
1010 
1011  }
1012  }
1013  else
1014  {
1015  G4Exception("G4DNARuddIonisationModel::RandomSelect","em0002",
1016  FatalException,"Model not applicable to particle type.");
1017  }
1018 
1019  return level;
1020 }
1021 
1022 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
1023 
1025 {
1026  G4double sigma = 0.;
1027 
1028  const G4DynamicParticle* particle = track.GetDynamicParticle();
1029  G4double k = particle->GetKineticEnergy();
1030 
1031  G4double lowLim = 0;
1032  G4double highLim = 0;
1033 
1034  const G4String& particleName = particle->GetDefinition()->GetParticleName();
1035 
1036  std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
1037  pos1 = lowEnergyLimit.find(particleName);
1038 
1039  if (pos1 != lowEnergyLimit.end())
1040  {
1041  lowLim = pos1->second;
1042  }
1043 
1044  std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
1045  pos2 = highEnergyLimit.find(particleName);
1046 
1047  if (pos2 != highEnergyLimit.end())
1048  {
1049  highLim = pos2->second;
1050  }
1051 
1052  if (k >= lowLim && k <= highLim)
1053  {
1054  std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
1055  pos = tableData.find(particleName);
1056 
1057  if (pos != tableData.end())
1058  {
1059  G4DNACrossSectionDataSet* table = pos->second;
1060  if (table != 0)
1061  {
1062  sigma = table->FindValue(k);
1063  }
1064  }
1065  else
1066  {
1067  G4Exception("G4DNARuddIonisationModel::PartialCrossSection","em0002",
1068  FatalException,"Model not applicable to particle type.");
1069  }
1070  }
1071 
1072  return sigma;
1073 }
1074 
1075 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
1076 
1077 G4double G4DNARuddIonisationModel::Sum(G4double /* energy */, const G4String& /* particle */)
1078 {
1079  return 0;
1080 }
1081 
static const double cm
Definition: G4SIunits.hh:106
G4double LowEnergyLimit() const
Definition: G4VEmModel.hh:623
static const double MeV
Definition: G4SIunits.hh:193
virtual G4double FindValue(G4double x, G4int componentId=0) const =0
static G4LossTableManager * Instance()
G4double GetKineticEnergy() const
CLHEP::Hep3Vector G4ThreeVector
G4double HighEnergyLimit() const
Definition: G4VEmModel.hh:616
const G4DynamicParticle * GetDynamicParticle() const
virtual const G4VEMDataSet * GetComponent(G4int componentId) const
G4ParticleChangeForGamma * fParticleChangeForGamma
static G4Material * GetMaterial(const G4String &name, G4bool warning=true)
Definition: G4Material.cc:603
size_t GetIndex() const
Definition: G4Material.hh:262
const G4double pi
static G4Proton * ProtonDefinition()
Definition: G4Proton.cc:88
std::map< G4String, G4double, std::less< G4String > > lowEnergyLimit
G4VEmAngularDistribution * GetAngularDistribution()
Definition: G4VEmModel.hh:599
G4double DifferentialCrossSection(G4ParticleDefinition *particleDefinition, G4double k, G4double energyTransfer, G4int shell)
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy)
virtual G4bool LoadData(const G4String &argFileName)
G4ParticleDefinition * GetDefinition() const
G4double S_2s(G4double t, G4double energyTransferred, G4double slaterEffectiveChg, G4double shellNumber)
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &)
int G4int
Definition: G4Types.hh:78
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
const G4String & GetParticleName() const
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
void SetHighEnergyLimit(G4double)
Definition: G4VEmModel.hh:707
virtual G4ThreeVector & SampleDirectionForShell(const G4DynamicParticle *dp, G4double finalTotalEnergy, G4int Z, G4int shellID, const G4Material *)
G4DNARuddIonisationModel(const G4ParticleDefinition *p=0, const G4String &nam="DNARuddIonisationModel")
virtual const G4AtomicShell * GetAtomicShell(G4int Z, G4AtomicShellEnumerator shell)=0
#define G4UniformRand()
Definition: Randomize.hh:93
G4GLOB_DLL std::ostream G4cout
const std::vector< double > * GetNumMolPerVolTableFor(const G4Material *) const
bool G4bool
Definition: G4Types.hh:79
const G4ThreeVector & GetMomentumDirection() const
const std::vector< G4double > * fpWaterDensity
G4double R(G4double t, G4double energyTransferred, G4double slaterEffectiveChg, G4double shellNumber)
std::map< G4String, G4double, std::less< G4String > > highEnergyLimit
static G4Proton * Proton()
Definition: G4Proton.cc:93
G4int RandomSelect(G4double energy, const G4String &particle)
static G4DNAGenericIonsManager * Instance(void)
const G4int n
virtual G4double FindValue(G4double e, G4int componentId=0) const
virtual size_t NumberOfComponents(void) const
G4double Sum(G4double energy, const G4String &particle)
G4double PartialCrossSection(const G4Track &track)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *comments)
Definition: G4Exception.cc:41
#define C1
static G4DNAChemistryManager * Instance()
static const double eV
Definition: G4SIunits.hh:194
static G4DNAMolecularMaterial * Instance()
void CreateWaterMolecule(ElectronicModification, G4int, const G4Track *)
Method used by DNA physics model to create a water molecule.
G4double S_1s(G4double t, G4double energyTransferred, G4double slaterEffectiveChg, G4double shellNumber)
void SetAngularDistribution(G4VEmAngularDistribution *)
Definition: G4VEmModel.hh:606
G4DNAWaterIonisationStructure waterStructure
G4double CorrectionFactor(G4ParticleDefinition *particleDefinition, G4double k)
const G4Track * GetCurrentTrack() const
G4double RandomizeEjectedElectronEnergy(G4ParticleDefinition *particleDefinition, G4double incomingParticleEnergy, G4int shell)
static G4Electron * Electron()
Definition: G4Electron.cc:94
void SetProposedKineticEnergy(G4double proposedKinEnergy)
#define G4endl
Definition: G4ios.hh:61
static const double m
Definition: G4SIunits.hh:110
static MCTruthManager * instance
G4VAtomDeexcitation * AtomDeexcitation()
static const double keV
Definition: G4SIunits.hh:195
double G4double
Definition: G4Types.hh:76
void ProposeTrackStatus(G4TrackStatus status)
void SetLowEnergyLimit(G4double)
Definition: G4VEmModel.hh:714
void GenerateParticles(std::vector< G4DynamicParticle * > *secVect, const G4AtomicShell *, G4int Z, G4int coupleIndex)
void SetDeexcitationFlag(G4bool val)
Definition: G4VEmModel.hh:763
static const double eplus
Definition: G4SIunits.hh:178
G4double GetPDGCharge() const
G4ThreeVector G4ParticleMomentum
G4double bindingEnergy(G4int A, G4int Z)
virtual G4double CrossSectionPerVolume(const G4Material *material, const G4ParticleDefinition *p, G4double ekin, G4double emin, G4double emax)
G4double S_2p(G4double t, G4double energyTransferred, G4double slaterEffectiveChg, G4double shellNumber)
G4VAtomDeexcitation * fAtomDeexcitation
static const G4double pos
G4AtomicShellEnumerator
G4ParticleChangeForGamma * GetParticleChangeForGamma()
Definition: G4VEmModel.cc:134
const G4Material * GetMaterial() const
G4ParticleDefinition * GetIon(const G4String &name)