Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4DNABornIonisationModel.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
29#include "G4SystemOfUnits.hh"
32#include "G4LossTableManager.hh"
33#include "G4EmParameters.hh"
34#include "G4NistManager.hh"
38#include "G4DNABornAngle.hh"
39#include "G4DNASamplingTable.hh"
41#include "G4DeltaAngle.hh"
42#include "G4Log.hh"
43#include "G4Exp.hh"
44#include "G4Electron.hh"
45#include "G4Proton.hh"
46
47//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
48
49G4DNACrossSectionDataSet* G4DNABornIonisationModel::xsdata_e = nullptr;
50G4DNACrossSectionDataSet* G4DNABornIonisationModel::xsdata_p = nullptr;
51G4DNASamplingTable* G4DNABornIonisationModel::sampling_e = nullptr;
52G4DNASamplingTable* G4DNABornIonisationModel::sampling_p = nullptr;
53const std::vector<G4double>* G4DNABornIonisationModel::fpWaterDensity = nullptr;
54
55namespace
56{
57 G4double scaleFactor = (1.e-22 / 3.343) * CLHEP::m*CLHEP::m;
58 G4double tolerance = 10*CLHEP::eV;
59}
60
61//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
62
64 const G4String& nam) :
65 G4VEmModel(nam)
66{
68
69 // Define default angular generator
71
72 fasterCode = G4EmParameters::Instance()->DNAFast();
73
74 if (nullptr == xsdata_p) {
75 isFirst = true;
76 LoadData();
77 }
78}
79
80//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
81
83{
84 if (isFirst) {
85 delete xsdata_e;
86 xsdata_e = nullptr;
87 delete xsdata_p;
88 xsdata_p = nullptr;
89 delete sampling_e;
90 sampling_e = nullptr;
91 delete sampling_p;
92 sampling_p = nullptr;
93 }
94}
95
96//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
97
98void G4DNABornIonisationModel::LoadData()
99{
100 // initialisation of static data once
101 G4String fileElectron("dna/sigma_ionisation_e_born");
102 xsdata_e = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
103 xsdata_e->LoadData(fileElectron);
104
105 G4String fileProton("dna/sigma_ionisation_p_born");
106 xsdata_p = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
107 xsdata_p->LoadData(fileProton);
108
109 // to avoid possible threading problem fill this vector only once
110 auto water = G4NistManager::Instance()->FindMaterial("G4_WATER");
111 fpWaterDensity =
113
114 G4bool verb = true;
115 sampling_e = new G4DNASamplingTable(100);
116 sampling_p = new G4DNASamplingTable(100);
117
118 if (fasterCode) {
119 G4String eb = "/dna/sigmadiff_cumulated_ionisation_e_born.dat";
120 sampling_e->LoadData(eb, CLHEP::eV, 1.0, verb);
121 G4String pb = "/dna/sigmadiff_cumulated_ionisation_p_born.dat";
122 sampling_p->LoadData(pb, CLHEP::eV, 1.0, verb);
123 } else {
124 G4String eb = "/dna/sigmadiff_ionisation_e_born.dat";
125 sampling_e->LoadData(eb, CLHEP::eV, scaleFactor, verb);
126 G4String pb = "/dna/sigmadiff_ionisation_p_born.dat";
127 sampling_p->LoadData(pb, CLHEP::eV, scaleFactor, verb);
128 }
129}
130
131//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
132
134 const G4DataVector&)
135{
136 if (isInitialised) { return; }
138 isInitialised = true;
139
140 if (p == G4Electron::Electron()) {
141 fParticle = p;
142 xsdata = xsdata_e;
143 sampling = sampling_e;
144 fLowEnergy = 8*CLHEP::eV;
145 fHighEnergy = 1*CLHEP::MeV;
146 feLimitEnergy = 19*CLHEP::eV;
147 fAbsorptionEnergy = 6*CLHEP::eV;
148 fMass = CLHEP::electron_mass_c2;
149 isElectron = true;
150 } else if (p == G4Proton::Proton()) {
151 fParticle = p;
152 xsdata = xsdata_p;
153 sampling = sampling_p;
154 fLowEnergy = 100*CLHEP::keV;
155 fHighEnergy = 100*CLHEP::MeV;
156 fpLimitEnergy = 70*CLHEP::MeV;
157 fAbsorptionEnergy = 50*CLHEP::eV;
158 fMass = CLHEP::proton_mass_c2;
159 isElectron = false;
160 } else {
162 ed << "Born ionisation model is used for " << p->GetParticleName();
163 G4Exception("G4DNABornIonisationModel::Initialise","em0003",
164 FatalException, ed, " it is not available.");
165 }
167
168 // defined stationary mode
170
171 // initialise atomic de-excitation
172 fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
173
174 // chemistry
176 if (chem->IsChemistryActivated()) {
177 fChemistry = chem;
178 }
179
180 InitialiseIntegrator(0.1, 0.25, 1.05, 1*CLHEP::eV, 0.2*CLHEP::eV, 10*CLHEP::keV);
181 if (verbose > 1) {
182 G4cout << "Born ionisation model is initialized for "
183 << fParticle->GetParticleName() << G4endl;
184 }
185}
186
187//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
188
190{
191 fTrack = track;
192}
193
194//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
195
199{
200 // check if model is applicable for given material
201 G4double density = (material->GetIndex() < fpWaterDensity->size())
202 ? (*fpWaterDensity)[material->GetIndex()] : 0.0;
203 if (0.0 == density) { return 0.0; }
204
205 // check on kinetic energy (not scaled energy) to stop low-energy ion
206 const G4double xSecMax = 1.e+10*CLHEP::barn;
207 if (ekin < fAbsorptionEnergy) { return xSecMax; }
208
209 G4double e = std::min(ekin, fHighEnergy);
210 G4double sigma = (e > fLowEnergy) ? xsdata->FindValue(e)
211 : xsdata->FindValue(fLowEnergy) * e / fLowEnergy;
212
213 sigma *= density;
214
215 // ICRU49 electronic SP scaling - ZF, SI
216 if (!isElectron && spScaling && e < fpLimitEnergy) {
217 const G4double A = 1.39241700556072800000e-9;
218 const G4double B = -8.52610412942622630000e-2;
219 sigma *= G4Exp(A*(ekin/CLHEP::eV) + B);
220 }
221 if (verbose > 1) {
222 G4cout << "G4DNABornIonisationModel for " << fParticle->GetParticleName()
223 << " Ekin(keV)=" << ekin/CLHEP::keV
224 << " sigma(cm^2)=" << sigma/CLHEP::cm2 << G4endl;
225 }
226 return sigma;
227}
228
229//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
230
231void G4DNABornIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
232 const G4MaterialCutsCouple* couple,
233 const G4DynamicParticle* dynParticle,
235{
236 fPrimaryEnergy = dynParticle->GetKineticEnergy();
237 // proton shoud be stopped - check on kinetic energy
238 // electrons never have such low energy
239 if (fPrimaryEnergy <= fAbsorptionEnergy) {
240 fParticleChangeForGamma->SetProposedKineticEnergy(0.);
241 fParticleChangeForGamma->ProposeTrackStatus(fStopButAlive);
242 fParticleChangeForGamma->ProposeLocalEnergyDeposit(fPrimaryEnergy);
243 return;
244 }
245
246 fSelectedShell = SelectShell();
247 G4double bindingEnergy = waterStructure.IonisationEnergy(fSelectedShell);
248
249 //SI: additional protection if tcs interpolation method is modified
250 if (fPrimaryEnergy < bindingEnergy) { return; }
251
252 // compute max energy
253 if (isElectron) {
254 fMaxEnergy = 0.5*(fPrimaryEnergy - bindingEnergy);
255 } else {
256 G4double tau = fPrimaryEnergy/fMass;
257 fMaxEnergy = 2.0*CLHEP::electron_mass_c2*tau*(tau + 2.0);
258 }
259 // SI: The following protection is necessary to avoid infinite loops :
260 // e- ionisation cross section has non zero partial xs at 18 eV for shell 2.
261 // e- has zero cumulated partial xs at 18 eV for shell 2.
262 // This is due to the fact that the max allowed transfered energy is
263 // (18+10.79)/2=17.025 eV and only transfered energies strictly above this
264 // value have non zero partial cross section starting at transition energy 17.12 eV.
265 if (fasterCode && isElectron && 2 == fSelectedShell && fPrimaryEnergy < feLimitEnergy) {
266 do {
267 fSelectedShell = SelectShell();
268 } while (2 == fSelectedShell);
269 }
270
271 G4double esec = fasterCode ? SampleCumulative() : SampleDifferential();
272 G4double esum = 0.0;
273
274 // sample deexcitation
275 // here we assume that H2O electronic levels are the same as Oxygen.
276 // this can be considered true with a rough 10% error in energy on K-shell,
277 G4int Z = 8;
278 G4ThreeVector deltaDir =
279 GetAngularDistribution()->SampleDirectionForShell(dynParticle, esec, Z,
280 fSelectedShell,
281 couple->GetMaterial());
282
283 // SI: only atomic deexcitation from K shell is considered
284 if (fAtomDeexcitation != nullptr && fSelectedShell == 4) {
285 auto as = G4AtomicShellEnumerator(0);
286 auto ashell = fAtomDeexcitation->GetAtomicShell(Z, as);
287 fAtomDeexcitation->GenerateParticles(fvect, ashell, Z, 0, 0);
288
289 // compute energy sum from de-excitation
290 for (auto const & ptr : *fvect) {
291 esum += ptr->GetKineticEnergy();
292 }
293 }
294 // check energy balance
295 // remaining excitation energy of water molecule
296 G4double exc = std::max(bindingEnergy - esum, 0.0);
297
298 // remaining projectile energy
299 G4double scatteredEnergy = fPrimaryEnergy - bindingEnergy - esec;
300 if (scatteredEnergy < -tolerance || exc < -tolerance) {
301 G4cout << "G4DNABornIonisationModel::SampleSecondaries: "
302 << "final E(keV)=" << scatteredEnergy/CLHEP::keV << " Ein(keV)="
303 << fPrimaryEnergy/CLHEP::keV << " " << fParticle->GetParticleName()
304 << " Edelta(keV)=" << esec/CLHEP::keV << " MeV, Exc(keV)=" << exc/CLHEP::keV
305 << G4endl;
306 }
307 scatteredEnergy = std::max(scatteredEnergy, 0.0);
308
309 // projectile
310 if (!statCode) {
311 fParticleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy);
312 fParticleChangeForGamma->ProposeLocalEnergyDeposit(exc);
313 } else {
314 fParticleChangeForGamma->SetProposedKineticEnergy(fPrimaryEnergy);
315 fParticleChangeForGamma->ProposeLocalEnergyDeposit(fPrimaryEnergy - scatteredEnergy);
316 }
317
318 // delta-electron
319 auto dp = new G4DynamicParticle(G4Electron::Electron(), deltaDir, esec);
320 fvect->push_back(dp);
321
322 // create radical
323 if (nullptr != fChemistry) {
324 fChemistry->CreateWaterMolecule(eIonizedMolecule, fSelectedShell, fTrack);
325 }
326}
327
328//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
329
330G4int G4DNABornIonisationModel::SelectShell()
331{
332 G4double sum = 0.0;
333 G4double xs;
334 G4double e = std::min(fPrimaryEnergy, fHighEnergy);
335 for (G4int i=0; i<5; ++i) {
336 auto ptr = xsdata->GetComponent(i);
337 xs = (e > fLowEnergy) ? ptr->FindValue(e)
338 : ptr->FindValue(fLowEnergy) * e/fLowEnergy;
339 sum += xs;
340 fTemp[i] = sum;
341 }
342 sum *= G4UniformRand();
343 for (G4int i=0; i<5; ++i) {
344 if (sum <= fTemp[i]) { return i; }
345 }
346 return 0;
347}
348
349//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
350
351G4double G4DNABornIonisationModel::SampleCumulative()
352{
353 G4double e = sampling->SampleCumulative(fPrimaryEnergy, fSelectedShell);
354 if (verbose > 1) {
355 G4cout << "G4DNABornIonisationModel::SampleCumulative: "
356 << fParticle->GetParticleName()
357 << " Ekin(keV)=" << fPrimaryEnergy/CLHEP::keV
358 << " Ee(keV)=" << e/CLHEP::keV << G4endl;
359 }
360 return e;
361}
362
363//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
364
365G4double G4DNABornIonisationModel::SampleDifferential()
366{
367 G4double xs = ComputeIntegral(0.0, fMaxEnergy);
368 G4double e = (xs > 0.0) ? SampleValue() : G4UniformRand()*fMaxEnergy;
369 if (verbose > 1) {
370 G4cout << "G4DNABornIonisationModel::SampleDifferential: "
371 << fParticle->GetParticleName()
372 << " Ekin(keV)=" << fPrimaryEnergy/CLHEP::keV
373 << " Ee(keV)=" << e/CLHEP::keV << G4endl;
374 }
375 return e;
376}
377
378//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
379
381{
382 return sampling->GetValue(fPrimaryEnergy, ekin, fSelectedShell);
383}
384
385//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@ eIonizedMolecule
G4double B(G4double temperature)
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
Definition G4Exp.hh:132
CLHEP::Hep3Vector G4ThreeVector
@ fStopButAlive
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
const G4double A[17]
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition Randomize.hh:52
G4DNABornIonisationModel(const G4ParticleDefinition *p=nullptr, const G4String &nam="DNABornIonisationModel")
void StartTracking(G4Track *) override
G4double CrossSectionPerVolume(const G4Material *material, const G4ParticleDefinition *p, G4double ekin, G4double emin, G4double emax) override
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
G4ParticleChangeForGamma * fParticleChangeForGamma
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double tmin, G4double maxEnergy) override
G4double ProbabilityDensityFunction(G4double ekin) override
static G4DNAChemistryManager * Instance()
G4bool LoadData(const G4String &argFileName) override
const G4VEMDataSet * GetComponent(G4int componentId) const override
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()
void LoadData(const G4String &filename, G4double factorE, G4double scaleFactor, G4bool verbose)
G4double GetKineticEnergy() const
static G4Electron * Electron()
Definition G4Electron.cc:91
static G4EmParameters * Instance()
G4bool DNAFast() const
G4bool DNAStationary() const
G4int WorkerVerbose() const
static G4LossTableManager * Instance()
G4VAtomDeexcitation * AtomDeexcitation()
const G4Material * GetMaterial() const
std::size_t GetIndex() const
G4Material * FindMaterial(const G4String &name) const
static G4NistManager * Instance()
const G4String & GetParticleName() const
static G4Proton * Proton()
Definition G4Proton.cc:90
virtual G4double FindValue(G4double x, G4int componentId=0) const =0
virtual G4ThreeVector & SampleDirectionForShell(const G4DynamicParticle *dp, G4double finalTotalEnergy, G4int Z, G4int shellID, const G4Material *)
G4VEmAngularDistribution * GetAngularDistribution()
G4ParticleChangeForGamma * GetParticleChangeForGamma()
void SetDeexcitationFlag(G4bool val)
G4VEmModel(const G4String &nam)
Definition G4VEmModel.cc:67
void SetAngularDistribution(G4VEmAngularDistribution *)
G4double ComputeIntegral(const G4double emin, const G4double emax)
void InitialiseIntegrator(G4double accuracy, G4double fact1, G4double fact2, G4double de, G4double dmin, G4double dmax)