Geant4  v4-10.4-release
 모두 클래스 네임스페이스들 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 Friends 매크로 그룹들 페이지들
G4DNABornIonisationModel2.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 // $Id: G4DNABornIonisationModel2.cc 87631 2014-12-14 12:42:05Z matkara $
27 //
28 
30 #include "G4PhysicalConstants.hh"
31 #include "G4SystemOfUnits.hh"
32 #include "G4UAtomicDeexcitation.hh"
33 #include "G4LossTableManager.hh"
34 #include "G4DNAChemistryManager.hh"
36 #include "G4DNABornAngle.hh"
37 #include "G4DeltaAngle.hh"
38 #include "G4Exp.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  verboseLevel = 0;
51  // Verbosity scale:
52  // 0 = nothing
53  // 1 = warning for energy non-conservation
54  // 2 = details of energy budget
55  // 3 = calculation of cross sections, file openings, sampling of atoms
56  // 4 = entering in methods
57 
58  if (verboseLevel > 0)
59  {
60  G4cout << "Born ionisation model is constructed " << G4endl;
61  }
62 
63  // Mark this model as "applicable" for atomic deexcitation
64 
65  SetDeexcitationFlag(true);
69  fTableData = 0;
70  fLowEnergyLimit = 0;
71  fHighEnergyLimit = 0;
72  fParticleDef = 0;
73 
74  // Define default angular generator
75 
77 
78  // Selection of computation method
79 
80  fasterCode = false;
81 
82  // Selection of stationary mode
83 
84  statCode = false;
85 
86  // Selection of SP scaling
87 
88  spScaling = true;
89 }
90 
91 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
92 
94 {
95  // Cross section
96 
97  if (fTableData)
98  delete fTableData;
99 
100  // Final state
101 
102  fVecm.clear();
103 }
104 
105 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
106 
108  const G4DataVector& /*cuts*/)
109 {
110 
111  if (verboseLevel > 3)
112  {
113  G4cout << "Calling G4DNABornIonisationModel2::Initialise()" << G4endl;
114  }
115 
116  if(fParticleDef != 0 && particle != fParticleDef)
117  {
118  G4ExceptionDescription description;
119  description << "You are trying to initialized G4DNABornIonisationModel2 "
120  "for particle "
121  << particle->GetParticleName()
122  << G4endl;
123  description << "G4DNABornIonisationModel2 was already initiliased "
124  "for particle:" << fParticleDef->GetParticleName() << G4endl;
125  G4Exception("G4DNABornIonisationModel2::Initialise","bornIonInit",
126  FatalException,description);
127  }
128 
129  fParticleDef = particle;
130 
131  // Energy limits
132  char *path = getenv("G4LEDATA");
133 
134  // ***
135 
136  G4String particleName = particle->GetParticleName();
137  std::ostringstream fullFileName;
138  fullFileName << path;
139 
140  if(particleName == "e-")
141  {
142  fTableFile = "dna/sigma_ionisation_e_born";
143  fLowEnergyLimit = 11.*eV;
144  fHighEnergyLimit = 1.*MeV;
145 
146  if (fasterCode)
147  {
148  fullFileName << "/dna/sigmadiff_cumulated_ionisation_e_born_hp.dat";
149  }
150  else
151  {
152  fullFileName << "/dna/sigmadiff_ionisation_e_born.dat";
153  }
154  }
155  else if(particleName == "proton")
156  {
157  fTableFile = "dna/sigma_ionisation_p_born";
158  fLowEnergyLimit = 500. * keV;
159  fHighEnergyLimit = 100. * MeV;
160 
161  if (fasterCode)
162  {
163  fullFileName << "/dna/sigmadiff_cumulated_ionisation_p_born_hp.dat";
164  }
165  else
166  {
167  fullFileName << "/dna/sigmadiff_ionisation_p_born.dat";
168  }
169  }
170 
171  // Cross section
172 
173  G4double scaleFactor = (1.e-22 / 3.343) * m*m;
176 
177  // Final state
178 
179  std::ifstream diffCrossSection(fullFileName.str().c_str());
180 
181  if (!diffCrossSection)
182  {
183  G4ExceptionDescription description;
184  description << "Missing data file:" << G4endl << fullFileName.str() << G4endl;
185  G4Exception("G4DNABornIonisationModel2::Initialise","em0003",
186  FatalException,description);
187  }
188 
189  // Clear the arrays for re-initialization case (MT mode)
190  // March 25th, 2014 - Vaclav Stepan, Sebastien Incerti
191 
192  fTdummyVec.clear();
193  fVecm.clear();
194 
195  for (int j=0; j<5; j++)
196  {
197  fProbaShellMap[j].clear();
198  fDiffCrossSectionData[j].clear();
199  fNrjTransfData[j].clear();
200  }
201 
202  //
203 
204  fTdummyVec.push_back(0.);
205  while(!diffCrossSection.eof())
206  {
207  G4double tDummy;
208  G4double eDummy;
209  diffCrossSection>>tDummy>>eDummy;
210  if (tDummy != fTdummyVec.back()) fTdummyVec.push_back(tDummy);
211 
212  G4double tmp;
213  for (int j=0; j<5; j++)
214  {
215  diffCrossSection>> tmp;
216 
217  fDiffCrossSectionData[j][tDummy][eDummy] = tmp;
218 
219  if (fasterCode)
220  {
221  fNrjTransfData[j][tDummy][fDiffCrossSectionData[j][tDummy][eDummy]]=eDummy;
222  fProbaShellMap[j][tDummy].push_back(fDiffCrossSectionData[j][tDummy][eDummy]);
223  }
224 
225  // SI - only if eof is not reached
226  if (!diffCrossSection.eof() && !fasterCode) fDiffCrossSectionData[j][tDummy][eDummy]*=scaleFactor;
227 
228  if (!fasterCode) fVecm[tDummy].push_back(eDummy);
229 
230  }
231  }
232 
233  //
236 
237  if( verboseLevel>0 )
238  {
239  G4cout << "Born ionisation model is initialized " << G4endl
240  << "Energy range: "
241  << LowEnergyLimit() / eV << " eV - "
242  << HighEnergyLimit() / keV << " keV for "
243  << particle->GetParticleName()
244  << G4endl;
245  }
246 
247  // Initialize water density pointer
248 
250  GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
251 
252  // AD
253 
255 
256  if (isInitialised)
257  { return;}
259  isInitialised = true;
260 }
261 
262 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
263 
265  const G4ParticleDefinition* particleDefinition,
266  G4double ekin,
267  G4double,
268  G4double)
269 {
270  if (verboseLevel > 3)
271  {
272  G4cout << "Calling CrossSectionPerVolume() of G4DNABornIonisationModel2"
273  << G4endl;
274  }
275 
276  if (particleDefinition != fParticleDef) return 0;
277 
278  // Calculate total cross section for model
279 
280  G4double sigma=0;
281 
282  G4double waterDensity = (*fpMolWaterDensity)[material->GetIndex()];
283 
284  if(waterDensity!= 0.0)
285  {
286  if (ekin >= fLowEnergyLimit && ekin < fHighEnergyLimit)
287  {
288  sigma = fTableData->FindValue(ekin);
289 
290  // ICRU49 electronic SP scaling - ZF, SI
291 
292  if (particleDefinition == G4Proton::ProtonDefinition() && ekin < 70*MeV && spScaling)
293  {
294  G4double A = 1.39241700556072800000E-009 ;
295  G4double B = -8.52610412942622630000E-002 ;
296  sigma = sigma * G4Exp(A*(ekin/eV)+B);
297  }
298  //
299  }
300 
301  if (verboseLevel > 2)
302  {
303  G4cout << "__________________________________" << G4endl;
304  G4cout << "G4DNABornIonisationModel2 - XS INFO START" << G4endl;
305  G4cout << "Kinetic energy(eV)=" << ekin/eV << " particle : " << particleDefinition->GetParticleName() << G4endl;
306  G4cout << "Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
307  G4cout << "Cross section per water molecule (cm^-1)=" << sigma*waterDensity/(1./cm) << G4endl;
308  G4cout << "G4DNABornIonisationModel2 - XS INFO END" << G4endl;
309  }
310  } // if (waterMaterial)
311 
312  return sigma*waterDensity;
313 }
314 
315 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
316 
317 void G4DNABornIonisationModel2::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
318  const G4MaterialCutsCouple* couple,
319  const G4DynamicParticle* particle,
320  G4double,
321  G4double)
322 {
323 
324  if (verboseLevel > 3)
325  {
326  G4cout << "Calling SampleSecondaries() of G4DNABornIonisationModel2"
327  << G4endl;
328  }
329 
330  G4double k = particle->GetKineticEnergy();
331 
332  if (k >= fLowEnergyLimit && k < fHighEnergyLimit)
333  {
334  G4ParticleMomentum primaryDirection = particle->GetMomentumDirection();
335  G4double particleMass = particle->GetDefinition()->GetPDGMass();
336  G4double totalEnergy = k + particleMass;
337  G4double pSquare = k * (totalEnergy + particleMass);
338  G4double totalMomentum = std::sqrt(pSquare);
339 
340  G4int ionizationShell = 0;
341 
342  if (!fasterCode) ionizationShell = RandomSelect(k);
343 
344  // SI: The following protection is necessary to avoid infinite loops :
345  // sigmadiff_ionisation_e_born.dat has non zero partial xs at 18 eV for shell 3 (ionizationShell ==2)
346  // sigmadiff_cumulated_ionisation_e_born.dat has zero cumulated partial xs at 18 eV for shell 3 (ionizationShell ==2)
347  // this is due to the fact that the max allowed transfered energy is (18+10.79)/2=17.025 eV and only transfered energies
348  // strictly above this value have non zero partial xs in sigmadiff_ionisation_e_born.dat (starting at trans = 17.12 eV)
349 
350  if (fasterCode)
351  do
352  {
353  ionizationShell = RandomSelect(k);
354  }while (k<19*eV && ionizationShell==2 && particle->GetDefinition()==G4Electron::ElectronDefinition());
355 
356  G4double secondaryKinetic=-1000*eV;
357 
358  if (fasterCode == false)
359  {
360  secondaryKinetic = RandomizeEjectedElectronEnergy(particle->GetDefinition(),k,ionizationShell);
361  }
362  else
363  {
364  secondaryKinetic = RandomizeEjectedElectronEnergyFromCumulatedDcs(particle->GetDefinition(),k,ionizationShell);
365  }
366 
367  G4int Z = 8;
368 
369  G4ThreeVector deltaDirection =
370  GetAngularDistribution()->SampleDirectionForShell(particle, secondaryKinetic,
371  Z, ionizationShell,
372  couple->GetMaterial());
373 
374  if (secondaryKinetic>0)
375  {
376  G4DynamicParticle* dp = new G4DynamicParticle (G4Electron::Electron(),deltaDirection,secondaryKinetic);
377  fvect->push_back(dp);
378  }
379 
380  if (particle->GetDefinition() == G4Electron::ElectronDefinition())
381  {
382  G4double deltaTotalMomentum = std::sqrt(secondaryKinetic*(secondaryKinetic + 2.*electron_mass_c2 ));
383 
384  G4double finalPx = totalMomentum*primaryDirection.x() - deltaTotalMomentum*deltaDirection.x();
385  G4double finalPy = totalMomentum*primaryDirection.y() - deltaTotalMomentum*deltaDirection.y();
386  G4double finalPz = totalMomentum*primaryDirection.z() - deltaTotalMomentum*deltaDirection.z();
387  G4double finalMomentum = std::sqrt(finalPx*finalPx + finalPy*finalPy + finalPz*finalPz);
388  finalPx /= finalMomentum;
389  finalPy /= finalMomentum;
390  finalPz /= finalMomentum;
391 
392  G4ThreeVector direction;
393  direction.set(finalPx,finalPy,finalPz);
394 
396  }
397 
398  else fParticleChangeForGamma->ProposeMomentumDirection(primaryDirection);
399 
400  // AM: sample deexcitation
401  // here we assume that H_{2}O electronic levels are the same as Oxygen.
402  // this can be considered true with a rough 10% error in energy on K-shell,
403 
404  G4int secNumberInit = 0;// need to know at a certain point the energy of secondaries
405  G4int secNumberFinal = 0;// So I'll make the diference and then sum the energies
406 
408  bindingEnergy = waterStructure.IonisationEnergy(ionizationShell);
409 
410  // SI: additional protection if tcs interpolation method is modified
411  if (k<bindingEnergy) return;
412  //
413 
415  {
417 
418  if (ionizationShell <5 && ionizationShell >1)
419  {
420  as = G4AtomicShellEnumerator(4-ionizationShell);
421  }
422  else if (ionizationShell <2)
423  {
424  as = G4AtomicShellEnumerator(3);
425  }
426 
427  // FOR DEBUG ONLY
428  // if (ionizationShell == 4) {
429  //
430  // G4cout << "Z: " << Z << " as: " << as
431  // << " ionizationShell: " << ionizationShell << " bindingEnergy: "<< bindingEnergy/eV << G4endl;
432  // G4cout << "Press <Enter> key to continue..." << G4endl;
433  // G4cin.ignore();
434  // }
435 
436  const G4AtomicShell* shell = fAtomDeexcitation->GetAtomicShell(Z, as);
437  secNumberInit = fvect->size();
438  fAtomDeexcitation->GenerateParticles(fvect, shell, Z, 0, 0);
439  secNumberFinal = fvect->size();
440  }
441 
442  // Note that secondaryKinetic is the energy of the delta ray, not of all secondaries.
443 
444  G4double scatteredEnergy = k-bindingEnergy-secondaryKinetic;
445  G4double deexSecEnergy = 0;
446  for (G4int j=secNumberInit; j < secNumberFinal; j++)
447  {
448  deexSecEnergy = deexSecEnergy + (*fvect)[j]->GetKineticEnergy();
449  }
450 
451  if (!statCode)
452  {
454  fParticleChangeForGamma->ProposeLocalEnergyDeposit(k-scatteredEnergy-secondaryKinetic-deexSecEnergy);
455  }
456  else
457  {
460  }
461 
462  // TEST //////////////////////////
463  // if (secondaryKinetic<0) abort();
464  // if (scatteredEnergy<0) abort();
465  // if (k-scatteredEnergy-secondaryKinetic-deexSecEnergy<0) abort();
466  // if (k-scatteredEnergy<0) abort();
468 
469  const G4Track * theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack();
471  ionizationShell,
472  theIncomingTrack);
473  }
474 }
475 
476 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
477 
479  G4double k,
480  G4int shell)
481 {
482  // G4cout << "*** SLOW computation for " << " " << particleDefinition->GetParticleName() << G4endl;
483 
484  if (particleDefinition == G4Electron::ElectronDefinition())
485  {
486  G4double maximumEnergyTransfer = 0.;
487  if ((k + waterStructure.IonisationEnergy(shell)) / 2. > k)
488  maximumEnergyTransfer = k;
489  else
490  maximumEnergyTransfer = (k + waterStructure.IonisationEnergy(shell)) / 2.;
491 
492  // SI : original method
493  /*
494  G4double crossSectionMaximum = 0.;
495  for(G4double value=waterStructure.IonisationEnergy(shell); value<=maximumEnergyTransfer; value+=0.1*eV)
496  {
497  G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k/eV, value/eV, shell);
498  if(differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
499  }
500  */
501 
502  // SI : alternative method
503  G4double crossSectionMaximum = 0.;
504 
505  G4double minEnergy = waterStructure.IonisationEnergy(shell);
506  G4double maxEnergy = maximumEnergyTransfer;
507  G4int nEnergySteps = 50;
508 
509  G4double value(minEnergy);
510  G4double stpEnergy(std::pow(maxEnergy / value,
511  1. / static_cast<G4double>(nEnergySteps - 1)));
512  G4int step(nEnergySteps);
513  while (step > 0)
514  {
515  step--;
516  G4double differentialCrossSection =
517  DifferentialCrossSection(particleDefinition,
518  k / eV,
519  value / eV,
520  shell);
521  if (differentialCrossSection >= crossSectionMaximum)
522  crossSectionMaximum = differentialCrossSection;
523  value *= stpEnergy;
524  }
525  //
526 
527  G4double secondaryElectronKineticEnergy = 0.;
528  do
529  {
530  secondaryElectronKineticEnergy = G4UniformRand()* (maximumEnergyTransfer-waterStructure.IonisationEnergy(shell));
531  }while(G4UniformRand()*crossSectionMaximum >
532  DifferentialCrossSection(particleDefinition, k/eV,
533  (secondaryElectronKineticEnergy+waterStructure.IonisationEnergy(shell))/eV,shell));
534 
535  return secondaryElectronKineticEnergy;
536 
537  }
538 
539  else if (particleDefinition == G4Proton::ProtonDefinition())
540  {
541  G4double maximumKineticEnergyTransfer = 4.
543 
544  G4double crossSectionMaximum = 0.;
546  value <= 4. * waterStructure.IonisationEnergy(shell); value += 0.1 * eV)
547  {
548  G4double differentialCrossSection =
549  DifferentialCrossSection(particleDefinition,
550  k / eV,
551  value / eV,
552  shell);
553  if (differentialCrossSection >= crossSectionMaximum)
554  crossSectionMaximum = differentialCrossSection;
555  }
556 
557  G4double secondaryElectronKineticEnergy = 0.;
558  do
559  {
560  secondaryElectronKineticEnergy = G4UniformRand()* maximumKineticEnergyTransfer;
561  }while(G4UniformRand()*crossSectionMaximum >=
562  DifferentialCrossSection(particleDefinition, k/eV,
563  (secondaryElectronKineticEnergy+waterStructure.IonisationEnergy(shell))/eV,shell));
564 
565  return secondaryElectronKineticEnergy;
566  }
567 
568  return 0;
569 }
570 
571 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
572 
573 // The following section is not used anymore but is kept for memory
574 // GetAngularDistribution()->SampleDirectionForShell is used instead
575 
576 /*
577  void G4DNABornIonisationModel2::RandomizeEjectedElectronDirection(G4ParticleDefinition* particleDefinition,
578  G4double k,
579  G4double secKinetic,
580  G4double & cosTheta,
581  G4double & phi )
582  {
583  if (particleDefinition == G4Electron::ElectronDefinition())
584  {
585  phi = twopi * G4UniformRand();
586  if (secKinetic < 50.*eV) cosTheta = (2.*G4UniformRand())-1.;
587  else if (secKinetic <= 200.*eV)
588  {
589  if (G4UniformRand() <= 0.1) cosTheta = (2.*G4UniformRand())-1.;
590  else cosTheta = G4UniformRand()*(std::sqrt(2.)/2);
591  }
592  else
593  {
594  G4double sin2O = (1.-secKinetic/k) / (1.+secKinetic/(2.*electron_mass_c2));
595  cosTheta = std::sqrt(1.-sin2O);
596  }
597  }
598 
599  else if (particleDefinition == G4Proton::ProtonDefinition())
600  {
601  G4double maxSecKinetic = 4.* (electron_mass_c2 / proton_mass_c2) * k;
602  phi = twopi * G4UniformRand();
603 
604  // cosTheta = std::sqrt(secKinetic / maxSecKinetic);
605 
606  // Restriction below 100 eV from Emfietzoglou (2000)
607 
608  if (secKinetic>100*eV) cosTheta = std::sqrt(secKinetic / maxSecKinetic);
609  else cosTheta = (2.*G4UniformRand())-1.;
610 
611  }
612  }
613  */
614 
615 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
617  G4double k,
618  G4double energyTransfer,
619  G4int ionizationLevelIndex)
620 {
621  G4double sigma = 0.;
622 
623  if (energyTransfer >= waterStructure.IonisationEnergy(ionizationLevelIndex)/eV)
624  {
625  G4double valueT1 = 0;
626  G4double valueT2 = 0;
627  G4double valueE21 = 0;
628  G4double valueE22 = 0;
629  G4double valueE12 = 0;
630  G4double valueE11 = 0;
631 
632  G4double xs11 = 0;
633  G4double xs12 = 0;
634  G4double xs21 = 0;
635  G4double xs22 = 0;
636 
637  // k should be in eV and energy transfer eV also
638 
639  std::vector<G4double>::iterator t2 = std::upper_bound(fTdummyVec.begin(),
640  fTdummyVec.end(),
641  k);
642 
643  std::vector<G4double>::iterator t1 = t2 - 1;
644 
645  // SI : the following condition avoids situations where energyTransfer >last vector element
646 
647  if (energyTransfer <= fVecm[(*t1)].back()
648  && energyTransfer <= fVecm[(*t2)].back())
649  {
650  std::vector<G4double>::iterator e12 = std::upper_bound(fVecm[(*t1)].begin(),
651  fVecm[(*t1)].end(),
652  energyTransfer);
653  std::vector<G4double>::iterator e11 = e12 - 1;
654 
655  std::vector<G4double>::iterator e22 = std::upper_bound(fVecm[(*t2)].begin(),
656  fVecm[(*t2)].end(),
657  energyTransfer);
658  std::vector<G4double>::iterator e21 = e22 - 1;
659 
660  valueT1 = *t1;
661  valueT2 = *t2;
662  valueE21 = *e21;
663  valueE22 = *e22;
664  valueE12 = *e12;
665  valueE11 = *e11;
666 
667  xs11 = fDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE11];
668  xs12 = fDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE12];
669  xs21 = fDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE21];
670  xs22 = fDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE22];
671 
672  }
673 
674  G4double xsProduct = xs11 * xs12 * xs21 * xs22;
675  if (xsProduct != 0.)
676  {
677  sigma = QuadInterpolator(valueE11,
678  valueE12,
679  valueE21,
680  valueE22,
681  xs11,
682  xs12,
683  xs21,
684  xs22,
685  valueT1,
686  valueT2,
687  k,
688  energyTransfer);
689  }
690  }
691 
692  return sigma;
693 }
694 
695 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
696 
698  G4double e2,
699  G4double e,
700  G4double xs1,
701  G4double xs2)
702 {
703  G4double value = 0.;
704 
705  // Log-log interpolation by default
706 
707  if (e1 != 0 && e2 != 0 && (std::log10(e2) - std::log10(e1)) != 0
708  && !fasterCode)
709  {
710  G4double a = (std::log10(xs2) - std::log10(xs1))
711  / (std::log10(e2) - std::log10(e1));
712  G4double b = std::log10(xs2) - a * std::log10(e2);
713  G4double sigma = a * std::log10(e) + b;
714  value = (std::pow(10., sigma));
715  }
716 
717  // Switch to lin-lin interpolation
718  /*
719  if ((e2-e1)!=0)
720  {
721  G4double d1 = xs1;
722  G4double d2 = xs2;
723  value = (d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
724  }
725  */
726 
727  // Switch to log-lin interpolation for faster code
728  if ((e2 - e1) != 0 && xs1 != 0 && xs2 != 0 && fasterCode)
729  {
730  G4double d1 = std::log10(xs1);
731  G4double d2 = std::log10(xs2);
732  value = std::pow(10., (d1 + (d2 - d1) * (e - e1) / (e2 - e1)));
733  }
734 
735  // Switch to lin-lin interpolation for faster code
736  // in case one of xs1 or xs2 (=cum proba) value is zero
737 
738  if ((e2 - e1) != 0 && (xs1 == 0 || xs2 == 0) && fasterCode)
739  {
740  G4double d1 = xs1;
741  G4double d2 = xs2;
742  value = (d1 + (d2 - d1) * (e - e1) / (e2 - e1));
743  }
744 
745  /*
746  G4cout
747  << e1 << " "
748  << e2 << " "
749  << e << " "
750  << xs1 << " "
751  << xs2 << " "
752  << value
753  << G4endl;
754  */
755 
756  return value;
757 }
758 
759 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
760 
762  G4double e12,
763  G4double e21,
764  G4double e22,
765  G4double xs11,
766  G4double xs12,
767  G4double xs21,
768  G4double xs22,
769  G4double t1,
770  G4double t2,
771  G4double t,
772  G4double e)
773 {
774  G4double interpolatedvalue1 = Interpolate(e11, e12, e, xs11, xs12);
775  G4double interpolatedvalue2 = Interpolate(e21, e22, e, xs21, xs22);
777  t2,
778  t,
779  interpolatedvalue1,
780  interpolatedvalue2);
781 
782  return value;
783 }
784 
785 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
786 
788  G4int level,
789  const G4ParticleDefinition* /*particle*/,
791 {
792  return fTableData->GetComponent(level)->FindValue(kineticEnergy);
793 }
794 
795 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
796 
798 {
799  G4int level = 0;
800 
801  G4double* valuesBuffer = new G4double[fTableData->NumberOfComponents()];
802  const size_t n(fTableData->NumberOfComponents());
803  size_t i(n);
804  G4double value = 0.;
805 
806  while (i > 0)
807  {
808  i--;
809  valuesBuffer[i] = fTableData->GetComponent(i)->FindValue(k);
810  value += valuesBuffer[i];
811  }
812 
813  value *= G4UniformRand();
814 
815  i = n;
816 
817  while (i > 0)
818  {
819  i--;
820 
821  if (valuesBuffer[i] > value)
822  {
823  delete[] valuesBuffer;
824  return i;
825  }
826  value -= valuesBuffer[i];
827  }
828 
829  if (valuesBuffer)
830  delete[] valuesBuffer;
831 
832  return level;
833 }
834 
835 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
836 
838  G4double k,
839  G4int shell)
840 {
841  // G4cout << "*** FAST computation for " << " " << particleDefinition->GetParticleName() << G4endl;
842 
843  G4double secondaryElectronKineticEnergy = 0.;
844 
845  G4double random = G4UniformRand();
846 
847  secondaryElectronKineticEnergy = TransferedEnergy(particleDefinition,
848  k / eV,
849  shell,
850  random) * eV
852 
853  // G4cout << TransferedEnergy(particleDefinition, k/eV, shell, random) << G4endl;
854  if (secondaryElectronKineticEnergy < 0.)
855  return 0.;
856  //
857 
858  return secondaryElectronKineticEnergy;
859 }
860 
861 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
862 
864  G4double k,
865  G4int ionizationLevelIndex,
866  G4double random)
867 {
868 
869  G4double nrj = 0.;
870 
871  G4double valueK1 = 0;
872  G4double valueK2 = 0;
873  G4double valuePROB21 = 0;
874  G4double valuePROB22 = 0;
875  G4double valuePROB12 = 0;
876  G4double valuePROB11 = 0;
877 
878  G4double nrjTransf11 = 0;
879  G4double nrjTransf12 = 0;
880  G4double nrjTransf21 = 0;
881  G4double nrjTransf22 = 0;
882 
883  // k should be in eV
884  std::vector<G4double>::iterator k2 = std::upper_bound(fTdummyVec.begin(),
885  fTdummyVec.end(),
886  k);
887  std::vector<G4double>::iterator k1 = k2 - 1;
888 
889  /*
890  G4cout << "----> k=" << k
891  << " " << *k1
892  << " " << *k2
893  << " " << random
894  << " " << ionizationLevelIndex
895  << " " << eProbaShellMap[ionizationLevelIndex][(*k1)].back()
896  << " " << eProbaShellMap[ionizationLevelIndex][(*k2)].back()
897  << G4endl;
898  */
899 
900  // SI : the following condition avoids situations where random >last vector element
901  if (random <= fProbaShellMap[ionizationLevelIndex][(*k1)].back()
902  && random <= fProbaShellMap[ionizationLevelIndex][(*k2)].back())
903  {
904  std::vector<G4double>::iterator prob12 =
905  std::upper_bound(fProbaShellMap[ionizationLevelIndex][(*k1)].begin(),
906  fProbaShellMap[ionizationLevelIndex][(*k1)].end(),
907  random);
908 
909  std::vector<G4double>::iterator prob11 = prob12 - 1;
910 
911  std::vector<G4double>::iterator prob22 =
912  std::upper_bound(fProbaShellMap[ionizationLevelIndex][(*k2)].begin(),
913  fProbaShellMap[ionizationLevelIndex][(*k2)].end(),
914  random);
915 
916  std::vector<G4double>::iterator prob21 = prob22 - 1;
917 
918  valueK1 = *k1;
919  valueK2 = *k2;
920  valuePROB21 = *prob21;
921  valuePROB22 = *prob22;
922  valuePROB12 = *prob12;
923  valuePROB11 = *prob11;
924 
925  /*
926  G4cout << " " << random << " " << valuePROB11 << " "
927  << valuePROB12 << " " << valuePROB21 << " " << valuePROB22 << G4endl;
928  */
929 
930  nrjTransf11 = fNrjTransfData[ionizationLevelIndex][valueK1][valuePROB11];
931  nrjTransf12 = fNrjTransfData[ionizationLevelIndex][valueK1][valuePROB12];
932  nrjTransf21 = fNrjTransfData[ionizationLevelIndex][valueK2][valuePROB21];
933  nrjTransf22 = fNrjTransfData[ionizationLevelIndex][valueK2][valuePROB22];
934 
935  /*
936  G4cout << " " << ionizationLevelIndex << " "
937  << random << " " <<valueK1 << " " << valueK2 << G4endl;
938 
939  G4cout << " " << random << " " << nrjTransf11 << " "
940  << nrjTransf12 << " " << nrjTransf21 << " " <<nrjTransf22 << G4endl;
941  */
942 
943  }
944  // Avoids cases where cum xs is zero for k1 and is not for k2 (with always k1<k2)
945  if (random > fProbaShellMap[ionizationLevelIndex][(*k1)].back())
946  {
947  std::vector<G4double>::iterator prob22 =
948  std::upper_bound(fProbaShellMap[ionizationLevelIndex][(*k2)].begin(),
949  fProbaShellMap[ionizationLevelIndex][(*k2)].end(),
950  random);
951 
952  std::vector<G4double>::iterator prob21 = prob22 - 1;
953 
954  valueK1 = *k1;
955  valueK2 = *k2;
956  valuePROB21 = *prob21;
957  valuePROB22 = *prob22;
958 
959  // G4cout << " " << random << " " << valuePROB21 << " " << valuePROB22 << G4endl;
960 
961  nrjTransf21 = fNrjTransfData[ionizationLevelIndex][valueK2][valuePROB21];
962  nrjTransf22 = fNrjTransfData[ionizationLevelIndex][valueK2][valuePROB22];
963 
964  G4double interpolatedvalue2 = Interpolate(valuePROB21,
965  valuePROB22,
966  random,
967  nrjTransf21,
968  nrjTransf22);
969 
970  // zeros are explicitly set
971 
972  G4double value = Interpolate(valueK1, valueK2, k, 0., interpolatedvalue2);
973 
974  /*
975  G4cout << " " << ionizationLevelIndex << " "
976  << random << " " <<valueK1 << " " << valueK2 << G4endl;
977 
978  G4cout << " " << random << " " << nrjTransf11 << " "
979  << nrjTransf12 << " " << nrjTransf21 << " " <<nrjTransf22 << G4endl;
980 
981  G4cout << "ici" << " " << value << G4endl;
982  */
983 
984  return value;
985  }
986 
987  // End electron and proton cases
988 
989  G4double nrjTransfProduct = nrjTransf11 * nrjTransf12 * nrjTransf21
990  * nrjTransf22;
991  //G4cout << "nrjTransfProduct=" << nrjTransfProduct << G4endl;
992 
993  if (nrjTransfProduct != 0.)
994  {
995  nrj = QuadInterpolator(valuePROB11,
996  valuePROB12,
997  valuePROB21,
998  valuePROB22,
999  nrjTransf11,
1000  nrjTransf12,
1001  nrjTransf21,
1002  nrjTransf22,
1003  valueK1,
1004  valueK2,
1005  k,
1006  random);
1007  }
1008  // G4cout << nrj << endl;
1009 
1010  return nrj;
1011 }
void set(double x, double y, double z)
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition: G4Exp.hh:183
virtual G4bool LoadData(const G4String &argFileName)
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:45
std::vector< ExP01TrackerHit * > a
Definition: ExP01Classes.hh:33
virtual const G4AtomicShell * GetAtomicShell(G4int Z, G4AtomicShellEnumerator shell)=0
TTree * t1
Definition: plottest35.C:26
G4VAtomDeexcitation * AtomDeexcitation()
static constexpr double MeV
Definition: G4SIunits.hh:214
void SetHighEnergyLimit(G4double)
Definition: G4VEmModel.hh:707
virtual size_t NumberOfComponents(void) const
static constexpr double keV
Definition: G4SIunits.hh:216
size_t GetIndex() const
Definition: G4Material.hh:262
#define G4endl
Definition: G4ios.hh:61
const G4ThreeVector & GetMomentumDirection() const
G4DNACrossSectionDataSet * fTableData
const G4String & GetParticleName() const
G4double TransferedEnergy(G4ParticleDefinition *aParticleDefinition, G4double incomingParticleEnergy, G4int shell, G4double random)
G4ParticleChangeForGamma * fParticleChangeForGamma
void SetProposedKineticEnergy(G4double proposedKinEnergy)
double z() const
Float_t tmp
G4AtomicShellEnumerator
static G4Material * GetMaterial(const G4String &name, G4bool warning=true)
Definition: G4Material.cc:608
G4double GetPDGMass() const
G4double LowEnergyLimit() const
Definition: G4VEmModel.hh:616
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &=*(new G4DataVector()))
static constexpr double proton_mass_c2
std::vector< G4double > fTdummyVec
Float_t Z
static constexpr double m
Definition: G4SIunits.hh:129
void SetDeexcitationFlag(G4bool val)
Definition: G4VEmModel.hh:763
double G4double
Definition: G4Types.hh:76
G4double Interpolate(G4double e1, G4double e2, G4double e, G4double xs1, G4double xs2)
G4ParticleDefinition * GetDefinition() const
static const G4double d2
void GenerateParticles(std::vector< G4DynamicParticle * > *secVect, const G4AtomicShell *, G4int Z, G4int coupleIndex)
const XML_Char int const XML_Char * value
Definition: expat.h:331
static G4Proton * ProtonDefinition()
Definition: G4Proton.cc:88
static constexpr double electron_mass_c2
static G4DNAMolecularMaterial * Instance()
static const G4double d1
void ProposeMomentumDirection(G4double Px, G4double Py, G4double Pz)
G4DNABornIonisationModel2(const G4ParticleDefinition *p=0, const G4String &nam="DNABornIonisationModel")
#define G4UniformRand()
Definition: Randomize.hh:53
void CreateWaterMolecule(ElectronicModification, G4int, const G4Track *)
virtual G4ThreeVector & SampleDirectionForShell(const G4DynamicParticle *dp, G4double finalTotalEnergy, G4int Z, G4int shellID, const G4Material *)
double A(double temperature)
static constexpr double eV
Definition: G4SIunits.hh:215
virtual G4double GetPartialCrossSection(const G4Material *, G4int, const G4ParticleDefinition *, G4double)
void SetAngularDistribution(G4VEmAngularDistribution *)
Definition: G4VEmModel.hh:582
const G4Track * GetCurrentTrack() const
G4VAtomDeexcitation * fAtomDeexcitation
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy)
static G4Electron * Electron()
Definition: G4Electron.cc:94
static G4Electron * ElectronDefinition()
Definition: G4Electron.cc:89
virtual G4double CrossSectionPerVolume(const G4Material *material, const G4ParticleDefinition *p, G4double ekin, G4double emin, G4double emax)
Hep3Vector unit() const
TTree * t2
Definition: plottest35.C:36
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.hh:65
G4double QuadInterpolator(G4double e11, G4double e12, G4double e21, G4double e22, G4double x11, G4double x12, G4double x21, G4double x22, G4double t1, G4double t2, G4double t, G4double e)
int G4int
Definition: G4Types.hh:78
void SetLowEnergyLimit(G4double)
Definition: G4VEmModel.hh:714
G4double GetKineticEnergy() const
virtual G4double FindValue(G4double e, G4int componentId=0) const
static constexpr double cm
Definition: G4SIunits.hh:119
G4GLOB_DLL std::ostream G4cout
double x() const
virtual const G4VEMDataSet * GetComponent(G4int componentId) const
static G4LossTableManager * Instance()
const G4ParticleDefinition * fParticleDef
G4VEmAngularDistribution * GetAngularDistribution()
Definition: G4VEmModel.hh:575
Char_t n[5]
const G4Material * GetMaterial() const
G4ParticleChangeForGamma * GetParticleChangeForGamma()
Definition: G4VEmModel.cc:131
double y() const
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
G4DNAWaterIonisationStructure waterStructure
const std::vector< G4double > * fpMolWaterDensity
G4double bindingEnergy(G4int A, G4int Z)
G4double HighEnergyLimit() const
Definition: G4VEmModel.hh:609
double B(double temperature)
static G4DNAChemistryManager * Instance()
virtual G4double FindValue(G4double x, G4int componentId=0) const =0
G4double DifferentialCrossSection(G4ParticleDefinition *aParticleDefinition, G4double k, G4double energyTransfer, G4int shell)
G4double RandomizeEjectedElectronEnergy(G4ParticleDefinition *aParticleDefinition, G4double incomingParticleEnergy, G4int shell)
G4double RandomizeEjectedElectronEnergyFromCumulatedDcs(G4ParticleDefinition *aParticleDefinition, G4double incomingParticleEnergy, G4int shell)