Files
geant4/source/processes/electromagnetic/lowenergy/src/G4BoldyshevTripletModel.cc
T
2016-06-09 17:01:34 +02:00

343 lines
12 KiB
C++

//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id$
// GEANT4 tag $Name: $
//
//
// Author: Gerardo Depaola & Francesco Longo
//
// History:
// --------
// 23-06-2010 First implementation as model
#include "G4BoldyshevTripletModel.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BoldyshevTripletModel::G4BoldyshevTripletModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),fParticleChange(0),smallEnergy(4.*MeV),isInitialised(false),
crossSectionHandler(0),meanFreePathTable(0)
{
lowEnergyLimit = 4.0*electron_mass_c2;
highEnergyLimit = 100 * GeV;
SetHighEnergyLimit(highEnergyLimit);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if(verboseLevel > 0) {
G4cout << "Triplet Gamma conversion is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / MeV << " MeV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4BoldyshevTripletModel::~G4BoldyshevTripletModel()
{
if (crossSectionHandler) delete crossSectionHandler;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void
G4BoldyshevTripletModel::Initialise(const G4ParticleDefinition*,
const G4DataVector&)
{
if (verboseLevel > 3)
G4cout << "Calling G4BoldyshevTripletModel::Initialise()" << G4endl;
if (crossSectionHandler)
{
crossSectionHandler->Clear();
delete crossSectionHandler;
}
// Read data tables for all materials
crossSectionHandler = new G4CrossSectionHandler();
crossSectionHandler->Initialise(0,lowEnergyLimit,100.*GeV,400);
G4String crossSectionFile = "tripdata/pp-trip-cs-"; // here only pair in electron field cs should be used
crossSectionHandler->LoadData(crossSectionFile);
//
if (verboseLevel > 0) {
G4cout << "Loaded cross section files for Livermore GammaConversion" << G4endl;
G4cout << "To obtain the total cross section this should be used only " << G4endl
<< "in connection with G4NuclearGammaConversion " << G4endl;
}
if (verboseLevel > 0) {
G4cout << "Livermore Electron Gamma Conversion model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / MeV << " MeV - "
<< HighEnergyLimit() / GeV << " GeV"
<< G4endl;
}
if(isInitialised) return;
fParticleChange = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double
G4BoldyshevTripletModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
G4double GammaEnergy,
G4double Z, G4double,
G4double, G4double)
{
if (verboseLevel > 3) {
G4cout << "Calling ComputeCrossSectionPerAtom() of G4BoldyshevTripletModel"
<< G4endl;
}
if (GammaEnergy < lowEnergyLimit || GammaEnergy > highEnergyLimit) return 0;
G4double cs = crossSectionHandler->FindValue(G4int(Z), GammaEnergy);
return cs;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4BoldyshevTripletModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* ,
const G4DynamicParticle* aDynamicGamma,
G4double,
G4double)
{
// The energies of the secondary particles are sampled using
// a modified Wheeler-Lamb model (see PhysRevD 7 (1973), 26)
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4BoldyshevTripletModel" << G4endl;
G4double photonEnergy = aDynamicGamma->GetKineticEnergy();
G4ParticleMomentum photonDirection = aDynamicGamma->GetMomentumDirection();
G4double epsilon ;
G4double p0 = electron_mass_c2;
G4double positronTotEnergy, electronTotEnergy, thetaEle, thetaPos;
G4double ener_re=0., theta_re, phi_re, phi;
// Calculo de theta - elecron de recoil
G4double energyThreshold = sqrt(2.)*electron_mass_c2; // -> momentumThreshold_N = 1
energyThreshold = 1.1*electron_mass_c2;
// G4cout << energyThreshold << G4endl;
G4double momentumThreshold_c = sqrt(energyThreshold * energyThreshold - electron_mass_c2*electron_mass_c2); // momentun in MeV/c unit
G4double momentumThreshold_N = momentumThreshold_c/electron_mass_c2; // momentun in mc unit
// Calculation of recoil electron production
G4double SigmaTot = (28./9.) * std::log ( 2.* photonEnergy / electron_mass_c2 ) - 218. / 27. ;
G4double X_0 = 2. * ( sqrt(momentumThreshold_N*momentumThreshold_N + 1) -1 );
G4double SigmaQ = (82./27. - (14./9.) * log (X_0) + 4./15.*X_0 - 0.0348 * X_0 * X_0);
G4double recoilProb = G4UniformRand();
//G4cout << "SIGMA TOT " << SigmaTot << " " << "SigmaQ " << SigmaQ << " " << SigmaQ/SigmaTot << " " << recoilProb << G4endl;
if (recoilProb >= SigmaQ/SigmaTot) // create electron recoil
{
G4double cosThetaMax = ( ( energyThreshold - electron_mass_c2 ) / (momentumThreshold_c) + electron_mass_c2*
( energyThreshold + electron_mass_c2 ) / (photonEnergy*momentumThreshold_c) );
if (cosThetaMax > 1) G4cout << "ERRORE " << G4endl;
G4double r1;
G4double r2;
G4double are, bre, loga, f1_re, greject, cost;
do {
r1 = G4UniformRand();
r2 = G4UniformRand();
// cost = (pow(4./enern,0.5*r1)) ;
cost = pow(cosThetaMax,r1);
theta_re = acos(cost);
are = 1./(14.*cost*cost);
bre = (1.-5.*cost*cost)/(2.*cost);
loga = log((1.+ cost)/(1.- cost));
f1_re = 1. - bre*loga;
if ( theta_re >= 4.47*CLHEP::pi/180.)
{
greject = are*f1_re;
} else {
greject = 1. ;
}
} while(greject < r2);
// Calculo de phi - elecron de recoil
G4double r3, r4, rt;
do {
r3 = G4UniformRand();
r4 = G4UniformRand();
phi_re = twopi*r3 ;
G4double sint2 = 1. - cost*cost ;
G4double fp = 1. - sint2*loga/(2.*cost) ;
rt = (1.-cos(2.*phi_re)*fp/f1_re)/(2.*pi) ;
} while(rt < r4);
// Calculo de la energia - elecron de recoil - relacion momento maximo <-> angulo
G4double S = electron_mass_c2*(2.* photonEnergy + electron_mass_c2);
G4double D2 = 4.*S * electron_mass_c2*electron_mass_c2
+ (S - electron_mass_c2*electron_mass_c2)
*(S - electron_mass_c2*electron_mass_c2)*sin(theta_re)*sin(theta_re);
ener_re = electron_mass_c2 * (S + electron_mass_c2*electron_mass_c2)/sqrt(D2);
// G4cout << "electron de retroceso " << ener_re << " " << theta_re << " " << phi_re << G4endl;
// Recoil electron creation
G4double dxEle_re=sin(theta_re)*std::cos(phi_re),dyEle_re=sin(theta_re)*std::sin(phi_re), dzEle_re=cos(theta_re);
G4double electronRKineEnergy = std::max(0.,ener_re - electron_mass_c2) ;
G4ThreeVector electronRDirection (dxEle_re, dyEle_re, dzEle_re);
electronRDirection.rotateUz(photonDirection);
G4DynamicParticle* particle3 = new G4DynamicParticle (G4Electron::Electron(),
electronRDirection,
electronRKineEnergy);
fvect->push_back(particle3);
}
else
{
// deposito la energia ener_re - electron_mass_c2
// G4cout << "electron de retroceso " << ener_re << G4endl;
fParticleChange->ProposeLocalEnergyDeposit(ener_re - electron_mass_c2);
}
// Depaola (2004) suggested distribution for e+e- energy
// G4double t = 0.5*asinh(momentumThreshold_N);
G4double t = 0.5*log(momentumThreshold_N + sqrt(momentumThreshold_N*momentumThreshold_N+1));
G4cout << 0.5*asinh(momentumThreshold_N) << " " << t << G4endl;
G4double J1 = 0.5*(t*cosh(t)/sinh(t) - log(2.*sinh(t)));
G4double J2 = (-2./3.)*log(2.*sinh(t)) + t*cosh(t)/sinh(t) + (sinh(t)-t*pow(cosh(t),3))/(3.*pow(sinh(t),3));
G4double b = 2.*(J1-J2)/J1;
G4double n = 1 - b/6.;
G4double re=0.;
re = G4UniformRand();
G4double a = 0.;
G4double b1 = 16. - 3.*b - 36.*b*re*n + 36.*b*pow(re,2.)*pow(n,2.) +
6.*pow(b,2.)*re*n;
a = pow((b1/b),0.5);
G4double c1 = (-6. + 12.*re*n + b + 2*a)*pow(b,2.);
epsilon = (pow(c1,1./3.))/(2.*b) + (b-4.)/(2.*pow(c1,1./3.))+0.5;
G4double photonEnergy1 = photonEnergy - ener_re ; // resto al foton la energia del electron de retro.
positronTotEnergy = epsilon*photonEnergy1;
electronTotEnergy = photonEnergy1 - positronTotEnergy; // temporarly
G4double momento_e = sqrt(electronTotEnergy*electronTotEnergy -
electron_mass_c2*electron_mass_c2) ;
G4double momento_p = sqrt(positronTotEnergy*positronTotEnergy -
electron_mass_c2*electron_mass_c2) ;
thetaEle = acos((sqrt(p0*p0/(momento_e*momento_e) +1.)- p0/momento_e)) ;
thetaPos = acos((sqrt(p0*p0/(momento_p*momento_p) +1.)- p0/momento_p)) ;
phi = twopi * G4UniformRand();
G4double dxEle= std::sin(thetaEle)*std::cos(phi),dyEle= std::sin(thetaEle)*std::sin(phi),dzEle=std::cos(thetaEle);
G4double dxPos=-std::sin(thetaPos)*std::cos(phi),dyPos=-std::sin(thetaPos)*std::sin(phi),dzPos=std::cos(thetaPos);
// Kinematics of the created pair:
// the electron and positron are assumed to have a symetric angular
// distribution with respect to the Z axis along the parent photon
G4double electronKineEnergy = std::max(0.,electronTotEnergy - electron_mass_c2) ;
// SI - The range test has been removed wrt original G4LowEnergyGammaconversion class
G4ThreeVector electronDirection (dxEle, dyEle, dzEle);
electronDirection.rotateUz(photonDirection);
G4DynamicParticle* particle1 = new G4DynamicParticle (G4Electron::Electron(),
electronDirection,
electronKineEnergy);
// The e+ is always created (even with kinetic energy = 0) for further annihilation
G4double positronKineEnergy = std::max(0.,positronTotEnergy - electron_mass_c2) ;
// SI - The range test has been removed wrt original G4LowEnergyGammaconversion class
G4ThreeVector positronDirection (dxPos, dyPos, dzPos);
positronDirection.rotateUz(photonDirection);
// Create G4DynamicParticle object for the particle2
G4DynamicParticle* particle2 = new G4DynamicParticle(G4Positron::Positron(),
positronDirection, positronKineEnergy);
// Fill output vector
fvect->push_back(particle1);
fvect->push_back(particle2);
// kill incident photon
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeTrackStatus(fStopAndKill);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....