Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4DNARPWBAIonisationModel.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// Reference:
27// A.D. Dominguez-Munoz, M.I. Gallardo, M.C. Bordage,
28// Z. Francis, S. Incerti, M.A. Cortes-Giraldo,
29// Radiat. Phys. Chem. 199 (2022) 110363.
30//
31// Class authors:
32// A.D. Dominguez-Munoz
33// M.A. Cortes-Giraldo (miancortes -at- us.es)
34//
35// Class creation: 2022-03-03
36//
37//
38
41#include "G4SystemOfUnits.hh"
43#include "G4LossTableManager.hh"
46#include "G4DNABornAngle.hh"
47#include "G4Exp.hh"
48using namespace std;
49//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
51 const G4ParticleDefinition*, const G4String& nam)
52 : G4VEmModel(nam)
53{
54 // Verbosity scale:
55 // 0 = nothing
56 // 1 = warning for energy non-conservation
57 // 2 = details of energy budget
58 // 3 = calculation of cross sections, file openings, sampling of atoms
59 // 4 = entering in methods
60
61 if(verboseLevel > 0)
62 {
63 G4cout << "RPWBA ionisation model is constructed " << G4endl;
64 }
67}
68
69//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
70
72{
73 eVecm.clear();
74 pVecm.clear();
75}
76//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
77
78G4bool G4DNARPWBAIonisationModel::InEnergyLimit(const G4double& k)
79{
80 if(lowEnergyLimit == highEnergyLimit)
81 {
82 G4Exception("G4DNARPWBAIonisationModel::InEnergyLimit", "em0102",
83 FatalException, "lowEnergyLimit == highEnergyLimit");
84 }
85 if(k >= lowEnergyLimit && k <= highEnergyLimit)
86 {
87 return true;
88 }
89 else
90 {
91 return false;
92 }
93}
94
95//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
96void G4DNARPWBAIonisationModel::InitialiseForProton(
97 const G4ParticleDefinition* part)
98{
99 if(part != fProtonDef)
100 {
101 G4Exception("G4DNARPWBAIonisationModel::InitialiseForProton", "em0002",
102 FatalException, "Model not applicable to particle type.");
103 }
104 // Energy limits
105 G4String fileProton("dna/sigma_ionisation_p_RPWBA");
106 G4double scaleFactor = 1 * cm * cm;
107 const char *path = G4FindDataDir("G4LEDATA");
108 lowEnergyLimit = 100. * MeV;
109 highEnergyLimit = 300. * MeV;
110
111 if(LowEnergyLimit() < lowEnergyLimit || HighEnergyLimit() > highEnergyLimit)
112 {
114 ed << "Model is applicable from "<<lowEnergyLimit<<" to "<<highEnergyLimit;
115 G4Exception("G4DNARPWBAIonisationModel::InitialiseForProton", "em0004",
116 FatalException, ed);
117 }
118
119 fpTotalCrossSection = make_unique<G4DNACrossSectionDataSet>(
120 new G4LogLogInterpolation, eV, scaleFactor);
121 fpTotalCrossSection->LoadData(fileProton);
122
123 // Final state
124
125 std::ostringstream pFullFileName;
126 fasterCode ? pFullFileName
127 << path << "/dna/sigmadiff_cumulated_ionisation_p_RPWBA.dat"
128 : pFullFileName << path << "/dna/sigmadiff_ionisation_p_RPWBA.dat";
129 std::ifstream pDiffCrossSection(pFullFileName.str().c_str());
130 if(!pDiffCrossSection)
131 {
132 G4ExceptionDescription exceptionDescription;
133 exceptionDescription << "Missing data file: " + pFullFileName.str();
134 G4Exception("G4DNARPWBAIonisationModel::InitialiseForProton", "em0003",
135 FatalException, exceptionDescription);
136 }
137
138 pTdummyVec.push_back(0.);
139 while(!pDiffCrossSection.eof())
140 {
141 G4double tDummy;
142 G4double eDummy;
143 pDiffCrossSection >> tDummy >> eDummy;
144 if(tDummy != pTdummyVec.back())
145 {
146 pTdummyVec.push_back(tDummy);
147 }
148
149 for(G4int j = 0; j < 5; j++)
150 {
151 pDiffCrossSection >> pDiffCrossSectionData[j][tDummy][eDummy];
152
153 if(fasterCode)
154 {
155 pNrjTransfData[j][tDummy][pDiffCrossSectionData[j][tDummy][eDummy]] =
156 eDummy;
157 pProbaShellMap[j][tDummy].push_back(
158 pDiffCrossSectionData[j][tDummy][eDummy]);
159 }
160
161 // SI - only if eof is not reached !
162 if(!pDiffCrossSection.eof() && !fasterCode)
163 {
164 pDiffCrossSectionData[j][tDummy][eDummy] *= scaleFactor;
165 }
166
167 if(!fasterCode)
168 {
169 pVecm[tDummy].push_back(eDummy);
170 }
171 }
172 }
173
174 // be careful about this
175 // SetLowEnergyLimit(lowEnergyLimit);
176 // SetHighEnergyLimit(highEnergyLimit);
177}
178
180 const G4DataVector& /*cuts*/)
181{
182 if(isInitialised)
183 {
184 return;
185 }
186 if(verboseLevel > 3)
187 {
188 G4cout << "Calling G4DNARPWBAIonisationModel::Initialise()"
189 << particle->GetParticleName() << G4endl;
190 }
191
192 InitialiseForProton(particle);
193
194 if(verboseLevel > 0)
195 {
196 G4cout << "RPWBA ionisation model is initialized " << G4endl
197 << "Energy range: " << LowEnergyLimit() / MeV << " MeV - "
198 << HighEnergyLimit() / MeV << " MeV for "
199 << particle->GetParticleName() << G4endl;
200 }
201
202 // Initialize water density pointer
203 if(G4Material::GetMaterial("G4_WATER") != nullptr)
204 {
205 fpMolWaterDensity =
207 G4Material::GetMaterial("G4_WATER"));
208 }
209 else
210 {
211 G4ExceptionDescription exceptionDescription;
212 exceptionDescription << "G4_WATER does not exist :";
213 G4Exception("G4DNARPWBAIonisationModel::Initialise", "em00020",
214 FatalException, exceptionDescription);
215 }
216 fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
218 isInitialised = true;
219}
220
221//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
222
224 const G4Material* material, const G4ParticleDefinition* particleDefinition,
226{
227 if(particleDefinition != fProtonDef)
228 {
229 G4Exception("G4DNARPWBAIonisationModel::CrossSectionPerVolume", "em0402",
230 FatalException, "Model not applicable to particle type.");
231 }
232 if(verboseLevel > 3)
233 {
234 G4cout << "Calling CrossSectionPerVolume() of G4DNARPWBAIonisationModel"
235 << G4endl;
236 }
237 G4double sigma;
238 G4double waterDensity = (*fpMolWaterDensity)[material->GetIndex()];
239
240 if(InEnergyLimit(ekin))
241 {
242 sigma = fpTotalCrossSection->FindValue(ekin);
243 }
244 else
245 {
246 // nput energy is outside this interval the cross section is set to zero
247 // should add a warning or exception ?
248 return 0;
249 }
250
251 if(verboseLevel > 2)
252 {
253 G4cout << "__________________________________" << G4endl;
254 G4cout << "G4DNARPWBAIonisationModel - XS INFO START" << G4endl;
255 G4cout << "Kinetic energy(eV)=" << ekin / eV
256 << " particle : " << fProtonDef->GetParticleName() << G4endl;
257 G4cout << "Cross section per water molecule (cm^2)=" << sigma / cm / cm
258 << G4endl;
259 G4cout << "Cross section per water molecule (cm^-1)="
260 << sigma * waterDensity / (1. / cm) << G4endl;
261 G4cout << "G4DNARPWBAIonisationModel - XS INFO END" << G4endl;
262 }
263
264 return sigma * waterDensity;
265}
266
267//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
268
270 std::vector<G4DynamicParticle*>* fvect, const G4MaterialCutsCouple* couple,
271 const G4DynamicParticle* particle, G4double, G4double)
272{
273 if(verboseLevel > 3)
274 {
275 G4cout << "Calling SampleSecondaries() of G4DNARPWBAIonisationModel"
276 << G4endl;
277 }
278 G4double k = particle->GetKineticEnergy();
279 if(InEnergyLimit(k))
280 {
281 G4ParticleMomentum primaryDirection = particle->GetMomentumDirection();
282 G4double particleMass = particle->GetDefinition()->GetPDGMass();
283 G4double totalEnergy = k + particleMass;
284 G4double pSquare = k * (totalEnergy + particleMass);
285 G4double totalMomentum = std::sqrt(pSquare);
286 G4int ionizationShell;
287
288 if(!fasterCode)
289 {
290 ionizationShell = RandomSelect(k);
291 }
292 else
293 {
294 // fasterCode = true
295 do
296 {
297 ionizationShell = RandomSelect(k);
298 } while(k < 19 * eV && ionizationShell == 2 &&
300 }
301
302 G4double bindingEnergy = waterStructure.IonisationEnergy(ionizationShell);
303
304 // SI: additional protection if tcs interpolation method is modified
305 if(k < bindingEnergy)
306 {
307 return;
308 }
309 //
310 G4double secondaryKinetic;
311 if(!fasterCode)
312 {
313 secondaryKinetic = RandomizeEjectedElectronEnergy(k, ionizationShell);
314 }
315 else
316 {
317 secondaryKinetic =
318 RandomizeEjectedElectronEnergyFromCumulatedDcs(k, ionizationShell);
319 }
320
321 G4int Z = 8; // water Z (6 Oxygen + 2 hydrogen)
322 G4ThreeVector deltaDirection =
324 particle, secondaryKinetic, Z, ionizationShell, couple->GetMaterial());
325
326 if(secondaryKinetic > 0){
327 auto dp = new G4DynamicParticle(G4Electron::Electron(), deltaDirection,
328 secondaryKinetic);
329 fvect->push_back(dp);
330 }
331
333 G4double deltaTotalMomentum = std::sqrt(
334 secondaryKinetic * (secondaryKinetic + 2. * electron_mass_c2));
335
336 G4double finalPx = totalMomentum * primaryDirection.x() -
337 deltaTotalMomentum * deltaDirection.x();
338 G4double finalPy = totalMomentum * primaryDirection.y() -
339 deltaTotalMomentum * deltaDirection.y();
340 G4double finalPz = totalMomentum * primaryDirection.z() -
341 deltaTotalMomentum * deltaDirection.z();
342 G4double finalMomentum =
343 std::sqrt(finalPx * finalPx + finalPy * finalPy + finalPz * finalPz);
344 finalPx /= finalMomentum;
345 finalPy /= finalMomentum;
346 finalPz /= finalMomentum;
347 G4ThreeVector direction;
348 direction.set(finalPx, finalPy, finalPz);
350 }
351 else
352 {
354 }
355
356 // AM: sample deexcitation
357 // here we assume that H_{2}O electronic levels are the same as Oxygen.
358 // this can be considered true with a rough 10% error in energy on K-shell,
359
360 size_t secNumberInit; // need to know at a certain point the energy of
361 // secondaries
362 size_t
363 secNumberFinal; // So I'll make the diference and then sum the energies
364
365 G4double scatteredEnergy = k - bindingEnergy - secondaryKinetic;
366
367 // SI: only atomic deexcitation from K shell is considered
368 if((fAtomDeexcitation != nullptr) && ionizationShell == 4)
369 {
370 const G4AtomicShell* shell =
371 fAtomDeexcitation->GetAtomicShell(Z, G4AtomicShellEnumerator(0));
372 secNumberInit = fvect->size();
373 fAtomDeexcitation->GenerateParticles(fvect, shell, Z, 0, 0);
374 secNumberFinal = fvect->size();
375
376 if(secNumberFinal > secNumberInit){
377 for(size_t i = secNumberInit; i < secNumberFinal; ++i){
378 if(bindingEnergy >= ((*fvect)[i])->GetKineticEnergy())
379 {
380 bindingEnergy -= ((*fvect)[i])->GetKineticEnergy();
381 }else{
382 delete(*fvect)[i];
383 (*fvect)[i] = nullptr;
384 }
385 }
386 }
387 }
388
389 // This should never happen
390 if(bindingEnergy < 0.0)
391 {
392 G4Exception("G4DNARPWBAIonisatioModel::SampleSecondaries()", "em2050",
393 FatalException, "Negative local energy deposit");
394 }
395
396 // bindingEnergy has been decreased
397 // by the amount of energy taken away by deexc. products
398 if(!statCode){
401 }else{
404 }
405 const G4Track* theIncomingTrack =
408 eIonizedMolecule, ionizationShell, theIncomingTrack);
409 }
410}
411
412//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
413
414G4double G4DNARPWBAIonisationModel::RandomizeEjectedElectronEnergy(
415 const G4double& k, const G4int& shell)
416{
417 G4double maximumKineticEnergyTransfer =
418 4. * (electron_mass_c2 / proton_mass_c2) * k;
419 G4double IonisationEnergyInShell = waterStructure.IonisationEnergy(shell);
420 G4double kIneV = k / eV;
421
422 G4double crossSectionMaximum = 0.;
423 for(G4double value = IonisationEnergyInShell;
424 value <= 4. * IonisationEnergyInShell; value += 0.1 * eV)
425 {
426 G4double differentialCrossSection =
427 DifferentialCrossSection(kIneV, value / eV, shell);
428 if(differentialCrossSection >= crossSectionMaximum)
429 {
430 crossSectionMaximum = differentialCrossSection;
431 }
432 }
433
434 G4double secondaryElectronKineticEnergy;
435 do
436 {
437 secondaryElectronKineticEnergy =
438 G4UniformRand() * maximumKineticEnergyTransfer;
439 } while(G4UniformRand() * crossSectionMaximum >=
441 (secondaryElectronKineticEnergy +
442 IonisationEnergyInShell) / eV, shell));
443
444 return secondaryElectronKineticEnergy;
445}
446
447//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
449 const G4double& kine, const G4double& energyTransfer,
450 const G4int& ionizationLevelIndex)
451{
452 G4double k = kine;
453 G4double sigma = 0.;
454 if(energyTransfer >=
455 waterStructure.IonisationEnergy(ionizationLevelIndex) / eV)
456 {
457 G4double valueT1 = 0;
458 G4double valueT2 = 0;
459 G4double valueE21 = 0;
460 G4double valueE22 = 0;
461 G4double valueE12 = 0;
462 G4double valueE11 = 0;
463
464 G4double xs11 = 0;
465 G4double xs12 = 0;
466 G4double xs21 = 0;
467 G4double xs22 = 0;
468
469 // Protection against out of boundary access - proton case : 100 MeV
470
471 if(k == pTdummyVec.back())
472 {
473 k = k * (1. - 1e-12);
474 }
475 // k should be in eV and energy transfer eV also
476 auto t2 = std::upper_bound(pTdummyVec.begin(), pTdummyVec.end(), k);
477 auto t1 = t2 - 1;
478
479 auto e12 = std::upper_bound(pVecm[(*t1)].begin(), pVecm[(*t1)].end(),
480 energyTransfer);
481 auto e11 = e12 - 1;
482
483 auto e22 = std::upper_bound(pVecm[(*t2)].begin(), pVecm[(*t2)].end(),
484 energyTransfer);
485 auto e21 = e22 - 1;
486
487 valueT1 = *t1;
488 valueT2 = *t2;
489 valueE21 = *e21;
490 valueE22 = *e22;
491 valueE12 = *e12;
492 valueE11 = *e11;
493
494 xs11 = pDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE11];
495 xs12 = pDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE12];
496 xs21 = pDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE21];
497 xs22 = pDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE22];
498
499 G4double xsProduct = xs11 * xs12 * xs21 * xs22;
500 if(xsProduct != 0.)
501 {
502 sigma =
503 QuadInterpolator(valueE11, valueE12, valueE21, valueE22, xs11, xs12,
504 xs21, xs22, valueT1, valueT2, k, energyTransfer);
505 }
506 }
507 return sigma;
508}
509
510//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
511
512G4double G4DNARPWBAIonisationModel::Interpolate(const G4double& e1,
513 const G4double& e2,
514 const G4double& e,
515 const G4double& xs1,
516 const G4double& xs2)
517{
518 G4double value = 0.;
519
520 // Log-log interpolation by default
521
522 if(e1 != 0 && e2 != 0 && (std::log10(e2) - std::log10(e1)) != 0 &&
523 !fasterCode)
524 {
525 G4double a =
526 (std::log10(xs2) - std::log10(xs1)) / (std::log10(e2) - std::log10(e1));
527 G4double b = std::log10(xs2) - a * std::log10(e2);
528 G4double sigma = a * std::log10(e) + b;
529 value = (std::pow(10., sigma));
530 }
531 // Switch to lin-lin interpolation
532 /*
533 if ((e2-e1)!=0)
534 {
535 G4double d1 = xs1;
536 G4double d2 = xs2;
537 value = (d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
538 }
539 */
540
541 // Switch to log-lin interpolation for faster code
542 if((e2 - e1) != 0 && xs1 != 0 && xs2 != 0 && fasterCode)
543 {
544 G4double d1 = std::log10(xs1);
545 G4double d2 = std::log10(xs2);
546 value = std::pow(10., (d1 + (d2 - d1) * (e - e1) / (e2 - e1)));
547 }
548
549 // Switch to lin-lin interpolation for faster code
550 // in case one of xs1 or xs2 (=cum proba) value is zero
551
552 if((e2 - e1) != 0 && (xs1 == 0 || xs2 == 0) && fasterCode)
553 {
554 G4double d1 = xs1;
555 G4double d2 = xs2;
556 value = (d1 + (d2 - d1) * (e - e1) / (e2 - e1));
557 }
558 return value;
559}
560
561//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
562
563G4double G4DNARPWBAIonisationModel::QuadInterpolator(
564 const G4double& e11, const G4double& e12, const G4double& e21,
565 const G4double& e22, const G4double& xs11, const G4double& xs12,
566 const G4double& xs21, const G4double& xs22, const G4double& t1,
567 const G4double& t2, const G4double& t, const G4double& e)
568{
569 G4double interpolatedvalue1 = Interpolate(e11, e12, e, xs11, xs12);
570 G4double interpolatedvalue2 = Interpolate(e21, e22, e, xs21, xs22);
571 G4double value =
572 Interpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
573
574 return value;
575}
576
578 const G4Material* /*material*/, G4int level,
579 const G4ParticleDefinition* particle, G4double kineticEnergy)
580{
581 if(fpTotalCrossSection != nullptr && particle != fProtonDef)
582 {
583 G4Exception("G4DNARPWBAIonisationModel::GetPartialCrossSection", "em0010",
584 FatalException, "Model not applicable to particle type.");
585 }
586 return fpTotalCrossSection->GetComponent(level)->FindValue(kineticEnergy);
587}
588
589//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
590
591G4int G4DNARPWBAIonisationModel::RandomSelect(G4double k)
592{
593 if(fpTotalCrossSection == nullptr)
594 {
595 G4Exception("G4DNARPWBAIonisationModel::RandomSelect", "em0010",
596 FatalException, "Model not applicable to particle type.");
597 }
598 else
599 {
600 auto valuesBuffer = new G4double[fpTotalCrossSection->NumberOfComponents()];
601 const G4int n = (G4int)fpTotalCrossSection->NumberOfComponents();
602 G4int i(n);
603 G4double value = 0.;
604 while(i > 0)
605 {
606 --i;
607 valuesBuffer[i] = fpTotalCrossSection->GetComponent(i)->FindValue(k);
608 value += valuesBuffer[i];
609 }
610 value *= G4UniformRand();
611 i = n;
612
613 while(i > 0)
614 {
615 --i;
616 if(valuesBuffer[i] > value)
617 {
618 delete[] valuesBuffer;
619 return i;
620 }
621 value -= valuesBuffer[i];
622 }
623 delete[] valuesBuffer;
624 }
625 return 0;
626}
627
628//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
629
631G4DNARPWBAIonisationModel::RandomizeEjectedElectronEnergyFromCumulatedDcs(
632 const G4double& k, const G4int& shell)
633{
634 G4double random = G4UniformRand();
635 G4double secondaryKineticEnergy =
636 TransferedEnergy(k / eV, shell, random) * eV -
637 waterStructure.IonisationEnergy(shell);
638 if(secondaryKineticEnergy < 0.)
639 {
640 return 0.;
641 }
642 return secondaryKineticEnergy;
643}
644
645//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
646
648 G4int ionizationLevelIndex,
649 const G4double& random)
650{
651 G4double nrj = 0.;
652 G4double valueK1 = 0;
653 G4double valueK2 = 0;
654 G4double valuePROB21 = 0;
655 G4double valuePROB22 = 0;
656 G4double valuePROB12 = 0;
657 G4double valuePROB11 = 0;
658 G4double nrjTransf11 = 0;
659 G4double nrjTransf12 = 0;
660 G4double nrjTransf21 = 0;
661 G4double nrjTransf22 = 0;
662 // Protection against out of boundary access - proton case : 100 MeV
663 if(k == pTdummyVec.back())
664 {
665 k = k * (1. - 1e-12);
666 }
667 // k should be in eV
668
669 auto k2 = std::upper_bound(pTdummyVec.begin(), pTdummyVec.end(), k);
670 auto k1 = k2 - 1;
671
672 // SI : the following condition avoids situations where random > last vector
673 // element,
674 // for eg. when the last element is zero
675 if(random <= pProbaShellMap[ionizationLevelIndex][(*k1)].back() &&
676 random <= pProbaShellMap[ionizationLevelIndex][(*k2)].back())
677 {
678 auto prob12 = std::upper_bound(
679 pProbaShellMap[ionizationLevelIndex][(*k1)].begin(),
680 pProbaShellMap[ionizationLevelIndex][(*k1)].end(), random);
681 auto prob11 = prob12 - 1;
682 auto prob22 = std::upper_bound(
683 pProbaShellMap[ionizationLevelIndex][(*k2)].begin(),
684 pProbaShellMap[ionizationLevelIndex][(*k2)].end(), random);
685
686 auto prob21 = prob22 - 1;
687
688 valueK1 = *k1;
689 valueK2 = *k2;
690 valuePROB21 = *prob21;
691 valuePROB22 = *prob22;
692 valuePROB12 = *prob12;
693 valuePROB11 = *prob11;
694
695 nrjTransf11 = pNrjTransfData[ionizationLevelIndex][valueK1][valuePROB11];
696 nrjTransf12 = pNrjTransfData[ionizationLevelIndex][valueK1][valuePROB12];
697 nrjTransf21 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB21];
698 nrjTransf22 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB22];
699 }
700
701 // Avoids cases where cum xs is zero for k1 and is not for k2 (with always
702 // k1<k2)
703
704 if(random > pProbaShellMap[ionizationLevelIndex][(*k1)].back())
705 {
706 auto prob22 = std::upper_bound(
707 pProbaShellMap[ionizationLevelIndex][(*k2)].begin(),
708 pProbaShellMap[ionizationLevelIndex][(*k2)].end(), random);
709 auto prob21 = prob22 - 1;
710
711 valueK1 = *k1;
712 valueK2 = *k2;
713 valuePROB21 = *prob21;
714 valuePROB22 = *prob22;
715 nrjTransf21 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB21];
716 nrjTransf22 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB22];
717
718 G4double interpolatedvalue2 =
719 Interpolate(valuePROB21, valuePROB22, random, nrjTransf21, nrjTransf22);
720
721 G4double value = Interpolate(valueK1, valueK2, k, 0., interpolatedvalue2);
722 return value;
723 }
724 G4double nrjTransfProduct =
725 nrjTransf11 * nrjTransf12 * nrjTransf21 * nrjTransf22;
726
727 if(nrjTransfProduct != 0.)
728 {
729 nrj = QuadInterpolator(valuePROB11, valuePROB12, valuePROB21, valuePROB22,
730 nrjTransf11, nrjTransf12, nrjTransf21, nrjTransf22,
731 valueK1, valueK2, k, random);
732 }
733 return nrj;
734}
G4AtomicShellEnumerator
@ eIonizedMolecule
const char * G4FindDataDir(const char *)
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
std::ostringstream G4ExceptionDescription
Definition: G4Exception.hh:40
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
const G4int Z[17]
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
double z() const
Hep3Vector unit() const
double x() const
double y() const
void set(double x, double y, double z)
static G4DNAChemistryManager * Instance()
void CreateWaterMolecule(ElectronicModification, G4int, const G4Track *)
const std::vector< G4double > * GetNumMolPerVolTableFor(const G4Material *) const
Retrieve a table of molecular densities (number of molecules per unit volume) in the G4 unit system f...
static G4DNAMolecularMaterial * Instance()
G4DNARPWBAIonisationModel(const G4ParticleDefinition *p=nullptr, const G4String &nam="DNARPWBAIonisationModel")
G4ParticleChangeForGamma * fParticleChangeForGamma
void Initialise(const G4ParticleDefinition *, const G4DataVector &= *(new G4DataVector())) override
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
G4double TransferedEnergy(G4double incomingParticleEnergy, G4int shell, const G4double &random)
G4double DifferentialCrossSection(const G4double &k, const G4double &energyTransfer, const G4int &shell)
G4double GetPartialCrossSection(const G4Material *, G4int, const G4ParticleDefinition *, G4double) override
G4double CrossSectionPerVolume(const G4Material *material, const G4ParticleDefinition *p, G4double ekin, G4double emin, G4double emax) override
const G4ThreeVector & GetMomentumDirection() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
static G4Electron * ElectronDefinition()
Definition: G4Electron.cc:88
static G4Electron * Electron()
Definition: G4Electron.cc:93
static G4LossTableManager * Instance()
G4VAtomDeexcitation * AtomDeexcitation()
const G4Material * GetMaterial() const
size_t GetIndex() const
Definition: G4Material.hh:255
static G4Material * GetMaterial(const G4String &name, G4bool warning=true)
Definition: G4Material.cc:691
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
const G4String & GetParticleName() const
virtual const G4AtomicShell * GetAtomicShell(G4int Z, G4AtomicShellEnumerator shell)=0
void GenerateParticles(std::vector< G4DynamicParticle * > *secVect, const G4AtomicShell *, G4int Z, G4int coupleIndex)
virtual G4ThreeVector & SampleDirectionForShell(const G4DynamicParticle *dp, G4double finalTotalEnergy, G4int Z, G4int shellID, const G4Material *)
G4VEmAngularDistribution * GetAngularDistribution()
Definition: G4VEmModel.hh:600
G4ParticleChangeForGamma * GetParticleChangeForGamma()
Definition: G4VEmModel.cc:124
G4double LowEnergyLimit() const
Definition: G4VEmModel.hh:641
G4double HighEnergyLimit() const
Definition: G4VEmModel.hh:634
void SetDeexcitationFlag(G4bool val)
Definition: G4VEmModel.hh:802
void SetAngularDistribution(G4VEmAngularDistribution *)
Definition: G4VEmModel.hh:607
const G4Track * GetCurrentTrack() const
void ProposeLocalEnergyDeposit(G4double anEnergyPart)