Import Geant4 10.7.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2020-06-26 10:23:25 +02:00
parent c02c370437
commit 67ba86d073
1871 changed files with 174422 additions and 131884 deletions
@@ -25,6 +25,8 @@
//
/*
Authors:
Updated 15 Novebmer 2019
M. Omer and R. Hajima on 17 October 2016
contact:
omer.mohamed@jaea.go.jp and hajima.ryoichi@qst.go.jp
@@ -25,6 +25,13 @@
//
/*
Authors:
Updated 15 Novebmer 2019
Updates:
1. Change reading method for cross section data.
2. Add warning not to use with polarized photons.
M. Omer and R. Hajima on 17 October 2016
contact:
omer.mohamed@jaea.go.jp and hajima.ryoichi@qst.go.jp
@@ -47,10 +54,8 @@ using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4int G4JAEAElasticScatteringModel::maxZ = 99;
G4LPhysicsFreeVector* G4JAEAElasticScatteringModel::dataCS[] ;
//Initialising an array to hold all elastic scattering data.
G4double Diff_CS_data[100][183][300];
G4LPhysicsFreeVector* G4JAEAElasticScatteringModel::dataCS[]={nullptr} ;
G4DataVector* G4JAEAElasticScatteringModel::ES_Data[]={nullptr};
G4JAEAElasticScatteringModel::G4JAEAElasticScatteringModel()
:G4VEmModel("G4JAEAElasticScatteringModel"),isInitialised(false)
@@ -77,10 +82,14 @@ G4JAEAElasticScatteringModel::G4JAEAElasticScatteringModel()
G4JAEAElasticScatteringModel::~G4JAEAElasticScatteringModel()
{
if(IsMaster()) {
for(G4int i=0; i<maxZ; ++i) {
for(G4int i=0; i<=maxZ; ++i) {
if(dataCS[i]) {
delete dataCS[i];
dataCS[i] = 0;
dataCS[i] = nullptr;
}
if (ES_Data[i]){
delete ES_Data[i];
ES_Data[i] = nullptr;
}
}
}
@@ -174,18 +183,19 @@ void G4JAEAElasticScatteringModel::ReadData(size_t Z, const char* path)
The first row is the energy, and the second row is the total cross section.
Rows from the 3rd to the 183rd are the differential cross section with an angular resolution of 1 degree.
*/
G4double ESdata[183][300];
std::ostringstream ostCS;
ostCS << datadir << "/JAEAESData/cs_Z_" << Z <<".dat";
std::ifstream alldata(ostCS.str().c_str());
if(!alldata.is_open())
ostCS << datadir << "/JAEAESData/amp_Z_" << Z ;
std::ifstream ES_Data_Buffer(ostCS.str().c_str(),ios::binary);
if( !ES_Data_Buffer.is_open() )
{
G4ExceptionDescription ed;
ed << "G4JAEAElasticScattering Model data file <" << ostCS.str().c_str()
ed << "G4JAEAElasticScattertingModel data file <" << ostCS.str().c_str()
<< "> is not opened!" << G4endl;
G4Exception("Elastic Scattering::ReadData()","em0003",FatalException,
ed,"G4LEDATA version should be G4EMLOW6.27 or later. Elastic Scattering Data are not loaded");
G4Exception("G4JAEAElasticScatteringModel::ReadData()","em0003",FatalException,
ed,
"G4LEDATA version should be G4EMLOW7.11 or later. Elastic Scattering Data are not loaded");
return;
}
else
@@ -195,19 +205,18 @@ else
<< " is opened by G4JAEAElasticScatteringModel" << G4endl;
}
}
while (!alldata.eof())
if (!ES_Data[Z])
ES_Data[Z] = new G4DataVector();
G4float buffer_var;
while (ES_Data_Buffer.read(reinterpret_cast<char*>(&buffer_var),sizeof(float)))
{
for (int i=0; i<183;i++)
{
for (int j=0; j<300; j++)
{
alldata >> ESdata[i][j];
Diff_CS_data[Z][i][j]=ESdata[i][j];
}
}
if (!alldata) break;
ES_Data[Z]->push_back(buffer_var);
}
/*
Writing the total cross section data to a G4LPhysicsFreeVector.
This provides an interpolation of the Energy-Total Cross Section data.
@@ -215,14 +224,14 @@ This provides an interpolation of the Energy-Total Cross Section data.
dataCS[Z] = new G4LPhysicsFreeVector(300,0.01,3.);
//Note that the total cross section and energy are converted to the internal units.
for (int i=0;i<300;i++)
dataCS[Z]->PutValue(i,Diff_CS_data[Z][0][i]*1e-3,Diff_CS_data[Z][1][i]*1e-22);
// Activation of spline interpolation
dataCS[Z] ->SetSpline(true);
for (G4int i=0;i<300;++i)
dataCS[Z]->PutValue(i,10.*i*1e-3,ES_Data[Z]->at(i)*1e-22);
// Activation of spline interpolation
dataCS[Z] ->SetSpline(true);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -234,7 +243,7 @@ G4double G4JAEAElasticScatteringModel::ComputeCrossSectionPerAtom(
G4double, G4double)
{
if (verboseLevel > 1)
if (verboseLevel > 2)
{
G4cout << "G4JAEAElasticScatteringModel::ComputeCrossSectionPerAtom()"
<< G4endl;
@@ -291,10 +300,11 @@ void G4JAEAElasticScatteringModel::SampleSecondaries(
const G4DynamicParticle* aDynamicGamma,
G4double, G4double)
{
if (verboseLevel > 1) {
G4cout << "Calling SampleSecondaries() of G4JAEAElasticScatteringModel"
if (verboseLevel > 2) {
G4cout << "Calling SampleSecondaries() of G4JAEAElasticScatteringModel."
<< G4endl;
}
G4double photonEnergy0 = aDynamicGamma->GetKineticEnergy();
// Absorption of low-energy gamma
@@ -303,46 +313,64 @@ void G4JAEAElasticScatteringModel::SampleSecondaries(
fParticleChange->ProposeTrackStatus(fStopAndKill);
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeLocalEnergyDeposit(photonEnergy0);
return ;
return;
}
//Warning if the incoming photon has polarization
G4double Xi1=0, Xi2=0, Xi3=0;
G4ThreeVector gammaPolarization0 = aDynamicGamma->GetPolarization();
Xi1=gammaPolarization0.x();
Xi2=gammaPolarization0.y();
Xi3=gammaPolarization0.z();
G4double polarization_magnitude=Xi1*Xi1+Xi2*Xi2+Xi3*Xi3;
if ((polarization_magnitude)>0 || (Xi1*Xi1>0) || (Xi2*Xi2>0) || (Xi3*Xi3>0))
{
G4cout<<"WARNING: G4JAEAElasticScatteringModel is only compatible with non-polarized photons."<<G4endl;
G4cout<<"The event is ignored."<<G4endl;
return;
}
// Select randomly one element in the current material
const G4ParticleDefinition* particle = aDynamicGamma->GetDefinition();
const G4Element* elm = SelectRandomAtom(couple,particle,photonEnergy0);
G4int Z = G4lrint(elm->GetZ());
//Select the angular distribution depending on the photon energy
G4double *whichdistribution = lower_bound(Diff_CS_data[Z][0],Diff_CS_data[Z][0]+300,photonEnergy0*1000.);
int index = max(0,(int)(whichdistribution-Diff_CS_data[Z][0]-1));
//Rounding up to half the energy-grid separation (5 keV)
if (photonEnergy0*1000>=0.5*(Diff_CS_data[Z][0][index]+Diff_CS_data[Z][0][index+1]))
index++;
G4int energyindex=round(100*photonEnergy0)-1;
/*
Getting the normalized probablity distrbution function and
normalization factor to create the probability distribution function
*/
G4double normdist=0;
for (int i=0;i<=180;i++)
{
distribution[i]=Diff_CS_data[Z][i+2][index];
normdist = normdist + distribution[i];
}
G4double a1=0, a2=0, a3=0,a4=0;
G4double normdist=0;
for (G4int i=0;i<=180;++i)
{
a1=ES_Data[Z]->at(4*i+300+181*4*(energyindex));
a2=ES_Data[Z]->at(4*i+1+300+181*4*(energyindex));
a3=ES_Data[Z]->at(4*i+2+300+181*4*(energyindex));
a4=ES_Data[Z]->at(4*i+3+300+181*4*(energyindex));
distribution[i]=a1*a1+a2*a2+a3*a3+a4*a4;
normdist += distribution[i];
}
//Create the cummulative distribution function (cdf)
for (int i =0;i<=180;i++) pdf[i]=distribution[i]/normdist;
for (G4int i =0;i<=180;++i)
pdf[i]=distribution[i]/normdist;
cdf[0]=0;
G4double cdfsum =0;
for (int i=0; i<=180;i++)
{
cdfsum=cdfsum+pdf[i];
cdf[i]=cdfsum;
}
//Sampling the polar angle by inverse transform uing cdf.
for (G4int i=0; i<=180;++i)
{
cdfsum=cdfsum+pdf[i];
cdf[i]=cdfsum;
}
//Sampling the polar angle by inverse transform uing cdf.
G4double r = G4UniformRand();
G4double *cdfptr=lower_bound(cdf,cdf+181,r);
int cdfindex = (int)(cdfptr-cdf-1);
G4int cdfindex = (G4int)(cdfptr-cdf-1);
G4double cdfinv = (r-cdf[cdfindex])/(cdf[cdfindex+1]-cdf[cdfindex]);
G4double theta = (cdfindex+cdfinv)/180.;
//polar is now ready
@@ -0,0 +1,604 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
/*/
Authors:
M. Omer and R. Hajima on 15 November 2019
contact:
omer.mohamed@jaea.go.jp and hajima.ryoichi@qst.go.jp
Publication Information:
1- M. Omer, R. Hajima, Validating polarization effects in gamma-rays elastic scattering by Monte
Carlo simulation, New J. Phys., vol. 21, 2019, pp. 113006 (1-10),
https://doi.org/10.1088/1367-2630/ab4d8a
*/
#include "G4JAEAPolarizedElasticScatteringModel.hh"
#include "G4SystemOfUnits.hh"
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LPhysicsFreeVector* G4JAEAPolarizedElasticScatteringModel::dataCS[] = {nullptr};
G4DataVector* G4JAEAPolarizedElasticScatteringModel::Polarized_ES_Data[] = {nullptr};
G4JAEAPolarizedElasticScatteringModel::G4JAEAPolarizedElasticScatteringModel()
:G4VEmModel("G4JAEAPolarizedElasticScatteringModel"),isInitialised(false)
{
fParticleChange = 0;
lowEnergyLimit = 100 * keV; //low energy limit for JAEAElasticScattering cross section data
fLinearPolarizationSensitvity1=1;
fLinearPolarizationSensitvity2=1;
fCircularPolarizationSensitvity=1;
verboseLevel= 0;
// Verbosity scale for debugging purposes:
// 0 = nothing
// 1 = calculation of cross sections, file openings...
// 2 = entering in methods
if(verboseLevel > 0)
{
G4cout << "G4JAEAPolarizedElasticScatteringModel is constructed " << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4JAEAPolarizedElasticScatteringModel::~G4JAEAPolarizedElasticScatteringModel()
{
if(IsMaster()) {
for(G4int i=0; i<=maxZ; ++i) {
if(dataCS[i]) {
delete dataCS[i];
dataCS[i] = nullptr;
}
if (Polarized_ES_Data[i]){
delete Polarized_ES_Data[i];
Polarized_ES_Data[i] = nullptr;
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4JAEAPolarizedElasticScatteringModel::Initialise(const G4ParticleDefinition* particle,
const G4DataVector& cuts)
{
if (verboseLevel > 1)
{
G4cout << "Calling Initialise() of G4JAEAPolarizedElasticScatteringModel." << G4endl
<< "Energy range: "
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / GeV << " GeV"
<< G4endl;
}
if(IsMaster()) {
// Initialise element selector
InitialiseElementSelectors(particle, cuts);
// Access to elements
char* path = std::getenv("G4LEDATA");
G4ProductionCutsTable* theCoupleTable =
G4ProductionCutsTable::GetProductionCutsTable();
G4int numOfCouples = theCoupleTable->GetTableSize();
for(G4int i=0; i<numOfCouples; ++i)
{
const G4MaterialCutsCouple* couple =
theCoupleTable->GetMaterialCutsCouple(i);
const G4Material* material = couple->GetMaterial();
const G4ElementVector* theElementVector = material->GetElementVector();
G4int nelm = material->GetNumberOfElements();
for (G4int j=0; j<nelm; ++j)
{
G4int Z = G4lrint((*theElementVector)[j]->GetZ());
if(Z < 1) { Z = 1; }
else if(Z > maxZ) { Z = maxZ; }
if( (!dataCS[Z]) ) { ReadData(Z, path); }
}
}
}
if(isInitialised) { return; }
fParticleChange = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4JAEAPolarizedElasticScatteringModel::InitialiseLocal(const G4ParticleDefinition*,
G4VEmModel* masterModel)
{
SetElementSelectors(masterModel->GetElementSelectors());
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4JAEAPolarizedElasticScatteringModel::ReadData(size_t Z, const char* path)
{
if (verboseLevel > 1)
{
G4cout << "Calling ReadData() of G4JAEAPolarizedElasticScatteringModel"
<< G4endl;
}
if(dataCS[Z]) { return; }
const char* datadir = path;
if(!datadir)
{
datadir = std::getenv("G4LEDATA");
if(!datadir)
{
G4Exception("G4JAEAPolarizedElasticScatteringModel::ReadData()","em0006",
FatalException,
"Environment variable G4LEDATA not defined");
return;
}
}
std::ostringstream ostCS;
ostCS << datadir << "/JAEAESData/amp_Z_" << Z ;
std::ifstream ES_Data_Buffer(ostCS.str().c_str(),ios::binary);
if( !ES_Data_Buffer.is_open() )
{
G4ExceptionDescription ed;
ed << "G4JAEAPolarizedElasticScattering Model data file <" << ostCS.str().c_str()
<< "> is not opened!" << G4endl;
G4Exception("G4JAEAPolarizedElasticScatteringModel::ReadData()","em0003",FatalException,
ed,"G4LEDATA version should be G4EMLOW7.11 or later. Polarized Elastic Scattering Data are not loaded");
return;
}
else
{
if(verboseLevel > 3) {
G4cout << "File " << ostCS.str()
<< " is opened by G4JAEAPolarizedElasticScatteringModel" << G4endl;
}
}
if (!Polarized_ES_Data[Z])
Polarized_ES_Data[Z] = new G4DataVector();
G4float buffer_var;
while (ES_Data_Buffer.read(reinterpret_cast<char*>(&buffer_var),sizeof(float)))
{
Polarized_ES_Data[Z]->push_back(buffer_var);
}
dataCS[Z] = new G4LPhysicsFreeVector(300,0.01,3.);
for (G4int i=0;i<300;++i)
dataCS[Z]->PutValue(i,10.*i*1e-3,Polarized_ES_Data[Z]->at(i)*1e-22);
// Activation of spline interpolation
dataCS[Z] ->SetSpline(true);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4JAEAPolarizedElasticScatteringModel::ComputeCrossSectionPerAtom(
const G4ParticleDefinition*,
G4double GammaEnergy,
G4double Z, G4double,
G4double, G4double)
{
//Select the energy-grid point closest to the photon energy
// G4double *whichenergy = lower_bound(ESdata[0],ESdata[0]+300,GammaEnergy);
// int energyindex = max(0,(int)(whichenergy-ESdata[0]-1));
if (verboseLevel > 1)
{
G4cout << "G4JAEAPolarizedElasticScatteringModel::ComputeCrossSectionPerAtom()"
<< G4endl;
}
if(GammaEnergy < lowEnergyLimit) { return 0.0; }
G4double xs = 0.0;
G4int intZ = G4lrint(Z);
if(intZ < 1 || intZ > maxZ) { return xs; }
G4LPhysicsFreeVector* pv = dataCS[intZ];
// if element was not initialised
// do initialisation safely for MT mode
if(!pv) {
InitialiseForElement(0, intZ);
pv = dataCS[intZ];
if(!pv) { return xs; }
}
G4int n = pv->GetVectorLength() - 1;
G4double e = GammaEnergy;
if(e >= pv->Energy(n)) {
xs = (*pv)[n];
} else if(e >= pv->Energy(0)) {
xs = pv->Value(e);
}
if(verboseLevel > 0)
{
G4cout << "****** DEBUG: tcs value for Z=" << Z << " at energy (MeV)="
<< e << G4endl;
G4cout << " cs (Geant4 internal unit)=" << xs << G4endl;
G4cout << " -> first E*E*cs value in CS data file (iu) =" << (*pv)[0]
<< G4endl;
G4cout << " -> last E*E*cs value in CS data file (iu) =" << (*pv)[n]
<< G4endl;
G4cout << "*********************************************************"
<< G4endl;
}
return (xs);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4JAEAPolarizedElasticScatteringModel::SampleSecondaries(
std::vector<G4DynamicParticle*>*,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicGamma,
G4double, G4double)
{
if (verboseLevel > 1) {
G4cout << "Calling SampleSecondaries() of G4JAEAPolarizedElasticScatteringModel."
<< G4endl;
}
G4double photonEnergy0 = aDynamicGamma->GetKineticEnergy();
// absorption of low-energy gamma
if (photonEnergy0 <= lowEnergyLimit)
{
fParticleChange->ProposeTrackStatus(fStopAndKill);
fParticleChange->SetProposedKineticEnergy(0.);
fParticleChange->ProposeLocalEnergyDeposit(photonEnergy0);
return ;
}
const G4ParticleDefinition* particle = aDynamicGamma->GetDefinition();
const G4Element* elm = SelectRandomAtom(couple,particle,photonEnergy0);
G4int Z = G4lrint(elm->GetZ());
//Getting the corresponding distrbution
G4int energyindex=round(100*photonEnergy0)-1;
//G4cout<<"Rounding Photon Energy for element Z = "<<Z<<G4endl;
//G4cout<<photonEnergy0<<" "<<" "<<round(1000*photonEnergy0)<<" "<<energyindex<<G4endl;
G4double a1=0, a2=0, a3=0,a4=0;
for (G4int i=0;i<=180;++i)
{
a1=Polarized_ES_Data[Z]->at(4*i+300+181*4*(energyindex));
a2=Polarized_ES_Data[Z]->at(4*i+1+300+181*4*(energyindex));
a3=Polarized_ES_Data[Z]->at(4*i+2+300+181*4*(energyindex));
a4=Polarized_ES_Data[Z]->at(4*i+3+300+181*4*(energyindex));
distribution[i]=a1*a1+a2*a2+a3*a3+a4*a4;
}
CLHEP::RandGeneral GenThetaDist(distribution,180);
//Intial sampling of the scattering angle. To be updated for the circular polarization
G4double theta = CLHEP::pi*GenThetaDist.shoot();
//G4double theta =45.*CLHEP::pi/180.;
//Theta is in degree to call scattering amplitudes
G4int theta_in_degree =round(theta*180./CLHEP::pi);
//theta_in_degree=45;
G4double am1=0,am2=0,am3=0,am4=0,aparaSquare=0,aperpSquare=0,apara_aper_Asterisk=0,img_apara_aper_Asterisk=0;
am1=Polarized_ES_Data[Z]->at(4*theta_in_degree+300+181*4*(energyindex));
am2=Polarized_ES_Data[Z]->at(4*theta_in_degree+1+300+181*4*(energyindex));
am3=Polarized_ES_Data[Z]->at(4*theta_in_degree+2+300+181*4*(energyindex));
am4=Polarized_ES_Data[Z]->at(4*theta_in_degree+3+300+181*4*(energyindex));
aparaSquare=am1*am1+am2*am2;
aperpSquare=am3*am3+am4*am4;
apara_aper_Asterisk=2*a1*a3+2*a2*a4;
img_apara_aper_Asterisk=2*a1*a4-2*a2*a3;
G4ThreeVector Direction_Unpolarized(0.,0.,0.);
G4ThreeVector Direction_Linear1(0.,0.,0.);
G4ThreeVector Direction_Linear2(0.,0.,0.);
G4ThreeVector Direction_Circular(0.,0.,0.);
G4ThreeVector Polarization_Unpolarized(0.,0.,0.);
G4ThreeVector Polarization_Linear1(0.,0.,0.);
G4ThreeVector Polarization_Linear2(0.,0.,0.);
G4ThreeVector Polarization_Circular(0.,0.,0.);
//Stokes parameters for the incoming and outgoing photon
G4double Xi1=0, Xi2=0, Xi3=0, Xi1_Prime=0,Xi2_Prime=0,Xi3_Prime=0;
//Getting the Stokes parameters for the incoming photon
G4ThreeVector gammaPolarization0 = aDynamicGamma->GetPolarization();
Xi1=gammaPolarization0.x();
Xi2=gammaPolarization0.y();
Xi3=gammaPolarization0.z();
//Polarization vector must be unit vector
G4double polarization_magnitude=Xi1*Xi1+Xi2*Xi2+Xi3*Xi3;
if ((polarization_magnitude)>1 || (Xi1*Xi1>1) || (Xi2*Xi2>1) || (Xi3*Xi3>1))
{
G4cout<<"WARNING: G4JAEAPolarizedElasticScatteringModel is only compatible with a unit polarization vector."<<G4endl;
G4cout<<"The event is ignored."<<G4endl;
return;
}
//Unpolarized gamma rays
if (Xi1==0 && Xi2==0 && Xi3==0)
{
G4double Phi_Unpolarized=0;
if (fLinearPolarizationSensitvity1)
Phi_Unpolarized=GeneratePolarizedPhi(aparaSquare,aperpSquare,0.);
else
Phi_Unpolarized=CLHEP::twopi*G4UniformRand();
Direction_Unpolarized.setX(sin(theta)*cos(Phi_Unpolarized));
Direction_Unpolarized.setY(sin(theta)*sin(Phi_Unpolarized));
Direction_Unpolarized.setZ(cos(theta));
Direction_Unpolarized.rotateUz(aDynamicGamma->GetMomentumDirection());
Xi1_Prime=(aparaSquare-aperpSquare)/(aparaSquare+aperpSquare);
Polarization_Unpolarized.setX(Xi1_Prime);
Polarization_Unpolarized.setY(0.);
Polarization_Unpolarized.setZ(0.);
fParticleChange->ProposeMomentumDirection(Direction_Unpolarized);
fParticleChange->ProposePolarization(Polarization_Unpolarized);
return;
}
//Linear polarization defined by first Stokes parameter
G4double InitialAzimuth=aDynamicGamma->GetMomentumDirection().phi();
if(InitialAzimuth<0) InitialAzimuth=InitialAzimuth+CLHEP::twopi;
G4double Phi_Linear1=0.;
Phi_Linear1 = GeneratePolarizedPhi(aparaSquare+aperpSquare+Xi1*(aparaSquare-aperpSquare),
aparaSquare+aperpSquare-Xi1*(aparaSquare-aperpSquare),InitialAzimuth);
Xi1_Prime=((aparaSquare-aperpSquare)+Xi1*(aparaSquare+aperpSquare)*cos(2*Phi_Linear1))/
((aparaSquare+aperpSquare)+Xi1*(aparaSquare-aperpSquare)*cos(2*Phi_Linear1));
Xi2_Prime=(-Xi1*apara_aper_Asterisk*sin(2*Phi_Linear1))/
((aparaSquare+aperpSquare)+Xi1*(aparaSquare-aperpSquare)*cos(2*Phi_Linear1));
Xi3_Prime=(-Xi1*img_apara_aper_Asterisk*sin(2*Phi_Linear1))/
((aparaSquare+aperpSquare)+Xi1*(aparaSquare-aperpSquare)*cos(2*Phi_Linear1));
//Store momentum direction and po;arization
Direction_Linear1.setX(sin(theta)*cos(Phi_Linear1));
Direction_Linear1.setY(sin(theta)*sin(Phi_Linear1));
Direction_Linear1.setZ(cos(theta));
Polarization_Linear1.setX(Xi1_Prime);
Polarization_Linear1.setY(Xi2_Prime);
Polarization_Linear1.setZ(Xi3_Prime);
//Set scattered photon polarization sensitivity
Xi1_Prime=Xi1_Prime*fLinearPolarizationSensitvity1;
Xi2_Prime=Xi2_Prime*fLinearPolarizationSensitvity2;
Xi3_Prime=Xi3_Prime*fCircularPolarizationSensitvity;
G4double dsigmaL1=0.0;
if(abs(Xi1)>0.0) dsigmaL1=0.25*((aparaSquare+aperpSquare)*(1+Xi1*Xi1_Prime*cos(2*Phi_Linear1))+(aparaSquare-aperpSquare)*(Xi1*cos(2*Phi_Linear1)+Xi1_Prime)
-Xi1*Xi2_Prime*apara_aper_Asterisk*sin(2*Phi_Linear1)-Xi1*Xi3_Prime*img_apara_aper_Asterisk*sin(2*Phi_Linear1));
//Linear polarization defined by second Stokes parameter
//G4double IntialAzimuth=aDynamicGamma->GetMomentumDirection().phi();
G4double Phi_Linear2=0.;
InitialAzimuth=InitialAzimuth-CLHEP::pi/4.;
if(InitialAzimuth<0) InitialAzimuth=InitialAzimuth+CLHEP::twopi;
Phi_Linear2 = GeneratePolarizedPhi(aparaSquare+aperpSquare+Xi1*(aparaSquare-aperpSquare)
,aparaSquare+aperpSquare-Xi1*(aparaSquare-aperpSquare),InitialAzimuth);
Xi1_Prime=((aparaSquare-aperpSquare)+Xi2*(aparaSquare+aperpSquare)*sin(2*Phi_Linear2))/
((aparaSquare+aperpSquare)+Xi2*(aparaSquare-aperpSquare)*sin(2*Phi_Linear2));
Xi2_Prime=(Xi2*apara_aper_Asterisk*cos(2*Phi_Linear2))/
((aparaSquare+aperpSquare)+Xi2*(aparaSquare-aperpSquare)*sin(2*Phi_Linear2));
Xi3_Prime=(Xi2*img_apara_aper_Asterisk*cos(2*Phi_Linear2))/
((aparaSquare+aperpSquare)+Xi2*(aparaSquare-aperpSquare)*sin(2*Phi_Linear2));
//Store momentum direction and polarization
Direction_Linear2.setX(sin(theta)*cos(Phi_Linear2));
Direction_Linear2.setY(sin(theta)*sin(Phi_Linear2));
Direction_Linear2.setZ(cos(theta));
Polarization_Linear2.setX(Xi1_Prime);
Polarization_Linear2.setY(Xi2_Prime);
Polarization_Linear2.setZ(Xi3_Prime);
//Set scattered photon polarization sensitivity
Xi1_Prime=Xi1_Prime*fLinearPolarizationSensitvity1;
Xi2_Prime=Xi2_Prime*fLinearPolarizationSensitvity2;
Xi3_Prime=Xi3_Prime*fCircularPolarizationSensitvity;
G4double dsigmaL2=0.0;
if(abs(Xi2)>0.0)
dsigmaL2=0.25*((aparaSquare+aperpSquare)*(1+Xi2*Xi1_Prime*sin(2*Phi_Linear2))+(aparaSquare-aperpSquare)*(Xi2*sin(2*Phi_Linear2)+Xi1_Prime)
+Xi2*Xi2_Prime*apara_aper_Asterisk*cos(2*Phi_Linear2)-Xi2*Xi3_Prime*img_apara_aper_Asterisk*cos(2*Phi_Linear2));
//Circular polarization
G4double Phi_Circular = CLHEP::twopi*G4UniformRand();
G4double Theta_Circular = 0;
Xi1_Prime=(aparaSquare-aperpSquare)/(aparaSquare+aperpSquare);
Xi2_Prime=(-Xi3*img_apara_aper_Asterisk)/(aparaSquare+aperpSquare);
Xi3_Prime=(Xi3*apara_aper_Asterisk)/(aparaSquare+aperpSquare);
Polarization_Circular.setX(Xi1_Prime);
Polarization_Circular.setY(Xi2_Prime);
Polarization_Circular.setZ(Xi3_Prime);
//Set scattered photon polarization sensitivity
Xi1_Prime=Xi1_Prime*fLinearPolarizationSensitvity1;
Xi2_Prime=Xi2_Prime*fLinearPolarizationSensitvity2;
Xi3_Prime=Xi3_Prime*fCircularPolarizationSensitvity;
G4double dsigmaC=0.0;
if(abs(Xi3)>0.0)
dsigmaC=0.25*(aparaSquare+aperpSquare+Xi1_Prime*(aparaSquare-aperpSquare)-Xi3*Xi2_Prime*img_apara_aper_Asterisk
+Xi3*Xi3_Prime*apara_aper_Asterisk);
if (abs(Xi3)==0.0 && abs(Xi1_Prime)==0.0)
{
Direction_Circular.setX(sin(theta)*cos(Phi_Circular));
Direction_Circular.setY(sin(theta)*sin(Phi_Circular));
Direction_Circular.setZ(cos(theta));
}
else
{
G4double c1=0, c2=0, c3=0,c4=0;
for (G4int i=0;i<=180;++i)
{
c1=Polarized_ES_Data[Z]->at(4*i+300+181*4*(energyindex));
c2=Polarized_ES_Data[Z]->at(4*i+1+300+181*4*(energyindex));
c3=Polarized_ES_Data[Z]->at(4*i+2+300+181*4*(energyindex));
c4=Polarized_ES_Data[Z]->at(4*i+3+300+181*4*(energyindex));
cdistribution[i]=0.25*((c1*c1+c2*c2+c3*c3+c4*c4)+Xi1_Prime*(c1*c1+c2*c2-c3*c3-c4*c4)-Xi3*Xi2_Prime*(2*c1*c4-2*c2*c3)
+Xi3*Xi3_Prime*(2*c1*c4-2*c2*c3));
}
CLHEP::RandGeneral GenTheta_Circ_Dist(cdistribution,180);
Theta_Circular=CLHEP::pi*GenTheta_Circ_Dist.shoot();
Direction_Circular.setX(sin(Theta_Circular)*cos(Phi_Circular));
Direction_Circular.setY(sin(Theta_Circular)*sin(Phi_Circular));
Direction_Circular.setZ(cos(Theta_Circular));
}
// Sampling scattered photon direction based on asymmetry arising from polarization mixing
G4double totalSigma= dsigmaL1+dsigmaL2+dsigmaC;
G4double prob1=dsigmaL1/totalSigma;
G4double prob2=dsigmaL2/totalSigma;
G4double probc=1-(prob1+prob2);
//Check the Probability of polarization mixing
if (abs(probc - dsigmaC)>=0.0001)
{
G4cout<<"WARNING: Polarization mixing might be incorrect."<<G4endl;
}
// Generate outgoing photon direction
G4ThreeVector finaldirection(0.0,0.0,0.0);
G4ThreeVector outcomingPhotonPolarization(0.0,0.0,0.0);
//Polarization mixing
G4double polmix=G4UniformRand();
if (polmix<=prob1)
{
finaldirection.setX(Direction_Linear1.x());
finaldirection.setY(Direction_Linear1.y());
finaldirection.setZ(Direction_Linear1.z());
outcomingPhotonPolarization.setX(Polarization_Linear1.x());
outcomingPhotonPolarization.setY(Polarization_Linear1.y());
outcomingPhotonPolarization.setZ(Polarization_Linear1.z());
}
else if ((polmix>prob1) && (polmix<=prob1+prob2))
{
finaldirection.setX(Direction_Linear2.x());
finaldirection.setY(Direction_Linear2.y());
finaldirection.setZ(Direction_Linear2.z());
outcomingPhotonPolarization.setX(Polarization_Linear2.x());
outcomingPhotonPolarization.setY(Polarization_Linear2.y());
outcomingPhotonPolarization.setZ(Polarization_Linear2.z());
}
else if (polmix>prob1+prob2)
{
finaldirection.setX(Direction_Circular.x());
finaldirection.setY(Direction_Circular.y());
finaldirection.setZ(Direction_Circular.z());
outcomingPhotonPolarization.setX(Polarization_Circular.x());
outcomingPhotonPolarization.setY(Polarization_Circular.y());
outcomingPhotonPolarization.setZ(Polarization_Circular.z());
}
//Sampling the Final State
finaldirection.rotateUz(aDynamicGamma->GetMomentumDirection());
fParticleChange->ProposeMomentumDirection(finaldirection);
fParticleChange->SetProposedKineticEnergy(photonEnergy0);
fParticleChange->ProposePolarization(outcomingPhotonPolarization);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4JAEAPolarizedElasticScatteringModel::GeneratePolarizedPhi(G4double Sigma_para,G4double Sigma_perp, G4double initial_Pol_Plane)
{
G4double phi;
G4double phiProbability;
G4double Probability=Sigma_perp/(Sigma_para+Sigma_perp);
if (Probability<=G4UniformRand())
{
do
{
phi = CLHEP::twopi * G4UniformRand();
phiProbability = cos(phi+initial_Pol_Plane)*cos(phi+initial_Pol_Plane);
}
while (phiProbability < G4UniformRand());
}
else
{
do
{
phi = CLHEP::twopi * G4UniformRand();
phiProbability = sin(phi+initial_Pol_Plane)*sin(phi+initial_Pol_Plane);
}
while (phiProbability < G4UniformRand());
}
return phi;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4AutoLock.hh"
namespace { G4Mutex G4JAEAPolarizedElasticScatteringModelMutex = G4MUTEX_INITIALIZER; }
void
G4JAEAPolarizedElasticScatteringModel::InitialiseForElement(const G4ParticleDefinition*,
G4int Z)
{
G4AutoLock l(&G4JAEAPolarizedElasticScatteringModelMutex);
// G4cout << "G4JAEAPolarizedElasticScatteringModel::InitialiseForElement Z= "
// << Z << G4endl;
if(!dataCS[Z]) { ReadData(Z); }
l.unlock();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,226 @@
//
// ********************************************************************
// * 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. *
// ********************************************************************
//
// Author: Zhuxin Li@CENBG
// 11 March 2020
// on the base of G4LivermoreGammaConversionModel
// derives from G4BetheHeitler5DModel
// -------------------------------------------------------------------
#include "G4LivermoreGammaConversion5DModel.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "G4EmParameters.hh"
#include "G4ParticleChangeForGamma.hh"
#include "G4LPhysicsFreeVector.hh"
#include "G4PhysicsLogVector.hh"
#include "G4ProductionCutsTable.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4Exp.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LivermoreGammaConversion5DModel::lowEnergyLimit = 2.*CLHEP::electron_mass_c2;
G4int G4LivermoreGammaConversion5DModel::verboseLevel = 0;
constexpr G4int G4LivermoreGammaConversion5DModel::maxZ;
G4LPhysicsFreeVector* G4LivermoreGammaConversion5DModel::data[] = {nullptr};
G4LivermoreGammaConversion5DModel::G4LivermoreGammaConversion5DModel(const G4ParticleDefinition* p,
const G4String& nam)
: G4BetheHeitler5DModel(p, nam), fParticleChange(nullptr)
{
// Verbosity scale for debugging purposes:
// 0 = nothing
// 1 = calculation of cross sections, file openings...
// 2 = entering in methods
if(verboseLevel > 0)
{
G4cout << "G4LivermoreGammaConversion5DModel is constructed " << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4LivermoreGammaConversion5DModel::~G4LivermoreGammaConversion5DModel()
{
if(IsMaster()) {
for(G4int i=0; i<maxZ; ++i) {
if(data[i]) {
delete data[i];
data[i] = nullptr;
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void
G4LivermoreGammaConversion5DModel::Initialise( const G4ParticleDefinition* particle,
const G4DataVector& cuts)
{
G4BetheHeitler5DModel::Initialise(particle, cuts);
if (verboseLevel > 1)
{
G4cout << "Calling Initialise() of G4LivermoreGammaConversion5DModel."
<< G4endl
<< "Energy range: "
<< LowEnergyLimit() / MeV << " MeV - "
<< HighEnergyLimit() / GeV << " GeV isMater: " << IsMaster()
<< G4endl;
}
if(!fParticleChange) {
fParticleChange = GetParticleChangeForGamma();
}
if(IsMaster())
{
// Initialise element selector
InitialiseElementSelectors(particle, cuts);
// Access to elements
char* path = std::getenv("G4LEDATA");
G4ProductionCutsTable* theCoupleTable =
G4ProductionCutsTable::GetProductionCutsTable();
G4int numOfCouples = theCoupleTable->GetTableSize();
for(G4int i=0; i<numOfCouples; ++i)
{
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(i);
SetCurrentCouple(couple);
const G4Material* mat = couple->GetMaterial();
const G4ElementVector* theElementVector = mat->GetElementVector();
G4int nelm = mat->GetNumberOfElements();
for (G4int j=0; j<nelm; ++j)
{
G4int Z = std::max(1, std::min((*theElementVector)[j]->GetZasInt(), maxZ));
if(!data[Z]) { ReadData(Z, path); }
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LivermoreGammaConversion5DModel::ReadData(size_t Z, const char* path)
{
if (verboseLevel > 1)
{
G4cout << "Calling ReadData() of G4LivermoreGammaConversion5DModel"
<< G4endl;
}
if(data[Z]) { return; }
const char* datadir = path;
if(!datadir)
{
datadir = std::getenv("G4LEDATA");
if(!datadir)
{
G4Exception("G4LivermoreGammaConversion5DModel::ReadData()",
"em0006",FatalException,
"Environment variable G4LEDATA not defined");
return;
}
}
data[Z] = new G4LPhysicsFreeVector();
std::ostringstream ost;
ost << datadir << "/epics2017/pair/pp-cs-" << Z <<".dat";
std::ifstream fin(ost.str().c_str());
if( !fin.is_open())
{
G4ExceptionDescription ed;
ed << "G4LivermoreGammaConversion5DModel data file <" << ost.str().c_str()
<< "> is not opened!" << G4endl;
G4Exception("G4LivermoreGammaConversion5DModel::ReadData()",
"em0003",FatalException,
ed,"G4LEDATA version should be G4EMLOW6.27 or later.");
return;
}
else
{
if(verboseLevel > 1) { G4cout << "File " << ost.str()
<< " is opened by G4LivermoreGammaConversion5DModel" << G4endl;}
data[Z]->Retrieve(fin, true);
}
// Activation of linear interpolation
data[Z]->SetSpline(false); // EPICS2017 has more points -> linear is fine
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double
G4LivermoreGammaConversion5DModel::ComputeCrossSectionPerAtom(
const G4ParticleDefinition* particle, G4double GammaEnergy, G4double Z,
G4double, G4double, G4double)
{
if (verboseLevel > 1)
{
G4cout << "G4LivermoreGammaConversion5DModel::ComputeCrossSectionPerAtom() Z= "
<< Z << G4endl;
}
G4double xs = 0.0;
if (GammaEnergy < lowEnergyLimit) { return xs; }
G4int intZ = std::max(1, std::min(G4lrint(Z), maxZ));
G4LPhysicsFreeVector* pv = data[intZ];
// if element was not initialised
// do initialisation safely for MT mode
if(!pv)
{
InitialiseForElement(particle, intZ);
pv = data[intZ];
if(!pv) { return xs; }
}
// x-section is taken from the table
xs = pv->Value(GammaEnergy);
if(verboseLevel > 0)
{
G4cout << "*** Gamma conversion xs for Z=" << Z << " at energy E(MeV)="
<< GammaEnergy/MeV << " cs=" << xs/millibarn << " mb" << G4endl;
}
return xs;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
#include "G4AutoLock.hh"
namespace { G4Mutex LivermoreGammaConversion5DModelMutex = G4MUTEX_INITIALIZER; }
void G4LivermoreGammaConversion5DModel::InitialiseForElement(
const G4ParticleDefinition*,
G4int Z)
{
G4AutoLock l(&LivermoreGammaConversion5DModelMutex);
// G4cout << "G4LivermoreGammaConversion5DModel::InitialiseForElement Z= "
// << Z << G4endl;
if(!data[Z]) { ReadData(Z); }
l.unlock();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -27,6 +27,11 @@
// 22 January 2012
// on base of G4LivermoreGammaConversionModel (original version)
// and G4LivermoreRayleighModel (MT version)
//
// Modifications: Zhuxin Li@CENBG
// 11 March 2020
// derives from G4PairProductionRelModel
// -------------------------------------------------------------------
#include "G4LivermoreGammaConversionModel.hh"
#include "G4Electron.hh"
@@ -44,17 +49,13 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4LivermoreGammaConversionModel::lowEnergyLimit = 2.*CLHEP::electron_mass_c2;
G4double G4LivermoreGammaConversionModel::tripletLowEnergy = 0.0;
G4double G4LivermoreGammaConversionModel::tripletHighEnergy = 100.0*CLHEP::GeV;
G4int G4LivermoreGammaConversionModel::verboseLevel = 0;
G4int G4LivermoreGammaConversionModel::nbinsTriplet = 0;
G4int G4LivermoreGammaConversionModel::maxZ = 99;
constexpr G4int G4LivermoreGammaConversionModel::maxZ;
G4LPhysicsFreeVector* G4LivermoreGammaConversionModel::data[] = {nullptr};
G4PhysicsLogVector* G4LivermoreGammaConversionModel::probTriplet[] = {nullptr};
G4LivermoreGammaConversionModel::G4LivermoreGammaConversionModel
(const G4ParticleDefinition*, const G4String& nam)
: G4VEmModel(nam),fParticleChange(nullptr)
(const G4ParticleDefinition* p, const G4String& nam)
: G4PairProductionRelModel(p,nam),fParticleChange(nullptr)
{
// Verbosity scale for debugging purposes:
// 0 = nothing
@@ -77,10 +78,6 @@ G4LivermoreGammaConversionModel::~G4LivermoreGammaConversionModel()
delete data[i];
data[i] = nullptr;
}
if(probTriplet[i]) {
delete probTriplet[i];
probTriplet[i] = nullptr;
}
}
}
}
@@ -90,7 +87,7 @@ G4LivermoreGammaConversionModel::~G4LivermoreGammaConversionModel()
void G4LivermoreGammaConversionModel::Initialise(
const G4ParticleDefinition* particle,
const G4DataVector& cuts)
{
{ G4PairProductionRelModel::Initialise(particle, cuts);
if (verboseLevel > 1)
{
G4cout << "Calling Initialise() of G4LivermoreGammaConversionModel."
@@ -103,12 +100,8 @@ void G4LivermoreGammaConversionModel::Initialise(
if(!fParticleChange) {
fParticleChange = GetParticleChangeForGamma();
if(GetTripletModel()) {
GetTripletModel()->SetParticleChange(fParticleChange);
}
}
if(GetTripletModel()) { GetTripletModel()->Initialise(particle, cuts); }
if(IsMaster())
{
// Initialise element selector
@@ -133,29 +126,11 @@ void G4LivermoreGammaConversionModel::Initialise(
{
G4int Z = std::min((*theElementVector)[j]->GetZasInt(), maxZ);
if(!data[Z]) { ReadData(Z, path); }
if(GetTripletModel()) { InitialiseProbability(particle, Z); }
}
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LivermoreGammaConversionModel::InitialiseLocal(
const G4ParticleDefinition*, G4VEmModel* masterModel)
{
SetElementSelectors(masterModel->GetElementSelectors());
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double
G4LivermoreGammaConversionModel::MinPrimaryEnergy(const G4Material*,
const G4ParticleDefinition*,
G4double)
{
return lowEnergyLimit;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -184,7 +159,7 @@ void G4LivermoreGammaConversionModel::ReadData(size_t Z, const char* path)
}
data[Z] = new G4LPhysicsFreeVector();
std::ostringstream ost;
ost << datadir << "/livermore/pair/pp-cs-" << Z <<".dat";
ost << datadir << "/epics2017/pair/pp-cs-" << Z <<".dat";
std::ifstream fin(ost.str().c_str());
if( !fin.is_open())
@@ -205,8 +180,8 @@ void G4LivermoreGammaConversionModel::ReadData(size_t Z, const char* path)
data[Z]->Retrieve(fin, true);
}
// Activation of spline interpolation
data[Z] ->SetSpline(true);
// Activation of linear interpolation
data[Z] ->SetSpline(false); // EPICS2017 has more points -> linear is fine
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -250,237 +225,19 @@ G4double G4LivermoreGammaConversionModel::ComputeCrossSectionPerAtom(
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4LivermoreGammaConversionModel::SampleSecondaries(
std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* aDynamicGamma,
G4double, G4double)
{
// The energies of the e+ e- secondaries are sampled using the Bethe - Heitler
// cross sections with Coulomb correction. A modified version of the random
// number techniques of Butcher & Messel is used (Nuc Phys 20(1960),15).
// Note 1 : Effects due to the breakdown of the Born approximation at low
// energy are ignored.
// Note 2 : The differential cross section implicitly takes account of
// pair creation in both nuclear and atomic electron fields. However triplet
// prodution is not generated.
if (verboseLevel > 1) {
G4cout << "Calling SampleSecondaries() of G4LivermoreGammaConversionModel"
<< G4endl;
}
G4double photonEnergy = aDynamicGamma->GetKineticEnergy();
G4ParticleMomentum photonDirection = aDynamicGamma->GetMomentumDirection();
G4double epsilon ;
G4double epsilon0Local = electron_mass_c2 / photonEnergy ;
CLHEP::HepRandomEngine* rndmEngine = G4Random::getTheEngine();
// Do it fast if photon energy < 2. MeV
static const G4double smallEnergy = 2.*CLHEP::MeV;
if (photonEnergy < smallEnergy )
{
epsilon = epsilon0Local + (0.5 - epsilon0Local) * rndmEngine->flat();
}
else
{
// Select randomly one element in the current material
const G4ParticleDefinition* particle = aDynamicGamma->GetDefinition();
const G4Element* element = SelectRandomAtom(couple,particle,photonEnergy);
G4int Z = element->GetZasInt();
// triplet production
if(GetTripletModel()) {
if(!probTriplet[Z]) { InitialiseForElement(particle, Z); }
/*
G4cout << "Liv: E= " << photonEnergy
<< " prob= " << probTriplet[Z]->Value(photonEnergy)
<< G4endl;
*/
if(probTriplet[Z] &&
rndmEngine->flat() < probTriplet[Z]->Value(photonEnergy)) {
GetTripletModel()->SampleSecondaries(fvect, couple, aDynamicGamma);
return;
}
}
G4IonisParamElm* ionisation = element->GetIonisation();
// Extract Coulomb factor for this Element
G4double fZ = 8. * (ionisation->GetlogZ3());
static const G4double midEnergy = 50.*CLHEP::MeV;
if (photonEnergy > midEnergy) { fZ += 8. * (element->GetfCoulomb()); }
// Limits of the screening variable
G4double screenFactor = 136. * epsilon0Local / (element->GetIonisation()->GetZ3());
G4double screenMax = G4Exp((42.24 - fZ)/8.368) + 0.952;
G4double screenMin = std::min(4.*screenFactor,screenMax);
// Limits of the energy sampling
G4double epsilon1 = 0.5 - 0.5 * std::sqrt(1. - screenMin / screenMax) ;
G4double epsilonMin = std::max(epsilon0Local,epsilon1);
G4double epsilonRange = 0.5 - epsilonMin ;
// Sample the energy rate of the created electron (or positron)
G4double screen;
G4double gReject;
G4double f10 = ScreenFunction1(screenMin) - fZ;
G4double f20 = ScreenFunction2(screenMin) - fZ;
G4double normF1 = std::max(f10 * epsilonRange * epsilonRange,0.);
G4double normF2 = std::max(1.5 * f20,0.);
do
{
if (normF1 > (normF1 + normF2)*rndmEngine->flat() )
{
epsilon = 0.5 - epsilonRange *G4Exp(G4Log(rndmEngine->flat())/3.);
screen = screenFactor / (epsilon * (1. - epsilon));
gReject = (ScreenFunction1(screen) - fZ) / f10 ;
}
else
{
epsilon = epsilonMin + epsilonRange * rndmEngine->flat();
screen = screenFactor / (epsilon * (1 - epsilon));
gReject = (ScreenFunction2(screen) - fZ) / f20 ;
}
} while ( gReject < rndmEngine->flat() );
} // End of epsilon sampling
// Fix charges randomly
G4double electronTotEnergy;
G4double positronTotEnergy;
if (rndmEngine->flat() > 0.5)
{
electronTotEnergy = (1. - epsilon) * photonEnergy;
positronTotEnergy = epsilon * photonEnergy;
}
else
{
positronTotEnergy = (1. - epsilon) * photonEnergy;
electronTotEnergy = epsilon * photonEnergy;
}
// Scattered electron (positron) angles. ( Z - axis along the parent photon)
// Universal distribution suggested by L. Urban (Geant3 manual (1993) Phys211),
// derived from Tsai distribution (Rev. Mod. Phys. 49, 421 (1977)
static const G4double a1 = 1.6;
static const G4double a2 = 0.5333333333;
G4double uu = -G4Log(rndmEngine->flat()*rndmEngine->flat());
G4double u = (0.25 > rndmEngine->flat()) ? uu*a1 : uu*a2;
G4double thetaEle = u*electron_mass_c2/electronTotEnergy;
G4double sinte = std::sin(thetaEle);
G4double coste = std::cos(thetaEle);
G4double thetaPos = u*electron_mass_c2/positronTotEnergy;
G4double sintp = std::sin(thetaPos);
G4double costp = std::cos(thetaPos);
G4double phi = twopi * rndmEngine->flat();
G4double sinp = std::sin(phi);
G4double cosp = std::cos(phi);
// 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) ;
G4ThreeVector electronDirection (sinte*cosp, sinte*sinp, coste);
electronDirection.rotateUz(photonDirection);
G4DynamicParticle* particle1 = new G4DynamicParticle (G4Electron::Electron(),
electronDirection,
electronKineEnergy);
// The e+ is always created
G4double positronKineEnergy = std::max(0.,positronTotEnergy - electron_mass_c2) ;
G4ThreeVector positronDirection (-sintp*cosp, -sintp*sinp, costp);
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......
#include "G4AutoLock.hh"
namespace { G4Mutex LivermoreGammaConversionModelMutex = G4MUTEX_INITIALIZER; }
void G4LivermoreGammaConversionModel::InitialiseForElement(
const G4ParticleDefinition* part,
const G4ParticleDefinition*,
G4int Z)
{
if(GetTripletModel()) { GetTripletModel()->InitialiseForElement(part, Z); }
G4AutoLock l(&LivermoreGammaConversionModelMutex);
// G4cout << "G4LivermoreGammaConversionModel::InitialiseForElement Z= "
// << Z << G4endl;
if(!data[Z]) { ReadData(Z); }
if(GetTripletModel() && !probTriplet[Z]) { InitialiseProbability(part, Z); }
l.unlock();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LivermoreGammaConversionModel::InitialiseProbability(
const G4ParticleDefinition* part, G4int Z)
{
if(!probTriplet[Z]) {
const G4Material* mat = (CurrentCouple()) ? CurrentCouple()->GetMaterial()
: nullptr;
if(0 == nbinsTriplet) {
tripletLowEnergy = GetTripletModel()->MinPrimaryEnergy(mat, part, 0.0);
tripletHighEnergy =
std::max(GetTripletModel()->HighEnergyLimit(), 10*tripletLowEnergy);
G4int nbins = G4EmParameters::Instance()->NumberOfBinsPerDecade();
nbinsTriplet = std::max(3,
(G4int)(nbins*G4Log(tripletHighEnergy/tripletLowEnergy)/(6*G4Log(10.))));
}
/*
G4cout << "G4LivermoreGammaConversionModel::InitialiseProbability Z= "
<< Z << " Nbin= " << nbinsTriplet
<< " Emin(MeV)= " << tripletLowEnergy
<< " Emax(MeV)= " << tripletHighEnergy << G4endl;
*/
probTriplet[Z] =
new G4PhysicsLogVector(tripletLowEnergy,tripletHighEnergy,nbinsTriplet);
probTriplet[Z]->SetSpline(true);
G4double zz = (G4double)Z;
// loop over bins
for(G4int j=0; j<=nbinsTriplet; ++j) {
G4double e = (probTriplet[Z])->Energy(j);
SetupForMaterial(part, mat, e);
G4double cross = ComputeCrossSectionPerAtom(part, e, zz);
G4double tcross =
GetTripletModel()->ComputeCrossSectionPerAtom(part, e, zz);
tcross = (0.0 < cross) ? tcross/cross : 0.0;
(probTriplet[Z])->PutValue(j, tcross);
//G4cout << j << ". E= " << e << " prob= " << tcross << G4endl;
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -130,7 +130,8 @@ G4LivermorePhotoElectricModel::Initialise(const G4ParticleDefinition*,
if(!fWater) {
fWater = G4Material::GetMaterial("G4_WATER", false);
if(fWater) { fWaterEnergyLimit = 13.6*eV; }
if(!fWater) { fWater = G4Material::GetMaterial("Water", false); }
if(fWater) { fWaterEnergyLimit = 13.6*eV; }
}
if(!fShellCrossSection) { fShellCrossSection = new G4ElementData(); }
@@ -575,26 +575,26 @@ G4double G4ecpssrBaseKxsModel::FunctionFK(G4double k, G4double theta)
// END PROTECTION
std::vector<double>::iterator t2 = std::upper_bound(dummyVec.begin(),dummyVec.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator t2 = std::upper_bound(dummyVec.begin(),dummyVec.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator e12 = std::upper_bound(aVecMap[(*t1)].begin(),aVecMap[(*t1)].end(), theta);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e12 = std::upper_bound(aVecMap[(*t1)].begin(),aVecMap[(*t1)].end(), theta);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e22 = std::upper_bound(aVecMap[(*t2)].begin(),aVecMap[(*t2)].end(), theta);
std::vector<double>::iterator e21 = e22-1;
std::vector<double>::iterator e22 = std::upper_bound(aVecMap[(*t2)].begin(),aVecMap[(*t2)].end(), theta);
std::vector<double>::iterator e21 = e22-1;
valueT1 =*t1;
valueT2 =*t2;
valueE21 =*e21;
valueE22 =*e22;
valueE12 =*e12;
valueE11 =*e11;
valueT1 =*t1;
valueT2 =*t2;
valueE21 =*e21;
valueE22 =*e22;
valueE12 =*e12;
valueE11 =*e11;
xs11 = FKData[valueT1][valueE11];
xs12 = FKData[valueT1][valueE12];
xs21 = FKData[valueT2][valueE21];
xs22 = FKData[valueT2][valueE22];
xs11 = FKData[valueT1][valueE11];
xs12 = FKData[valueT1][valueE12];
xs21 = FKData[valueT2][valueE21];
xs22 = FKData[valueT2][valueE22];
/*
if (verboseLevel>0)
@@ -799,26 +799,26 @@ G4double G4ecpssrBaseLixsModel::FunctionFL1(G4double k, G4double theta)
// END PROTECTION
std::vector<double>::iterator t2 = std::upper_bound(dummyVec1.begin(),dummyVec1.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator t2 = std::upper_bound(dummyVec1.begin(),dummyVec1.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator e12 = std::upper_bound(aVecMap1[(*t1)].begin(),aVecMap1[(*t1)].end(), theta);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e12 = std::upper_bound(aVecMap1[(*t1)].begin(),aVecMap1[(*t1)].end(), theta);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e22 = std::upper_bound(aVecMap1[(*t2)].begin(),aVecMap1[(*t2)].end(), theta);
std::vector<double>::iterator e21 = e22-1;
std::vector<double>::iterator e22 = std::upper_bound(aVecMap1[(*t2)].begin(),aVecMap1[(*t2)].end(), theta);
std::vector<double>::iterator e21 = e22-1;
valueT1 =*t1;
valueT2 =*t2;
valueE21 =*e21;
valueE22 =*e22;
valueE12 =*e12;
valueE11 =*e11;
valueT1 =*t1;
valueT2 =*t2;
valueE21 =*e21;
valueE22 =*e22;
valueE12 =*e12;
valueE11 =*e11;
xs11 = FL1Data[valueT1][valueE11];
xs12 = FL1Data[valueT1][valueE12];
xs21 = FL1Data[valueT2][valueE21];
xs22 = FL1Data[valueT2][valueE22];
xs11 = FL1Data[valueT1][valueE11];
xs12 = FL1Data[valueT1][valueE12];
xs21 = FL1Data[valueT2][valueE21];
xs22 = FL1Data[valueT2][valueE22];
if (verboseLevel>0)
G4cout
@@ -890,26 +890,26 @@ G4double G4ecpssrBaseLixsModel::FunctionFL2(G4double k, G4double theta)
// END PROTECTION
std::vector<double>::iterator t2 = std::upper_bound(dummyVec2.begin(),dummyVec2.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator t2 = std::upper_bound(dummyVec2.begin(),dummyVec2.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator e12 = std::upper_bound(aVecMap2[(*t1)].begin(),aVecMap2[(*t1)].end(), theta);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e12 = std::upper_bound(aVecMap2[(*t1)].begin(),aVecMap2[(*t1)].end(), theta);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e22 = std::upper_bound(aVecMap2[(*t2)].begin(),aVecMap2[(*t2)].end(), theta);
std::vector<double>::iterator e21 = e22-1;
std::vector<double>::iterator e22 = std::upper_bound(aVecMap2[(*t2)].begin(),aVecMap2[(*t2)].end(), theta);
std::vector<double>::iterator e21 = e22-1;
valueT1 =*t1;
valueT2 =*t2;
valueE21 =*e21;
valueE22 =*e22;
valueE12 =*e12;
valueE11 =*e11;
valueT1 =*t1;
valueT2 =*t2;
valueE21 =*e21;
valueE22 =*e22;
valueE12 =*e12;
valueE11 =*e11;
xs11 = FL2Data[valueT1][valueE11];
xs12 = FL2Data[valueT1][valueE12];
xs21 = FL2Data[valueT2][valueE21];
xs22 = FL2Data[valueT2][valueE22];
xs11 = FL2Data[valueT1][valueE11];
xs12 = FL2Data[valueT1][valueE12];
xs21 = FL2Data[valueT2][valueE21];
xs22 = FL2Data[valueT2][valueE22];
if (verboseLevel>0)
G4cout