| 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 |
|
|---|
| 28 | // ------------------------------------------------------------
|
|---|
| 29 | // G4RDHadronIonisation
|
|---|
| 30 | //
|
|---|
| 31 | // $Id: G4hImpactIonisation.cc,v 1.4 2010/11/25 19:49:43 pia Exp $
|
|---|
| 32 | // GEANT4 tag $Name: geant4-09-04-ref-00 $
|
|---|
| 33 | //
|
|---|
| 34 | // Author: Maria Grazia Pia (MariaGrazia.Pia@ge.infn.it)
|
|---|
| 35 | //
|
|---|
| 36 | // 08 Sep 2008 - MGP - Created (initially based on G4hLowEnergyIonisation)
|
|---|
| 37 | // Added PIXE capabilities
|
|---|
| 38 | // Partial clean-up of the implementation (more needed)
|
|---|
| 39 | // Calculation of MicroscopicCrossSection delegated to specialised cla// Documentation available in:
|
|---|
| 40 | // M.G. Pia et al., PIXE Simulation With Geant4,
|
|---|
| 41 | // IEEE Trans. Nucl. Sci., vol. 56, no. 6, pp. 3614-3649, Dec. 2009.
|
|---|
| 42 |
|
|---|
| 43 | //
|
|---|
| 44 | // ------------------------------------------------------------
|
|---|
| 45 |
|
|---|
| 46 | #include "G4hImpactIonisation.hh"
|
|---|
| 47 | #include "globals.hh"
|
|---|
| 48 | #include "G4ios.hh"
|
|---|
| 49 | #include "Randomize.hh"
|
|---|
| 50 | #include "G4Poisson.hh"
|
|---|
| 51 | #include "G4UnitsTable.hh"
|
|---|
| 52 | #include "G4EnergyLossTables.hh"
|
|---|
| 53 | #include "G4Material.hh"
|
|---|
| 54 | #include "G4DynamicParticle.hh"
|
|---|
| 55 | #include "G4ParticleDefinition.hh"
|
|---|
| 56 | #include "G4AtomicDeexcitation.hh"
|
|---|
| 57 | #include "G4AtomicTransitionManager.hh"
|
|---|
| 58 | #include "G4PixeCrossSectionHandler.hh"
|
|---|
| 59 | #include "G4IInterpolator.hh"
|
|---|
| 60 | #include "G4LogLogInterpolator.hh"
|
|---|
| 61 | #include "G4Gamma.hh"
|
|---|
| 62 | #include "G4Electron.hh"
|
|---|
| 63 | #include "G4Proton.hh"
|
|---|
| 64 | #include "G4ProcessManager.hh"
|
|---|
| 65 | #include "G4ProductionCutsTable.hh"
|
|---|
| 66 | #include "G4PhysicsLogVector.hh"
|
|---|
| 67 | #include "G4PhysicsLinearVector.hh"
|
|---|
| 68 |
|
|---|
| 69 | #include "G4VLowEnergyModel.hh"
|
|---|
| 70 | #include "G4hNuclearStoppingModel.hh"
|
|---|
| 71 | #include "G4hBetheBlochModel.hh"
|
|---|
| 72 | #include "G4hParametrisedLossModel.hh"
|
|---|
| 73 | #include "G4QAOLowEnergyLoss.hh"
|
|---|
| 74 | #include "G4hIonEffChargeSquare.hh"
|
|---|
| 75 | #include "G4IonChuFluctuationModel.hh"
|
|---|
| 76 | #include "G4IonYangFluctuationModel.hh"
|
|---|
| 77 |
|
|---|
| 78 | #include "G4MaterialCutsCouple.hh"
|
|---|
| 79 | #include "G4Track.hh"
|
|---|
| 80 | #include "G4Step.hh"
|
|---|
| 81 |
|
|---|
| 82 | G4hImpactIonisation::G4hImpactIonisation(const G4String& processName)
|
|---|
| 83 | : G4hRDEnergyLoss(processName),
|
|---|
| 84 | betheBlochModel(0),
|
|---|
| 85 | protonModel(0),
|
|---|
| 86 | antiprotonModel(0),
|
|---|
| 87 | theIonEffChargeModel(0),
|
|---|
| 88 | theNuclearStoppingModel(0),
|
|---|
| 89 | theIonChuFluctuationModel(0),
|
|---|
| 90 | theIonYangFluctuationModel(0),
|
|---|
| 91 | protonTable("ICRU_R49p"),
|
|---|
| 92 | antiprotonTable("ICRU_R49p"),
|
|---|
| 93 | theNuclearTable("ICRU_R49"),
|
|---|
| 94 | nStopping(true),
|
|---|
| 95 | theBarkas(true),
|
|---|
| 96 | theMeanFreePathTable(0),
|
|---|
| 97 | paramStepLimit (0.005),
|
|---|
| 98 | pixeCrossSectionHandler(0)
|
|---|
| 99 | {
|
|---|
| 100 | InitializeMe();
|
|---|
| 101 | }
|
|---|
| 102 |
|
|---|
| 103 |
|
|---|
| 104 |
|
|---|
| 105 | void G4hImpactIonisation::InitializeMe()
|
|---|
| 106 | {
|
|---|
| 107 | LowestKineticEnergy = 10.0*eV ;
|
|---|
| 108 | HighestKineticEnergy = 100.0*GeV ;
|
|---|
| 109 | MinKineticEnergy = 10.0*eV ;
|
|---|
| 110 | TotBin = 360 ;
|
|---|
| 111 | protonLowEnergy = 1.*keV ;
|
|---|
| 112 | protonHighEnergy = 100.*MeV ;
|
|---|
| 113 | antiprotonLowEnergy = 25.*keV ;
|
|---|
| 114 | antiprotonHighEnergy = 2.*MeV ;
|
|---|
| 115 | minGammaEnergy = 100 * eV;
|
|---|
| 116 | minElectronEnergy = 250.* eV;
|
|---|
| 117 | verboseLevel = 0;
|
|---|
| 118 |
|
|---|
| 119 | // Min and max energy of incident particle for the calculation of shell cross sections
|
|---|
| 120 | // for PIXE generation
|
|---|
| 121 | eMinPixe = 1.* keV;
|
|---|
| 122 | eMaxPixe = 200. * MeV;
|
|---|
| 123 |
|
|---|
| 124 | G4String defaultPixeModel("ecpssr");
|
|---|
| 125 | modelK = defaultPixeModel;
|
|---|
| 126 | modelL = defaultPixeModel;
|
|---|
| 127 | modelM = defaultPixeModel;
|
|---|
| 128 | }
|
|---|
| 129 |
|
|---|
| 130 |
|
|---|
| 131 | G4hImpactIonisation::~G4hImpactIonisation()
|
|---|
| 132 | {
|
|---|
| 133 | if (theMeanFreePathTable)
|
|---|
| 134 | {
|
|---|
| 135 | theMeanFreePathTable->clearAndDestroy();
|
|---|
| 136 | delete theMeanFreePathTable;
|
|---|
| 137 | }
|
|---|
| 138 |
|
|---|
| 139 | if (betheBlochModel) delete betheBlochModel;
|
|---|
| 140 | if (protonModel) delete protonModel;
|
|---|
| 141 | if (antiprotonModel) delete antiprotonModel;
|
|---|
| 142 | if (theNuclearStoppingModel) delete theNuclearStoppingModel;
|
|---|
| 143 | if (theIonEffChargeModel) delete theIonEffChargeModel;
|
|---|
| 144 | if (theIonChuFluctuationModel) delete theIonChuFluctuationModel;
|
|---|
| 145 | if (theIonYangFluctuationModel) delete theIonYangFluctuationModel;
|
|---|
| 146 |
|
|---|
| 147 | delete pixeCrossSectionHandler;
|
|---|
| 148 |
|
|---|
| 149 | // ---- MGP ---- The following is to be checked
|
|---|
| 150 | // if (shellVacancy) delete shellVacancy;
|
|---|
| 151 |
|
|---|
| 152 | cutForDelta.clear();
|
|---|
| 153 | }
|
|---|
| 154 |
|
|---|
| 155 | // --------------------------------------------------------------------
|
|---|
| 156 | void G4hImpactIonisation::SetElectronicStoppingPowerModel(const G4ParticleDefinition* particle,
|
|---|
| 157 | const G4String& dedxTable)
|
|---|
| 158 | // This method defines the ionisation parametrisation method via its name
|
|---|
| 159 | {
|
|---|
| 160 | if (particle->GetPDGCharge() > 0 )
|
|---|
| 161 | {
|
|---|
| 162 | // Positive charge
|
|---|
| 163 | SetProtonElectronicStoppingPowerModel(dedxTable) ;
|
|---|
| 164 | }
|
|---|
| 165 | else
|
|---|
| 166 | {
|
|---|
| 167 | // Antiprotons
|
|---|
| 168 | SetAntiProtonElectronicStoppingPowerModel(dedxTable) ;
|
|---|
| 169 | }
|
|---|
| 170 | }
|
|---|
| 171 |
|
|---|
| 172 |
|
|---|
| 173 | // --------------------------------------------------------------------
|
|---|
| 174 | void G4hImpactIonisation::InitializeParametrisation()
|
|---|
| 175 |
|
|---|
| 176 | {
|
|---|
| 177 | // Define models for parametrisation of electronic energy losses
|
|---|
| 178 | betheBlochModel = new G4hBetheBlochModel("Bethe-Bloch") ;
|
|---|
| 179 | protonModel = new G4hParametrisedLossModel(protonTable) ;
|
|---|
| 180 | protonHighEnergy = std::min(protonHighEnergy,protonModel->HighEnergyLimit(0, 0));
|
|---|
| 181 | antiprotonModel = new G4QAOLowEnergyLoss(antiprotonTable) ;
|
|---|
| 182 | theNuclearStoppingModel = new G4hNuclearStoppingModel(theNuclearTable) ;
|
|---|
| 183 | theIonEffChargeModel = new G4hIonEffChargeSquare("Ziegler1988") ;
|
|---|
| 184 | theIonChuFluctuationModel = new G4IonChuFluctuationModel("Chu") ;
|
|---|
| 185 | theIonYangFluctuationModel = new G4IonYangFluctuationModel("Yang") ;
|
|---|
| 186 | }
|
|---|
| 187 |
|
|---|
| 188 |
|
|---|
| 189 | // --------------------------------------------------------------------
|
|---|
| 190 | void G4hImpactIonisation::BuildPhysicsTable(const G4ParticleDefinition& particleDef)
|
|---|
| 191 |
|
|---|
| 192 | // just call BuildLossTable+BuildLambdaTable
|
|---|
| 193 | {
|
|---|
| 194 |
|
|---|
| 195 | // Verbose print-out
|
|---|
| 196 | if(verboseLevel > 0)
|
|---|
| 197 | {
|
|---|
| 198 | G4cout << "G4hImpactIonisation::BuildPhysicsTable for "
|
|---|
| 199 | << particleDef.GetParticleName()
|
|---|
| 200 | << " mass(MeV)= " << particleDef.GetPDGMass()/MeV
|
|---|
| 201 | << " charge= " << particleDef.GetPDGCharge()/eplus
|
|---|
| 202 | << " type= " << particleDef.GetParticleType()
|
|---|
| 203 | << G4endl;
|
|---|
| 204 |
|
|---|
| 205 | if(verboseLevel > 1)
|
|---|
| 206 | {
|
|---|
| 207 | G4ProcessVector* pv = particleDef.GetProcessManager()->GetProcessList();
|
|---|
| 208 |
|
|---|
| 209 | G4cout << " 0: " << (*pv)[0]->GetProcessName() << " " << (*pv)[0]
|
|---|
| 210 | << " 1: " << (*pv)[1]->GetProcessName() << " " << (*pv)[1]
|
|---|
| 211 | // << " 2: " << (*pv)[2]->GetProcessName() << " " << (*pv)[2]
|
|---|
| 212 | << G4endl;
|
|---|
| 213 | G4cout << "ionModel= " << theIonEffChargeModel
|
|---|
| 214 | << " MFPtable= " << theMeanFreePathTable
|
|---|
| 215 | << " iniMass= " << initialMass
|
|---|
| 216 | << G4endl;
|
|---|
| 217 | }
|
|---|
| 218 | }
|
|---|
| 219 | // End of verbose print-out
|
|---|
| 220 |
|
|---|
| 221 | if (particleDef.GetParticleType() == "nucleus" &&
|
|---|
| 222 | particleDef.GetParticleName() != "GenericIon" &&
|
|---|
| 223 | particleDef.GetParticleSubType() == "generic")
|
|---|
| 224 | {
|
|---|
| 225 |
|
|---|
| 226 | G4EnergyLossTables::Register(&particleDef,
|
|---|
| 227 | theDEDXpTable,
|
|---|
| 228 | theRangepTable,
|
|---|
| 229 | theInverseRangepTable,
|
|---|
| 230 | theLabTimepTable,
|
|---|
| 231 | theProperTimepTable,
|
|---|
| 232 | LowestKineticEnergy, HighestKineticEnergy,
|
|---|
| 233 | proton_mass_c2/particleDef.GetPDGMass(),
|
|---|
| 234 | TotBin);
|
|---|
| 235 |
|
|---|
| 236 | return;
|
|---|
| 237 | }
|
|---|
| 238 |
|
|---|
| 239 | if( !CutsWhereModified() && theLossTable) return;
|
|---|
| 240 |
|
|---|
| 241 | InitializeParametrisation() ;
|
|---|
| 242 | G4Proton* proton = G4Proton::Proton();
|
|---|
| 243 | G4AntiProton* antiproton = G4AntiProton::AntiProton();
|
|---|
| 244 |
|
|---|
| 245 | charge = particleDef.GetPDGCharge() / eplus;
|
|---|
| 246 | chargeSquare = charge*charge ;
|
|---|
| 247 |
|
|---|
| 248 | const G4ProductionCutsTable* theCoupleTable=
|
|---|
| 249 | G4ProductionCutsTable::GetProductionCutsTable();
|
|---|
| 250 | size_t numOfCouples = theCoupleTable->GetTableSize();
|
|---|
| 251 |
|
|---|
| 252 | cutForDelta.clear();
|
|---|
| 253 | cutForGamma.clear();
|
|---|
| 254 |
|
|---|
| 255 | for (size_t j=0; j<numOfCouples; j++) {
|
|---|
| 256 |
|
|---|
| 257 | // get material parameters needed for the energy loss calculation
|
|---|
| 258 | const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(j);
|
|---|
| 259 | const G4Material* material= couple->GetMaterial();
|
|---|
| 260 |
|
|---|
| 261 | // the cut cannot be below lowest limit
|
|---|
| 262 | G4double tCut = (*(theCoupleTable->GetEnergyCutsVector(1)))[j];
|
|---|
| 263 | if(tCut > HighestKineticEnergy) tCut = HighestKineticEnergy;
|
|---|
| 264 |
|
|---|
| 265 | G4double excEnergy = material->GetIonisation()->GetMeanExcitationEnergy();
|
|---|
| 266 |
|
|---|
| 267 | tCut = std::max(tCut,excEnergy);
|
|---|
| 268 | cutForDelta.push_back(tCut);
|
|---|
| 269 |
|
|---|
| 270 | // the cut cannot be below lowest limit
|
|---|
| 271 | tCut = (*(theCoupleTable->GetEnergyCutsVector(0)))[j];
|
|---|
| 272 | if(tCut > HighestKineticEnergy) tCut = HighestKineticEnergy;
|
|---|
| 273 | tCut = std::max(tCut,minGammaEnergy);
|
|---|
| 274 | cutForGamma.push_back(tCut);
|
|---|
| 275 | }
|
|---|
| 276 |
|
|---|
| 277 | if(verboseLevel > 0) {
|
|---|
| 278 | G4cout << "Cuts are defined " << G4endl;
|
|---|
| 279 | }
|
|---|
| 280 |
|
|---|
| 281 | if(0.0 < charge)
|
|---|
| 282 | {
|
|---|
| 283 | {
|
|---|
| 284 | BuildLossTable(*proton) ;
|
|---|
| 285 |
|
|---|
| 286 | // The following vector has a fixed dimension (see src/G4hImpactLoss.cc for more details)
|
|---|
| 287 | // It happended in the past that caused memory corruption errors. The problem is still pending, even if temporary solved
|
|---|
| 288 | // G4cout << "[NOTE]: __LINE__=" << __LINE__ << ", particleDef=" << particleDef.GetParticleName() << ", proton=" << proton << ", theLossTable=" << theLossTable << ", CounterOfpProcess=" << CounterOfpProcess << G4endl;
|
|---|
| 289 |
|
|---|
| 290 | RecorderOfpProcess[CounterOfpProcess] = theLossTable ;
|
|---|
| 291 | CounterOfpProcess++;
|
|---|
| 292 | }
|
|---|
| 293 | } else {
|
|---|
| 294 | {
|
|---|
| 295 | BuildLossTable(*antiproton) ;
|
|---|
| 296 |
|
|---|
| 297 | // The following vector has a fixed dimension (see src/G4hImpactLoss.cc for more details)
|
|---|
| 298 | // It happended in the past that caused memory corruption errors. The problem is still pending, even if temporary solved
|
|---|
| 299 | // G4cout << "[NOTE]: __LINE__=" << __LINE__ << ", particleDef=" << particleDef.GetParticleName() << ", antiproton=" << antiproton << ", theLossTable=" << theLossTable << ", CounterOfpbarProcess=" << CounterOfpbarProcess << G4endl;
|
|---|
| 300 |
|
|---|
| 301 | RecorderOfpbarProcess[CounterOfpbarProcess] = theLossTable ;
|
|---|
| 302 | CounterOfpbarProcess++;
|
|---|
| 303 | }
|
|---|
| 304 | }
|
|---|
| 305 |
|
|---|
| 306 | if(verboseLevel > 0) {
|
|---|
| 307 | G4cout << "G4hImpactIonisation::BuildPhysicsTable: "
|
|---|
| 308 | << "Loss table is built "
|
|---|
| 309 | // << theLossTable
|
|---|
| 310 | << G4endl;
|
|---|
| 311 | }
|
|---|
| 312 |
|
|---|
| 313 | BuildLambdaTable(particleDef) ;
|
|---|
| 314 | // BuildDataForFluorescence(particleDef);
|
|---|
| 315 |
|
|---|
| 316 | if(verboseLevel > 1) {
|
|---|
| 317 | G4cout << (*theMeanFreePathTable) << G4endl;
|
|---|
| 318 | }
|
|---|
| 319 |
|
|---|
| 320 | if(verboseLevel > 0) {
|
|---|
| 321 | G4cout << "G4hImpactIonisation::BuildPhysicsTable: "
|
|---|
| 322 | << "DEDX table will be built "
|
|---|
| 323 | // << theDEDXpTable << " " << theDEDXpbarTable
|
|---|
| 324 | // << " " << theRangepTable << " " << theRangepbarTable
|
|---|
| 325 | << G4endl;
|
|---|
| 326 | }
|
|---|
| 327 |
|
|---|
| 328 | BuildDEDXTable(particleDef) ;
|
|---|
| 329 |
|
|---|
| 330 | if(verboseLevel > 1) {
|
|---|
| 331 | G4cout << (*theDEDXpTable) << G4endl;
|
|---|
| 332 | }
|
|---|
| 333 |
|
|---|
| 334 | if((&particleDef == proton) || (&particleDef == antiproton)) PrintInfoDefinition() ;
|
|---|
| 335 |
|
|---|
| 336 | if(verboseLevel > 0) {
|
|---|
| 337 | G4cout << "G4hImpactIonisation::BuildPhysicsTable: end for "
|
|---|
| 338 | << particleDef.GetParticleName() << G4endl;
|
|---|
| 339 | }
|
|---|
| 340 | }
|
|---|
| 341 |
|
|---|
| 342 |
|
|---|
| 343 |
|
|---|
| 344 |
|
|---|
| 345 |
|
|---|
| 346 | // --------------------------------------------------------------------
|
|---|
| 347 | void G4hImpactIonisation::BuildLossTable(const G4ParticleDefinition& particleDef)
|
|---|
| 348 | {
|
|---|
| 349 |
|
|---|
| 350 | // Initialisation
|
|---|
| 351 | G4double lowEdgeEnergy , ionloss, ionlossBB, paramB ;
|
|---|
| 352 | G4double lowEnergy, highEnergy;
|
|---|
| 353 | G4Proton* proton = G4Proton::Proton();
|
|---|
| 354 |
|
|---|
| 355 | if (particleDef == *proton)
|
|---|
| 356 | {
|
|---|
| 357 | lowEnergy = protonLowEnergy ;
|
|---|
| 358 | highEnergy = protonHighEnergy ;
|
|---|
| 359 | charge = 1. ;
|
|---|
| 360 | }
|
|---|
| 361 | else
|
|---|
| 362 | {
|
|---|
| 363 | lowEnergy = antiprotonLowEnergy ;
|
|---|
| 364 | highEnergy = antiprotonHighEnergy ;
|
|---|
| 365 | charge = -1. ;
|
|---|
| 366 | }
|
|---|
| 367 | chargeSquare = 1. ;
|
|---|
| 368 |
|
|---|
| 369 | const G4ProductionCutsTable* theCoupleTable=
|
|---|
| 370 | G4ProductionCutsTable::GetProductionCutsTable();
|
|---|
| 371 | size_t numOfCouples = theCoupleTable->GetTableSize();
|
|---|
| 372 |
|
|---|
| 373 | if ( theLossTable)
|
|---|
| 374 | {
|
|---|
| 375 | theLossTable->clearAndDestroy();
|
|---|
| 376 | delete theLossTable;
|
|---|
| 377 | }
|
|---|
| 378 |
|
|---|
| 379 | theLossTable = new G4PhysicsTable(numOfCouples);
|
|---|
| 380 |
|
|---|
| 381 | // loop for materials
|
|---|
| 382 | for (size_t j=0; j<numOfCouples; j++) {
|
|---|
| 383 |
|
|---|
| 384 | // create physics vector and fill it
|
|---|
| 385 | G4PhysicsLogVector* aVector = new G4PhysicsLogVector(LowestKineticEnergy,
|
|---|
| 386 | HighestKineticEnergy,
|
|---|
| 387 | TotBin);
|
|---|
| 388 |
|
|---|
| 389 | // get material parameters needed for the energy loss calculation
|
|---|
| 390 | const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(j);
|
|---|
| 391 | const G4Material* material= couple->GetMaterial();
|
|---|
| 392 |
|
|---|
| 393 | if ( charge > 0.0 ) {
|
|---|
| 394 | ionloss = ProtonParametrisedDEDX(couple,highEnergy) ;
|
|---|
| 395 | } else {
|
|---|
| 396 | ionloss = AntiProtonParametrisedDEDX(couple,highEnergy) ;
|
|---|
| 397 | }
|
|---|
| 398 |
|
|---|
| 399 | ionlossBB = betheBlochModel->TheValue(&particleDef,material,highEnergy) ;
|
|---|
| 400 | ionlossBB -= DeltaRaysEnergy(couple,highEnergy,proton_mass_c2) ;
|
|---|
| 401 |
|
|---|
| 402 |
|
|---|
| 403 | paramB = ionloss/ionlossBB - 1.0 ;
|
|---|
| 404 |
|
|---|
| 405 | // now comes the loop for the kinetic energy values
|
|---|
| 406 | for (G4int i = 0 ; i < TotBin ; i++) {
|
|---|
| 407 | lowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
|
|---|
| 408 |
|
|---|
| 409 | // low energy part for this material, parametrised energy loss formulae
|
|---|
| 410 | if ( lowEdgeEnergy < highEnergy ) {
|
|---|
| 411 |
|
|---|
| 412 | if ( charge > 0.0 ) {
|
|---|
| 413 | ionloss = ProtonParametrisedDEDX(couple,lowEdgeEnergy) ;
|
|---|
| 414 | } else {
|
|---|
| 415 | ionloss = AntiProtonParametrisedDEDX(couple,lowEdgeEnergy) ;
|
|---|
| 416 | }
|
|---|
| 417 |
|
|---|
| 418 | } else {
|
|---|
| 419 |
|
|---|
| 420 | // high energy part for this material, Bethe-Bloch formula
|
|---|
| 421 | ionloss = betheBlochModel->TheValue(proton,material,
|
|---|
| 422 | lowEdgeEnergy) ;
|
|---|
| 423 |
|
|---|
| 424 | ionloss -= DeltaRaysEnergy(couple,lowEdgeEnergy,proton_mass_c2) ;
|
|---|
| 425 |
|
|---|
| 426 | ionloss *= (1.0 + paramB*highEnergy/lowEdgeEnergy) ;
|
|---|
| 427 | }
|
|---|
| 428 |
|
|---|
| 429 | // now put the loss into the vector
|
|---|
| 430 | if(verboseLevel > 1) {
|
|---|
| 431 | G4cout << "E(MeV)= " << lowEdgeEnergy/MeV
|
|---|
| 432 | << " dE/dx(MeV/mm)= " << ionloss*mm/MeV
|
|---|
| 433 | << " in " << material->GetName() << G4endl;
|
|---|
| 434 | }
|
|---|
| 435 | aVector->PutValue(i,ionloss) ;
|
|---|
| 436 | }
|
|---|
| 437 | // Insert vector for this material into the table
|
|---|
| 438 | theLossTable->insert(aVector) ;
|
|---|
| 439 | }
|
|---|
| 440 | }
|
|---|
| 441 |
|
|---|
| 442 |
|
|---|
| 443 |
|
|---|
| 444 | // --------------------------------------------------------------------
|
|---|
| 445 | void G4hImpactIonisation::BuildLambdaTable(const G4ParticleDefinition& particleDef)
|
|---|
| 446 |
|
|---|
| 447 | {
|
|---|
| 448 | // Build mean free path tables for the delta ray production process
|
|---|
| 449 | // tables are built for MATERIALS
|
|---|
| 450 |
|
|---|
| 451 | if(verboseLevel > 1) {
|
|---|
| 452 | G4cout << "G4hImpactIonisation::BuildLambdaTable for "
|
|---|
| 453 | << particleDef.GetParticleName() << " is started" << G4endl;
|
|---|
| 454 | }
|
|---|
| 455 |
|
|---|
| 456 |
|
|---|
| 457 | G4double lowEdgeEnergy, value;
|
|---|
| 458 | charge = particleDef.GetPDGCharge()/eplus ;
|
|---|
| 459 | chargeSquare = charge*charge ;
|
|---|
| 460 | initialMass = particleDef.GetPDGMass();
|
|---|
| 461 |
|
|---|
| 462 | const G4ProductionCutsTable* theCoupleTable=
|
|---|
| 463 | G4ProductionCutsTable::GetProductionCutsTable();
|
|---|
| 464 | size_t numOfCouples = theCoupleTable->GetTableSize();
|
|---|
| 465 |
|
|---|
| 466 |
|
|---|
| 467 | if (theMeanFreePathTable) {
|
|---|
| 468 | theMeanFreePathTable->clearAndDestroy();
|
|---|
| 469 | delete theMeanFreePathTable;
|
|---|
| 470 | }
|
|---|
| 471 |
|
|---|
| 472 | theMeanFreePathTable = new G4PhysicsTable(numOfCouples);
|
|---|
| 473 |
|
|---|
| 474 | // loop for materials
|
|---|
| 475 |
|
|---|
| 476 | for (size_t j=0 ; j < numOfCouples; j++) {
|
|---|
| 477 |
|
|---|
| 478 | //create physics vector then fill it ....
|
|---|
| 479 | G4PhysicsLogVector* aVector = new G4PhysicsLogVector(LowestKineticEnergy,
|
|---|
| 480 | HighestKineticEnergy,
|
|---|
| 481 | TotBin);
|
|---|
| 482 |
|
|---|
| 483 | // compute the (macroscopic) cross section first
|
|---|
| 484 | const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(j);
|
|---|
| 485 | const G4Material* material= couple->GetMaterial();
|
|---|
| 486 |
|
|---|
| 487 | const G4ElementVector* theElementVector = material->GetElementVector() ;
|
|---|
| 488 | const G4double* theAtomicNumDensityVector = material->GetAtomicNumDensityVector();
|
|---|
| 489 | const G4int numberOfElements = material->GetNumberOfElements() ;
|
|---|
| 490 |
|
|---|
| 491 | // get the electron kinetic energy cut for the actual material,
|
|---|
| 492 | // it will be used in ComputeMicroscopicCrossSection
|
|---|
| 493 | // ( it is the SAME for ALL the ELEMENTS in THIS MATERIAL )
|
|---|
| 494 | // ------------------------------------------------------
|
|---|
| 495 |
|
|---|
| 496 | G4double deltaCut = cutForDelta[j];
|
|---|
| 497 |
|
|---|
| 498 | for ( G4int i = 0 ; i < TotBin ; i++ ) {
|
|---|
| 499 | lowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
|
|---|
| 500 | G4double sigma = 0.0 ;
|
|---|
| 501 | G4int Z;
|
|---|
| 502 |
|
|---|
| 503 | for (G4int iel=0; iel<numberOfElements; iel++ )
|
|---|
| 504 | {
|
|---|
| 505 | Z = (G4int) (*theElementVector)[iel]->GetZ();
|
|---|
| 506 | // ---- MGP --- Corrected duplicated cross section calculation here from
|
|---|
| 507 | // G4hLowEnergyIonisation original
|
|---|
| 508 | G4double microCross = MicroscopicCrossSection( particleDef,
|
|---|
| 509 | lowEdgeEnergy,
|
|---|
| 510 | Z,
|
|---|
| 511 | deltaCut ) ;
|
|---|
| 512 | //totalCrossSectionMap [Z] = microCross;
|
|---|
| 513 | sigma += theAtomicNumDensityVector[iel] * microCross ;
|
|---|
| 514 | }
|
|---|
| 515 |
|
|---|
| 516 | // mean free path = 1./macroscopic cross section
|
|---|
| 517 |
|
|---|
| 518 | value = sigma<=0 ? DBL_MAX : 1./sigma ;
|
|---|
| 519 |
|
|---|
| 520 | aVector->PutValue(i, value) ;
|
|---|
| 521 | }
|
|---|
| 522 |
|
|---|
| 523 | theMeanFreePathTable->insert(aVector);
|
|---|
| 524 | }
|
|---|
| 525 |
|
|---|
| 526 | }
|
|---|
| 527 |
|
|---|
| 528 |
|
|---|
| 529 | // --------------------------------------------------------------------
|
|---|
| 530 | G4double G4hImpactIonisation::MicroscopicCrossSection(const G4ParticleDefinition& particleDef,
|
|---|
| 531 | G4double kineticEnergy,
|
|---|
| 532 | G4double atomicNumber,
|
|---|
| 533 | G4double deltaCutInEnergy) const
|
|---|
| 534 | {
|
|---|
| 535 | //******************************************************************
|
|---|
| 536 | // cross section formula is OK for spin=0, 1/2, 1 only !
|
|---|
| 537 | // *****************************************************************
|
|---|
| 538 |
|
|---|
| 539 | // Calculates the microscopic cross section in GEANT4 internal units
|
|---|
| 540 | // Formula documented in Geant4 Phys. Ref. Manual
|
|---|
| 541 | // ( it is called for elements, AtomicNumber = z )
|
|---|
| 542 |
|
|---|
| 543 | G4double totalCrossSection = 0.;
|
|---|
| 544 |
|
|---|
| 545 | // Particle mass and energy
|
|---|
| 546 | G4double particleMass = initialMass;
|
|---|
| 547 | G4double energy = kineticEnergy + particleMass;
|
|---|
| 548 |
|
|---|
| 549 | // Some kinematics
|
|---|
| 550 | G4double gamma = energy / particleMass;
|
|---|
| 551 | G4double beta2 = 1. - 1. / (gamma * gamma);
|
|---|
| 552 | G4double var = electron_mass_c2 / particleMass;
|
|---|
| 553 | G4double tMax = 2. * electron_mass_c2 * (gamma*gamma - 1.) / (1. + 2.* gamma*var + var*var);
|
|---|
| 554 |
|
|---|
| 555 | // Calculate the total cross section
|
|---|
| 556 |
|
|---|
| 557 | if ( tMax > deltaCutInEnergy )
|
|---|
| 558 | {
|
|---|
| 559 | var = deltaCutInEnergy / tMax;
|
|---|
| 560 | totalCrossSection = (1. - var * (1. - beta2 * std::log(var))) / deltaCutInEnergy ;
|
|---|
| 561 |
|
|---|
| 562 | G4double spin = particleDef.GetPDGSpin() ;
|
|---|
| 563 |
|
|---|
| 564 | // +term for spin=1/2 particle
|
|---|
| 565 | if (spin == 0.5)
|
|---|
| 566 | {
|
|---|
| 567 | totalCrossSection += 0.5 * (tMax - deltaCutInEnergy) / (energy*energy);
|
|---|
| 568 | }
|
|---|
| 569 | // +term for spin=1 particle
|
|---|
| 570 | else if (spin > 0.9 )
|
|---|
| 571 | {
|
|---|
| 572 | totalCrossSection += -std::log(var) /
|
|---|
| 573 | (3. * deltaCutInEnergy) + (tMax - deltaCutInEnergy) * ( (5. + 1. /var)*0.25 / (energy*energy) -
|
|---|
| 574 | beta2 / (tMax * deltaCutInEnergy) ) / 3. ;
|
|---|
| 575 | }
|
|---|
| 576 | totalCrossSection *= twopi_mc2_rcl2 * atomicNumber / beta2 ;
|
|---|
| 577 | }
|
|---|
| 578 |
|
|---|
| 579 | //std::cout << "Microscopic = " << totalCrossSection/barn
|
|---|
| 580 | // << ", e = " << kineticEnergy/MeV <<std:: endl;
|
|---|
| 581 |
|
|---|
| 582 | return totalCrossSection ;
|
|---|
| 583 | }
|
|---|
| 584 |
|
|---|
| 585 |
|
|---|
| 586 |
|
|---|
| 587 | // --------------------------------------------------------------------
|
|---|
| 588 | G4double G4hImpactIonisation::GetMeanFreePath(const G4Track& track,
|
|---|
| 589 | G4double, // previousStepSize
|
|---|
| 590 | enum G4ForceCondition* condition)
|
|---|
| 591 | {
|
|---|
| 592 | const G4DynamicParticle* dynamicParticle = track.GetDynamicParticle();
|
|---|
| 593 | const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
|
|---|
| 594 | const G4Material* material = couple->GetMaterial();
|
|---|
| 595 |
|
|---|
| 596 | G4double meanFreePath = DBL_MAX;
|
|---|
| 597 | // ---- MGP ---- What is the meaning of the local variable isOutOfRange?
|
|---|
| 598 | G4bool isOutRange = false;
|
|---|
| 599 |
|
|---|
| 600 | *condition = NotForced ;
|
|---|
| 601 |
|
|---|
| 602 | G4double kineticEnergy = (dynamicParticle->GetKineticEnergy())*initialMass/(dynamicParticle->GetMass());
|
|---|
| 603 | charge = dynamicParticle->GetCharge()/eplus;
|
|---|
| 604 | chargeSquare = theIonEffChargeModel->TheValue(dynamicParticle, material);
|
|---|
| 605 |
|
|---|
| 606 | if (kineticEnergy < LowestKineticEnergy)
|
|---|
| 607 | {
|
|---|
| 608 | meanFreePath = DBL_MAX;
|
|---|
| 609 | }
|
|---|
| 610 | else
|
|---|
| 611 | {
|
|---|
| 612 | if (kineticEnergy > HighestKineticEnergy) kineticEnergy = HighestKineticEnergy;
|
|---|
| 613 | meanFreePath = (((*theMeanFreePathTable)(couple->GetIndex()))->
|
|---|
| 614 | GetValue(kineticEnergy,isOutRange))/chargeSquare;
|
|---|
| 615 | }
|
|---|
| 616 |
|
|---|
| 617 | return meanFreePath ;
|
|---|
| 618 | }
|
|---|
| 619 |
|
|---|
| 620 |
|
|---|
| 621 | // --------------------------------------------------------------------
|
|---|
| 622 | G4double G4hImpactIonisation::GetConstraints(const G4DynamicParticle* particle,
|
|---|
| 623 | const G4MaterialCutsCouple* couple)
|
|---|
| 624 | {
|
|---|
| 625 | // returns the Step limit
|
|---|
| 626 | // dEdx is calculated as well as the range
|
|---|
| 627 | // based on Effective Charge Approach
|
|---|
| 628 |
|
|---|
| 629 | const G4Material* material = couple->GetMaterial();
|
|---|
| 630 | G4Proton* proton = G4Proton::Proton();
|
|---|
| 631 | G4AntiProton* antiproton = G4AntiProton::AntiProton();
|
|---|
| 632 |
|
|---|
| 633 | G4double stepLimit = 0.;
|
|---|
| 634 | G4double dx, highEnergy;
|
|---|
| 635 |
|
|---|
| 636 | G4double massRatio = proton_mass_c2/(particle->GetMass()) ;
|
|---|
| 637 | G4double kineticEnergy = particle->GetKineticEnergy() ;
|
|---|
| 638 |
|
|---|
| 639 | // Scale the kinetic energy
|
|---|
| 640 |
|
|---|
| 641 | G4double tScaled = kineticEnergy*massRatio ;
|
|---|
| 642 | fBarkas = 0.;
|
|---|
| 643 |
|
|---|
| 644 | if (charge > 0.)
|
|---|
| 645 | {
|
|---|
| 646 | highEnergy = protonHighEnergy ;
|
|---|
| 647 | fRangeNow = G4EnergyLossTables::GetRange(proton, tScaled, couple);
|
|---|
| 648 | dx = G4EnergyLossTables::GetRange(proton, highEnergy, couple);
|
|---|
| 649 | fdEdx = G4EnergyLossTables::GetDEDX(proton, tScaled, couple)
|
|---|
| 650 | * chargeSquare ;
|
|---|
| 651 |
|
|---|
| 652 | // Correction for positive ions
|
|---|
| 653 | if (theBarkas && tScaled > highEnergy)
|
|---|
| 654 | {
|
|---|
| 655 | fBarkas = BarkasTerm(material,tScaled)*std::sqrt(chargeSquare)*chargeSquare
|
|---|
| 656 | + BlochTerm(material,tScaled,chargeSquare);
|
|---|
| 657 | }
|
|---|
| 658 | // Antiprotons and negative hadrons
|
|---|
| 659 | }
|
|---|
| 660 | else
|
|---|
| 661 | {
|
|---|
| 662 | highEnergy = antiprotonHighEnergy ;
|
|---|
| 663 | fRangeNow = G4EnergyLossTables::GetRange(antiproton, tScaled, couple);
|
|---|
| 664 | dx = G4EnergyLossTables::GetRange(antiproton, highEnergy, couple);
|
|---|
| 665 | fdEdx = G4EnergyLossTables::GetDEDX(antiproton, tScaled, couple) * chargeSquare ;
|
|---|
| 666 |
|
|---|
| 667 | if (theBarkas && tScaled > highEnergy)
|
|---|
| 668 | {
|
|---|
| 669 | fBarkas = -BarkasTerm(material,tScaled)*std::sqrt(chargeSquare)*chargeSquare
|
|---|
| 670 | + BlochTerm(material,tScaled,chargeSquare);
|
|---|
| 671 | }
|
|---|
| 672 | }
|
|---|
| 673 | /*
|
|---|
| 674 | const G4Material* mat = couple->GetMaterial();
|
|---|
| 675 | G4double fac = gram/(MeV*cm2*mat->GetDensity());
|
|---|
| 676 | G4cout << particle->GetDefinition()->GetParticleName()
|
|---|
| 677 | << " in " << mat->GetName()
|
|---|
| 678 | << " E(MeV)= " << kineticEnergy/MeV
|
|---|
| 679 | << " dedx(MeV*cm^2/g)= " << fdEdx*fac
|
|---|
| 680 | << " barcas(MeV*cm^2/gram)= " << fBarkas*fac
|
|---|
| 681 | << " Q^2= " << chargeSquare
|
|---|
| 682 | << G4endl;
|
|---|
| 683 | */
|
|---|
| 684 | // scaling back
|
|---|
| 685 | fRangeNow /= (chargeSquare*massRatio) ;
|
|---|
| 686 | dx /= (chargeSquare*massRatio) ;
|
|---|
| 687 |
|
|---|
| 688 | stepLimit = fRangeNow ;
|
|---|
| 689 | G4double r = std::min(finalRange, couple->GetProductionCuts()
|
|---|
| 690 | ->GetProductionCut(idxG4ElectronCut));
|
|---|
| 691 |
|
|---|
| 692 | if (fRangeNow > r)
|
|---|
| 693 | {
|
|---|
| 694 | stepLimit = dRoverRange*fRangeNow + r*(1.0 - dRoverRange)*(2.0 - r/fRangeNow);
|
|---|
| 695 | if (stepLimit > fRangeNow) stepLimit = fRangeNow;
|
|---|
| 696 | }
|
|---|
| 697 | // compute the (random) Step limit in standard energy range
|
|---|
| 698 | if(tScaled > highEnergy )
|
|---|
| 699 | {
|
|---|
| 700 | // add Barkas correction directly to dedx
|
|---|
| 701 | fdEdx += fBarkas;
|
|---|
| 702 |
|
|---|
| 703 | if(stepLimit > fRangeNow - dx*0.9) stepLimit = fRangeNow - dx*0.9 ;
|
|---|
| 704 |
|
|---|
| 705 | // Step limit in low energy range
|
|---|
| 706 | }
|
|---|
| 707 | else
|
|---|
| 708 | {
|
|---|
| 709 | G4double x = dx*paramStepLimit;
|
|---|
| 710 | if (stepLimit > x) stepLimit = x;
|
|---|
| 711 | }
|
|---|
| 712 | return stepLimit;
|
|---|
| 713 | }
|
|---|
| 714 |
|
|---|
| 715 |
|
|---|
| 716 | // --------------------------------------------------------------------
|
|---|
| 717 | G4VParticleChange* G4hImpactIonisation::AlongStepDoIt(const G4Track& track,
|
|---|
| 718 | const G4Step& step)
|
|---|
| 719 | {
|
|---|
| 720 | // compute the energy loss after a step
|
|---|
| 721 | G4Proton* proton = G4Proton::Proton();
|
|---|
| 722 | G4AntiProton* antiproton = G4AntiProton::AntiProton();
|
|---|
| 723 | G4double finalT = 0.;
|
|---|
| 724 |
|
|---|
| 725 | aParticleChange.Initialize(track) ;
|
|---|
| 726 |
|
|---|
| 727 | const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
|
|---|
| 728 | const G4Material* material = couple->GetMaterial();
|
|---|
| 729 |
|
|---|
| 730 | // get the actual (true) Step length from step
|
|---|
| 731 | const G4double stepLength = step.GetStepLength() ;
|
|---|
| 732 |
|
|---|
| 733 | const G4DynamicParticle* particle = track.GetDynamicParticle() ;
|
|---|
| 734 |
|
|---|
| 735 | G4double kineticEnergy = particle->GetKineticEnergy() ;
|
|---|
| 736 | G4double massRatio = proton_mass_c2/(particle->GetMass()) ;
|
|---|
| 737 | G4double tScaled = kineticEnergy * massRatio ;
|
|---|
| 738 | G4double eLoss = 0.0 ;
|
|---|
| 739 | G4double nLoss = 0.0 ;
|
|---|
| 740 |
|
|---|
| 741 |
|
|---|
| 742 | // very small particle energy
|
|---|
| 743 | if (kineticEnergy < MinKineticEnergy)
|
|---|
| 744 | {
|
|---|
| 745 | eLoss = kineticEnergy ;
|
|---|
| 746 | // particle energy outside tabulated energy range
|
|---|
| 747 | }
|
|---|
| 748 |
|
|---|
| 749 | else if( kineticEnergy > HighestKineticEnergy)
|
|---|
| 750 | {
|
|---|
| 751 | eLoss = stepLength * fdEdx ;
|
|---|
| 752 | // big step
|
|---|
| 753 | }
|
|---|
| 754 | else if (stepLength >= fRangeNow )
|
|---|
| 755 | {
|
|---|
| 756 | eLoss = kineticEnergy ;
|
|---|
| 757 |
|
|---|
| 758 | // tabulated range
|
|---|
| 759 | }
|
|---|
| 760 | else
|
|---|
| 761 | {
|
|---|
| 762 | // step longer than linear step limit
|
|---|
| 763 | if(stepLength > linLossLimit * fRangeNow)
|
|---|
| 764 | {
|
|---|
| 765 | G4double rScaled = fRangeNow * massRatio * chargeSquare ;
|
|---|
| 766 | G4double sScaled = stepLength * massRatio * chargeSquare ;
|
|---|
| 767 |
|
|---|
| 768 | if(charge > 0.0)
|
|---|
| 769 | {
|
|---|
| 770 | eLoss = G4EnergyLossTables::GetPreciseEnergyFromRange(proton,rScaled, couple) -
|
|---|
| 771 | G4EnergyLossTables::GetPreciseEnergyFromRange(proton,rScaled-sScaled,couple) ;
|
|---|
| 772 |
|
|---|
| 773 | }
|
|---|
| 774 | else
|
|---|
| 775 | {
|
|---|
| 776 | // Antiproton
|
|---|
| 777 | eLoss = G4EnergyLossTables::GetPreciseEnergyFromRange(antiproton,rScaled,couple) -
|
|---|
| 778 | G4EnergyLossTables::GetPreciseEnergyFromRange(antiproton,rScaled-sScaled,couple) ;
|
|---|
| 779 | }
|
|---|
| 780 | eLoss /= massRatio ;
|
|---|
| 781 |
|
|---|
| 782 | // Barkas correction at big step
|
|---|
| 783 | eLoss += fBarkas * stepLength;
|
|---|
| 784 |
|
|---|
| 785 | // step shorter than linear step limit
|
|---|
| 786 | }
|
|---|
| 787 | else
|
|---|
| 788 | {
|
|---|
| 789 | eLoss = stepLength *fdEdx ;
|
|---|
| 790 | }
|
|---|
| 791 | if (nStopping && tScaled < protonHighEnergy)
|
|---|
| 792 | {
|
|---|
| 793 | nLoss = (theNuclearStoppingModel->TheValue(particle, material)) * stepLength;
|
|---|
| 794 | }
|
|---|
| 795 | }
|
|---|
| 796 |
|
|---|
| 797 | if (eLoss < 0.0) eLoss = 0.0;
|
|---|
| 798 |
|
|---|
| 799 | finalT = kineticEnergy - eLoss - nLoss;
|
|---|
| 800 |
|
|---|
| 801 | if ( EnlossFlucFlag && 0.0 < eLoss && finalT > MinKineticEnergy)
|
|---|
| 802 | {
|
|---|
| 803 |
|
|---|
| 804 | // now the electron loss with fluctuation
|
|---|
| 805 | eLoss = ElectronicLossFluctuation(particle, couple, eLoss, stepLength) ;
|
|---|
| 806 | if (eLoss < 0.0) eLoss = 0.0;
|
|---|
| 807 | finalT = kineticEnergy - eLoss - nLoss;
|
|---|
| 808 | }
|
|---|
| 809 |
|
|---|
| 810 | // stop particle if the kinetic energy <= MinKineticEnergy
|
|---|
| 811 | if (finalT*massRatio <= MinKineticEnergy )
|
|---|
| 812 | {
|
|---|
| 813 |
|
|---|
| 814 | finalT = 0.0;
|
|---|
| 815 | if (!particle->GetDefinition()->GetProcessManager()->GetAtRestProcessVector()->size())
|
|---|
| 816 | aParticleChange.ProposeTrackStatus(fStopAndKill);
|
|---|
| 817 | else
|
|---|
| 818 | aParticleChange.ProposeTrackStatus(fStopButAlive);
|
|---|
| 819 | }
|
|---|
| 820 |
|
|---|
| 821 | aParticleChange.ProposeEnergy( finalT );
|
|---|
| 822 | eLoss = kineticEnergy-finalT;
|
|---|
| 823 |
|
|---|
| 824 | aParticleChange.ProposeLocalEnergyDeposit(eLoss);
|
|---|
| 825 | return &aParticleChange ;
|
|---|
| 826 | }
|
|---|
| 827 |
|
|---|
| 828 |
|
|---|
| 829 |
|
|---|
| 830 | // --------------------------------------------------------------------
|
|---|
| 831 | G4double G4hImpactIonisation::ProtonParametrisedDEDX(const G4MaterialCutsCouple* couple,
|
|---|
| 832 | G4double kineticEnergy) const
|
|---|
| 833 | {
|
|---|
| 834 | const G4Material* material = couple->GetMaterial();
|
|---|
| 835 | G4Proton* proton = G4Proton::Proton();
|
|---|
| 836 | G4double eLoss = 0.;
|
|---|
| 837 |
|
|---|
| 838 | // Free Electron Gas Model
|
|---|
| 839 | if(kineticEnergy < protonLowEnergy) {
|
|---|
| 840 | eLoss = (protonModel->TheValue(proton, material, protonLowEnergy))
|
|---|
| 841 | * std::sqrt(kineticEnergy/protonLowEnergy) ;
|
|---|
| 842 |
|
|---|
| 843 | // Parametrisation
|
|---|
| 844 | } else {
|
|---|
| 845 | eLoss = protonModel->TheValue(proton, material, kineticEnergy) ;
|
|---|
| 846 | }
|
|---|
| 847 |
|
|---|
| 848 | // Delta rays energy
|
|---|
| 849 | eLoss -= DeltaRaysEnergy(couple,kineticEnergy,proton_mass_c2) ;
|
|---|
| 850 |
|
|---|
| 851 | if(verboseLevel > 2) {
|
|---|
| 852 | G4cout << "p E(MeV)= " << kineticEnergy/MeV
|
|---|
| 853 | << " dE/dx(MeV/mm)= " << eLoss*mm/MeV
|
|---|
| 854 | << " for " << material->GetName()
|
|---|
| 855 | << " model: " << protonModel << G4endl;
|
|---|
| 856 | }
|
|---|
| 857 |
|
|---|
| 858 | if(eLoss < 0.0) eLoss = 0.0 ;
|
|---|
| 859 |
|
|---|
| 860 | return eLoss ;
|
|---|
| 861 | }
|
|---|
| 862 |
|
|---|
| 863 |
|
|---|
| 864 |
|
|---|
| 865 | // --------------------------------------------------------------------
|
|---|
| 866 | G4double G4hImpactIonisation::AntiProtonParametrisedDEDX(const G4MaterialCutsCouple* couple,
|
|---|
| 867 | G4double kineticEnergy) const
|
|---|
| 868 | {
|
|---|
| 869 | const G4Material* material = couple->GetMaterial();
|
|---|
| 870 | G4AntiProton* antiproton = G4AntiProton::AntiProton();
|
|---|
| 871 | G4double eLoss = 0.0 ;
|
|---|
| 872 |
|
|---|
| 873 | // Antiproton model is used
|
|---|
| 874 | if(antiprotonModel->IsInCharge(antiproton,material)) {
|
|---|
| 875 | if(kineticEnergy < antiprotonLowEnergy) {
|
|---|
| 876 | eLoss = antiprotonModel->TheValue(antiproton,material,antiprotonLowEnergy)
|
|---|
| 877 | * std::sqrt(kineticEnergy/antiprotonLowEnergy) ;
|
|---|
| 878 |
|
|---|
| 879 | // Parametrisation
|
|---|
| 880 | } else {
|
|---|
| 881 | eLoss = antiprotonModel->TheValue(antiproton,material,
|
|---|
| 882 | kineticEnergy);
|
|---|
| 883 | }
|
|---|
| 884 |
|
|---|
| 885 | // The proton model is used + Barkas correction
|
|---|
| 886 | } else {
|
|---|
| 887 | if(kineticEnergy < protonLowEnergy) {
|
|---|
| 888 | eLoss = protonModel->TheValue(G4Proton::Proton(),material,protonLowEnergy)
|
|---|
| 889 | * std::sqrt(kineticEnergy/protonLowEnergy) ;
|
|---|
| 890 |
|
|---|
| 891 | // Parametrisation
|
|---|
| 892 | } else {
|
|---|
| 893 | eLoss = protonModel->TheValue(G4Proton::Proton(),material,
|
|---|
| 894 | kineticEnergy);
|
|---|
| 895 | }
|
|---|
| 896 | //if(theBarkas) eLoss -= 2.0*BarkasTerm(material, kineticEnergy);
|
|---|
| 897 | }
|
|---|
| 898 |
|
|---|
| 899 | // Delta rays energy
|
|---|
| 900 | eLoss -= DeltaRaysEnergy(couple,kineticEnergy,proton_mass_c2) ;
|
|---|
| 901 |
|
|---|
| 902 | if(verboseLevel > 2) {
|
|---|
| 903 | G4cout << "pbar E(MeV)= " << kineticEnergy/MeV
|
|---|
| 904 | << " dE/dx(MeV/mm)= " << eLoss*mm/MeV
|
|---|
| 905 | << " for " << material->GetName()
|
|---|
| 906 | << " model: " << protonModel << G4endl;
|
|---|
| 907 | }
|
|---|
| 908 |
|
|---|
| 909 | if(eLoss < 0.0) eLoss = 0.0 ;
|
|---|
| 910 |
|
|---|
| 911 | return eLoss ;
|
|---|
| 912 | }
|
|---|
| 913 |
|
|---|
| 914 |
|
|---|
| 915 | // --------------------------------------------------------------------
|
|---|
| 916 | G4double G4hImpactIonisation::DeltaRaysEnergy(const G4MaterialCutsCouple* couple,
|
|---|
| 917 | G4double kineticEnergy,
|
|---|
| 918 | G4double particleMass) const
|
|---|
| 919 | {
|
|---|
| 920 | G4double dLoss = 0.;
|
|---|
| 921 |
|
|---|
| 922 | G4double deltaCutNow = cutForDelta[(couple->GetIndex())] ;
|
|---|
| 923 | const G4Material* material = couple->GetMaterial();
|
|---|
| 924 | G4double electronDensity = material->GetElectronDensity();
|
|---|
| 925 | G4double excitationEnergy = material->GetIonisation()->GetMeanExcitationEnergy();
|
|---|
| 926 |
|
|---|
| 927 | G4double tau = kineticEnergy / particleMass ;
|
|---|
| 928 | G4double rateMass = electron_mass_c2/particleMass ;
|
|---|
| 929 |
|
|---|
| 930 | // some local variables
|
|---|
| 931 |
|
|---|
| 932 | G4double gamma = tau + 1.0 ;
|
|---|
| 933 | G4double bg2 = tau*(tau+2.0) ;
|
|---|
| 934 | G4double beta2 = bg2/(gamma*gamma) ;
|
|---|
| 935 | G4double tMax = 2.*electron_mass_c2*bg2/(1.0+2.0*gamma*rateMass+rateMass*rateMass) ;
|
|---|
| 936 |
|
|---|
| 937 | // Validity range for delta electron cross section
|
|---|
| 938 | G4double deltaCut = std::max(deltaCutNow, excitationEnergy);
|
|---|
| 939 |
|
|---|
| 940 | if ( deltaCut < tMax)
|
|---|
| 941 | {
|
|---|
| 942 | G4double x = deltaCut / tMax ;
|
|---|
| 943 | dLoss = ( beta2 * (x-1.) - std::log(x) ) * twopi_mc2_rcl2 * electronDensity / beta2 ;
|
|---|
| 944 | }
|
|---|
| 945 | return dLoss ;
|
|---|
| 946 | }
|
|---|
| 947 |
|
|---|
| 948 |
|
|---|
| 949 | // -------------------------------------------------------------------------
|
|---|
| 950 |
|
|---|
| 951 | G4VParticleChange* G4hImpactIonisation::PostStepDoIt(const G4Track& track,
|
|---|
| 952 | const G4Step& step)
|
|---|
| 953 | {
|
|---|
| 954 | // Units are expressed in GEANT4 internal units.
|
|---|
| 955 |
|
|---|
| 956 | // std::cout << "----- Calling PostStepDoIt ----- " << std::endl;
|
|---|
| 957 |
|
|---|
| 958 | aParticleChange.Initialize(track) ;
|
|---|
| 959 | const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
|
|---|
| 960 | const G4DynamicParticle* aParticle = track.GetDynamicParticle() ;
|
|---|
| 961 |
|
|---|
| 962 | // Some kinematics
|
|---|
| 963 |
|
|---|
| 964 | G4ParticleDefinition* definition = track.GetDefinition();
|
|---|
| 965 | G4double mass = definition->GetPDGMass();
|
|---|
| 966 | G4double kineticEnergy = aParticle->GetKineticEnergy();
|
|---|
| 967 | G4double totalEnergy = kineticEnergy + mass ;
|
|---|
| 968 | G4double pSquare = kineticEnergy *( totalEnergy + mass) ;
|
|---|
| 969 | G4double eSquare = totalEnergy * totalEnergy;
|
|---|
| 970 | G4double betaSquare = pSquare / eSquare;
|
|---|
| 971 | G4ThreeVector particleDirection = aParticle->GetMomentumDirection() ;
|
|---|
| 972 |
|
|---|
| 973 | G4double gamma = kineticEnergy / mass + 1.;
|
|---|
| 974 | G4double r = electron_mass_c2 / mass;
|
|---|
| 975 | G4double tMax = 2. * electron_mass_c2 *(gamma*gamma - 1.) / (1. + 2.*gamma*r + r*r);
|
|---|
| 976 |
|
|---|
| 977 | // Validity range for delta electron cross section
|
|---|
| 978 | G4double deltaCut = cutForDelta[couple->GetIndex()];
|
|---|
| 979 |
|
|---|
| 980 | // This should not be a case
|
|---|
| 981 | if (deltaCut >= tMax)
|
|---|
| 982 | return G4VContinuousDiscreteProcess::PostStepDoIt(track,step);
|
|---|
| 983 |
|
|---|
| 984 | G4double xc = deltaCut / tMax;
|
|---|
| 985 | G4double rate = tMax / totalEnergy;
|
|---|
| 986 | rate = rate*rate ;
|
|---|
| 987 | G4double spin = aParticle->GetDefinition()->GetPDGSpin() ;
|
|---|
| 988 |
|
|---|
| 989 | // Sampling follows ...
|
|---|
| 990 | G4double x = 0.;
|
|---|
| 991 | G4double gRej = 0.;
|
|---|
| 992 |
|
|---|
| 993 | do {
|
|---|
| 994 | x = xc / (1. - (1. - xc) * G4UniformRand());
|
|---|
| 995 |
|
|---|
| 996 | if (0.0 == spin)
|
|---|
| 997 | {
|
|---|
| 998 | gRej = 1.0 - betaSquare * x ;
|
|---|
| 999 | }
|
|---|
| 1000 | else if (0.5 == spin)
|
|---|
| 1001 | {
|
|---|
| 1002 | gRej = (1. - betaSquare * x + 0.5 * x*x * rate) / (1. + 0.5 * rate) ;
|
|---|
| 1003 | }
|
|---|
| 1004 | else
|
|---|
| 1005 | {
|
|---|
| 1006 | gRej = (1. - betaSquare * x ) * (1. + x/(3.*xc)) +
|
|---|
| 1007 | x*x * rate * (1. + 0.5*x/xc) / 3.0 /
|
|---|
| 1008 | (1. + 1./(3.*xc) + rate *(1.+ 0.5/xc) / 3.);
|
|---|
| 1009 | }
|
|---|
| 1010 |
|
|---|
| 1011 | } while( G4UniformRand() > gRej );
|
|---|
| 1012 |
|
|---|
| 1013 | G4double deltaKineticEnergy = x * tMax;
|
|---|
| 1014 | G4double deltaTotalMomentum = std::sqrt(deltaKineticEnergy *
|
|---|
| 1015 | (deltaKineticEnergy + 2. * electron_mass_c2 ));
|
|---|
| 1016 | G4double totalMomentum = std::sqrt(pSquare) ;
|
|---|
| 1017 | G4double cosTheta = deltaKineticEnergy * (totalEnergy + electron_mass_c2) / (deltaTotalMomentum*totalMomentum);
|
|---|
| 1018 |
|
|---|
| 1019 | // protection against cosTheta > 1 or < -1
|
|---|
| 1020 | if ( cosTheta < -1. ) cosTheta = -1.;
|
|---|
| 1021 | if ( cosTheta > 1. ) cosTheta = 1.;
|
|---|
| 1022 |
|
|---|
| 1023 | // direction of the delta electron
|
|---|
| 1024 | G4double phi = twopi * G4UniformRand();
|
|---|
| 1025 | G4double sinTheta = std::sqrt(1. - cosTheta*cosTheta);
|
|---|
| 1026 | G4double dirX = sinTheta * std::cos(phi);
|
|---|
| 1027 | G4double dirY = sinTheta * std::sin(phi);
|
|---|
| 1028 | G4double dirZ = cosTheta;
|
|---|
| 1029 |
|
|---|
| 1030 | G4ThreeVector deltaDirection(dirX,dirY,dirZ);
|
|---|
| 1031 | deltaDirection.rotateUz(particleDirection);
|
|---|
| 1032 |
|
|---|
| 1033 | // create G4DynamicParticle object for delta ray
|
|---|
| 1034 | G4DynamicParticle* deltaRay = new G4DynamicParticle;
|
|---|
| 1035 | deltaRay->SetKineticEnergy( deltaKineticEnergy );
|
|---|
| 1036 | deltaRay->SetMomentumDirection(deltaDirection.x(),
|
|---|
| 1037 | deltaDirection.y(),
|
|---|
| 1038 | deltaDirection.z());
|
|---|
| 1039 | deltaRay->SetDefinition(G4Electron::Electron());
|
|---|
| 1040 |
|
|---|
| 1041 | // fill aParticleChange
|
|---|
| 1042 | G4double finalKineticEnergy = kineticEnergy - deltaKineticEnergy;
|
|---|
| 1043 | size_t totalNumber = 1;
|
|---|
| 1044 |
|
|---|
| 1045 | // Atomic relaxation
|
|---|
| 1046 |
|
|---|
| 1047 | // ---- MGP ---- Temporary limitation: currently PIXE only for incident protons
|
|---|
| 1048 |
|
|---|
| 1049 | size_t nSecondaries = 0;
|
|---|
| 1050 | std::vector<G4DynamicParticle*>* secondaryVector = 0;
|
|---|
| 1051 |
|
|---|
| 1052 | if (definition == G4Proton::ProtonDefinition())
|
|---|
| 1053 | {
|
|---|
| 1054 | const G4Material* material = couple->GetMaterial();
|
|---|
| 1055 |
|
|---|
| 1056 | // Lazy initialization of pixeCrossSectionHandler
|
|---|
| 1057 | if (pixeCrossSectionHandler == 0)
|
|---|
| 1058 | {
|
|---|
| 1059 | // Instantiate pixeCrossSectionHandler with selected shell cross section models
|
|---|
| 1060 | // Ownership of interpolation is transferred to pixeCrossSectionHandler
|
|---|
| 1061 | G4IInterpolator* interpolation = new G4LogLogInterpolator();
|
|---|
| 1062 | pixeCrossSectionHandler =
|
|---|
| 1063 | new G4PixeCrossSectionHandler(interpolation,modelK,modelL,modelM,eMinPixe,eMaxPixe);
|
|---|
| 1064 | G4String fileName("proton");
|
|---|
| 1065 | pixeCrossSectionHandler->LoadShellData(fileName);
|
|---|
| 1066 | // pixeCrossSectionHandler->PrintData();
|
|---|
| 1067 | }
|
|---|
| 1068 |
|
|---|
| 1069 | // Select an atom in the current material based on the total shell cross sections
|
|---|
| 1070 | G4int Z = pixeCrossSectionHandler->SelectRandomAtom(material,kineticEnergy);
|
|---|
| 1071 | // std::cout << "G4hImpactIonisation::PostStepDoIt - Z = " << Z << std::endl;
|
|---|
| 1072 |
|
|---|
| 1073 | // G4double microscopicCross = MicroscopicCrossSection(*definition,
|
|---|
| 1074 | // kineticEnergy,
|
|---|
| 1075 | // Z, deltaCut);
|
|---|
| 1076 | // G4double crossFromShells = pixeCrossSectionHandler->FindValue(Z,kineticEnergy);
|
|---|
| 1077 |
|
|---|
| 1078 | //std::cout << "G4hImpactIonisation: Z= "
|
|---|
| 1079 | // << Z
|
|---|
| 1080 | // << ", energy = "
|
|---|
| 1081 | // << kineticEnergy/MeV
|
|---|
| 1082 | // <<" MeV, microscopic = "
|
|---|
| 1083 | // << microscopicCross/barn
|
|---|
| 1084 | // << " barn, from shells = "
|
|---|
| 1085 | // << crossFromShells/barn
|
|---|
| 1086 | // << " barn"
|
|---|
| 1087 | // << std::endl;
|
|---|
| 1088 |
|
|---|
| 1089 | // Select a shell in the target atom based on the individual shell cross sections
|
|---|
| 1090 | G4int shellIndex = pixeCrossSectionHandler->SelectRandomShell(Z,kineticEnergy);
|
|---|
| 1091 |
|
|---|
| 1092 | G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
|
|---|
| 1093 | const G4AtomicShell* atomicShell = transitionManager->Shell(Z,shellIndex);
|
|---|
| 1094 | G4double bindingEnergy = atomicShell->BindingEnergy();
|
|---|
| 1095 |
|
|---|
| 1096 | // if (verboseLevel > 1)
|
|---|
| 1097 | // {
|
|---|
| 1098 | // G4cout << "G4hImpactIonisation::PostStepDoIt - Z = "
|
|---|
| 1099 | // << Z
|
|---|
| 1100 | // << ", shell = "
|
|---|
| 1101 | // << shellIndex
|
|---|
| 1102 | // << ", bindingE (keV) = "
|
|---|
| 1103 | // << bindingEnergy/keV
|
|---|
| 1104 | // << G4endl;
|
|---|
| 1105 | // }
|
|---|
| 1106 |
|
|---|
| 1107 | // Generate PIXE if binding energy larger than cut for photons or electrons
|
|---|
| 1108 |
|
|---|
| 1109 | G4ParticleDefinition* type = 0;
|
|---|
| 1110 |
|
|---|
| 1111 | if (finalKineticEnergy >= bindingEnergy)
|
|---|
| 1112 | // && (bindingEnergy >= minGammaEnergy || bindingEnergy >= minElectronEnergy) )
|
|---|
| 1113 | {
|
|---|
| 1114 | // Vacancy in subshell shellIndex; shellId is the subshell identifier in EADL jargon
|
|---|
| 1115 | G4int shellId = atomicShell->ShellId();
|
|---|
| 1116 | // Atomic relaxation: generate secondaries
|
|---|
| 1117 | secondaryVector = atomicDeexcitation.GenerateParticles(Z, shellId);
|
|---|
| 1118 |
|
|---|
| 1119 | // ---- Debug ----
|
|---|
| 1120 | //std::cout << "ShellId = "
|
|---|
| 1121 | // <<shellId << " ---- Atomic relaxation secondaries: ---- "
|
|---|
| 1122 | // << secondaryVector->size()
|
|---|
| 1123 | // << std::endl;
|
|---|
| 1124 |
|
|---|
| 1125 | // ---- End debug ---
|
|---|
| 1126 |
|
|---|
| 1127 | if (secondaryVector != 0)
|
|---|
| 1128 | {
|
|---|
| 1129 | nSecondaries = secondaryVector->size();
|
|---|
| 1130 | for (size_t i = 0; i<nSecondaries; i++)
|
|---|
| 1131 | {
|
|---|
| 1132 | G4DynamicParticle* aSecondary = (*secondaryVector)[i];
|
|---|
| 1133 | if (aSecondary)
|
|---|
| 1134 | {
|
|---|
| 1135 | G4double e = aSecondary->GetKineticEnergy();
|
|---|
| 1136 | type = aSecondary->GetDefinition();
|
|---|
| 1137 |
|
|---|
| 1138 | // ---- Debug ----
|
|---|
| 1139 | //if (type == G4Gamma::GammaDefinition())
|
|---|
| 1140 | // {
|
|---|
| 1141 | // std::cout << "Z = " << Z
|
|---|
| 1142 | // << ", shell: " << shellId
|
|---|
| 1143 | // << ", PIXE photon energy (keV) = " << e/keV
|
|---|
| 1144 | // << std::endl;
|
|---|
| 1145 | // }
|
|---|
| 1146 | // ---- End debug ---
|
|---|
| 1147 |
|
|---|
| 1148 | if (e < finalKineticEnergy &&
|
|---|
| 1149 | ((type == G4Gamma::Gamma() && e > minGammaEnergy ) ||
|
|---|
| 1150 | (type == G4Electron::Electron() && e > minElectronEnergy )))
|
|---|
| 1151 | {
|
|---|
| 1152 | // Subtract the energy of the emitted secondary from the primary
|
|---|
| 1153 | finalKineticEnergy -= e;
|
|---|
| 1154 | totalNumber++;
|
|---|
| 1155 | // ---- Debug ----
|
|---|
| 1156 | //if (type == G4Gamma::GammaDefinition())
|
|---|
| 1157 | // {
|
|---|
| 1158 | // std::cout << "Z = " << Z
|
|---|
| 1159 | // << ", shell: " << shellId
|
|---|
| 1160 | // << ", PIXE photon energy (keV) = " << e/keV
|
|---|
| 1161 | // << std::endl;
|
|---|
| 1162 | // }
|
|---|
| 1163 | // ---- End debug ---
|
|---|
| 1164 | }
|
|---|
| 1165 | else
|
|---|
| 1166 | {
|
|---|
| 1167 | // The atomic relaxation product has energy below the cut
|
|---|
| 1168 | // ---- Debug ----
|
|---|
| 1169 | // if (type == G4Gamma::GammaDefinition())
|
|---|
| 1170 | // {
|
|---|
| 1171 | // std::cout << "Z = " << Z
|
|---|
| 1172 | //
|
|---|
| 1173 | // << ", PIXE photon energy = " << e/keV
|
|---|
| 1174 | // << " keV below threshold " << minGammaEnergy/keV << " keV"
|
|---|
| 1175 | // << std::endl;
|
|---|
| 1176 | // }
|
|---|
| 1177 | // ---- End debug ---
|
|---|
| 1178 |
|
|---|
| 1179 | delete aSecondary;
|
|---|
| 1180 | (*secondaryVector)[i] = 0;
|
|---|
| 1181 | }
|
|---|
| 1182 | }
|
|---|
| 1183 | }
|
|---|
| 1184 | }
|
|---|
| 1185 | }
|
|---|
| 1186 | }
|
|---|
| 1187 |
|
|---|
| 1188 |
|
|---|
| 1189 | // Save delta-electrons
|
|---|
| 1190 |
|
|---|
| 1191 | G4double eDeposit = 0.;
|
|---|
| 1192 |
|
|---|
| 1193 | if (finalKineticEnergy > MinKineticEnergy)
|
|---|
| 1194 | {
|
|---|
| 1195 | G4double finalPx = totalMomentum*particleDirection.x() - deltaTotalMomentum*deltaDirection.x();
|
|---|
| 1196 | G4double finalPy = totalMomentum*particleDirection.y() - deltaTotalMomentum*deltaDirection.y();
|
|---|
| 1197 | G4double finalPz = totalMomentum*particleDirection.z() - deltaTotalMomentum*deltaDirection.z();
|
|---|
| 1198 | G4double finalMomentum = std::sqrt(finalPx*finalPx + finalPy*finalPy + finalPz*finalPz) ;
|
|---|
| 1199 | finalPx /= finalMomentum;
|
|---|
| 1200 | finalPy /= finalMomentum;
|
|---|
| 1201 | finalPz /= finalMomentum;
|
|---|
| 1202 |
|
|---|
| 1203 | aParticleChange.ProposeMomentumDirection( finalPx,finalPy,finalPz );
|
|---|
| 1204 | }
|
|---|
| 1205 | else
|
|---|
| 1206 | {
|
|---|
| 1207 | eDeposit = finalKineticEnergy;
|
|---|
| 1208 | finalKineticEnergy = 0.;
|
|---|
| 1209 | aParticleChange.ProposeMomentumDirection(particleDirection.x(),
|
|---|
| 1210 | particleDirection.y(),
|
|---|
| 1211 | particleDirection.z());
|
|---|
| 1212 | if(!aParticle->GetDefinition()->GetProcessManager()->
|
|---|
| 1213 | GetAtRestProcessVector()->size())
|
|---|
| 1214 | aParticleChange.ProposeTrackStatus(fStopAndKill);
|
|---|
| 1215 | else
|
|---|
| 1216 | aParticleChange.ProposeTrackStatus(fStopButAlive);
|
|---|
| 1217 | }
|
|---|
| 1218 |
|
|---|
| 1219 | aParticleChange.ProposeEnergy(finalKineticEnergy);
|
|---|
| 1220 | aParticleChange.ProposeLocalEnergyDeposit (eDeposit);
|
|---|
| 1221 | aParticleChange.SetNumberOfSecondaries(totalNumber);
|
|---|
| 1222 | aParticleChange.AddSecondary(deltaRay);
|
|---|
| 1223 |
|
|---|
| 1224 | // ---- Debug ----
|
|---|
| 1225 | // std::cout << "RDHadronIonisation - finalKineticEnergy (MeV) = "
|
|---|
| 1226 | // << finalKineticEnergy/MeV
|
|---|
| 1227 | // << ", delta KineticEnergy (keV) = "
|
|---|
| 1228 | // << deltaKineticEnergy/keV
|
|---|
| 1229 | // << ", energy deposit (MeV) = "
|
|---|
| 1230 | // << eDeposit/MeV
|
|---|
| 1231 | // << std::endl;
|
|---|
| 1232 | // ---- End debug ---
|
|---|
| 1233 |
|
|---|
| 1234 | // Save Fluorescence and Auger
|
|---|
| 1235 |
|
|---|
| 1236 | if (secondaryVector != 0)
|
|---|
| 1237 | {
|
|---|
| 1238 | for (size_t l = 0; l < nSecondaries; l++)
|
|---|
| 1239 | {
|
|---|
| 1240 | G4DynamicParticle* secondary = (*secondaryVector)[l];
|
|---|
| 1241 | if (secondary) aParticleChange.AddSecondary(secondary);
|
|---|
| 1242 |
|
|---|
| 1243 | // ---- Debug ----
|
|---|
| 1244 | //if (secondary != 0)
|
|---|
| 1245 | // {
|
|---|
| 1246 | // if (secondary->GetDefinition() == G4Gamma::GammaDefinition())
|
|---|
| 1247 | // {
|
|---|
| 1248 | // G4double eX = secondary->GetKineticEnergy();
|
|---|
| 1249 | // std::cout << " PIXE photon of energy " << eX/keV
|
|---|
| 1250 | // << " keV added to ParticleChange; total number of secondaries is " << totalNumber
|
|---|
| 1251 | // << std::endl;
|
|---|
| 1252 | // }
|
|---|
| 1253 | //}
|
|---|
| 1254 | // ---- End debug ---
|
|---|
| 1255 |
|
|---|
| 1256 | }
|
|---|
| 1257 | delete secondaryVector;
|
|---|
| 1258 | }
|
|---|
| 1259 |
|
|---|
| 1260 | return G4VContinuousDiscreteProcess::PostStepDoIt(track,step);
|
|---|
| 1261 | }
|
|---|
| 1262 |
|
|---|
| 1263 | // -------------------------------------------------------------------------
|
|---|
| 1264 |
|
|---|
| 1265 | G4double G4hImpactIonisation::ComputeDEDX(const G4ParticleDefinition* aParticle,
|
|---|
| 1266 | const G4MaterialCutsCouple* couple,
|
|---|
| 1267 | G4double kineticEnergy)
|
|---|
| 1268 | {
|
|---|
| 1269 | const G4Material* material = couple->GetMaterial();
|
|---|
| 1270 | G4Proton* proton = G4Proton::Proton();
|
|---|
| 1271 | G4AntiProton* antiproton = G4AntiProton::AntiProton();
|
|---|
| 1272 | G4double dedx = 0.;
|
|---|
| 1273 |
|
|---|
| 1274 | G4double tScaled = kineticEnergy * proton_mass_c2 / (aParticle->GetPDGMass()) ;
|
|---|
| 1275 | charge = aParticle->GetPDGCharge() ;
|
|---|
| 1276 |
|
|---|
| 1277 | if( charge > 0.)
|
|---|
| 1278 | {
|
|---|
| 1279 | if (tScaled > protonHighEnergy)
|
|---|
| 1280 | {
|
|---|
| 1281 | dedx = G4EnergyLossTables::GetDEDX(proton,tScaled,couple) ;
|
|---|
| 1282 | }
|
|---|
| 1283 | else
|
|---|
| 1284 | {
|
|---|
| 1285 | dedx = ProtonParametrisedDEDX(couple,tScaled) ;
|
|---|
| 1286 | }
|
|---|
| 1287 | }
|
|---|
| 1288 | else
|
|---|
| 1289 | {
|
|---|
| 1290 | if (tScaled > antiprotonHighEnergy)
|
|---|
| 1291 | {
|
|---|
| 1292 | dedx = G4EnergyLossTables::GetDEDX(antiproton,tScaled,couple);
|
|---|
| 1293 | }
|
|---|
| 1294 | else
|
|---|
| 1295 | {
|
|---|
| 1296 | dedx = AntiProtonParametrisedDEDX(couple,tScaled) ;
|
|---|
| 1297 | }
|
|---|
| 1298 | }
|
|---|
| 1299 | dedx *= theIonEffChargeModel->TheValue(aParticle, material, kineticEnergy) ;
|
|---|
| 1300 |
|
|---|
| 1301 | return dedx ;
|
|---|
| 1302 | }
|
|---|
| 1303 |
|
|---|
| 1304 |
|
|---|
| 1305 | G4double G4hImpactIonisation::BarkasTerm(const G4Material* material,
|
|---|
| 1306 | G4double kineticEnergy) const
|
|---|
| 1307 | //Function to compute the Barkas term for protons:
|
|---|
| 1308 | //
|
|---|
| 1309 | //Ref. Z_1^3 effect in the stopping power of matter for charged particles
|
|---|
| 1310 | // J.C Ashley and R.H.Ritchie
|
|---|
| 1311 | // Physical review B Vol.5 No.7 1 April 1972 pagg. 2393-2397
|
|---|
| 1312 | //
|
|---|
| 1313 | {
|
|---|
| 1314 | static double FTable[47][2] = {
|
|---|
| 1315 | { 0.02, 21.5},
|
|---|
| 1316 | { 0.03, 20.0},
|
|---|
| 1317 | { 0.04, 18.0},
|
|---|
| 1318 | { 0.05, 15.6},
|
|---|
| 1319 | { 0.06, 15.0},
|
|---|
| 1320 | { 0.07, 14.0},
|
|---|
| 1321 | { 0.08, 13.5},
|
|---|
| 1322 | { 0.09, 13.},
|
|---|
| 1323 | { 0.1, 12.2},
|
|---|
| 1324 | { 0.2, 9.25},
|
|---|
| 1325 | { 0.3, 7.0},
|
|---|
| 1326 | { 0.4, 6.0},
|
|---|
| 1327 | { 0.5, 4.5},
|
|---|
| 1328 | { 0.6, 3.5},
|
|---|
| 1329 | { 0.7, 3.0},
|
|---|
| 1330 | { 0.8, 2.5},
|
|---|
| 1331 | { 0.9, 2.0},
|
|---|
| 1332 | { 1.0, 1.7},
|
|---|
| 1333 | { 1.2, 1.2},
|
|---|
| 1334 | { 1.3, 1.0},
|
|---|
| 1335 | { 1.4, 0.86},
|
|---|
| 1336 | { 1.5, 0.7},
|
|---|
| 1337 | { 1.6, 0.61},
|
|---|
| 1338 | { 1.7, 0.52},
|
|---|
| 1339 | { 1.8, 0.5},
|
|---|
| 1340 | { 1.9, 0.43},
|
|---|
| 1341 | { 2.0, 0.42},
|
|---|
| 1342 | { 2.1, 0.3},
|
|---|
| 1343 | { 2.4, 0.2},
|
|---|
| 1344 | { 3.0, 0.13},
|
|---|
| 1345 | { 3.08, 0.1},
|
|---|
| 1346 | { 3.1, 0.09},
|
|---|
| 1347 | { 3.3, 0.08},
|
|---|
| 1348 | { 3.5, 0.07},
|
|---|
| 1349 | { 3.8, 0.06},
|
|---|
| 1350 | { 4.0, 0.051},
|
|---|
| 1351 | { 4.1, 0.04},
|
|---|
| 1352 | { 4.8, 0.03},
|
|---|
| 1353 | { 5.0, 0.024},
|
|---|
| 1354 | { 5.1, 0.02},
|
|---|
| 1355 | { 6.0, 0.013},
|
|---|
| 1356 | { 6.5, 0.01},
|
|---|
| 1357 | { 7.0, 0.009},
|
|---|
| 1358 | { 7.1, 0.008},
|
|---|
| 1359 | { 8.0, 0.006},
|
|---|
| 1360 | { 9.0, 0.0032},
|
|---|
| 1361 | { 10.0, 0.0025} };
|
|---|
| 1362 |
|
|---|
| 1363 | // Information on particle and material
|
|---|
| 1364 | G4double kinE = kineticEnergy ;
|
|---|
| 1365 | if(0.5*MeV > kinE) kinE = 0.5*MeV ;
|
|---|
| 1366 | G4double gamma = 1.0 + kinE / proton_mass_c2 ;
|
|---|
| 1367 | G4double beta2 = 1.0 - 1.0/(gamma*gamma) ;
|
|---|
| 1368 | if(0.0 >= beta2) return 0.0;
|
|---|
| 1369 |
|
|---|
| 1370 | G4double BarkasTerm = 0.0;
|
|---|
| 1371 | G4double AMaterial = 0.0;
|
|---|
| 1372 | G4double ZMaterial = 0.0;
|
|---|
| 1373 | const G4ElementVector* theElementVector = material->GetElementVector();
|
|---|
| 1374 | G4int numberOfElements = material->GetNumberOfElements();
|
|---|
| 1375 |
|
|---|
| 1376 | for (G4int i = 0; i<numberOfElements; i++) {
|
|---|
| 1377 |
|
|---|
| 1378 | AMaterial = (*theElementVector)[i]->GetA()*mole/g;
|
|---|
| 1379 | ZMaterial = (*theElementVector)[i]->GetZ();
|
|---|
| 1380 |
|
|---|
| 1381 | G4double X = 137.0 * 137.0 * beta2 / ZMaterial;
|
|---|
| 1382 |
|
|---|
| 1383 | // Variables to compute L_1
|
|---|
| 1384 | G4double Eta0Chi = 0.8;
|
|---|
| 1385 | G4double EtaChi = Eta0Chi * ( 1.0 + 6.02*std::pow( ZMaterial,-1.19 ) );
|
|---|
| 1386 | G4double W = ( EtaChi * std::pow( ZMaterial,1.0/6.0 ) ) / std::sqrt(X);
|
|---|
| 1387 | G4double FunctionOfW = FTable[46][1]*FTable[46][0]/W ;
|
|---|
| 1388 |
|
|---|
| 1389 | for(G4int j=0; j<47; j++) {
|
|---|
| 1390 |
|
|---|
| 1391 | if( W < FTable[j][0] ) {
|
|---|
| 1392 |
|
|---|
| 1393 | if(0 == j) {
|
|---|
| 1394 | FunctionOfW = FTable[0][1] ;
|
|---|
| 1395 |
|
|---|
| 1396 | } else {
|
|---|
| 1397 | FunctionOfW = (FTable[j][1] - FTable[j-1][1]) * (W - FTable[j-1][0])
|
|---|
| 1398 | / (FTable[j][0] - FTable[j-1][0])
|
|---|
| 1399 | + FTable[j-1][1] ;
|
|---|
| 1400 | }
|
|---|
| 1401 |
|
|---|
| 1402 | break;
|
|---|
| 1403 | }
|
|---|
| 1404 |
|
|---|
| 1405 | }
|
|---|
| 1406 |
|
|---|
| 1407 | BarkasTerm += FunctionOfW /( std::sqrt(ZMaterial * X) * X);
|
|---|
| 1408 | }
|
|---|
| 1409 |
|
|---|
| 1410 | BarkasTerm *= twopi_mc2_rcl2 * (material->GetElectronDensity()) / beta2 ;
|
|---|
| 1411 |
|
|---|
| 1412 | return BarkasTerm;
|
|---|
| 1413 | }
|
|---|
| 1414 |
|
|---|
| 1415 |
|
|---|
| 1416 |
|
|---|
| 1417 | G4double G4hImpactIonisation::BlochTerm(const G4Material* material,
|
|---|
| 1418 | G4double kineticEnergy,
|
|---|
| 1419 | G4double cSquare) const
|
|---|
| 1420 | //Function to compute the Bloch term for protons:
|
|---|
| 1421 | //
|
|---|
| 1422 | //Ref. Z_1^3 effect in the stopping power of matter for charged particles
|
|---|
| 1423 | // J.C Ashley and R.H.Ritchie
|
|---|
| 1424 | // Physical review B Vol.5 No.7 1 April 1972 pagg. 2393-2397
|
|---|
| 1425 | //
|
|---|
| 1426 | {
|
|---|
| 1427 | G4double eLoss = 0.0 ;
|
|---|
| 1428 | G4double gamma = 1.0 + kineticEnergy / proton_mass_c2 ;
|
|---|
| 1429 | G4double beta2 = 1.0 - 1.0/(gamma*gamma) ;
|
|---|
| 1430 | G4double y = cSquare / (137.0*137.0*beta2) ;
|
|---|
| 1431 |
|
|---|
| 1432 | if(y < 0.05) {
|
|---|
| 1433 | eLoss = 1.202 ;
|
|---|
| 1434 |
|
|---|
| 1435 | } else {
|
|---|
| 1436 | eLoss = 1.0 / (1.0 + y) ;
|
|---|
| 1437 | G4double de = eLoss ;
|
|---|
| 1438 |
|
|---|
| 1439 | for(G4int i=2; de>eLoss*0.01; i++) {
|
|---|
| 1440 | de = 1.0/( i * (i*i + y)) ;
|
|---|
| 1441 | eLoss += de ;
|
|---|
| 1442 | }
|
|---|
| 1443 | }
|
|---|
| 1444 | eLoss *= -1.0 * y * cSquare * twopi_mc2_rcl2 *
|
|---|
| 1445 | (material->GetElectronDensity()) / beta2 ;
|
|---|
| 1446 |
|
|---|
| 1447 | return eLoss;
|
|---|
| 1448 | }
|
|---|
| 1449 |
|
|---|
| 1450 |
|
|---|
| 1451 |
|
|---|
| 1452 | G4double G4hImpactIonisation::ElectronicLossFluctuation(
|
|---|
| 1453 | const G4DynamicParticle* particle,
|
|---|
| 1454 | const G4MaterialCutsCouple* couple,
|
|---|
| 1455 | G4double meanLoss,
|
|---|
| 1456 | G4double step) const
|
|---|
| 1457 | // calculate actual loss from the mean loss
|
|---|
| 1458 | // The model used to get the fluctuation is essentially the same
|
|---|
| 1459 | // as in Glandz in Geant3.
|
|---|
| 1460 | {
|
|---|
| 1461 | // data members to speed up the fluctuation calculation
|
|---|
| 1462 | // G4int imat ;
|
|---|
| 1463 | // G4double f1Fluct,f2Fluct,e1Fluct,e2Fluct,rateFluct,ipotFluct;
|
|---|
| 1464 | // G4double e1LogFluct,e2LogFluct,ipotLogFluct;
|
|---|
| 1465 |
|
|---|
| 1466 | static const G4double minLoss = 1.*eV ;
|
|---|
| 1467 | static const G4double kappa = 10. ;
|
|---|
| 1468 | static const G4double theBohrBeta2 = 50.0 * keV/proton_mass_c2 ;
|
|---|
| 1469 |
|
|---|
| 1470 | const G4Material* material = couple->GetMaterial();
|
|---|
| 1471 | G4int imaterial = couple->GetIndex() ;
|
|---|
| 1472 | G4double ipotFluct = material->GetIonisation()->GetMeanExcitationEnergy() ;
|
|---|
| 1473 | G4double electronDensity = material->GetElectronDensity() ;
|
|---|
| 1474 | G4double zeff = electronDensity/(material->GetTotNbOfAtomsPerVolume()) ;
|
|---|
| 1475 |
|
|---|
| 1476 | // get particle data
|
|---|
| 1477 | G4double tkin = particle->GetKineticEnergy();
|
|---|
| 1478 | G4double particleMass = particle->GetMass() ;
|
|---|
| 1479 | G4double deltaCutInKineticEnergyNow = cutForDelta[imaterial];
|
|---|
| 1480 |
|
|---|
| 1481 | // shortcut for very very small loss
|
|---|
| 1482 | if(meanLoss < minLoss) return meanLoss ;
|
|---|
| 1483 |
|
|---|
| 1484 | // Validity range for delta electron cross section
|
|---|
| 1485 | G4double threshold = std::max(deltaCutInKineticEnergyNow,ipotFluct);
|
|---|
| 1486 | G4double loss, siga;
|
|---|
| 1487 |
|
|---|
| 1488 | G4double rmass = electron_mass_c2/particleMass;
|
|---|
| 1489 | G4double tau = tkin/particleMass;
|
|---|
| 1490 | G4double tau1 = tau+1.0;
|
|---|
| 1491 | G4double tau2 = tau*(tau+2.);
|
|---|
| 1492 | G4double tMax = 2.*electron_mass_c2*tau2/(1.+2.*tau1*rmass+rmass*rmass);
|
|---|
| 1493 |
|
|---|
| 1494 |
|
|---|
| 1495 | if(tMax > threshold) tMax = threshold;
|
|---|
| 1496 | G4double beta2 = tau2/(tau1*tau1);
|
|---|
| 1497 |
|
|---|
| 1498 | // Gaussian fluctuation
|
|---|
| 1499 | if(meanLoss > kappa*tMax || tMax < kappa*ipotFluct )
|
|---|
| 1500 | {
|
|---|
| 1501 | siga = tMax * (1.0-0.5*beta2) * step * twopi_mc2_rcl2
|
|---|
| 1502 | * electronDensity / beta2 ;
|
|---|
| 1503 |
|
|---|
| 1504 | // High velocity or negatively charged particle
|
|---|
| 1505 | if( beta2 > 3.0*theBohrBeta2*zeff || charge < 0.0) {
|
|---|
| 1506 | siga = std::sqrt( siga * chargeSquare ) ;
|
|---|
| 1507 |
|
|---|
| 1508 | // Low velocity - additional ion charge fluctuations according to
|
|---|
| 1509 | // Q.Yang et al., NIM B61(1991)149-155.
|
|---|
| 1510 | } else {
|
|---|
| 1511 | G4double chu = theIonChuFluctuationModel->TheValue(particle, material);
|
|---|
| 1512 | G4double yang = theIonYangFluctuationModel->TheValue(particle, material);
|
|---|
| 1513 | siga = std::sqrt( siga * (chargeSquare * chu + yang)) ;
|
|---|
| 1514 | }
|
|---|
| 1515 |
|
|---|
| 1516 | do {
|
|---|
| 1517 | loss = G4RandGauss::shoot(meanLoss,siga);
|
|---|
| 1518 | } while (loss < 0. || loss > 2.0*meanLoss);
|
|---|
| 1519 | return loss;
|
|---|
| 1520 | }
|
|---|
| 1521 |
|
|---|
| 1522 | // Non Gaussian fluctuation
|
|---|
| 1523 | static const G4double probLim = 0.01 ;
|
|---|
| 1524 | static const G4double sumaLim = -std::log(probLim) ;
|
|---|
| 1525 | static const G4double alim = 10.;
|
|---|
| 1526 |
|
|---|
| 1527 | G4double suma,w1,w2,C,e0,lossc,w;
|
|---|
| 1528 | G4double a1,a2,a3;
|
|---|
| 1529 | G4int p1,p2,p3;
|
|---|
| 1530 | G4int nb;
|
|---|
| 1531 | G4double corrfac, na,alfa,rfac,namean,sa,alfa1,ea,sea;
|
|---|
| 1532 | G4double dp3;
|
|---|
| 1533 |
|
|---|
| 1534 | G4double f1Fluct = material->GetIonisation()->GetF1fluct();
|
|---|
| 1535 | G4double f2Fluct = material->GetIonisation()->GetF2fluct();
|
|---|
| 1536 | G4double e1Fluct = material->GetIonisation()->GetEnergy1fluct();
|
|---|
| 1537 | G4double e2Fluct = material->GetIonisation()->GetEnergy2fluct();
|
|---|
| 1538 | G4double e1LogFluct = material->GetIonisation()->GetLogEnergy1fluct();
|
|---|
| 1539 | G4double e2LogFluct = material->GetIonisation()->GetLogEnergy2fluct();
|
|---|
| 1540 | G4double rateFluct = material->GetIonisation()->GetRateionexcfluct();
|
|---|
| 1541 | G4double ipotLogFluct= material->GetIonisation()->GetLogMeanExcEnergy();
|
|---|
| 1542 |
|
|---|
| 1543 | w1 = tMax/ipotFluct;
|
|---|
| 1544 | w2 = std::log(2.*electron_mass_c2*tau2);
|
|---|
| 1545 |
|
|---|
| 1546 | C = meanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
|
|---|
| 1547 |
|
|---|
| 1548 | a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluct;
|
|---|
| 1549 | a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluct;
|
|---|
| 1550 | a3 = rateFluct*meanLoss*(tMax-ipotFluct)/(ipotFluct*tMax*std::log(w1));
|
|---|
| 1551 | if(a1 < 0.0) a1 = 0.0;
|
|---|
| 1552 | if(a2 < 0.0) a2 = 0.0;
|
|---|
| 1553 | if(a3 < 0.0) a3 = 0.0;
|
|---|
| 1554 |
|
|---|
| 1555 | suma = a1+a2+a3;
|
|---|
| 1556 |
|
|---|
| 1557 | loss = 0.;
|
|---|
| 1558 |
|
|---|
| 1559 |
|
|---|
| 1560 | if(suma < sumaLim) // very small Step
|
|---|
| 1561 | {
|
|---|
| 1562 | e0 = material->GetIonisation()->GetEnergy0fluct();
|
|---|
| 1563 |
|
|---|
| 1564 | if(tMax == ipotFluct)
|
|---|
| 1565 | {
|
|---|
| 1566 | a3 = meanLoss/e0;
|
|---|
| 1567 |
|
|---|
| 1568 | if(a3>alim)
|
|---|
| 1569 | {
|
|---|
| 1570 | siga=std::sqrt(a3) ;
|
|---|
| 1571 | p3 = std::max(0,G4int(G4RandGauss::shoot(a3,siga)+0.5));
|
|---|
| 1572 | }
|
|---|
| 1573 | else
|
|---|
| 1574 | p3 = G4Poisson(a3);
|
|---|
| 1575 |
|
|---|
| 1576 | loss = p3*e0 ;
|
|---|
| 1577 |
|
|---|
| 1578 | if(p3 > 0)
|
|---|
| 1579 | loss += (1.-2.*G4UniformRand())*e0 ;
|
|---|
| 1580 |
|
|---|
| 1581 | }
|
|---|
| 1582 | else
|
|---|
| 1583 | {
|
|---|
| 1584 | tMax = tMax-ipotFluct+e0 ;
|
|---|
| 1585 | a3 = meanLoss*(tMax-e0)/(tMax*e0*std::log(tMax/e0));
|
|---|
| 1586 |
|
|---|
| 1587 | if(a3>alim)
|
|---|
| 1588 | {
|
|---|
| 1589 | siga=std::sqrt(a3) ;
|
|---|
| 1590 | p3 = std::max(0,int(G4RandGauss::shoot(a3,siga)+0.5));
|
|---|
| 1591 | }
|
|---|
| 1592 | else
|
|---|
| 1593 | p3 = G4Poisson(a3);
|
|---|
| 1594 |
|
|---|
| 1595 | if(p3 > 0)
|
|---|
| 1596 | {
|
|---|
| 1597 | w = (tMax-e0)/tMax ;
|
|---|
| 1598 | if(p3 > nmaxCont2)
|
|---|
| 1599 | {
|
|---|
| 1600 | dp3 = G4float(p3) ;
|
|---|
| 1601 | corrfac = dp3/G4float(nmaxCont2) ;
|
|---|
| 1602 | p3 = nmaxCont2 ;
|
|---|
| 1603 | }
|
|---|
| 1604 | else
|
|---|
| 1605 | corrfac = 1. ;
|
|---|
| 1606 |
|
|---|
| 1607 | for(G4int i=0; i<p3; i++) loss += 1./(1.-w*G4UniformRand()) ;
|
|---|
| 1608 | loss *= e0*corrfac ;
|
|---|
| 1609 | }
|
|---|
| 1610 | }
|
|---|
| 1611 | }
|
|---|
| 1612 |
|
|---|
| 1613 | else // not so small Step
|
|---|
| 1614 | {
|
|---|
| 1615 | // excitation type 1
|
|---|
| 1616 | if(a1>alim)
|
|---|
| 1617 | {
|
|---|
| 1618 | siga=std::sqrt(a1) ;
|
|---|
| 1619 | p1 = std::max(0,G4int(G4RandGauss::shoot(a1,siga)+0.5));
|
|---|
| 1620 | }
|
|---|
| 1621 | else
|
|---|
| 1622 | p1 = G4Poisson(a1);
|
|---|
| 1623 |
|
|---|
| 1624 | // excitation type 2
|
|---|
| 1625 | if(a2>alim)
|
|---|
| 1626 | {
|
|---|
| 1627 | siga=std::sqrt(a2) ;
|
|---|
| 1628 | p2 = std::max(0,G4int(G4RandGauss::shoot(a2,siga)+0.5));
|
|---|
| 1629 | }
|
|---|
| 1630 | else
|
|---|
| 1631 | p2 = G4Poisson(a2);
|
|---|
| 1632 |
|
|---|
| 1633 | loss = p1*e1Fluct+p2*e2Fluct;
|
|---|
| 1634 |
|
|---|
| 1635 | // smearing to avoid unphysical peaks
|
|---|
| 1636 | if(p2 > 0)
|
|---|
| 1637 | loss += (1.-2.*G4UniformRand())*e2Fluct;
|
|---|
| 1638 | else if (loss>0.)
|
|---|
| 1639 | loss += (1.-2.*G4UniformRand())*e1Fluct;
|
|---|
| 1640 |
|
|---|
| 1641 | // ionisation .......................................
|
|---|
| 1642 | if(a3 > 0.)
|
|---|
| 1643 | {
|
|---|
| 1644 | if(a3>alim)
|
|---|
| 1645 | {
|
|---|
| 1646 | siga=std::sqrt(a3) ;
|
|---|
| 1647 | p3 = std::max(0,G4int(G4RandGauss::shoot(a3,siga)+0.5));
|
|---|
| 1648 | }
|
|---|
| 1649 | else
|
|---|
| 1650 | p3 = G4Poisson(a3);
|
|---|
| 1651 |
|
|---|
| 1652 | lossc = 0.;
|
|---|
| 1653 | if(p3 > 0)
|
|---|
| 1654 | {
|
|---|
| 1655 | na = 0.;
|
|---|
| 1656 | alfa = 1.;
|
|---|
| 1657 | if (p3 > nmaxCont2)
|
|---|
| 1658 | {
|
|---|
| 1659 | dp3 = G4float(p3);
|
|---|
| 1660 | rfac = dp3/(G4float(nmaxCont2)+dp3);
|
|---|
| 1661 | namean = G4float(p3)*rfac;
|
|---|
| 1662 | sa = G4float(nmaxCont1)*rfac;
|
|---|
| 1663 | na = G4RandGauss::shoot(namean,sa);
|
|---|
| 1664 | if (na > 0.)
|
|---|
| 1665 | {
|
|---|
| 1666 | alfa = w1*G4float(nmaxCont2+p3)/
|
|---|
| 1667 | (w1*G4float(nmaxCont2)+G4float(p3));
|
|---|
| 1668 | alfa1 = alfa*std::log(alfa)/(alfa-1.);
|
|---|
| 1669 | ea = na*ipotFluct*alfa1;
|
|---|
| 1670 | sea = ipotFluct*std::sqrt(na*(alfa-alfa1*alfa1));
|
|---|
| 1671 | lossc += G4RandGauss::shoot(ea,sea);
|
|---|
| 1672 | }
|
|---|
| 1673 | }
|
|---|
| 1674 |
|
|---|
| 1675 | nb = G4int(G4float(p3)-na);
|
|---|
| 1676 | if (nb > 0)
|
|---|
| 1677 | {
|
|---|
| 1678 | w2 = alfa*ipotFluct;
|
|---|
| 1679 | w = (tMax-w2)/tMax;
|
|---|
| 1680 | for (G4int k=0; k<nb; k++) lossc += w2/(1.-w*G4UniformRand());
|
|---|
| 1681 | }
|
|---|
| 1682 | }
|
|---|
| 1683 | loss += lossc;
|
|---|
| 1684 | }
|
|---|
| 1685 | }
|
|---|
| 1686 |
|
|---|
| 1687 | return loss ;
|
|---|
| 1688 | }
|
|---|
| 1689 |
|
|---|
| 1690 |
|
|---|
| 1691 |
|
|---|
| 1692 | void G4hImpactIonisation::SetCutForSecondaryPhotons(G4double cut)
|
|---|
| 1693 | {
|
|---|
| 1694 | minGammaEnergy = cut;
|
|---|
| 1695 | }
|
|---|
| 1696 |
|
|---|
| 1697 |
|
|---|
| 1698 |
|
|---|
| 1699 | void G4hImpactIonisation::SetCutForAugerElectrons(G4double cut)
|
|---|
| 1700 | {
|
|---|
| 1701 | minElectronEnergy = cut;
|
|---|
| 1702 | }
|
|---|
| 1703 |
|
|---|
| 1704 |
|
|---|
| 1705 |
|
|---|
| 1706 | void G4hImpactIonisation::ActivateAugerElectronProduction(G4bool val)
|
|---|
| 1707 | {
|
|---|
| 1708 | atomicDeexcitation.ActivateAugerElectronProduction(val);
|
|---|
| 1709 | }
|
|---|
| 1710 |
|
|---|
| 1711 |
|
|---|
| 1712 |
|
|---|
| 1713 | void G4hImpactIonisation::PrintInfoDefinition() const
|
|---|
| 1714 | {
|
|---|
| 1715 | G4String comments = " Knock-on electron cross sections . ";
|
|---|
| 1716 | comments += "\n Good description above the mean excitation energy.\n";
|
|---|
| 1717 | comments += " Delta ray energy sampled from differential Xsection.";
|
|---|
| 1718 |
|
|---|
| 1719 | G4cout << G4endl << GetProcessName() << ": " << comments
|
|---|
| 1720 | << "\n PhysicsTables from " << LowestKineticEnergy / eV << " eV "
|
|---|
| 1721 | << " to " << HighestKineticEnergy / TeV << " TeV "
|
|---|
| 1722 | << " in " << TotBin << " bins."
|
|---|
| 1723 | << "\n Electronic stopping power model is "
|
|---|
| 1724 | << protonTable
|
|---|
| 1725 | << "\n from " << protonLowEnergy / keV << " keV "
|
|---|
| 1726 | << " to " << protonHighEnergy / MeV << " MeV " << "." << G4endl ;
|
|---|
| 1727 | G4cout << "\n Parametrisation model for antiprotons is "
|
|---|
| 1728 | << antiprotonTable
|
|---|
| 1729 | << "\n from " << antiprotonLowEnergy / keV << " keV "
|
|---|
| 1730 | << " to " << antiprotonHighEnergy / MeV << " MeV " << "." << G4endl ;
|
|---|
| 1731 | if(theBarkas){
|
|---|
| 1732 | G4cout << " Parametrization of the Barkas effect is switched on."
|
|---|
| 1733 | << G4endl ;
|
|---|
| 1734 | }
|
|---|
| 1735 | if(nStopping) {
|
|---|
| 1736 | G4cout << " Nuclear stopping power model is " << theNuclearTable
|
|---|
| 1737 | << G4endl ;
|
|---|
| 1738 | }
|
|---|
| 1739 |
|
|---|
| 1740 | G4bool printHead = true;
|
|---|
| 1741 |
|
|---|
| 1742 | const G4ProductionCutsTable* theCoupleTable=
|
|---|
| 1743 | G4ProductionCutsTable::GetProductionCutsTable();
|
|---|
| 1744 | size_t numOfCouples = theCoupleTable->GetTableSize();
|
|---|
| 1745 |
|
|---|
| 1746 | // loop for materials
|
|---|
| 1747 |
|
|---|
| 1748 | for (size_t j=0 ; j < numOfCouples; j++) {
|
|---|
| 1749 |
|
|---|
| 1750 | const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(j);
|
|---|
| 1751 | const G4Material* material= couple->GetMaterial();
|
|---|
| 1752 | G4double deltaCutNow = cutForDelta[(couple->GetIndex())] ;
|
|---|
| 1753 | G4double excitationEnergy = material->GetIonisation()->GetMeanExcitationEnergy();
|
|---|
| 1754 |
|
|---|
| 1755 | if(excitationEnergy > deltaCutNow) {
|
|---|
| 1756 | if(printHead) {
|
|---|
| 1757 | printHead = false ;
|
|---|
| 1758 |
|
|---|
| 1759 | G4cout << " material min.delta energy(keV) " << G4endl;
|
|---|
| 1760 | G4cout << G4endl;
|
|---|
| 1761 | }
|
|---|
| 1762 |
|
|---|
| 1763 | G4cout << std::setw(20) << material->GetName()
|
|---|
| 1764 | << std::setw(15) << excitationEnergy/keV << G4endl;
|
|---|
| 1765 | }
|
|---|
| 1766 | }
|
|---|
| 1767 | }
|
|---|