G4LivermoreBremsstrahlungModel.cc

Go to the documentation of this file.
00001 //
00002 // ********************************************************************
00003 // * License and Disclaimer                                           *
00004 // *                                                                  *
00005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
00006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
00007 // * conditions of the Geant4 Software License,  included in the file *
00008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
00009 // * include a list of copyright holders.                             *
00010 // *                                                                  *
00011 // * Neither the authors of this software system, nor their employing *
00012 // * institutes,nor the agencies providing financial support for this *
00013 // * work  make  any representation or  warranty, express or implied, *
00014 // * regarding  this  software system or assume any liability for its *
00015 // * use.  Please see the license in the file  LICENSE  and URL above *
00016 // * for the full disclaimer and the limitation of liability.         *
00017 // *                                                                  *
00018 // * This  code  implementation is the result of  the  scientific and *
00019 // * technical work of the GEANT4 collaboration.                      *
00020 // * By using,  copying,  modifying or  distributing the software (or *
00021 // * any work based  on the software)  you  agree  to acknowledge its *
00022 // * use  in  resulting  scientific  publications,  and indicate your *
00023 // * acceptance of all terms of the Geant4 Software license.          *
00024 // ********************************************************************
00025 //
00026 // $Id$
00027 //
00028 // Author: Luciano Pandola
00029 //         on base of G4LowEnergyBremsstrahlung developed by A.Forti and V.Ivanchenko
00030 //
00031 // History:
00032 // --------
00033 // 03 Mar 2009   L Pandola    Migration from process to model 
00034 // 12 Apr 2009   V Ivanchenko Cleanup initialisation and generation of secondaries:
00035 //                  - apply internal high-energy limit only in constructor 
00036 //                  - do not apply low-energy limit (default is 0)
00037 //                  - added MinEnergyCut method
00038 //                  - do not change track status
00039 //                  - do not initialize element selectors
00040 //                  - use cut value from the interface 
00041 //                  - fixed bug in sampling of angles between keV and MeV
00042 // 19 May 2009   L Pandola    Explicitely set to zero pointers deleted in 
00043 //                            Initialise(), since they might be checked later on
00044 //
00045 
00046 #include "G4LivermoreBremsstrahlungModel.hh"
00047 #include "G4PhysicalConstants.hh"
00048 #include "G4SystemOfUnits.hh"
00049 #include "G4ParticleDefinition.hh"
00050 #include "G4MaterialCutsCouple.hh"
00051 
00052 #include "G4DynamicParticle.hh"
00053 #include "G4Element.hh"
00054 #include "G4Gamma.hh"
00055 #include "G4Electron.hh"
00056 #include "G4SemiLogInterpolation.hh"
00057 //
00058 #include "G4VEmAngularDistribution.hh"
00059 #include "G4ModifiedTsai.hh"
00060 #include "G4Generator2BS.hh"
00061 //#include "G4Generator2BN.hh"
00062 //
00063 #include "G4BremsstrahlungCrossSectionHandler.hh"
00064 //
00065 #include "G4VEnergySpectrum.hh"
00066 #include "G4eBremsstrahlungSpectrum.hh"
00067 #include "G4VEMDataSet.hh"
00068 
00069 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00070 
00071 
00072 G4LivermoreBremsstrahlungModel::G4LivermoreBremsstrahlungModel(const G4ParticleDefinition*,
00073                                                                const G4String& nam)
00074   :G4VEmModel(nam),fParticleChange(0),isInitialised(false),
00075    crossSectionHandler(0),energySpectrum(0)
00076 {
00077   fIntrinsicLowEnergyLimit = 10.0*eV;
00078   fIntrinsicHighEnergyLimit = 100.0*GeV;
00079   fNBinEnergyLoss = 360;
00080   //  SetLowEnergyLimit(fIntrinsicLowEnergyLimit);
00081   SetHighEnergyLimit(fIntrinsicHighEnergyLimit);
00082   //
00083   verboseLevel = 0;
00084   SetAngularDistribution(new G4Generator2BS());
00085   //
00086   //generatorName = "tsai";
00087   //angularDistribution = new G4ModifiedTsai("TsaiGenerator"); //default generator
00088   //
00089   //TsaiAngularDistribution = new G4ModifiedTsai("TsaiGenerator");
00090   //
00091 }
00092 
00093 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00094 
00095 G4LivermoreBremsstrahlungModel::~G4LivermoreBremsstrahlungModel()
00096 {
00097   if (crossSectionHandler) delete crossSectionHandler;
00098   if (energySpectrum) delete energySpectrum;
00099   energyBins.clear();
00100   //delete angularDistribution;
00101   //delete TsaiAngularDistribution;
00102 }
00103 
00104 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00105 
00106 void G4LivermoreBremsstrahlungModel::Initialise(const G4ParticleDefinition* particle,
00107                                                 const G4DataVector& cuts)
00108 {
00109   //Check that the Livermore Bremsstrahlung is NOT attached to e+
00110   if (particle != G4Electron::Electron())
00111     {
00112       G4Exception("G4LivermoreBremsstrahlungModel::Initialise",
00113                     "em0002",FatalException,"Livermore Bremsstrahlung Model is applicable only to electrons");
00114     }
00115   //Prepare energy spectrum
00116   if (energySpectrum) 
00117     {
00118       delete energySpectrum;
00119       energySpectrum = 0;
00120     }
00121 
00122   energyBins.clear();
00123   for(size_t i=0; i<15; i++) 
00124     {
00125       G4double x = 0.1*((G4double)i);
00126       if(i == 0)  x = 0.01;
00127       if(i == 10) x = 0.95;
00128       if(i == 11) x = 0.97;
00129       if(i == 12) x = 0.99;
00130       if(i == 13) x = 0.995;
00131       if(i == 14) x = 1.0;
00132       energyBins.push_back(x);
00133     }
00134   const G4String dataName("/brem/br-sp.dat");
00135   energySpectrum = new G4eBremsstrahlungSpectrum(energyBins,dataName);
00136   
00137   if (verboseLevel > 0)
00138     G4cout << "G4eBremsstrahlungSpectrum is initialized" << G4endl;
00139 
00140   //Initialize cross section handler
00141   if (crossSectionHandler) 
00142     {
00143       delete crossSectionHandler;
00144       crossSectionHandler = 0;
00145     }
00146   G4VDataSetAlgorithm* interpolation = 0;//new G4SemiLogInterpolation();
00147   crossSectionHandler = new G4BremsstrahlungCrossSectionHandler(energySpectrum,interpolation);
00148   crossSectionHandler->Initialise(0,LowEnergyLimit(),HighEnergyLimit(),
00149                                   fNBinEnergyLoss);
00150   crossSectionHandler->Clear();
00151   crossSectionHandler->LoadShellData("brem/br-cs-");
00152   //This is used to retrieve cross section values later on
00153   G4VEMDataSet* p = crossSectionHandler->BuildMeanFreePathForMaterials(&cuts);
00154   delete p;  
00155  
00156   if (verboseLevel > 0)
00157     {
00158       G4cout << "Livermore Bremsstrahlung model is initialized " << G4endl
00159              << "Energy range: "
00160              << LowEnergyLimit() / keV << " keV - "
00161              << HighEnergyLimit() / GeV << " GeV"
00162              << G4endl;
00163     }
00164 
00165   if (verboseLevel > 1)
00166     {
00167       G4cout << "Cross section data: " << G4endl; 
00168       crossSectionHandler->PrintData();
00169       G4cout << "Parameters: " << G4endl;
00170       energySpectrum->PrintData();
00171     }
00172 
00173   if(isInitialised) return;
00174   fParticleChange = GetParticleChangeForLoss();
00175   isInitialised = true; 
00176 }
00177 
00178 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00179 
00180 G4double G4LivermoreBremsstrahlungModel::MinEnergyCut(const G4ParticleDefinition*,
00181                                                       const G4MaterialCutsCouple*)
00182 {
00183   return 250.*eV;
00184 }
00185 
00186 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00187 
00188 G4double 
00189 G4LivermoreBremsstrahlungModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
00190                                                            G4double energy,
00191                                                            G4double Z, G4double,
00192                                                            G4double cutEnergy, 
00193                                                            G4double)
00194 {
00195   G4int iZ = (G4int) Z;
00196   if (!crossSectionHandler)
00197     {
00198       G4Exception("G4LivermoreBremsstrahlungModel::ComputeCrossSectionPerAtom",
00199                     "em1007",FatalException,"The cross section handler is not correctly initialized");
00200       return 0;
00201     }
00202   
00203   //The cut is already included in the crossSectionHandler
00204   G4double cs = 
00205     crossSectionHandler->GetCrossSectionAboveThresholdForElement(energy,cutEnergy,iZ);
00206 
00207   if (verboseLevel > 1)
00208     {
00209       G4cout << "G4LivermoreBremsstrahlungModel " << G4endl;
00210       G4cout << "Cross section for gamma emission > " << cutEnergy/keV << " keV at " <<
00211         energy/keV << " keV and Z = " << iZ << " --> " << cs/barn << " barn" << G4endl;
00212     }
00213   return cs;
00214 }
00215 
00216 
00217 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00218 
00219 G4double G4LivermoreBremsstrahlungModel::ComputeDEDXPerVolume(const G4Material* material,
00220                                            const G4ParticleDefinition* ,
00221                                            G4double kineticEnergy,
00222                                            G4double cutEnergy)
00223 {
00224   G4double sPower = 0.0;
00225 
00226   const G4ElementVector* theElementVector = material->GetElementVector();
00227   size_t NumberOfElements = material->GetNumberOfElements() ;
00228   const G4double* theAtomicNumDensityVector =
00229                     material->GetAtomicNumDensityVector();
00230 
00231   // loop for elements in the material
00232   for (size_t iel=0; iel<NumberOfElements; iel++ ) 
00233     {
00234       G4int iZ = (G4int)((*theElementVector)[iel]->GetZ());
00235       G4double e = energySpectrum->AverageEnergy(iZ, 0.0,cutEnergy,
00236                                                  kineticEnergy);
00237       G4double cs= crossSectionHandler->FindValue(iZ,kineticEnergy);
00238       sPower   += e * cs * theAtomicNumDensityVector[iel];
00239     }
00240 
00241   if (verboseLevel > 2)
00242     {
00243       G4cout << "G4LivermoreBremsstrahlungModel " << G4endl;
00244       G4cout << "Stopping power < " << cutEnergy/keV << " keV at " << 
00245         kineticEnergy/keV << " keV = " << sPower/(keV/mm) << " keV/mm" << G4endl;
00246     }
00247     
00248   return sPower;
00249 }
00250 
00251 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00252 
00253 void G4LivermoreBremsstrahlungModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
00254                                               const G4MaterialCutsCouple* couple,
00255                                               const G4DynamicParticle* aDynamicParticle,
00256                                               G4double energyCut,
00257                                               G4double)
00258 {
00259   
00260   G4double kineticEnergy = aDynamicParticle->GetKineticEnergy();
00261 
00262   // this is neede for pathalogical cases of no ionisation
00263   if (kineticEnergy <= fIntrinsicLowEnergyLimit)
00264     {
00265       fParticleChange->SetProposedKineticEnergy(0.);
00266       fParticleChange->ProposeLocalEnergyDeposit(kineticEnergy);
00267       return;
00268     }
00269 
00270   //Sample material
00271   G4int Z = crossSectionHandler->SelectRandomAtom(couple, kineticEnergy);
00272 
00273   //Sample gamma energy
00274   G4double tGamma = energySpectrum->SampleEnergy(Z, energyCut, kineticEnergy, kineticEnergy);
00275   //nothing happens
00276   if (tGamma == 0.) { return; }
00277 
00278   G4double totalEnergy = kineticEnergy + electron_mass_c2;
00279   G4double finalEnergy = kineticEnergy - tGamma; // electron final energy  
00280 
00281   //Sample gamma direction
00282   G4ThreeVector gammaDirection = 
00283     GetAngularDistribution()->SampleDirection(aDynamicParticle, 
00284                                               totalEnergy-tGamma,
00285                                               Z, 
00286                                               couple->GetMaterial());
00287 
00288   G4ThreeVector electronDirection = aDynamicParticle->GetMomentumDirection();
00289 
00290   //Update the incident particle    
00291   if (finalEnergy < 0.) 
00292     {
00293       // Kinematic problem
00294       tGamma = kineticEnergy;
00295       fParticleChange->SetProposedKineticEnergy(0.);
00296     }
00297   else
00298     {
00299       G4double momentum = std::sqrt((totalEnergy + electron_mass_c2)*kineticEnergy);
00300       G4double finalX = momentum*electronDirection.x() - tGamma*gammaDirection.x();
00301       G4double finalY = momentum*electronDirection.y() - tGamma*gammaDirection.y();
00302       G4double finalZ = momentum*electronDirection.z() - tGamma*gammaDirection.z();
00303       G4double norm = 1./std::sqrt(finalX*finalX + finalY*finalY + finalZ*finalZ);
00304       
00305       fParticleChange->ProposeMomentumDirection(finalX*norm, finalY*norm, finalZ*norm);
00306       fParticleChange->SetProposedKineticEnergy(finalEnergy);
00307     }
00308 
00309   //Generate the bremsstrahlung gamma
00310   G4DynamicParticle* aGamma= new G4DynamicParticle (G4Gamma::Gamma(),
00311                                                     gammaDirection, tGamma);
00312   fvect->push_back(aGamma);
00313 
00314   if (verboseLevel > 1)
00315     {
00316       G4cout << "-----------------------------------------------------------" << G4endl;
00317       G4cout << "Energy balance from G4LivermoreBremsstrahlung" << G4endl;
00318       G4cout << "Incoming primary energy: " << kineticEnergy/keV << " keV" << G4endl;
00319       G4cout << "-----------------------------------------------------------" << G4endl;
00320       G4cout << "Outgoing primary energy: " << finalEnergy/keV << " keV" << G4endl;
00321       G4cout << "Gamma ray " << tGamma/keV << " keV" << G4endl;
00322       G4cout << "Total final state: " << (finalEnergy+tGamma)/keV << " keV" << G4endl;
00323       G4cout << "-----------------------------------------------------------" << G4endl;
00324     }
00325   if (verboseLevel > 0)
00326     {
00327       G4double energyDiff = std::fabs(finalEnergy+tGamma-kineticEnergy);
00328       if (energyDiff > 0.05*keV)
00329         G4cout << "G4LivermoreBremsstrahlung WARNING: problem with energy conservation: " 
00330                << (finalEnergy+tGamma)/keV << " keV (final) vs. " 
00331                << kineticEnergy/keV << " keV (initial)" << G4endl;
00332     }
00333   return;
00334 }
00335 
00336 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00337 /*
00338 void 
00339 G4LivermoreBremsstrahlungModel::SetAngularGenerator(G4VBremAngularDistribution* distribution)
00340 {
00341   if(angularDistribution == distribution) return;
00342   if(angularDistribution) delete angularDistribution;
00343   angularDistribution = distribution;
00344   angularDistribution->PrintGeneratorInformation();
00345 }
00346 */
00347 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00348  /*
00349 void G4LivermoreBremsstrahlungModel::SetAngularGenerator(const G4String& theGenName)
00350 {
00351   if(theGenName == generatorName) return;
00352   if (theGenName == "tsai") 
00353     {
00354       delete angularDistribution;
00355       angularDistribution = new G4ModifiedTsai("TsaiGenerator");
00356       generatorName = theGenName;
00357     }
00358   else if (theGenName == "2bn")
00359     {
00360       delete angularDistribution;
00361       angularDistribution = new G4Generator2BN("2BNGenerator");
00362       generatorName = theGenName;
00363     }
00364   else if (theGenName == "2bs")
00365     {
00366       delete angularDistribution;
00367       angularDistribution = new G4Generator2BS("2BSGenerator");
00368       generatorName = theGenName;
00369     }
00370   else
00371     {
00372       G4cout << "### G4LivermoreBremsstrahlungModel::SetAngularGenerator WARNING:"
00373              << " generator <" << theGenName << "> is not known" << G4endl;
00374       return; 
00375 
00376     }
00377 
00378   angularDistribution->PrintGeneratorInformation();
00379 }
00380  */

Generated on Mon May 27 17:48:48 2013 for Geant4 by  doxygen 1.4.7