G4LivermorePolarizedRayleighModel.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: Sebastien Incerti
00029 //         30 October 2008
00030 //         on base of G4LowEnergyPolarizedRayleigh developed by R. Capra
00031 //
00032 // History:
00033 // --------
00034 // 02 May 2009   S Incerti as V. Ivanchenko proposed in G4LivermoreRayleighModel.cc
00035 //
00036 // Cleanup initialisation and generation of secondaries:
00037 //                  - apply internal high-energy limit only in constructor 
00038 //                  - do not apply low-energy limit (default is 0)
00039 //                  - remove GetMeanFreePath method and table
00040 //                  - remove initialisation of element selector 
00041 //                  - use G4ElementSelector
00042 
00043 #include "G4LivermorePolarizedRayleighModel.hh"
00044 #include "G4PhysicalConstants.hh"
00045 #include "G4SystemOfUnits.hh"
00046 
00047 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00048 
00049 using namespace std;
00050 
00051 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00052 
00053 G4LivermorePolarizedRayleighModel::G4LivermorePolarizedRayleighModel(const G4ParticleDefinition*,
00054                                              const G4String& nam)
00055   :G4VEmModel(nam),fParticleChange(0),isInitialised(false),
00056    crossSectionHandler(0),formFactorData(0)
00057 {
00058   lowEnergyLimit = 250 * eV; 
00059   highEnergyLimit = 100 * GeV;
00060   
00061   //SetLowEnergyLimit(lowEnergyLimit);
00062   SetHighEnergyLimit(highEnergyLimit);
00063   //
00064   verboseLevel= 0;
00065   // Verbosity scale:
00066   // 0 = nothing 
00067   // 1 = warning for energy non-conservation 
00068   // 2 = details of energy budget
00069   // 3 = calculation of cross sections, file openings, sampling of atoms
00070   // 4 = entering in methods
00071 
00072   if(verboseLevel > 0) {
00073     G4cout << "Livermore Polarized Rayleigh is constructed " << G4endl
00074          << "Energy range: "
00075          << lowEnergyLimit / eV << " eV - "
00076          << highEnergyLimit / GeV << " GeV"
00077          << G4endl;
00078   }
00079 }
00080 
00081 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00082 
00083 G4LivermorePolarizedRayleighModel::~G4LivermorePolarizedRayleighModel()
00084 {  
00085   if (crossSectionHandler) delete crossSectionHandler;
00086   if (formFactorData) delete formFactorData;
00087 }
00088 
00089 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00090 
00091 void G4LivermorePolarizedRayleighModel::Initialise(const G4ParticleDefinition* particle,
00092                                        const G4DataVector& cuts)
00093 {
00094 // Rayleigh process:                      The Quantum Theory of Radiation
00095 //                                        W. Heitler,       Oxford at the Clarendon Press, Oxford (1954)                                                 
00096 // Scattering function:                   A simple model of photon transport
00097 //                                        D.E. Cullen,      Nucl. Instr. Meth. in Phys. Res. B 101 (1995) 499-510                                       
00098 // Polarization of the outcoming photon:  Beam test of a prototype detector array for the PoGO astronomical hard X-ray/soft gamma-ray polarimeter
00099 //                                        T. Mizuno et al., Nucl. Instr. Meth. in Phys. Res. A 540 (2005) 158-168                                        
00100 
00101   if (verboseLevel > 3)
00102     G4cout << "Calling G4LivermorePolarizedRayleighModel::Initialise()" << G4endl;
00103 
00104   if (crossSectionHandler)
00105   {
00106     crossSectionHandler->Clear();
00107     delete crossSectionHandler;
00108   }
00109   
00110   // Read data files for all materials
00111 
00112   crossSectionHandler = new G4CrossSectionHandler;
00113   crossSectionHandler->Clear();
00114   G4String crossSectionFile = "rayl/re-cs-";
00115   crossSectionHandler->LoadData(crossSectionFile);
00116 
00117   G4VDataSetAlgorithm* ffInterpolation = new G4LogLogInterpolation;
00118   G4String formFactorFile = "rayl/re-ff-";
00119   formFactorData = new G4CompositeEMDataSet(ffInterpolation,1.,1.);
00120   formFactorData->LoadData(formFactorFile);
00121 
00122   InitialiseElementSelectors(particle,cuts);
00123 
00124   //
00125   if (verboseLevel > 2) 
00126     G4cout << "Loaded cross section files for Livermore Polarized Rayleigh model" << G4endl;
00127 
00128   InitialiseElementSelectors(particle,cuts);
00129 
00130   if (verboseLevel > 0) { 
00131     G4cout << "Livermore Polarized Rayleigh model is initialized " << G4endl
00132          << "Energy range: "
00133          << LowEnergyLimit() / eV << " eV - "
00134          << HighEnergyLimit() / GeV << " GeV"
00135          << G4endl;
00136          }
00137 
00138   if(isInitialised) return;
00139   fParticleChange = GetParticleChangeForGamma();
00140   isInitialised = true;
00141 }
00142 
00143 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00144 
00145 G4double G4LivermorePolarizedRayleighModel::ComputeCrossSectionPerAtom(
00146                                        const G4ParticleDefinition*,
00147                                              G4double GammaEnergy,
00148                                              G4double Z, G4double,
00149                                              G4double, G4double)
00150 {
00151   if (verboseLevel > 3)
00152     G4cout << "Calling CrossSectionPerAtom() of G4LivermorePolarizedRayleighModel" << G4endl;
00153 
00154   if (GammaEnergy < lowEnergyLimit || GammaEnergy > highEnergyLimit) return 0.0;
00155 
00156   G4double cs = crossSectionHandler->FindValue(G4int(Z), GammaEnergy);
00157   return cs;
00158 }
00159 
00160 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00161 
00162 void G4LivermorePolarizedRayleighModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
00163                                               const G4MaterialCutsCouple* couple,
00164                                               const G4DynamicParticle* aDynamicGamma,
00165                                               G4double,
00166                                               G4double)
00167 {
00168   if (verboseLevel > 3)
00169     G4cout << "Calling SampleSecondaries() of G4LivermorePolarizedRayleighModel" << G4endl;
00170 
00171   G4double photonEnergy0 = aDynamicGamma->GetKineticEnergy();
00172   
00173   if (photonEnergy0 <= lowEnergyLimit)
00174   {
00175       fParticleChange->ProposeTrackStatus(fStopAndKill);
00176       fParticleChange->SetProposedKineticEnergy(0.);
00177       fParticleChange->ProposeLocalEnergyDeposit(photonEnergy0);
00178       return ;
00179   }
00180 
00181   G4ParticleMomentum photonDirection0 = aDynamicGamma->GetMomentumDirection();
00182 
00183   // Select randomly one element in the current material
00184   // G4int Z = crossSectionHandler->SelectRandomAtom(couple,photonEnergy0);
00185   const G4ParticleDefinition* particle =  aDynamicGamma->GetDefinition();
00186   const G4Element* elm = SelectRandomAtom(couple,particle,photonEnergy0);
00187   G4int Z = (G4int)elm->GetZ();
00188 
00189   G4double outcomingPhotonCosTheta = GenerateCosTheta(photonEnergy0, Z);
00190   G4double outcomingPhotonPhi = GeneratePhi(outcomingPhotonCosTheta);
00191   G4double beta=GeneratePolarizationAngle();
00192  
00193   // incomingPhoton reference frame:
00194   // z = versor parallel to the incomingPhotonDirection
00195   // x = versor parallel to the incomingPhotonPolarization
00196   // y = defined as z^x
00197  
00198   // outgoingPhoton reference frame:
00199   // z' = versor parallel to the outgoingPhotonDirection
00200   // x' = defined as x-x*z'z' normalized
00201   // y' = defined as z'^x'
00202  
00203   G4ThreeVector z(aDynamicGamma->GetMomentumDirection().unit()); 
00204   G4ThreeVector x(GetPhotonPolarization(*aDynamicGamma));
00205   G4ThreeVector y(z.cross(x));
00206  
00207   // z' = std::cos(phi)*std::sin(theta) x + std::sin(phi)*std::sin(theta) y + std::cos(theta) z
00208   G4double xDir;
00209   G4double yDir;
00210   G4double zDir;
00211   zDir=outcomingPhotonCosTheta;
00212   xDir=std::sqrt(1-outcomingPhotonCosTheta*outcomingPhotonCosTheta);
00213   yDir=xDir;
00214   xDir*=std::cos(outcomingPhotonPhi);
00215   yDir*=std::sin(outcomingPhotonPhi);
00216  
00217   G4ThreeVector zPrime((xDir*x + yDir*y + zDir*z).unit());
00218   G4ThreeVector xPrime(x.perpPart(zPrime).unit());
00219   G4ThreeVector yPrime(zPrime.cross(xPrime));
00220  
00221   // outgoingPhotonPolarization is directed as x' std::cos(beta) + y' std::sin(beta)
00222   G4ThreeVector outcomingPhotonPolarization(xPrime*std::cos(beta) + yPrime*std::sin(beta));
00223  
00224   fParticleChange->ProposeMomentumDirection(zPrime);
00225   fParticleChange->ProposePolarization(outcomingPhotonPolarization);
00226   fParticleChange->SetProposedKineticEnergy(photonEnergy0); 
00227 
00228 }
00229 
00230 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00231 
00232 G4double G4LivermorePolarizedRayleighModel::GenerateCosTheta(G4double incomingPhotonEnergy, G4int zAtom) const
00233 {
00234   //  d sigma                                                                    k0
00235   // --------- =  r0^2 * pi * F^2(x, Z) * ( 2 - sin^2 theta) * std::sin (theta), x = ---- std::sin(theta/2)
00236   //  d theta                                                                    hc
00237  
00238   //  d sigma                                             k0          1 - y
00239   // --------- = r0^2 * pi * F^2(x, Z) * ( 1 + y^2), x = ---- std::sqrt ( ------- ), y = std::cos(theta)
00240   //    d y                                               hc            2
00241 
00242   //              Z
00243   // F(x, Z) ~ --------
00244   //            a + bx
00245   //
00246   // The time to exit from the outer loop grows as ~ k0
00247   // On pcgeant2 the time is ~ 1 s for k0 ~ 1 MeV on the oxygen element. A 100 GeV
00248   // event will take ~ 10 hours.
00249   //
00250   // On the avarage the inner loop does 1.5 iterations before exiting
00251  
00252   const G4double xFactor = (incomingPhotonEnergy*cm)/(h_Planck*c_light);
00253   //const G4VEMDataSet * formFactorData = GetScatterFunctionData();
00254 
00255   G4double cosTheta;
00256   G4double fCosTheta;
00257   G4double x;
00258   G4double fValue;
00259 
00260   if (incomingPhotonEnergy > 5.*MeV)
00261   {
00262     cosTheta = 1.;
00263   }
00264   else
00265   {
00266     do
00267     {
00268       do
00269         {
00270           cosTheta = 2.*G4UniformRand()-1.;
00271           fCosTheta = (1.+cosTheta*cosTheta)/2.;
00272         }
00273       while (fCosTheta < G4UniformRand());
00274   
00275       x = xFactor*std::sqrt((1.-cosTheta)/2.);
00276   
00277       if (x > 1.e+005)
00278         fValue = formFactorData->FindValue(x, zAtom-1);
00279       else
00280         fValue = formFactorData->FindValue(0., zAtom-1);
00281    
00282       fValue/=zAtom;
00283       fValue*=fValue;
00284     }
00285     while(fValue < G4UniformRand());
00286   }
00287 
00288   return cosTheta;
00289 }
00290 
00291 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00292 
00293 G4double G4LivermorePolarizedRayleighModel::GeneratePhi(G4double cosTheta) const
00294 {
00295   //  d sigma
00296   // --------- = alpha * ( 1 - sin^2 (theta) * cos^2 (phi) )
00297   //   d phi
00298  
00299   // On the average the loop takes no more than 2 iterations before exiting 
00300 
00301   G4double phi;
00302   G4double cosPhi;
00303   G4double phiProbability;
00304   G4double sin2Theta;
00305  
00306   sin2Theta=1.-cosTheta*cosTheta;
00307  
00308   do
00309     {
00310       phi = twopi * G4UniformRand();
00311       cosPhi = std::cos(phi);
00312       phiProbability= 1. - sin2Theta*cosPhi*cosPhi;
00313     }
00314   while (phiProbability < G4UniformRand());
00315  
00316   return phi;
00317 }
00318 
00319 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00320 
00321 G4double G4LivermorePolarizedRayleighModel::GeneratePolarizationAngle(void) const
00322 {
00323   // Rayleigh polarization is always on the x' direction
00324 
00325   return 0;
00326 }
00327 
00328 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
00329 
00330 G4ThreeVector G4LivermorePolarizedRayleighModel::GetPhotonPolarization(const G4DynamicParticle&  photon)
00331 {
00332 
00333 // SI - From G4VLowEnergyDiscretePhotonProcess.cc
00334  
00335   G4ThreeVector photonMomentumDirection;
00336   G4ThreeVector photonPolarization;
00337 
00338   photonPolarization = photon.GetPolarization(); 
00339   photonMomentumDirection = photon.GetMomentumDirection();
00340 
00341   if ((!photonPolarization.isOrthogonal(photonMomentumDirection, 1e-6)) || photonPolarization.mag()==0.)
00342     {
00343       // if |photonPolarization|==0. or |photonPolarization * photonDirection0| > 1e-6 * |photonPolarization ^ photonDirection0|
00344       // then polarization is choosen randomly.
00345   
00346       G4ThreeVector e1(photonMomentumDirection.orthogonal().unit());
00347       G4ThreeVector e2(photonMomentumDirection.cross(e1).unit());
00348   
00349       G4double angle(G4UniformRand() * twopi);
00350   
00351       e1*=std::cos(angle);
00352       e2*=std::sin(angle);
00353   
00354       photonPolarization=e1+e2;
00355     }
00356   else if (photonPolarization.howOrthogonal(photonMomentumDirection) != 0.)
00357     {
00358       // if |photonPolarization * photonDirection0| != 0.
00359       // then polarization is made orthonormal;
00360   
00361       photonPolarization=photonPolarization.perpPart(photonMomentumDirection);
00362     }
00363  
00364   return photonPolarization.unit();
00365 }
00366 

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