Geant4 Cross Reference |
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 // 27 // Modified by Z. Francis, S. Incerti to handle HZE 28 // && inverse rudd function sampling 26-10-2010 29 // 30 // Rewitten by V.Ivanchenko 21.05.2023 31 // 32 33 #include "G4EmCorrections.hh" 34 #include "G4DNARuddIonisationExtendedModel.hh" 35 #include "G4PhysicalConstants.hh" 36 #include "G4SystemOfUnits.hh" 37 #include "G4UAtomicDeexcitation.hh" 38 #include "G4LossTableManager.hh" 39 #include "G4NistManager.hh" 40 #include "G4DNAChemistryManager.hh" 41 #include "G4DNAMolecularMaterial.hh" 42 43 #include "G4IonTable.hh" 44 #include "G4DNARuddAngle.hh" 45 #include "G4DeltaAngle.hh" 46 #include "G4Exp.hh" 47 #include "G4Log.hh" 48 #include "G4Pow.hh" 49 #include "G4Alpha.hh" 50 #include "G4Proton.hh" 51 52 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 53 54 G4DNACrossSectionDataSet* G4DNARuddIonisationExtendedModel::xsdata[] = {nullptr}; 55 G4DNACrossSectionDataSet* G4DNARuddIonisationExtendedModel::xshelium = nullptr; 56 G4DNACrossSectionDataSet* G4DNARuddIonisationExtendedModel::xsalphaplus = nullptr; 57 const std::vector<G4double>* G4DNARuddIonisationExtendedModel::fpWaterDensity = nullptr; 58 59 namespace 60 { 61 const G4double scaleFactor = CLHEP::m*CLHEP::m; 62 const G4double tolerance = 1*CLHEP::eV; 63 const G4double Ry = 13.6*CLHEP::eV; 64 65 // Following values provided by M. Dingfelder (priv. comm) 66 const G4double Bj[5] = {12.60*CLHEP::eV, 14.70*CLHEP::eV, 18.40*CLHEP::eV, 67 32.20*CLHEP::eV, 539*CLHEP::eV}; 68 } 69 70 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 71 72 G4DNARuddIonisationExtendedModel::G4DNARuddIonisationExtendedModel(const G4ParticleDefinition*, 73 const G4String& nam) 74 : G4VEmModel(nam) 75 { 76 fEmCorrections = G4LossTableManager::Instance()->EmCorrections(); 77 fGpow = G4Pow::GetInstance(); 78 fLowestEnergy = 100*CLHEP::eV; 79 fLimitEnergy = 1*CLHEP::keV; 80 81 // Mark this model as "applicable" for atomic deexcitation 82 SetDeexcitationFlag(true); 83 84 // Define default angular generator 85 SetAngularDistribution(new G4DNARuddAngle()); 86 87 if (nullptr == xshelium) { LoadData(); } 88 } 89 90 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 91 92 G4DNARuddIonisationExtendedModel::~G4DNARuddIonisationExtendedModel() 93 { 94 if(isFirst) { 95 for(auto & i : xsdata) { delete i; } 96 } 97 } 98 99 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 100 101 void G4DNARuddIonisationExtendedModel::LoadData() 102 { 103 // initialisation of static data once 104 isFirst = true; 105 G4String filename("dna/sigma_ionisation_h_rudd"); 106 xsdata[0] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 107 xsdata[0]->LoadData(filename); 108 109 filename = "dna/sigma_ionisation_p_rudd"; 110 xsdata[1] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 111 xsdata[1]->LoadData(filename); 112 113 filename = "dna/sigma_ionisation_alphaplusplus_rudd"; 114 xsdata[2] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 115 xsdata[2]->LoadData(filename); 116 117 filename = "dna/sigma_ionisation_li_rudd"; 118 xsdata[3] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 119 xsdata[3]->LoadData(filename); 120 121 filename = "dna/sigma_ionisation_be_rudd"; 122 xsdata[4] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 123 xsdata[4]->LoadData(filename); 124 125 filename = "dna/sigma_ionisation_b_rudd"; 126 xsdata[5] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 127 xsdata[5]->LoadData(filename); 128 129 filename = "dna/sigma_ionisation_c_rudd"; 130 xsdata[6] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 131 xsdata[6]->LoadData(filename); 132 133 filename = "dna/sigma_ionisation_n_rudd"; 134 xsdata[7] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 135 xsdata[7]->LoadData(filename); 136 137 filename = "dna/sigma_ionisation_o_rudd"; 138 xsdata[8] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 139 xsdata[8]->LoadData(filename); 140 141 filename = "dna/sigma_ionisation_si_rudd"; 142 xsdata[14] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 143 xsdata[14]->LoadData(filename); 144 145 filename = "dna/sigma_ionisation_fe_rudd"; 146 xsdata[26] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 147 xsdata[26]->LoadData(filename); 148 149 filename = "dna/sigma_ionisation_alphaplus_rudd"; 150 xsalphaplus = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 151 xsalphaplus->LoadData(filename); 152 153 filename = "dna/sigma_ionisation_he_rudd"; 154 xshelium = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor); 155 xshelium->LoadData(filename); 156 157 // to avoid possible threading problem fill this vector only once 158 auto water = G4NistManager::Instance()->FindMaterial("G4_WATER"); 159 fpWaterDensity = 160 G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(water); 161 } 162 163 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 164 165 void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* p, 166 const G4DataVector&) 167 { 168 if (p != fParticle) { SetParticle(p); } 169 170 // particle change object may be externally set 171 if (nullptr == fParticleChangeForGamma) { 172 fParticleChangeForGamma = GetParticleChangeForGamma(); 173 } 174 175 // initialisation once in each thread 176 if (!isInitialised) { 177 isInitialised = true; 178 const G4String& pname = fParticle->GetParticleName(); 179 if (pname == "proton") { 180 idx = 1; 181 xscurrent = xsdata[1]; 182 fElow = fLowestEnergy; 183 } else if (pname == "hydrogen") { 184 idx = 0; 185 xscurrent = xsdata[0]; 186 fElow = fLowestEnergy; 187 } else if (pname == "alpha") { 188 idx = 1; 189 xscurrent = xsdata[2]; 190 isHelium = true; 191 fElow = fLimitEnergy; 192 } else if (pname == "alpha+") { 193 idx = 1; 194 isHelium = true; 195 xscurrent = xsalphaplus; 196 fElow = fLimitEnergy; 197 // The following values are provided by M. Dingfelder (priv. comm) 198 slaterEffectiveCharge[0]=2.0; 199 slaterEffectiveCharge[1]=2.0; 200 slaterEffectiveCharge[2]=2.0; 201 sCoefficient[0]=0.7; 202 sCoefficient[1]=0.15; 203 sCoefficient[2]=0.15; 204 } else if (pname == "helium") { 205 idx = 0; 206 isHelium = true; 207 fElow = fLimitEnergy; 208 xscurrent = xshelium; 209 slaterEffectiveCharge[0]=1.7; 210 slaterEffectiveCharge[1]=1.15; 211 slaterEffectiveCharge[2]=1.15; 212 sCoefficient[0]=0.5; 213 sCoefficient[1]=0.25; 214 sCoefficient[2]=0.25; 215 } else { 216 isIon = true; 217 idx = -1; 218 xscurrent = xsdata[1]; 219 fElow = fLowestEnergy; 220 } 221 // defined stationary mode 222 statCode = G4EmParameters::Instance()->DNAStationary(); 223 224 // initialise atomic de-excitation 225 fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation(); 226 227 if (verbose > 0) { 228 G4cout << "### G4DNARuddIonisationExtendedModel::Initialise(..) " << pname 229 << "/n idx=" << idx << " isIon=" << isIon 230 << " isHelium=" << isHelium << G4endl; 231 } 232 } 233 } 234 235 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 236 237 void G4DNARuddIonisationExtendedModel::SetParticle(const G4ParticleDefinition* p) 238 { 239 fParticle = p; 240 fMass = p->GetPDGMass(); 241 fMassRate = (isIon) ? CLHEP::proton_mass_c2/fMass : 1.0; 242 } 243 244 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 245 246 G4double 247 G4DNARuddIonisationExtendedModel::CrossSectionPerVolume(const G4Material* material, 248 const G4ParticleDefinition* part, 249 G4double kinE, 250 G4double, G4double) 251 { 252 // check if model is applicable for given material 253 G4double density = (material->GetIndex() < fpWaterDensity->size()) 254 ? (*fpWaterDensity)[material->GetIndex()] : 0.0; 255 if (0.0 == density) { return 0.0; } 256 257 // ion may be different 258 if (fParticle != part) { SetParticle(part); } 259 260 // ion shoud be stopped - check on kinetic energy and not scaled energy 261 if (kinE < fLowestEnergy) { return DBL_MAX; } 262 263 G4double e = kinE*fMassRate; 264 265 G4double sigma = (e > fElow) ? xscurrent->FindValue(e) 266 : xscurrent->FindValue(fElow) * e / fElow; 267 268 if (idx == -1) { 269 sigma *= fEmCorrections->EffectiveChargeSquareRatio(part, material, kinE); 270 } 271 272 sigma *= density; 273 274 if (verbose > 1) { 275 G4cout << "G4DNARuddIonisationExtendedModel for " << part->GetParticleName() 276 << " Ekin(keV)=" << kinE/CLHEP::keV 277 << " sigma(cm^2)=" << sigma/CLHEP::cm2 << G4endl; 278 } 279 return sigma; 280 } 281 282 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... 283 284 void 285 G4DNARuddIonisationExtendedModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect, 286 const G4MaterialCutsCouple* couple, 287 const G4DynamicParticle* dpart, 288 G4double, G4double) 289 { 290 const G4ParticleDefinition* pd = dpart->GetDefinition(); 291 if (fParticle != pd) { SetParticle(pd); } 292 293 // stop ion with energy below low energy limit 294 G4double kinE = dpart->GetKineticEnergy(); 295 // ion shoud be stopped - check on kinetic energy and not scaled energy 296 if (kinE <= fLowestEnergy) { 297 fParticleChangeForGamma->SetProposedKineticEnergy(0.); 298 fParticleChangeForGamma->ProposeTrackStatus(fStopButAlive); 299 fParticleChangeForGamma->ProposeLocalEnergyDeposit(kinE); 300 return; 301 } 302 303 G4int shell = SelectShell(kinE*fMassRate); 304 G4double bindingEnergy = (useDNAWaterStructure) 305 ? waterStructure.IonisationEnergy(shell) : Bj[shell]; 306 307 //Si: additional protection if tcs interpolation method is modified 308 if (kinE < bindingEnergy) { return; } 309 310 G4double esec = SampleElectronEnergy(kinE, shell); 311 G4double esum = 0.0; 312 313 // sample deexcitation 314 // here we assume that H2O electronic levels are the same as Oxygen. 315 // this can be considered true with a rough 10% error in energy on K-shell, 316 G4int Z = 8; 317 G4ThreeVector deltaDir = 318 GetAngularDistribution()->SampleDirectionForShell(dpart, esec, Z, shell, couple->GetMaterial()); 319 320 // SI: only atomic deexcitation from K shell is considered 321 if(fAtomDeexcitation != nullptr && shell == 4) { 322 auto as = G4AtomicShellEnumerator(0); 323 auto ashell = fAtomDeexcitation->GetAtomicShell(Z, as); 324 fAtomDeexcitation->GenerateParticles(fvect, ashell, Z, 0, 0); 325 326 // compute energy sum from de-excitation 327 for (auto const & ptr : *fvect) { 328 esum += ptr->GetKineticEnergy(); 329 } 330 } 331 // check energy balance 332 // remaining excitation energy of water molecule 333 G4double exc = bindingEnergy - esum; 334 335 // remaining projectile energy 336 G4double scatteredEnergy = kinE - bindingEnergy - esec; 337 if(scatteredEnergy < -tolerance || exc < -tolerance) { 338 G4cout << "G4DNARuddIonisationExtendedModel::SampleSecondaries: " 339 << "negative final E(keV)=" << scatteredEnergy/CLHEP::keV << " Ein(keV)=" 340 << kinE/CLHEP::keV << " " << pd->GetParticleName() 341 << " Edelta(keV)=" << esec/CLHEP::keV << " MeV, Exc(keV)=" << exc/CLHEP::keV 342 << G4endl; 343 } 344 345 // projectile 346 if (!statCode) { 347 fParticleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy); 348 fParticleChangeForGamma->ProposeLocalEnergyDeposit(exc); 349 } else { 350 fParticleChangeForGamma->SetProposedKineticEnergy(kinE); 351 fParticleChangeForGamma->ProposeLocalEnergyDeposit(kinE - scatteredEnergy); 352 } 353 354 // delta-electron 355 auto dp = new G4DynamicParticle(G4Electron::Electron(), deltaDir, esec); 356 fvect->push_back(dp); 357 358 // create radical 359 const G4Track* theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack(); 360 G4DNAChemistryManager::Instance()->CreateWaterMolecule(eIonizedMolecule, shell, 361 theIncomingTrack); 362 } 363 364 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 365 366 G4int G4DNARuddIonisationExtendedModel::SelectShell(G4double e) 367 { 368 G4double sum = 0.0; 369 G4double xs; 370 for (G4int i=0; i<5; ++i) { 371 auto ptr = xscurrent->GetComponent(i); 372 xs = (e > fElow) ? ptr->FindValue(e) : ptr->FindValue(fElow)*e/fElow; 373 sum += xs; 374 fTemp[i] = sum; 375 } 376 sum *= G4UniformRand(); 377 for (G4int i=0; i<5; ++i) { 378 if (sum <= fTemp[i]) { return i; } 379 } 380 return 0; 381 } 382 383 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 384 385 G4double G4DNARuddIonisationExtendedModel::MaxEnergy(G4double kine, G4int shell) 386 { 387 // kinematic limit 388 G4double tau = kine/fMass; 389 G4double gam = 1.0 + tau; 390 G4double emax = 2.0*CLHEP::electron_mass_c2*tau*(tau + 2.0); 391 392 // Initialisation of sampling 393 G4double A1, B1, C1, D1, E1, A2, B2, C2, D2; 394 if (shell == 4) { 395 //Data For Liquid Water K SHELL from Dingfelder (Protons in Water) 396 A1 = 1.25; 397 B1 = 0.5; 398 C1 = 1.00; 399 D1 = 1.00; 400 E1 = 3.00; 401 A2 = 1.10; 402 B2 = 1.30; 403 C2 = 1.00; 404 D2 = 0.00; 405 alphaConst = 0.66; 406 } else { 407 //Data For Liquid Water from Dingfelder (Protons in Water) 408 A1 = 1.02; 409 B1 = 82.0; 410 C1 = 0.45; 411 D1 = -0.80; 412 E1 = 0.38; 413 A2 = 1.07; 414 // Value provided by M. Dingfelder (priv. comm) 415 B2 = 11.6; 416 C2 = 0.60; 417 D2 = 0.04; 418 alphaConst = 0.64; 419 } 420 bEnergy = Bj[shell]; 421 G4double v2 = 0.25*emax/(bEnergy*gam*gam); 422 v = std::sqrt(v2); 423 u = Ry/bEnergy; 424 wc = 4.*v2 - 2.*v - 0.25*u; 425 426 G4double L1 = (C1 * fGpow->powA(v, D1)) / (1. + E1 * fGpow->powA(v, (D1 + 4.))); 427 G4double L2 = C2 * fGpow->powA(v, D2); 428 G4double H1 = (A1 * G4Log(1. + v2)) / (v2 + (B1 / v2)); 429 G4double H2 = (A2 / v2) + (B2 / (v2 * v2)); 430 431 F1 = L1 + H1; 432 F2 = (L2 * H2) / (L2 + H2); 433 return emax; 434 } 435 436 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 437 438 G4double G4DNARuddIonisationExtendedModel::SampleElectronEnergy(G4double kine, 439 G4int shell) 440 { 441 G4double emax = MaxEnergy(kine, shell); 442 // compute cumulative probability function 443 G4double step = 1*CLHEP::eV; 444 auto nn = (G4int)(emax/step); 445 nn = std::min(std::max(nn, 10), 100); 446 step = emax/(G4double)nn; 447 448 // find max probability 449 G4double pmax = ProbabilityFunction(kine, 0.0, shell); 450 //G4cout << "## E(keV)=" << kine/keV << " emax=" << emax/keV 451 // << " pmax(0)=" << pmax << " shell=" << shell << " nn=" << nn << G4endl; 452 453 G4double e0 = 0.0; // energy with max probability 454 // 2 areas after point with max probability 455 G4double e1 = emax; 456 G4double e2 = emax; 457 G4double p1 = 0.0; 458 G4double p2 = 0.0; 459 const G4double f = 0.25; 460 461 // find max probability 462 G4double e = 0.0; 463 G4double p = 0.0; 464 for (G4int i=0; i<nn; ++i) { 465 e += step; 466 p = ProbabilityFunction(kine, e, shell); 467 if (p > pmax) { 468 pmax = p; 469 e0 = e; 470 } else { 471 break; 472 } 473 } 474 // increase step to be more effective 475 step *= 2.0; 476 // 2-nd area 477 for (G4int i=0; i<nn; ++i) { 478 e += step; 479 if (std::abs(e - emax) < step) { 480 e1 = emax; 481 break; 482 } 483 p = ProbabilityFunction(kine, e, shell); 484 if (p < f*pmax) { 485 p1 = p; 486 e1 = e; 487 break; 488 } 489 } 490 // 3-d area 491 if (e < emax) { 492 for (G4int i=0; i<nn; ++i) { 493 e += step; 494 if (std::abs(e - emax) < step) { 495 e2 = emax; 496 break; 497 } 498 p = ProbabilityFunction(kine, e, shell); 499 if (p < f*p1) { 500 p2 = p; 501 e2 = e; 502 break; 503 } 504 } 505 } 506 pmax *= 1.05; 507 // regression method with 3 regions 508 G4double s0 = pmax*e1; 509 G4double s1 = s0 + p1 * (e2 - e1); 510 G4double s2 = s1 + p2 * (emax - e2); 511 s0 = (s0 == s1) ? 1.0 : s0 / s2; 512 s1 = (s1 == s2) ? 1.0 : s1 / s2; 513 514 //G4cout << "pmax=" << pmax << " e1(keV)=" << e1/keV << " p1=" << p1 << " e2(keV)=" << e2/keV 515 // << " p2=" << p2 << " s0=" << s0 << " s1=" << s1 << " s2=" << s2 << G4endl; 516 517 // sampling 518 G4int count = 0; 519 G4double ymax, y, deltae; 520 for (G4int i = 0; i<100000; ++i) { 521 G4double q = G4UniformRand(); 522 if (q <= s0) { 523 ymax = pmax; 524 deltae = e1 * q / s0; 525 } else if (q <= s1) { 526 ymax = p1; 527 deltae = e1 + (e2 - e1) * (q - s0) / (s1 - s0); 528 } else { 529 ymax = p2; 530 deltae = e2 + (emax - e2) * (q - s1) / (1.0 - s1); 531 } 532 y = ProbabilityFunction(kine, deltae, shell); 533 //G4cout << " " << i << ". deltae=" << deltae/CLHEP::keV 534 // << " y=" << y << " ymax=" << ymax << G4endl; 535 if (y > ymax && count < 10) { 536 ++count; 537 G4cout << "G4DNARuddIonisationExtendedModel::SampleElectronEnergy warning: " 538 << fParticle->GetParticleName() << " E(keV)=" << kine/CLHEP::keV 539 << " Edelta(keV)=" << deltae/CLHEP::keV 540 << " y=" << y << " ymax=" << ymax << " n=" << i << G4endl; 541 } 542 if (ymax * G4UniformRand() <= y) { 543 return deltae; 544 } 545 } 546 deltae = std::min(e0 + step, 0.5*emax); 547 return deltae; 548 } 549 550 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 551 552 G4double G4DNARuddIonisationExtendedModel::ProbabilityFunction(G4double kine, 553 G4double deltae, 554 G4int shell) 555 { 556 // Shells ids are 0 1 2 3 4 (4 is k shell) 557 // !!Attention, "energyTransfer" here is the energy transfered to the electron which means 558 // that the secondary kinetic energy is w = energyTransfer - bindingEnergy 559 // 560 // ds S F1(nu) + w * F2(nu) 561 // ---- = G(k) * ---- ------------------------------------------- 562 // dw Bj (1+w)^3 * [1 + exp{alpha * (w - wc) / nu}] 563 // 564 // w is the secondary electron kinetic Energy in eV 565 // 566 // All the other parameters can be found in Rudd's Papers 567 // 568 // M.Eugene Rudd, 1988, User-Friendly model for the energy distribution of 569 // electrons from protons or electron collisions. Nucl. Tracks Rad. Meas.Vol 16 N0 2/3 pp 219-218 570 // 571 G4double w = deltae/bEnergy; 572 G4double x = alphaConst*(w - wc)/v; 573 G4double y = (x > -15.) ? 1.0 + G4Exp(x) : 1.0; 574 575 G4double res = CorrectionFactor(kine, shell) * (F1 + w*F2) / 576 (fGpow->powN((1. + w)/u, 3) * y); 577 578 if (isHelium) { 579 G4double energyTransfer = deltae + bEnergy; 580 G4double Zeff = 2.0 - 581 (sCoefficient[0] * S_1s(kine, energyTransfer, slaterEffectiveCharge[0], 1.) + 582 sCoefficient[1] * S_2s(kine, energyTransfer, slaterEffectiveCharge[1], 2.) + 583 sCoefficient[2] * S_2p(kine, energyTransfer, slaterEffectiveCharge[2], 2.) ); 584 585 res *= Zeff * Zeff; 586 } 587 return std::max(res, 0.0); 588 } 589 590 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 591 592 G4double G4DNARuddIonisationExtendedModel::ComputeProbabilityFunction( 593 const G4ParticleDefinition* p, G4double e, G4double deltae, G4int shell) 594 { 595 if (fParticle != p) { SetParticle(p); } 596 MaxEnergy(e, shell); 597 return ProbabilityFunction(e, deltae, shell); 598 } 599 600 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 601 602 G4double G4DNARuddIonisationExtendedModel::S_1s(G4double kine, 603 G4double energyTransfer, 604 G4double slaterEffCharge, 605 G4double shellNumber) 606 { 607 // 1 - e^(-2r) * ( 1 + 2 r + 2 r^2) 608 // Dingfelder, in Chattanooga 2005 proceedings, formula (7) 609 610 G4double r = Rh(kine, energyTransfer, slaterEffCharge, shellNumber); 611 G4double value = 1. - G4Exp(-2 * r) * ( ( 2. * r + 2. ) * r + 1. ); 612 return value; 613 } 614 615 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 616 617 G4double G4DNARuddIonisationExtendedModel::S_2s(G4double kine, 618 G4double energyTransfer, 619 G4double slaterEffCharge, 620 G4double shellNumber) 621 { 622 // 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 2 r^4) 623 // Dingfelder, in Chattanooga 2005 proceedings, formula (8) 624 625 G4double r = Rh(kine, energyTransfer, slaterEffCharge, shellNumber); 626 G4double value = 627 1. - G4Exp(-2 * r) * (((2. * r * r + 2.) * r + 2.) * r + 1.); 628 629 return value; 630 } 631 632 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 633 634 G4double G4DNARuddIonisationExtendedModel::S_2p(G4double kine, 635 G4double energyTransfer, 636 G4double slaterEffCharge, 637 G4double shellNumber) 638 { 639 // 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 4/3 r^3 + 2/3 r^4) 640 // Dingfelder, in Chattanooga 2005 proceedings, formula (9) 641 642 G4double r = Rh(kine, energyTransfer, slaterEffCharge, shellNumber); 643 G4double value = 644 1. - G4Exp(-2 * r) * (((( 2./3. * r + 4./3.) * r + 2.) * r + 2.) * r + 1.); 645 646 return value; 647 } 648 649 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 650 651 G4double G4DNARuddIonisationExtendedModel::Rh(G4double ekin, G4double etrans, 652 G4double q, G4double shell) 653 { 654 // The following values are provided by M. Dingfelder (priv. comm) 655 // Dingfelder, in Chattanooga 2005 proceedings, p 4 656 657 G4double escaled = CLHEP::electron_mass_c2/fMass * ekin; 658 const G4double H = 13.60569172 * CLHEP::eV; 659 G4double value = 2.0*std::sqrt(escaled / H)*q*H /(etrans*shell); 660 661 return value; 662 } 663 664 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 665 666 G4double 667 G4DNARuddIonisationExtendedModel::CorrectionFactor(G4double kine, G4int shell) 668 { 669 // ZF Shortened 670 G4double res = 1.0; 671 if (shell < 4 && 0 != idx) { 672 const G4double ln10 = fGpow->logZ(10); 673 G4double x = 2.0*((G4Log(kine/CLHEP::eV)/ln10) - 4.2); 674 // The following values are provided by M. Dingfelder (priv. comm) 675 res = 0.6/(1.0 + G4Exp(x)) + 0.9; 676 } 677 return res; 678 } 679 680 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... 681