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
G4DNAPTBIonisationModel.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// Authors: S. Meylan and C. Villagrasa (IRSN, France)
27// Models come from
28// M. Bug et al, Rad. Phys and Chem. 130, 459-479 (2017)
29//
30
33#include "G4SystemOfUnits.hh"
35#include "G4LossTableManager.hh"
37
40 const G4String& nam, const G4bool isAuger)
41 : G4VDNAModel(nam, applyToMaterial)
42{
43 verboseLevel= 0;
44 // Verbosity scale:
45 // 0 = nothing
46 // 1 = warning for energy non-conservation
47 // 2 = details of energy budget
48 // 3 = calculation of cross sections, file openings, sampling of atoms
49 // 4 = entering in methods
50
51 if( verboseLevel>0 )
52 {
53 G4cout << "PTB ionisation model is constructed " << G4endl;
54 }
55
56 if(isAuger)
57 {
58 // create the PTB Auger model
59 fDNAPTBAugerModel = new G4DNAPTBAugerModel("e-_G4DNAPTBAugerModel");
60 }
61 else
62 {
63 // no PTB Auger model
64 fDNAPTBAugerModel = 0;
65 }
66}
67
68//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
69
71{
72 // To delete the DNAPTBAugerModel created at initialisation of the ionisation class
73 if(fDNAPTBAugerModel) delete fDNAPTBAugerModel;
74}
75
76//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
77
79 const G4DataVector& /*cuts*/, G4ParticleChangeForGamma*)
80{
81
82 if (verboseLevel > 3)
83 G4cout << "Calling G4DNAPTBIonisationModel::Initialise()" << G4endl;
84
85 G4double scaleFactor = 1e-16 * cm*cm;
86 G4double scaleFactorBorn = (1.e-22 / 3.343) * m*m;
87
90
91 //*******************************************************
92 // Cross section data
93 //*******************************************************
94
95 if(particle == electronDef)
96 {
97 G4String particleName = particle->GetParticleName();
98
99 // Raw materials
100 //
101 // MPietrzak
103 particleName,
104 "dna/sigma_ionisation_e-_PTB_N2",
105 "dna/sigmadiff_cumulated_ionisation_e-_PTB_N2",
106 scaleFactor);
107 SetLowELimit("N2", particleName, 15.5*eV);
108 SetHighELimit("N2", particleName, 1.02*MeV);
109 // MPietrzak
110
112 particleName,
113 "dna/sigma_ionisation_e-_PTB_THF",
114 "dna/sigmadiff_cumulated_ionisation_e-_PTB_THF",
115 scaleFactor);
116 SetLowELimit("THF", particleName, 12.*eV);
117 SetHighELimit("THF", particleName, 1.*keV);
118
120 particleName,
121 "dna/sigma_ionisation_e-_PTB_PY",
122 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PY",
123 scaleFactor);
124 SetLowELimit("PY", particleName, 12.*eV);
125 SetHighELimit("PY", particleName, 1.*keV);
126
128 particleName,
129 "dna/sigma_ionisation_e-_PTB_PU",
130 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PU",
131 scaleFactor);
132 SetLowELimit("PU", particleName, 12.*eV);
133 SetHighELimit("PU", particleName, 1.*keV);
134
136 particleName,
137 "dna/sigma_ionisation_e-_PTB_TMP",
138 "dna/sigmadiff_cumulated_ionisation_e-_PTB_TMP",
139 scaleFactor);
140 SetLowELimit("TMP", particleName, 12.*eV);
141 SetHighELimit("TMP", particleName, 1.*keV);
142
143 AddCrossSectionData("G4_WATER",
144 particleName,
145 "dna/sigma_ionisation_e_born",
146 "dna/sigmadiff_ionisation_e_born",
147 scaleFactorBorn);
148 SetLowELimit("G4_WATER", particleName, 12.*eV);
149 SetHighELimit("G4_WATER", particleName, 1.*keV);
150
151 // DNA materials
152 //
153 AddCrossSectionData("backbone_THF",
154 particleName,
155 "dna/sigma_ionisation_e-_PTB_THF",
156 "dna/sigmadiff_cumulated_ionisation_e-_PTB_THF",
157 scaleFactor*33./30);
158 SetLowELimit("backbone_THF", particleName, 12.*eV);
159 SetHighELimit("backbone_THF", particleName, 1.*keV);
160
161 AddCrossSectionData("cytosine_PY",
162 particleName,
163 "dna/sigma_ionisation_e-_PTB_PY",
164 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PY",
165 scaleFactor*42./30);
166 SetLowELimit("cytosine_PY", particleName, 12.*eV);
167 SetHighELimit("cytosine_PY", particleName, 1.*keV);
168
169 AddCrossSectionData("thymine_PY",
170 particleName,
171 "dna/sigma_ionisation_e-_PTB_PY",
172 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PY",
173 scaleFactor*48./30);
174 SetLowELimit("thymine_PY", particleName, 12.*eV);
175 SetHighELimit("thymine_PY", particleName, 1.*keV);
176
177 AddCrossSectionData("adenine_PU",
178 particleName,
179 "dna/sigma_ionisation_e-_PTB_PU",
180 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PU",
181 scaleFactor*50./44);
182 SetLowELimit("adenine_PU", particleName, 12.*eV);
183 SetHighELimit("adenine_PU", particleName, 1.*keV);
184
185 AddCrossSectionData("guanine_PU",
186 particleName,
187 "dna/sigma_ionisation_e-_PTB_PU",
188 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PU",
189 scaleFactor*56./44);
190 SetLowELimit("guanine_PU", particleName, 12.*eV);
191 SetHighELimit("guanine_PU", particleName, 1.*keV);
192
193 AddCrossSectionData("backbone_TMP",
194 particleName,
195 "dna/sigma_ionisation_e-_PTB_TMP",
196 "dna/sigmadiff_cumulated_ionisation_e-_PTB_TMP",
197 scaleFactor*33./50);
198 SetLowELimit("backbone_TMP", particleName, 12.*eV);
199 SetHighELimit("backbone_TMP", particleName, 1.*keV);
200 }
201
202 else if (particle == protonDef)
203 {
204 G4String particleName = particle->GetParticleName();
205
206 // Raw materials
207 //
209 particleName,
210 "dna/sigma_ionisation_p_HKS_THF",
211 "dna/sigmadiff_cumulated_ionisation_p_PTB_THF",
212 scaleFactor);
213 SetLowELimit("THF", particleName, 70.*keV);
214 SetHighELimit("THF", particleName, 10.*MeV);
215
216
218 particleName,
219 "dna/sigma_ionisation_p_HKS_PY",
220 "dna/sigmadiff_cumulated_ionisation_p_PTB_PY",
221 scaleFactor);
222 SetLowELimit("PY", particleName, 70.*keV);
223 SetHighELimit("PY", particleName, 10.*MeV);
224
225 /*
226 AddCrossSectionData("PU",
227 particleName,
228 "dna/sigma_ionisation_e-_PTB_PU",
229 "dna/sigmadiff_cumulated_ionisation_e-_PTB_PU",
230 scaleFactor);
231 SetLowELimit("PU", particleName2, 70.*keV);
232 SetHighELimit("PU", particleName2, 10.*keV);
233*/
234
236 particleName,
237 "dna/sigma_ionisation_p_HKS_TMP",
238 "dna/sigmadiff_cumulated_ionisation_p_PTB_TMP",
239 scaleFactor);
240 SetLowELimit("TMP", particleName, 70.*keV);
241 SetHighELimit("TMP", particleName, 10.*MeV);
242 }
243
244 // *******************************************************
245 // deal with composite materials
246 // *******************************************************
247
249
250 // *******************************************************
251 // Verbose
252 // *******************************************************
253
254 // initialise DNAPTBAugerModel
255 if(fDNAPTBAugerModel) fDNAPTBAugerModel->Initialise();
256}
257
258//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
259
261 const G4String& materialName,
262 const G4ParticleDefinition* p,
263 G4double ekin,
264 G4double /*emin*/,
265 G4double /*emax*/)
266{
267 if(verboseLevel > 3)
268 G4cout << "Calling CrossSectionPerVolume() of G4DNAPTBIonisationModel" << G4endl;
269
270 // initialise the cross section value (output value)
271 G4double sigma(0);
272
273 // Get the current particle name
274 const G4String& particleName = p->GetParticleName();
275
276 // Set the low and high energy limits
277 G4double lowLim = GetLowELimit(materialName, particleName);
278 G4double highLim = GetHighELimit(materialName, particleName);
279
280 // Check that we are in the correct energy range
281 if (ekin >= lowLim && ekin < highLim)
282 {
283 // Get the map with all the model data tables
284 TableMapData* tableData = GetTableData();
285
286 // Retrieve the cross section value for the current material, particle and energy values
287 sigma = (*tableData)[materialName][particleName]->FindValue(ekin);
288
289 if (verboseLevel > 2)
290 {
291 G4cout << "__________________________________" << G4endl;
292 G4cout << "°°° G4DNAPTBIonisationModel - XS INFO START" << G4endl;
293 G4cout << "°°° Kinetic energy(eV)=" << ekin/eV << " particle : " << particleName << G4endl;
294 G4cout << "°°° Cross section per "<< materialName <<" molecule (cm^2)=" << sigma/cm/cm << G4endl;
295 G4cout << "°°° G4DNAPTBIonisationModel - XS INFO END" << G4endl;
296 }
297 }
298
299 // Return the cross section value
300 return sigma;
301}
302
303//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
304
305void G4DNAPTBIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
306 const G4MaterialCutsCouple* /*couple*/,
307 const G4String& materialName,
308 const G4DynamicParticle* aDynamicParticle,
309 G4ParticleChangeForGamma* particleChangeForGamma,
310 G4double /*tmin*/,
311 G4double /*tmax*/)
312{
313 if (verboseLevel > 3)
314 G4cout << "Calling SampleSecondaries() of G4DNAPTBIonisationModel" << G4endl;
315
316 // Get the current particle energy
317 G4double k = aDynamicParticle->GetKineticEnergy();
318
319 // Get the current particle name
320 const G4String& particleName = aDynamicParticle->GetDefinition()->GetParticleName();
321
322 // Get the energy limits
323 G4double lowLim = GetLowELimit(materialName, particleName);
324 G4double highLim = GetHighELimit(materialName, particleName);
325
326 // Check if we are in the correct energy range
327 if (k >= lowLim && k < highLim)
328 {
329 G4ParticleMomentum primaryDirection = aDynamicParticle->GetMomentumDirection();
330 G4double particleMass = aDynamicParticle->GetDefinition()->GetPDGMass();
331 G4double totalEnergy = k + particleMass;
332 G4double pSquare = k * (totalEnergy + particleMass);
333 G4double totalMomentum = std::sqrt(pSquare);
334
335 // Get the ionisation shell from a random sampling
336 G4int ionizationShell = RandomSelectShell(k, particleName, materialName);
337
338 // Get the binding energy from the ptbStructure class
339 G4double bindingEnergy = ptbStructure.IonisationEnergy(ionizationShell, materialName);
340
341 // Initialize the secondary kinetic energy to a negative value.
342 G4double secondaryKinetic (-1000*eV);
343
344 if(materialName!="G4_WATER")
345 {
346 // Get the energy of the secondary particle
347 secondaryKinetic = RandomizeEjectedElectronEnergyFromCumulated(aDynamicParticle->GetDefinition(),k/eV,ionizationShell, materialName);
348 }
349 else
350 {
351 secondaryKinetic = RandomizeEjectedElectronEnergy(aDynamicParticle->GetDefinition(),k,ionizationShell, materialName);
352 }
353
354 if(secondaryKinetic<=0)
355 {
356 G4cout<<"Fatal error *************************************** "<<secondaryKinetic/eV<<G4endl;
357 G4cout<<"secondaryKinetic: "<<secondaryKinetic/eV<<G4endl;
358 G4cout<<"k: "<<k/eV<<G4endl;
359 G4cout<<"shell: "<<ionizationShell<<G4endl;
360 G4cout<<"material:"<<materialName<<G4endl;
361 exit(EXIT_FAILURE);
362 }
363
364 G4double cosTheta = 0.;
365 G4double phi = 0.;
366 RandomizeEjectedElectronDirection(aDynamicParticle->GetDefinition(), k, secondaryKinetic, cosTheta, phi);
367
368 G4double sinTheta = std::sqrt(1.-cosTheta*cosTheta);
369 G4double dirX = sinTheta*std::cos(phi);
370 G4double dirY = sinTheta*std::sin(phi);
371 G4double dirZ = cosTheta;
372 G4ThreeVector deltaDirection(dirX,dirY,dirZ);
373 deltaDirection.rotateUz(primaryDirection);
374
375 // The model is written only for electron and thus we want the change the direction of the incident electron
376 // after each ionization. However, if other particle are going to be introduced within this model the following should be added:
377 //
378 // Check if the particle is an electron
379 if(aDynamicParticle->GetDefinition() == G4Electron::ElectronDefinition() )
380 {
381 // If yes do the following code until next commented "else" statement
382
383 G4double deltaTotalMomentum = std::sqrt(secondaryKinetic*(secondaryKinetic + 2.*electron_mass_c2 ));
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(finalPx,finalPy,finalPz);
393 if(direction.unit().getX()>1||direction.unit().getY()>1||direction.unit().getZ()>1)
394 {
395 G4cout<<"Fatal error ****************************"<<G4endl;
396 G4cout<<"direction problem "<<direction.unit()<<G4endl;
397 exit(EXIT_FAILURE);
398 }
399
400 // Give the new direction to the particle
401 particleChangeForGamma->ProposeMomentumDirection(direction.unit()) ;
402 }
403 // If the particle is not an electron
404 else particleChangeForGamma->ProposeMomentumDirection(primaryDirection) ;
405
406 // note that secondaryKinetic is the energy of the delta ray, not of all secondaries.
407 G4double scatteredEnergy = k-bindingEnergy-secondaryKinetic;
408
409 if(scatteredEnergy<=0)
410 {
411 G4cout<<"Fatal error ****************************"<<G4endl;
412 G4cout<<"k: "<<k/eV<<G4endl;
413 G4cout<<"secondaryKinetic: "<<secondaryKinetic/eV<<G4endl;
414 G4cout<<"shell: "<<ionizationShell<<G4endl;
415 G4cout<<"bindingEnergy: "<<bindingEnergy/eV<<G4endl;
416 G4cout<<"scatteredEnergy: "<<scatteredEnergy/eV<<G4endl;
417 G4cout<<"material: "<<materialName<<G4endl;
418 exit(EXIT_FAILURE);
419 }
420
421 // Set the new energy of the particle
422 particleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy);
423
424 // Set the energy deposited by the ionization
425 particleChangeForGamma->ProposeLocalEnergyDeposit(k-scatteredEnergy-secondaryKinetic);
426
427 // Create the new particle with its characteristics
428 G4DynamicParticle* dp = new G4DynamicParticle (G4Electron::Electron(),deltaDirection,secondaryKinetic) ;
429 fvect->push_back(dp);
430
431 // Check if the auger model is activated (ie instanciated)
432 if(fDNAPTBAugerModel)
433 {
434 // run the PTB Auger model
435 if(materialName!="G4_WATER") fDNAPTBAugerModel->ComputeAugerEffect(fvect, materialName, bindingEnergy);
436 }
437 }
438}
439
440//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
441
442void G4DNAPTBIonisationModel::ReadDiffCSFile(const G4String& materialName,
443 const G4String& particleName,
444 const G4String& file,
445 const G4double scaleFactor)
446{
447 // To read and save the informations contained within the differential cross section files
448
449 // get the path of the G4LEDATA data folder
450 const char* path = G4FindDataDir("G4LEDATA");
451 // if it is not found then quit and print error message
452 if(!path)
453 {
454 G4Exception("G4DNAPTBIonisationModel::ReadAllDiffCSFiles","em0006",
455 FatalException,"G4LEDATA environment variable not set.");
456 return;
457 }
458
459 // build the fullFileName path of the data file
460 std::ostringstream fullFileName;
461 fullFileName << path <<"/"<< file<<".dat";
462
463 // open the data file
464 std::ifstream diffCrossSection (fullFileName.str().c_str());
465 // error if file is not there
466 std::stringstream endPath;
467 if (!diffCrossSection)
468 {
469 endPath << "Missing data file: "<<file;
470 G4Exception("G4DNAPTBIonisationModel::Initialise","em0003",
471 FatalException, endPath.str().c_str());
472 }
473
474 // load data from the file
475 fTMapWithVec[materialName][particleName].push_back(0.);
476
477 G4String line;
478
479 // read the file until we reach the end of file point
480 // fill fTMapWithVec, diffCrossSectionData, fEnergyTransferData, fProbaShellMap and fEMapWithVector
481 while(std::getline(diffCrossSection, line))
482 {
483 // check if the line is comment or empty
484 //
485 std::istringstream testIss(line);
486 G4String test;
487 testIss >> test;
488 // check first caracter to determine if following information is data or comments
489 if(test=="#")
490 {
491 // skip the line by beginning a new while loop.
492 continue;
493 }
494 // check if line is empty
495 else if(line.empty())
496 {
497 // skip the line by beginning a new while loop.
498 continue;
499 }
500 //
501 // end of the check
502
503 // transform the line into a iss
504 std::istringstream iss(line);
505
506 // Initialise the variables to be filled
507 double T;
508 double E;
509
510 // Filled T and E with the first two numbers of each file line
511 iss>>T>>E;
512
513 // Fill the fTMapWithVec container with all the different T values contained within the file.
514 // Duplicate must be avoided and this is the purpose of the if statement
515 if (T != fTMapWithVec[materialName][particleName].back()) fTMapWithVec[materialName][particleName].push_back(T);
516
517 // iterate on each shell of the corresponding material
518 for (int shell=0, eshell=ptbStructure.NumberOfLevels(materialName); shell<eshell; ++shell)
519 {
520 // map[material][particle][shell][T][E]=diffCrossSectionValue
521 // Fill the map with the informations of the input file
522 iss>>diffCrossSectionData[materialName][particleName][shell][T][E];
523
524 if(materialName!="G4_WATER")
525 {
526 // map[material][particle][shell][T][CS]=E
527 // Fill the map
528 fEnergySecondaryData[materialName][particleName][shell][T][diffCrossSectionData[materialName][particleName][shell][T][E] ]=E;
529
530 // map[material][particle][shell][T]=CS_vector
531 // Fill the vector within the map
532 fProbaShellMap[materialName][particleName][shell][T].push_back(diffCrossSectionData[materialName][particleName][shell][T][E]);
533 }
534 else
535 {
536 diffCrossSectionData[materialName][particleName][shell][T][E]*=scaleFactor;
537
538 fEMapWithVector[materialName][particleName][T].push_back(E);
539 }
540 }
541 }
542}
543
544
545//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
546
547G4double G4DNAPTBIonisationModel::RandomizeEjectedElectronEnergy(G4ParticleDefinition* particleDefinition,
548 G4double k, G4int shell, const G4String& materialName)
549{
550 if (particleDefinition == G4Electron::ElectronDefinition())
551 {
552 //G4double Tcut=25.0E-6;
553 G4double maximumEnergyTransfer=0.;
554 if ((k+ptbStructure.IonisationEnergy(shell, materialName))/2. > k) maximumEnergyTransfer=k;
555 else maximumEnergyTransfer = (k+ptbStructure.IonisationEnergy(shell,materialName))/2.;
556
557 // SI : original method
558 /*
559 G4double crossSectionMaximum = 0.;
560 for(G4double value=waterStructure.IonisationEnergy(shell); value<=maximumEnergyTransfer; value+=0.1*eV)
561 {
562 G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k/eV, value/eV, shell);
563 if(differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
564 }
565 */
566
567
568 // SI : alternative method
569
570 //if (k > Tcut)
571 //{
572 G4double crossSectionMaximum = 0.;
573
574 G4double minEnergy = ptbStructure.IonisationEnergy(shell, materialName);
575 G4double maxEnergy = maximumEnergyTransfer;
576 G4int nEnergySteps = 50;
577 G4double value(minEnergy);
578 G4double stpEnergy(std::pow(maxEnergy/value, 1./static_cast<G4double>(nEnergySteps-1)));
579 G4int step(nEnergySteps);
580 while (step>0)
581 {
582 step--;
583 G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k/eV, value/eV, shell, materialName);
584 if(differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
585 value *= stpEnergy;
586
587 }
588 //
589
590
591 G4double secondaryElectronKineticEnergy=0.;
592
593 do
594 {
595 secondaryElectronKineticEnergy = G4UniformRand() * (maximumEnergyTransfer-ptbStructure.IonisationEnergy(shell, materialName));
596
597 } while(G4UniformRand()*crossSectionMaximum >
598 DifferentialCrossSection(particleDefinition, k/eV,(secondaryElectronKineticEnergy+ptbStructure.IonisationEnergy(shell, materialName))/eV,shell, materialName));
599
600 return secondaryElectronKineticEnergy;
601
602 // }
603
604 // else if (k < Tcut)
605 // {
606
607 // G4double bindingEnergy = ptbStructure.IonisationEnergy(shell, materialName);
608 // G4double maxEnergy = ((k-bindingEnergy)/2.);
609
610 // G4double secondaryElectronKineticEnergy = G4UniformRand()*maxEnergy;
611 // return secondaryElectronKineticEnergy;
612 // }
613 }
614
615
616 else if (particleDefinition == G4Proton::ProtonDefinition())
617 {
618 G4double maximumKineticEnergyTransfer = 4.* (electron_mass_c2 / proton_mass_c2) * k;
619
620 G4double crossSectionMaximum = 0.;
621 for (G4double value = ptbStructure.IonisationEnergy(shell, materialName);
622 value<=4.*ptbStructure.IonisationEnergy(shell, materialName) ;
623 value+=0.1*eV)
624 {
625 G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k/eV, value/eV, shell, materialName);
626 if (differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
627 }
628
629 G4double secondaryElectronKineticEnergy = 0.;
630 do
631 {
632 secondaryElectronKineticEnergy = G4UniformRand() * maximumKineticEnergyTransfer;
633 } while(G4UniformRand()*crossSectionMaximum >=
634 DifferentialCrossSection(particleDefinition, k/eV,(secondaryElectronKineticEnergy+ptbStructure.IonisationEnergy(shell, materialName))/eV,shell, materialName));
635
636 return secondaryElectronKineticEnergy;
637 }
638
639 return 0;
640}
641
642//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
643
644void G4DNAPTBIonisationModel::RandomizeEjectedElectronDirection(G4ParticleDefinition* particleDefinition,
645 G4double k,
646 G4double secKinetic,
647 G4double & cosTheta,
648 G4double & phi)
649{
650 if (particleDefinition == G4Electron::ElectronDefinition())
651 {
652 phi = twopi * G4UniformRand();
653 if (secKinetic < 50.*eV) cosTheta = (2.*G4UniformRand())-1.;
654 else if (secKinetic <= 200.*eV)
655 {
656 if (G4UniformRand() <= 0.1) cosTheta = (2.*G4UniformRand())-1.;
657 else cosTheta = G4UniformRand()*(std::sqrt(2.)/2);
658 }
659 else
660 {
661 G4double sin2O = (1.-secKinetic/k) / (1.+secKinetic/(2.*electron_mass_c2));
662 cosTheta = std::sqrt(1.-sin2O);
663 }
664 }
665
666 else if (particleDefinition == G4Proton::ProtonDefinition())
667 {
668 G4double maxSecKinetic = 4.* (electron_mass_c2 / proton_mass_c2) * k;
669 phi = twopi * G4UniformRand();
670
671 // cosTheta = std::sqrt(secKinetic / maxSecKinetic);
672
673 // Restriction below 100 eV from Emfietzoglou (2000)
674
675 if (secKinetic>100*eV) cosTheta = std::sqrt(secKinetic / maxSecKinetic);
676 else cosTheta = (2.*G4UniformRand())-1.;
677
678 }
679}
680
681//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
682
683double G4DNAPTBIonisationModel::DifferentialCrossSection(G4ParticleDefinition * particleDefinition,
684 G4double k,
685 G4double energyTransfer,
686 G4int ionizationLevelIndex,
687 const G4String& materialName)
688{
689 G4double sigma = 0.;
690 const G4String& particleName = particleDefinition->GetParticleName();
691
692 G4double shellEnergy (ptbStructure.IonisationEnergy(ionizationLevelIndex, materialName));
693 G4double kSE (energyTransfer-shellEnergy);
694
695 if (energyTransfer >= shellEnergy)
696 {
697 G4double valueT1 = 0;
698 G4double valueT2 = 0;
699 G4double valueE21 = 0;
700 G4double valueE22 = 0;
701 G4double valueE12 = 0;
702 G4double valueE11 = 0;
703
704 G4double xs11 = 0;
705 G4double xs12 = 0;
706 G4double xs21 = 0;
707 G4double xs22 = 0;
708
709 if (particleDefinition == G4Electron::ElectronDefinition())
710 {
711 // k should be in eV and energy transfer eV also
712 std::vector<double>::iterator t2 = std::upper_bound(fTMapWithVec[materialName][particleName].begin(),fTMapWithVec[materialName][particleName].end(), k);
713 std::vector<double>::iterator t1 = t2-1;
714
715 // SI : the following condition avoids situations where energyTransfer >last vector element
716 if (kSE <= fEMapWithVector[materialName][particleName][(*t1)].back() && kSE <= fEMapWithVector[materialName][particleName][(*t2)].back() )
717 {
718 std::vector<double>::iterator e12 = std::upper_bound(fEMapWithVector[materialName][particleName][(*t1)].begin(),fEMapWithVector[materialName][particleName][(*t1)].end(), kSE);
719 std::vector<double>::iterator e11 = e12-1;
720
721 std::vector<double>::iterator e22 = std::upper_bound(fEMapWithVector[materialName][particleName][(*t2)].begin(),fEMapWithVector[materialName][particleName][(*t2)].end(), kSE);
722 std::vector<double>::iterator e21 = e22-1;
723
724 valueT1 =*t1;
725 valueT2 =*t2;
726 valueE21 =*e21;
727 valueE22 =*e22;
728 valueE12 =*e12;
729 valueE11 =*e11;
730
731 xs11 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT1][valueE11];
732 xs12 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT1][valueE12];
733 xs21 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT2][valueE21];
734 xs22 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT2][valueE22];
735 }
736 }
737
738 if (particleDefinition == G4Proton::ProtonDefinition())
739 {
740 // k should be in eV and energy transfer eV also
741 std::vector<double>::iterator t2 = std::upper_bound(fTMapWithVec[materialName][particleName].begin(),fTMapWithVec[materialName][particleName].end(), k);
742 std::vector<double>::iterator t1 = t2-1;
743
744 std::vector<double>::iterator e12 = std::upper_bound(fEMapWithVector[materialName][particleName][(*t1)].begin(),fEMapWithVector[materialName][particleName][(*t1)].end(), kSE);
745 std::vector<double>::iterator e11 = e12-1;
746
747 std::vector<double>::iterator e22 = std::upper_bound(fEMapWithVector[materialName][particleName][(*t2)].begin(),fEMapWithVector[materialName][particleName][(*t2)].end(), kSE);
748 std::vector<double>::iterator e21 = e22-1;
749
750 valueT1 =*t1;
751 valueT2 =*t2;
752 valueE21 =*e21;
753 valueE22 =*e22;
754 valueE12 =*e12;
755 valueE11 =*e11;
756
757 xs11 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT1][valueE11];
758 xs12 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT1][valueE12];
759 xs21 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT2][valueE21];
760 xs22 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT2][valueE22];
761 }
762
763 G4double xsProduct = xs11 * xs12 * xs21 * xs22;
764
765 if (xsProduct != 0.)
766 {
767 sigma = QuadInterpolator(valueE11, valueE12,
768 valueE21, valueE22,
769 xs11, xs12,
770 xs21, xs22,
771 valueT1, valueT2,
772 k, kSE);
773 }
774 }
775
776
777 return sigma;
778}
779
780//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
781
782G4double G4DNAPTBIonisationModel::RandomizeEjectedElectronEnergyFromCumulated(G4ParticleDefinition* particleDefinition,G4double k, G4int ionizationLevelIndex, const G4String& materialName)
783{
784 // k should be in eV
785
786 // Schematic explanation.
787 // We will do an interpolation to get a final E value (ejected electron energy).
788 // 1/ We choose a random number between 0 and 1 (ie we select a cumulated cross section).
789 // 2/ We look for T_lower and T_upper.
790 // 3/ We look for the cumulated corresponding cross sections and their associated E values.
791 //
792 // T_low | CS_low_1 -> E_low_1
793 // | CS_low_2 -> E_low_2
794 // T_up | CS_up_1 -> E_up_1
795 // | CS_up_2 -> E_up_2
796 //
797 // 4/ We interpolate to get our E value.
798 //
799 // T_low | CS_low_1 -> E_low_1 -----
800 // | |----> E_low --
801 // | CS_low_2 -> E_low_2 ----- |
802 // | ---> E_final
803 // T_up | CS_up_1 -> E_up_1 ------- |
804 // | |----> E_up ---
805 // | CS_up_2 -> E_up_2 -------
806
807 // Initialize some values
808 //
809 G4double ejectedElectronEnergy = 0.;
810 G4double valueK1 = 0;
811 G4double valueK2 = 0;
812 G4double valueCumulCS21 = 0;
813 G4double valueCumulCS22 = 0;
814 G4double valueCumulCS12 = 0;
815 G4double valueCumulCS11 = 0;
816 G4double secElecE11 = 0;
817 G4double secElecE12 = 0;
818 G4double secElecE21 = 0;
819 G4double secElecE22 = 0;
820 G4String particleName = particleDefinition->GetParticleName();
821
822 // ***************************************************************************
823 // Get a random number between 0 and 1 to compare with the cumulated CS
824 // ***************************************************************************
825 //
826 // It will allow us to choose an ejected electron energy with respect to the CS.
827 G4double random = G4UniformRand();
828
829 // **********************************************
830 // Take the input from the data tables
831 // **********************************************
832
833 // Cumulated tables are like this: T E cumulatedCS1 cumulatedCS2 cumulatedCS3
834 // We have two sets of loaded data: fTMapWithVec which contains data about T (incident particle energy)
835 // and fProbaShellMap which contains cumulated cross section data.
836 // Since we already have a specific T energy value which could not be explicitly in the table, we must interpolate all the values.
837
838 // First, we select the upper and lower T data values surrounding our T value (ie "k").
839 std::vector<double>::iterator k2 = std::upper_bound(fTMapWithVec[materialName][particleName].begin(),fTMapWithVec[materialName][particleName].end(), k);
840 std::vector<double>::iterator k1 = k2-1;
841
842 // Check if we have found a k2 value (0 if we did not found it).
843 // A missing k2 value can be caused by a energy to high for the data table,
844 // Ex : table done for 12*eV -> 1000*eV and k=2000*eV
845 // then k2 = 0 and k1 = max of the table.
846 // To detect this, we check that k1 is not superior to k2.
847 if(*k1 > *k2)
848 {
849 // Error
850 G4cerr<<"**************** Fatal error ******************"<<G4endl;
851 G4cerr<<"G4DNAPTBIonisationModel::RandomizeEjectedElectronEnergyFromCumulated"<<G4endl;
852 G4cerr<<"You have *k1 > *k2 with k1 "<<*k1<<" and k2 "<<*k2<<G4endl;
853 G4cerr<<"This may be because the energy of the incident particle is to high for the data table."<<G4endl;
854 G4cerr<<"Particle energy (eV): "<<k<<G4endl;
855 exit(EXIT_FAILURE);
856 }
857
858
859 // We have a random number and we select the cumulated cross section data values surrounding our random number.
860 // But we need to do that for each T value (ie two T values) previously selected.
861 //
862 // First one.
863 std::vector<double>::iterator cumulCS12 = std::upper_bound(fProbaShellMap[materialName][particleName][ionizationLevelIndex][(*k1)].begin(),
864 fProbaShellMap[materialName][particleName][ionizationLevelIndex][(*k1)].end(), random);
865 std::vector<double>::iterator cumulCS11 = cumulCS12-1;
866 // Second one.
867 std::vector<double>::iterator cumulCS22 = std::upper_bound(fProbaShellMap[materialName][particleName][ionizationLevelIndex][(*k2)].begin(),
868 fProbaShellMap[materialName][particleName][ionizationLevelIndex][(*k2)].end(), random);
869 std::vector<double>::iterator cumulCS21 = cumulCS22-1;
870
871 // Now that we have the "values" through pointers, we access them.
872 valueK1 = *k1;
873 valueK2 = *k2;
874 valueCumulCS11 = *cumulCS11;
875 valueCumulCS12 = *cumulCS12;
876 valueCumulCS21 = *cumulCS21;
877 valueCumulCS22 = *cumulCS22;
878
879 // *************************************************************
880 // Do the interpolation to get the ejected electron energy
881 // *************************************************************
882
883 // Here we will get four E values corresponding to our four cumulated cross section values previously selected.
884 // But we need to take into account a specific case: we have selected a shell by using the ionisation cross section table
885 // and, since we get two T values, we could have differential cross sections (or cumulated) equal to 0 for the lower T
886 // and not for the upper T. When looking for the cumulated cross section values which surround the selected random number (for the lower T),
887 // the upper_bound method will only found 0 values. Thus, the upper_bound method will return the last E value present in the table for the
888 // selected T. The last E value being the highest, we will later perform an interpolation between a high E value (for the lower T) and
889 // a small E value (for the upper T). This is inconsistent because if the cross section are equal to zero for the lower T then it
890 // means it is not possible to ionize and, thus, to have a secondary electron. But, in our situation, it is possible to ionize for the upper T
891 // AND for an interpolate T value between Tupper Tlower. That's why the final E value should be interpolate between 0 and the E value (upper T).
892 //
893 if(cumulCS12==fProbaShellMap[materialName][particleName][ionizationLevelIndex][(*k1)].end())
894 {
895 // Here we are in the special case and we force Elower1 and Elower2 to be equal at 0 for the interpolation.
896 secElecE11 = 0;
897 secElecE12 = 0;
898 secElecE21 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK2][valueCumulCS21];
899 secElecE22 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK2][valueCumulCS22];
900
901 valueCumulCS11 = 0;
902 valueCumulCS12 = 0;
903 }
904 else
905 {
906 // No special case, interpolation will happen as usual.
907 secElecE11 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK1][valueCumulCS11];
908 secElecE12 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK1][valueCumulCS12];
909 secElecE21 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK2][valueCumulCS21];
910 secElecE22 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK2][valueCumulCS22];
911 }
912
913 ejectedElectronEnergy = QuadInterpolator(valueCumulCS11, valueCumulCS12,
914 valueCumulCS21, valueCumulCS22,
915 secElecE11, secElecE12,
916 secElecE21, secElecE22,
917 valueK1, valueK2,
918 k, random);
919
920 // **********************************************
921 // Some tests for debugging
922 // **********************************************
923
924 G4double bindingEnergy (ptbStructure.IonisationEnergy(ionizationLevelIndex, materialName)/eV);
925 if(k-ejectedElectronEnergy-bindingEnergy<=0 || ejectedElectronEnergy<=0)
926 {
927 G4cout<<"k "<<k<<G4endl;
928 G4cout<<"material "<<materialName<<G4endl;
929 G4cout<<"secondaryKin "<<ejectedElectronEnergy<<G4endl;
930 G4cout<<"shell "<<ionizationLevelIndex<<G4endl;
931 G4cout<<"bindingEnergy "<<bindingEnergy<<G4endl;
932 G4cout<<"scatteredEnergy "<<k-ejectedElectronEnergy-bindingEnergy<<G4endl;
933 G4cout<<"rand "<<random<<G4endl;
934 G4cout<<"surrounding k values: valueK1 valueK2\n"<<valueK1<<" "<<valueK2<<G4endl;
935 G4cout<<"surrounding E values: secElecE11 secElecE12 secElecE21 secElecE22\n"
936 <<secElecE11<<" "<<secElecE12<<" "<<secElecE21<<" "<<secElecE22<<" "<<G4endl;
937 G4cout<<"surrounding cumulCS values: valueCumulCS11 valueCumulCS12 valueCumulCS21 valueCumulCS22\n"
938 <<valueCumulCS11<<" "<<valueCumulCS12<<" "<<valueCumulCS21<<" "<<valueCumulCS22<<" "<<G4endl;
939 G4cerr<<"*****************************"<<G4endl;
940 G4cerr<<"Fatal error, EXIT."<<G4endl;
941 exit(EXIT_FAILURE);
942 }
943
944 return ejectedElectronEnergy*eV;
945}
946
947//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
948
949G4double G4DNAPTBIonisationModel::LogLogInterpolate(G4double e1,
950 G4double e2,
951 G4double e,
952 G4double xs1,
953 G4double xs2)
954{
955 G4double value (0);
956
957 // Switch to log-lin interpolation for faster code
958
959 if ((e2-e1)!=0 && xs1 !=0 && xs2 !=0)
960 {
961 G4double d1 = std::log10(xs1);
962 G4double d2 = std::log10(xs2);
963 value = std::pow(10.,(d1 + (d2 - d1)*(e - e1)/ (e2 - e1)) );
964 }
965
966 // Switch to lin-lin interpolation for faster code
967 // in case one of xs1 or xs2 (=cum proba) value is zero
968
969 if ((e2-e1)!=0 && (xs1 ==0 || xs2 ==0))
970 {
971 G4double d1 = xs1;
972 G4double d2 = xs2;
973 value = (d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
974 }
975
976 return value;
977}
978
979//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
980
981G4double G4DNAPTBIonisationModel::QuadInterpolator(G4double e11, G4double e12,
982 G4double e21, G4double e22,
983 G4double xs11, G4double xs12,
984 G4double xs21, G4double xs22,
985 G4double t1, G4double t2,
986 G4double t, G4double e)
987{
988 G4double interpolatedvalue1 (-1);
989 if(xs11!=xs12) interpolatedvalue1 = LogLogInterpolate(e11, e12, e, xs11, xs12);
990 else interpolatedvalue1 = xs11;
991
992 G4double interpolatedvalue2 (-1);
993 if(xs21!=xs22) interpolatedvalue2 = LogLogInterpolate(e21, e22, e, xs21, xs22);
994 else interpolatedvalue2 = xs21;
995
996 G4double value (-1);
997 if(interpolatedvalue1!=interpolatedvalue2) value = LogLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
998 else value = interpolatedvalue1;
999
1000 return value;
1001
1002 // G4double interpolatedvalue1 = LogLogInterpolate(e11, e12, e, xs11, xs12);
1003 // G4double interpolatedvalue2 = LogLogInterpolate(e21, e22, e, xs21, xs22);
1004 // G4double value = LogLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
1005 // return value;
1006}
const char * G4FindDataDir(const char *)
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
G4GLOB_DLL std::ostream G4cerr
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
double z() const
Hep3Vector unit() const
double getZ() const
double x() const
double y() const
double getX() const
Hep3Vector & rotateUz(const Hep3Vector &)
Definition: ThreeVector.cc:33
double getY() const
The G4DNAPTBAugerModel class Implement the PTB Auger model.
void ComputeAugerEffect(std::vector< G4DynamicParticle * > *fvect, const G4String &materialNameIni, G4double bindingEnergy)
ComputeAugerEffect Main method to be called by the ionisation model.
virtual void Initialise()
Initialise Set the verbose value.
virtual void Initialise(const G4ParticleDefinition *particle, const G4DataVector &= *(new G4DataVector()), G4ParticleChangeForGamma *fpChangeForGamme=nullptr)
Initialise Method called once at the beginning of the simulation. It is used to setup the list of the...
virtual G4double CrossSectionPerVolume(const G4Material *material, const G4String &materialName, const G4ParticleDefinition *p, G4double ekin, G4double emin, G4double emax)
CrossSectionPerVolume Mandatory for every model the CrossSectionPerVolume method is in charge of retu...
G4DNAPTBIonisationModel(const G4String &applyToMaterial="all", const G4ParticleDefinition *p=0, const G4String &nam="DNAPTBIonisationModel", const G4bool isAuger=true)
G4DNAPTBIonisationModel Constructor.
virtual void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4String &materialName, const G4DynamicParticle *, G4ParticleChangeForGamma *particleChangeForGamma, G4double tmin, G4double tmax)
SampleSecondaries If the model is selected for the ModelInterface then SampleSecondaries will be call...
virtual ~G4DNAPTBIonisationModel()
~G4DNAPTBIonisationModel Destructor
G4double IonisationEnergy(G4int level, const G4String &materialName)
G4int NumberOfLevels(const G4String &materialName)
const G4ThreeVector & GetMomentumDirection() const
G4ParticleDefinition * GetDefinition() const
G4double GetKineticEnergy() const
static G4Electron * ElectronDefinition()
Definition: G4Electron.cc:88
static G4Electron * Electron()
Definition: G4Electron.cc:93
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void ProposeMomentumDirection(const G4ThreeVector &Pfinal)
const G4String & GetParticleName() const
static G4Proton * ProtonDefinition()
Definition: G4Proton.cc:87
The G4VDNAModel class.
Definition: G4VDNAModel.hh:50
G4int RandomSelectShell(G4double k, const G4String &particle, const G4String &materialName)
RandomSelectShell Method to randomely select a shell from the data table uploaded....
Definition: G4VDNAModel.cc:182
TableMapData * GetTableData()
GetTableData.
Definition: G4VDNAModel.hh:193
void SetHighELimit(const G4String &material, const G4String &particle, G4double lim)
SetHighEnergyLimit.
Definition: G4VDNAModel.hh:169
std::map< G4String, std::map< G4String, G4DNACrossSectionDataSet *, std::less< G4String > > > TableMapData
Definition: G4VDNAModel.hh:183
void AddCrossSectionData(G4String materialName, G4String particleName, G4String fileCS, G4String fileDiffCS, G4double scaleFactor)
AddCrossSectionData Method used during the initialization of the model class to add a new material....
Definition: G4VDNAModel.cc:58
void SetLowELimit(const G4String &material, const G4String &particle, G4double lim)
SetLowEnergyLimit.
Definition: G4VDNAModel.hh:177
G4double GetHighELimit(const G4String &material, const G4String &particle)
GetHighEnergyLimit.
Definition: G4VDNAModel.hh:153
void LoadCrossSectionData(const G4String &particleName)
LoadCrossSectionData Method to loop on all the registered materials in the model and load the corresp...
Definition: G4VDNAModel.cc:75
G4double GetLowELimit(const G4String &material, const G4String &particle)
GetLowEnergyLimit.
Definition: G4VDNAModel.hh:161
void ProposeLocalEnergyDeposit(G4double anEnergyPart)
G4double bindingEnergy(G4int A, G4int Z)