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