Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
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)