Import Geant4 11.3.0 source tree
This commit is contained in:
@@ -105,9 +105,13 @@ void G4BetheBlochModel::Initialise(const G4ParticleDefinition* p,
|
||||
(pname == "proton" || pname == "GenericIon" || pname == "alpha")) {
|
||||
fICRU90 = nist->GetICRU90StoppingData();
|
||||
}
|
||||
if(particle->GetPDGCharge() > CLHEP::eplus ||
|
||||
pname == "GenericIon") { isIon = true; }
|
||||
if(pname == "alpha") { isAlpha = true; }
|
||||
if (pname == "GenericIon") {
|
||||
isIon = true;
|
||||
} else if (pname == "alpha") {
|
||||
isAlpha = true;
|
||||
} else if (particle->GetPDGCharge() > 1.1*CLHEP::eplus) {
|
||||
isIon = true;
|
||||
}
|
||||
|
||||
fParticleChange = GetParticleChangeForLoss();
|
||||
if(UseAngularGeneratorFlag() && nullptr == GetAngularDistribution()) {
|
||||
@@ -150,7 +154,6 @@ void G4BetheBlochModel::SetupParameters(const G4ParticleDefinition* p)
|
||||
mass = particle->GetPDGMass();
|
||||
spin = particle->GetPDGSpin();
|
||||
G4double q = particle->GetPDGCharge()*inveplus;
|
||||
isIon = (!isAlpha && q > 1.1);
|
||||
chargeSquare = q*q;
|
||||
ratio = electron_mass_c2/mass;
|
||||
constexpr G4double aMag = 1./(0.5*eplus*CLHEP::hbar_Planck*CLHEP::c_squared);
|
||||
|
||||
@@ -307,7 +307,7 @@ G4BetheHeitler5DModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
|
||||
// End of Protection
|
||||
//
|
||||
const G4double GammaPolarizationMag = GammaPolarization.mag();
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
// target element
|
||||
// select randomly one element constituting the material
|
||||
@@ -505,16 +505,22 @@ G4BetheHeitler5DModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
|
||||
const G4double Jacob1 = 2.*X1*lnPairInvMassRange*PairInvMass;
|
||||
const G4double Jacob2 = std::abs(sinThetaLept);
|
||||
|
||||
// there is no probability to have a lepton with zero momentum
|
||||
// X and Y components of momentum may be zero, in that case SinPhi=1, cosPhi=0
|
||||
const G4double EPlus = LeptonPlus.t();
|
||||
const G4double PPlus = LeptonPlus.vect().mag();
|
||||
const G4double sinThetaPlus = LeptonPlus.vect().perp()/PPlus;
|
||||
const G4double cosThetaPlus = LeptonPlus.vect().cosTheta();
|
||||
|
||||
const G4double pPX = LeptonPlus.x();
|
||||
const G4double pPY = LeptonPlus.y();
|
||||
const G4double dum1 = 1./std::sqrt( pPX*pPX + pPY*pPY );
|
||||
const G4double cosPhiPlus = pPX*dum1;
|
||||
const G4double sinPhiPlus = pPY*dum1;
|
||||
const G4double pPX = LeptonPlus.x();
|
||||
const G4double pPY = LeptonPlus.y();
|
||||
const G4double pPZ = LeptonPlus.z();
|
||||
G4double sinPhiPlus = 1.0;
|
||||
G4double cosPhiPlus = 0.0;
|
||||
G4double sinThetaPlus = 0.0;
|
||||
G4double cosThetaPlus = pPZ/PPlus;
|
||||
if (cosThetaPlus < 1.0 && cosThetaPlus > -1.0) {
|
||||
sinThetaPlus = std::sqrt((1.0 - cosThetaPlus)*(1.0 + cosThetaPlus));
|
||||
sinPhiPlus = pPY/(PPlus*sinThetaPlus);
|
||||
cosPhiPlus = pPX/(PPlus*sinThetaPlus);
|
||||
}
|
||||
|
||||
// denominators:
|
||||
// the two cancelling leading terms for forward emission at high energy, removed
|
||||
@@ -523,16 +529,22 @@ G4BetheHeitler5DModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
|
||||
const G4double DPlus = (elMassCTP*elMassCTP + ePlusSTP*ePlusSTP)
|
||||
/(EPlus + PPlus*cosThetaPlus);
|
||||
|
||||
// there is no probability to have a lepton with zero momentum
|
||||
// X and Y components of momentum may be zero, in that case SinPhi=0, cosPhi=1
|
||||
const G4double EMinus = LeptonMinus.t();
|
||||
const G4double PMinus = LeptonMinus.vect().mag();
|
||||
const G4double sinThetaMinus = LeptonMinus.vect().perp()/PMinus;
|
||||
const G4double cosThetaMinus = LeptonMinus.vect().cosTheta();
|
||||
|
||||
const G4double ePX = LeptonMinus.x();
|
||||
const G4double ePY = LeptonMinus.y();
|
||||
const G4double dum2 = 1./std::sqrt( ePX*ePX + ePY*ePY );
|
||||
const G4double cosPhiMinus = ePX*dum2;
|
||||
const G4double sinPhiMinus = ePY*dum2;
|
||||
const G4double ePX = LeptonMinus.x();
|
||||
const G4double ePY = LeptonMinus.y();
|
||||
const G4double ePZ = LeptonMinus.z();
|
||||
G4double sinPhiMinus = 0.0;
|
||||
G4double cosPhiMinus = 1.0;
|
||||
G4double sinThetaMinus = 0.0;
|
||||
G4double cosThetaMinus = ePZ/PMinus;
|
||||
if (cosThetaMinus < 1.0 && cosThetaMinus > -1.0) {
|
||||
sinThetaMinus = std::sqrt((1.0 - cosThetaMinus)*(1.0 + cosThetaMinus));
|
||||
sinPhiMinus = ePY/(PMinus*sinThetaMinus);
|
||||
cosPhiMinus = ePX/(PMinus*sinThetaMinus);
|
||||
}
|
||||
|
||||
const G4double elMassCTM = LeptonMass*cosThetaMinus;
|
||||
const G4double eMinSTM = EMinus*sinThetaMinus;
|
||||
|
||||
@@ -53,6 +53,8 @@
|
||||
#include "G4Pow.hh"
|
||||
#include "G4Exp.hh"
|
||||
#include "G4ModifiedTsai.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4EmElementXS.hh"
|
||||
#include "G4AutoLock.hh"
|
||||
|
||||
const G4int G4BetheHeitlerModel::gMaxZet = 120;
|
||||
@@ -79,6 +81,7 @@ G4BetheHeitlerModel::~G4BetheHeitlerModel()
|
||||
for (auto const & ptr : gElementData) { delete ptr; }
|
||||
gElementData.clear();
|
||||
}
|
||||
delete fXSection;
|
||||
}
|
||||
|
||||
void G4BetheHeitlerModel::Initialise(const G4ParticleDefinition* p,
|
||||
@@ -91,6 +94,12 @@ void G4BetheHeitlerModel::Initialise(const G4ParticleDefinition* p,
|
||||
if (gElementData.empty()) {
|
||||
isFirstInstance = true;
|
||||
gElementData.resize(gMaxZet+1, nullptr);
|
||||
|
||||
// EPICS2017 flag should be checked only once
|
||||
useEPICS2017 = G4EmParameters::Instance()->UseEPICS2017XS();
|
||||
if (useEPICS2017) {
|
||||
fXSection = new G4EmElementXS(1, 100, "convEPICS2017", "/epics2017/pair/pp-cs-");
|
||||
}
|
||||
}
|
||||
// static data should be initialised only in the one instance
|
||||
InitialiseElementData();
|
||||
@@ -124,6 +133,12 @@ G4BetheHeitlerModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
|
||||
static const G4double kMC2 = CLHEP::electron_mass_c2;
|
||||
// zero cross section below the kinematical limit: Eg<2mc^2
|
||||
if (Z < 0.9 || gammaEnergy <= 2.0*kMC2) { return xSection; }
|
||||
|
||||
G4int iZ = G4lrint(Z);
|
||||
if (useEPICS2017 && iZ < 101) {
|
||||
return fXSection->GetXS(iZ, gammaEnergy);
|
||||
}
|
||||
|
||||
//
|
||||
static const G4double gammaEnergyLimit = 1.5*CLHEP::MeV;
|
||||
// set coefficients a, b c
|
||||
@@ -310,7 +325,8 @@ void G4BetheHeitlerModel::InitialiseElementData()
|
||||
// create for all elements that are in the detector
|
||||
auto elemTable = G4Element::GetElementTable();
|
||||
for (auto const & elem : *elemTable) {
|
||||
const G4int iz = std::min(gMaxZet, elem->GetZasInt());
|
||||
const G4int Z = elem->GetZasInt();
|
||||
const G4int iz = std::min(gMaxZet, Z);
|
||||
if (nullptr == gElementData[iz]) { // create it if doesn't exist yet
|
||||
G4double FZLow = 8.*elem->GetIonisation()->GetlogZ3();
|
||||
G4double FZHigh = FZLow + 8.*elem->GetfCoulomb();
|
||||
@@ -319,6 +335,10 @@ void G4BetheHeitlerModel::InitialiseElementData()
|
||||
elD->fDeltaMaxHigh = G4Exp((42.038 - FZHigh)/8.29) - 0.958;
|
||||
gElementData[iz] = elD;
|
||||
}
|
||||
if (useEPICS2017 && Z < 101) {
|
||||
fXSection->Retrieve(Z);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -259,18 +259,20 @@ G4double G4BraggModel::ComputeDEDXPerVolume(const G4Material* material,
|
||||
G4double cut)
|
||||
{
|
||||
const G4double tmax = MaxSecondaryEnergy(p, kinEnergy);
|
||||
const G4double tlim = lowestKinEnergy*massRate;
|
||||
const G4double tmin = std::max(std::min(cut, tmax), tlim);
|
||||
const G4double tkin = kinEnergy/massRate;
|
||||
const G4double cutEnergy = std::max(cut, lowestKinEnergy*massRate);
|
||||
G4double dedx = 0.0;
|
||||
|
||||
if(kinEnergy < tlim) {
|
||||
dedx = DEDX(material, lowestKinEnergy)*std::sqrt(kinEnergy/tlim);
|
||||
// tkin is the scaled energy to proton
|
||||
if (tkin < lowestKinEnergy) {
|
||||
dedx = DEDX(material, lowestKinEnergy)*std::sqrt(tkin/lowestKinEnergy);
|
||||
} else {
|
||||
dedx = DEDX(material, kinEnergy);
|
||||
dedx = DEDX(material, tkin);
|
||||
|
||||
if (tmin < tmax) {
|
||||
// correction for low cut value using Bethe-Bloch main term
|
||||
if (cutEnergy < tmax) {
|
||||
const G4double tau = kinEnergy/mass;
|
||||
const G4double x = tmin/tmax;
|
||||
const G4double x = cutEnergy/tmax;
|
||||
|
||||
dedx += (G4Log(x)*(tau + 1.)*(tau + 1.)/(tau * (tau + 2.0)) + 1.0 - x) *
|
||||
CLHEP::twopi_mc2_rcl2 * material->GetElectronDensity();
|
||||
@@ -686,7 +688,9 @@ G4double G4BraggModel::DEDX(const G4Material* material, G4double kineticEnergy)
|
||||
}
|
||||
|
||||
// Chemical factor is taken into account
|
||||
eloss *= ChemicalFactor(kineticEnergy, eloss125) ;
|
||||
if (eloss125 > 0.0) {
|
||||
eloss *= ChemicalFactor(kineticEnergy, eloss125);
|
||||
}
|
||||
|
||||
// Brugg's rule calculation
|
||||
} else {
|
||||
|
||||
@@ -296,7 +296,7 @@ void G4GSMottCorrection::LoadMCDataElement(const G4Element *elem) {
|
||||
}
|
||||
|
||||
// uncompress one data file into the input string stream
|
||||
void G4GSMottCorrection::ReadCompressedFile(std::string fname, std::istringstream &iss) {
|
||||
void G4GSMottCorrection::ReadCompressedFile(const std::string& fname, std::istringstream &iss) {
|
||||
std::string *dataString = nullptr;
|
||||
std::string compfilename(fname+".z");
|
||||
// create input stream with binary mode operation and positioning at the end of the file
|
||||
@@ -381,8 +381,11 @@ void G4GSMottCorrection::InitMCDataMaterial(const G4Material *mat) {
|
||||
}
|
||||
G4double density = mat->GetDensity()*CLHEP::cm3/CLHEP::g; // [g/cm3]
|
||||
//
|
||||
moliereBc = const1*density*zs/sa*G4Exp(ze/zs)/G4Exp(zx/zs); //[1/cm]
|
||||
moliereXc2 = const2*density*zs/sa; // [MeV2/cm]
|
||||
G4double z0 = (0.0 == sa) ? 0.0 : zs/sa;
|
||||
G4double z1 = (0.0 == zs) ? 0.0 : (ze - zx)/zs;
|
||||
|
||||
moliereBc = const1*density*z0*G4Exp(z1); //[1/cm]
|
||||
moliereXc2 = const2*density*z0; // [MeV2/cm]
|
||||
// change to Geant4 internal units of 1/length and energ2/length
|
||||
moliereBc *= 1.0/CLHEP::cm;
|
||||
moliereXc2 *= CLHEP::MeV*CLHEP::MeV/CLHEP::cm;
|
||||
|
||||
@@ -254,8 +254,10 @@ void G4GSPWACorrections::InitDataMaterial(const G4Material *mat) {
|
||||
}
|
||||
G4double density = mat->GetDensity()*CLHEP::cm3/CLHEP::g; // [g/cm3]
|
||||
//
|
||||
moliereBc = const1*density*zs/sa*G4Exp(ze/zs)/G4Exp(zx/zs); //[1/cm]
|
||||
moliereXc2 = const2*density*zs/sa; // [MeV2/cm]
|
||||
G4double z0 = (0.0 == sa) ? 0.0 : zs/sa;
|
||||
G4double z1 = (0.0 == zs) ? 0.0 : (ze - zx)/zs;
|
||||
moliereBc = const1*density*z0*G4Exp(z1); //[1/cm]
|
||||
moliereXc2 = const2*density*z0; // [MeV2/cm]
|
||||
// change to Geant4 internal units of 1/length and energ2/length
|
||||
moliereBc *= 1.0/CLHEP::cm;
|
||||
moliereXc2 *= CLHEP::MeV*CLHEP::MeV/CLHEP::cm;
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4OrePowellAtRestModel::G4OrePowellAtRestModel() : G4VPositronAtRestModel("OrePawell") {}
|
||||
G4OrePowellAtRestModel::G4OrePowellAtRestModel() : G4VPositronAtRestModel("OrePowell") {}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -63,13 +63,11 @@ void G4OrePowellAtRestModel::SampleSecondaries(
|
||||
|
||||
G4double cos12;
|
||||
G4double cos13;
|
||||
G4double sin12;
|
||||
G4double sin13;
|
||||
G4double r1;
|
||||
G4double r2;
|
||||
G4double r3;
|
||||
G4double theta12;
|
||||
G4double theta13;
|
||||
G4double sin12;
|
||||
G4double sin13;
|
||||
G4double pdf;
|
||||
|
||||
G4double rndmv2[2];
|
||||
@@ -91,10 +89,9 @@ void G4OrePowellAtRestModel::SampleSecondaries(
|
||||
// request both cosines < 1.
|
||||
} while ( std::abs(cos12) > 1 || std::abs(cos13) > 1 );
|
||||
|
||||
theta12 = std::acos(cos12);
|
||||
theta13 = - std::acos(cos13);
|
||||
sin12 = std::sin(theta12);
|
||||
sin13 = std::sin(theta13);
|
||||
sin12 = std::sqrt((1 + cos12)*(1 - cos12));
|
||||
sin13 = -std::sqrt((1 + cos13)*(1 - cos13));
|
||||
|
||||
G4double cos23=cos12*cos13+sin12*sin13;
|
||||
|
||||
pdf = (1 - cos12)*(1 - cos12) + (1 - cos13)*(1 - cos13) + (1 - cos23)*(1 - cos23);
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// GEANT4 Class file
|
||||
//
|
||||
//
|
||||
// File name: G4PolarizedOrePowellAtRestModel
|
||||
//
|
||||
// Author: I.Semeniouk & D.Bernard
|
||||
//
|
||||
// Creation date: 26 July 2024
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
|
||||
#include "G4PolarizedOrePowellAtRestModel.hh"
|
||||
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4Material.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4RandomDirection.hh"
|
||||
#include "G4RotationMatrix.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4PolarizedOrePowellAtRestModel::G4PolarizedOrePowellAtRestModel()
|
||||
: G4VPositronAtRestModel("OrePowellPolarized")
|
||||
{
|
||||
// DEBUG
|
||||
//G4cout << "G4PolarizedOrePowellAtRestModel in contractor" << G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4PolarizedOrePowellAtRestModel::SampleSecondaries(
|
||||
std::vector<G4DynamicParticle*>& secParticles, G4double&, const G4Material*) const
|
||||
{
|
||||
const G4double PositronMass = CLHEP::electron_mass_c2;
|
||||
const G4double ymax = 22.0;
|
||||
const G4double sq2 = std::sqrt(2.);
|
||||
|
||||
CLHEP::HepRandomEngine* rndmEngine = G4Random::getTheEngine();
|
||||
|
||||
// OrthoPositronium polarization
|
||||
|
||||
// Random mState in 1:1:1 proportion, must be a user parameter
|
||||
G4int mPos = static_cast<G4int>(std::floor(3.0 * rndmEngine->flat()) - 1.0);
|
||||
|
||||
const G4complex iComplex(0., 1.);
|
||||
|
||||
// The u vector defined in global coordinate system
|
||||
//quantization along z - axis, must be a user parameter
|
||||
G4complex ux, uy, uz;
|
||||
|
||||
if (mPos == 0) {
|
||||
uz = 1.;
|
||||
uy = 0.;
|
||||
ux = 0.;
|
||||
}
|
||||
else if (mPos == 1) {
|
||||
uz = 0.;
|
||||
uy = iComplex / sq2;
|
||||
ux = 1. / sq2;
|
||||
}
|
||||
else if (mPos == -1) {
|
||||
uz = 0.;
|
||||
uy = -iComplex / sq2;
|
||||
ux = 1. / sq2;
|
||||
}
|
||||
|
||||
G4double r1, r2, r3;
|
||||
G4double cos12, cos13;
|
||||
G4double pdf;
|
||||
|
||||
G4double rndmv2[2];
|
||||
G4double rndmv1;
|
||||
|
||||
G4ThreeVector PhotonDir1, PhotonDir2, PhotonDir3;
|
||||
G4ThreeVector PhotonPol1, PhotonPol2, PhotonPol3;
|
||||
|
||||
// rotate from local to world coordinate;
|
||||
G4RotationMatrix LtoW;
|
||||
|
||||
do {
|
||||
rndmv1 = rndmEngine->flat();
|
||||
|
||||
do {
|
||||
rndmEngine->flatArray(2, rndmv2);
|
||||
// energies of photon1 and photon2 normalized to electron rest mass
|
||||
r1 = rndmv2[0];
|
||||
r2 = rndmv2[1];
|
||||
|
||||
// energy conservation, with positronium assumed = 2 * electron rest mass
|
||||
r3 = 2.0 - (r1 + r2);
|
||||
// cosine of angles between photons, from momentum conservation
|
||||
cos12 = (r3 * r3 - r1 * r1 - r2 * r2) / (2 * r1 * r2);
|
||||
cos13 = (r2 * r2 - r1 * r1 - r3 * r3) / (2 * r1 * r3);
|
||||
// request both cosines < 1.
|
||||
} while (std::abs(cos12) > 1 || std::abs(cos13) > 1);
|
||||
|
||||
G4double sin12 = std::sqrt((1 + cos12)*(1 - cos12));
|
||||
G4double sin13 = -std::sqrt((1 + cos13)*(1 - cos13));
|
||||
|
||||
// Photon directions in the decay plane (y-z), photon 1 along z
|
||||
PhotonDir1 = {0., 0., 1.};
|
||||
PhotonDir2 = {0., sin12, cos12};
|
||||
PhotonDir3 = {0., sin13, cos13};
|
||||
|
||||
// Polarization
|
||||
|
||||
// direction perpendicular to the photon direction, still in the decay plane
|
||||
G4ThreeVector PhotonPerp1(0., 1., 0.);
|
||||
G4ThreeVector PhotonPerp2(0., cos12, -sin12);
|
||||
G4ThreeVector PhotonPerp3(0., cos13, -sin13);
|
||||
|
||||
G4ThreeVector xDir(1., 0., 0.);
|
||||
|
||||
// photon polarization vector (a_i in Ore & Powell)
|
||||
G4double eta1 = CLHEP::pi * G4UniformRand();
|
||||
PhotonPol1 = std::cos(eta1) * PhotonPerp1 + std::sin(eta1) * xDir;
|
||||
|
||||
G4double eta2 = CLHEP::pi * G4UniformRand();
|
||||
PhotonPol2 = std::cos(eta2) * PhotonPerp2 + std::sin(eta2) * xDir;
|
||||
|
||||
G4double eta3 = CLHEP::pi * G4UniformRand();
|
||||
PhotonPol3 = std::cos(eta3) * PhotonPerp3 + std::sin(eta3) * xDir;
|
||||
|
||||
// direction perpendicular to the photon direction and to polarization (a'_i in Ore & Powell)
|
||||
G4ThreeVector PhotonPrime1 = PhotonPol1.cross(PhotonDir1);
|
||||
G4ThreeVector PhotonPrime2 = PhotonPol2.cross(PhotonDir2);
|
||||
G4ThreeVector PhotonPrime3 = PhotonPol3.cross(PhotonDir3);
|
||||
|
||||
// transition matrix elements (t_i in Ore & Powell)
|
||||
G4ThreeVector t1(-PhotonPol3 * (PhotonPol1.dot(PhotonPol2))
|
||||
+ PhotonPol1 * (PhotonPrime2.dot(PhotonPrime3))
|
||||
- PhotonPrime2 * (PhotonPrime3.dot(PhotonPol1))
|
||||
- PhotonPrime3 * (PhotonPol1.dot(PhotonPrime2)));
|
||||
G4ThreeVector t2(-PhotonPol1 * (PhotonPol2.dot(PhotonPol3))
|
||||
+ PhotonPol2 * (PhotonPrime3.dot(PhotonPrime1))
|
||||
- PhotonPrime3 * (PhotonPrime1.dot(PhotonPol2))
|
||||
- PhotonPrime1 * (PhotonPol2.dot(PhotonPrime3)));
|
||||
G4ThreeVector t3(-PhotonPol2 * (PhotonPol3.dot(PhotonPol1))
|
||||
+ PhotonPol3 * (PhotonPrime1.dot(PhotonPrime2))
|
||||
- PhotonPrime1 * (PhotonPrime2.dot(PhotonPol3))
|
||||
- PhotonPrime2 * (PhotonPol3.dot(PhotonPrime1)));
|
||||
|
||||
// Transformation matrix
|
||||
|
||||
G4ThreeVector z = G4RandomDirection();
|
||||
auto tmp = G4RandomDirection();
|
||||
G4ThreeVector x = z.cross(tmp).unit();
|
||||
G4ThreeVector y = z.cross(x);
|
||||
|
||||
LtoW = G4RotationMatrix(x, y, z);
|
||||
|
||||
// G4cout << x << y << z << G4endl;
|
||||
|
||||
G4ThreeVector t = t1 + t2 + t3;
|
||||
t.transform(LtoW); // t in World coordinate system
|
||||
|
||||
G4complex H = t(0) * ux + t(1) * uy + t(2) * uz;
|
||||
pdf = std::abs(conj(H) * H);
|
||||
} while (pdf < ymax * rndmv1);
|
||||
// END of Sampling
|
||||
|
||||
PhotonDir1.transform(LtoW);
|
||||
PhotonDir2.transform(LtoW);
|
||||
PhotonDir3.transform(LtoW);
|
||||
|
||||
PhotonPol1.transform(LtoW);
|
||||
PhotonPol2.transform(LtoW);
|
||||
PhotonPol3.transform(LtoW);
|
||||
|
||||
auto aGamma1 = new G4DynamicParticle(G4Gamma::Gamma(), PhotonDir1, r1 * PositronMass);
|
||||
aGamma1->SetPolarization(PhotonPol1);
|
||||
secParticles.push_back(aGamma1);
|
||||
|
||||
auto aGamma2 = new G4DynamicParticle(G4Gamma::Gamma(), PhotonDir2, r2 * PositronMass);
|
||||
aGamma2->SetPolarization(PhotonPol2);
|
||||
secParticles.push_back(aGamma2);
|
||||
|
||||
auto aGamma3 = new G4DynamicParticle(G4Gamma::Gamma(), PhotonDir3, r3 * PositronMass);
|
||||
aGamma3->SetPolarization(PhotonPol3);
|
||||
secParticles.push_back(aGamma3);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4PolarizedOrePowellAtRestModel::PrintGeneratorInformation() const
|
||||
{
|
||||
G4cout << "Polarized Ore Powell AtRest positron 3-gamma annihilation model" << G4endl;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -282,7 +282,7 @@ void G4SBBremTable::InitSamplingTables() {
|
||||
stZ->fGamCutIndxToMatCutIndx[i] = stZ->fGamCutIndxToMatCutIndx[j];
|
||||
stZ->fGammaECuts[j] = dum0;
|
||||
stZ->fLogGammaECuts[j] = dum1;
|
||||
stZ->fGamCutIndxToMatCutIndx[j] = dumv;
|
||||
stZ->fGamCutIndxToMatCutIndx[j] = std::move(dumv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// GEANT4 Class file
|
||||
//
|
||||
//
|
||||
// File name: G4SimplePsAtRestModel
|
||||
//
|
||||
// Author: I.Semeniouk & D.Bernard
|
||||
//
|
||||
// Creation date: 04 Juin 2024
|
||||
//
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
|
||||
#include "G4SimplePsAtRestModel.hh"
|
||||
#include "G4SimplePositronAtRestModel.hh"
|
||||
#include "G4OrePowellAtRestModel.hh"
|
||||
#include "G4DynamicParticle.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4RandomDirection.hh"
|
||||
#include "G4ThreeVector.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4SimplePsAtRestModel::G4SimplePsAtRestModel()
|
||||
: G4VPositronAtRestModel("SimplePs")
|
||||
{
|
||||
f3gFranction = G4EmParameters::Instance()->OrtoPsFraction();
|
||||
model2g = new G4SimplePositronAtRestModel();
|
||||
model3g = new G4OrePowellAtRestModel();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4SimplePsAtRestModel::SampleSecondaries(
|
||||
std::vector<G4DynamicParticle*>& secParticles,
|
||||
G4double& localEnergyDeposit, const G4Material* mat) const
|
||||
{
|
||||
// G4cout << "SampleSecondaries model " << GetName() << G4endl;
|
||||
// G4cout << "3 gamma fraction " << f3gFranction << G4endl;
|
||||
if ( G4UniformRand() > f3gFranction ) {
|
||||
model2g->SampleSecondaries(secParticles,localEnergyDeposit,mat);
|
||||
} else {
|
||||
model3g->SampleSecondaries(secParticles,localEnergyDeposit,mat);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4SimplePsAtRestModel::PrintGeneratorInformation() const
|
||||
{
|
||||
G4cout << G4endl;
|
||||
model2g->PrintGeneratorInformation();
|
||||
model3g->PrintGeneratorInformation();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4SimplePsAtRestModel::~G4SimplePsAtRestModel()
|
||||
{
|
||||
delete model2g;
|
||||
delete model3g;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -367,10 +367,10 @@ G4WentzelOKandVIxSection::SampleSingleScattering(G4double cosTMin,
|
||||
G4double grej;
|
||||
if(nullptr != fMottXSection) {
|
||||
fMottXSection->SetupKinematic(tkin, targetZ);
|
||||
grej = fMottXSection->RatioMottRutherfordCosT(std::sqrt(z1))*fm*fm;
|
||||
grej = fMottXSection->RatioMottRutherfordCosT(std::sqrt(z1))*fm;
|
||||
} else {
|
||||
grej = (1. - z1*factB + factB1*targetZ*sqrt(z1*factB)*(2. - z1))
|
||||
*fm*fm/(1.0 + z1*factD);
|
||||
*fm/(1.0 + z1*factD);
|
||||
}
|
||||
if(fMottFactor*rndmEngineMod->flat() <= grej ) {
|
||||
// exclude "false" scattering due to formfactor and spin effect
|
||||
|
||||
@@ -324,7 +324,7 @@ G4double G4WentzelVIModel::ComputeTruePathLengthLimit(
|
||||
//G4cout << "rcut= " << rcut << " rlimit= " << rlimit << " presafety= "
|
||||
// << presafety << " 1-cosThetaMax= " <<1-cosThetaMax
|
||||
//<< " 1-cosTetMaxNuc= " << 1-cosTetMaxNuc << G4endl;
|
||||
if(rcut > rlimit) { rlimit = std::min(rlimit, rcut*sqrt(rlimit/rcut)); }
|
||||
if(rcut > rlimit) { rlimit = std::min(rlimit, rcut*std::sqrt(rlimit/rcut)); }
|
||||
|
||||
tlimit = std::min(tlimit, rlimit);
|
||||
tlimit = std::max(tlimit, tlimitminfix);
|
||||
@@ -518,33 +518,27 @@ G4WentzelVIModel::SampleScattering(const G4ThreeVector& oldDirection,
|
||||
G4int nMscSteps = 1;
|
||||
G4double x0 = tPathLength;
|
||||
G4double z0 = x0*invlambda;
|
||||
//G4double zzz = 0.0;
|
||||
G4double prob2 = 0.0;
|
||||
|
||||
CLHEP::HepRandomEngine* rndmEngine = G4Random::getTheEngine();
|
||||
|
||||
// large scattering angle case - two step approach
|
||||
if(!singleScatteringMode) {
|
||||
static const G4double zzmin = 0.05;
|
||||
if(useSecondMoment) {
|
||||
G4double z1 = invlambda*invlambda;
|
||||
G4double z2 = SecondMoment(particle, currentCouple, effKinEnergy);
|
||||
prob2 = (z2 - z1)/(1.5*z1 - z2);
|
||||
}
|
||||
// if(z0 > zzmin && safety > tlimitminfix) {
|
||||
if(z0 > zzmin) {
|
||||
// numerical limitation on step length for 2-step mode
|
||||
if (z0 > 0.05 && z0 < 30.) {
|
||||
x0 *= 0.5;
|
||||
z0 *= 0.5;
|
||||
nMscSteps = 2;
|
||||
}
|
||||
//if(z0 > zzmin) { zzz = G4Exp(-1.0/z0); }
|
||||
G4double zzz = 0.0;
|
||||
if(z0 > zzmin) {
|
||||
zzz = G4Exp(-1.0/z0);
|
||||
G4double zzz = G4Exp(-1.0/z0);
|
||||
z0 += zzz;
|
||||
prob2 *= (1 + zzz);
|
||||
prob2 *= (1.0 + zzz);
|
||||
}
|
||||
prob2 /= (1 + prob2);
|
||||
prob2 /= (1.0 + prob2);
|
||||
}
|
||||
|
||||
// step limit due to single scattering
|
||||
@@ -636,7 +630,6 @@ G4WentzelVIModel::SampleScattering(const G4ThreeVector& oldDirection,
|
||||
G4bool isFirst = true;
|
||||
if(prob2 > 0.0 && rndmEngine->flat() < prob2) { isFirst = false; }
|
||||
do {
|
||||
//z = -z0*G4Log(1.0 - (1.0 - zzz)*rndmEngine->flat());
|
||||
if(isFirst) { z = -G4Log(rndmEngine->flat()); }
|
||||
else { z = G4RandGamma::shoot(rndmEngine, 2.0, 2.0); }
|
||||
z *= z0;
|
||||
@@ -648,12 +641,12 @@ G4WentzelVIModel::SampleScattering(const G4ThreeVector& oldDirection,
|
||||
else if(cost < -1.0) { cost =-1.0; }
|
||||
sint = sqrt((1.0 - cost)*(1.0 + cost));
|
||||
phi = twopi*rndmEngine->flat();
|
||||
G4double vx1 = sint*cos(phi);
|
||||
G4double vy1 = sint*sin(phi);
|
||||
G4double vx1 = sint*std::cos(phi);
|
||||
G4double vy1 = sint*std::sin(phi);
|
||||
|
||||
// lateral displacement
|
||||
if (latDisplasment) {
|
||||
G4double rms = invsqrt12*sqrt(2*z0);
|
||||
G4double rms = z0 > 0.0 ? invsqrt12*std::sqrt(2*z0) : 0.0;
|
||||
G4double r = x0*mscfac;
|
||||
G4double dx = r*(0.5*vx1 + rms*G4RandGauss::shoot(rndmEngine,0.0,1.0));
|
||||
G4double dy = r*(0.5*vy1 + rms*G4RandGauss::shoot(rndmEngine,0.0,1.0));
|
||||
@@ -661,7 +654,7 @@ G4WentzelVIModel::SampleScattering(const G4ThreeVector& oldDirection,
|
||||
|
||||
// change position
|
||||
if(d >= 0.0) {
|
||||
temp.set(dx,dy,sqrt(d) - r);
|
||||
temp.set(dx, dy, std::sqrt(d) - r);
|
||||
temp.rotateUz(dir);
|
||||
fDisplacement += temp;
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ void G4WentzelVIRelModel::ComputeEffectiveMass()
|
||||
sum += mass*Z2;
|
||||
norm += Z2;
|
||||
}
|
||||
effMass[i] = sum/norm;
|
||||
effMass[i] = (0.0 < norm) ? sum/norm : sum;
|
||||
}
|
||||
}
|
||||
l.unlock();
|
||||
|
||||
@@ -113,10 +113,26 @@ const G4double G4eBremsstrahlungRelModel::gFinelLowZet[] = {
|
||||
};
|
||||
|
||||
// LPM supression functions evaluated at initialisation time
|
||||
G4eBremsstrahlungRelModel::LPMFuncs G4eBremsstrahlungRelModel::gLPMFuncs;
|
||||
std::shared_ptr<G4eBremsstrahlungRelModel::LPMFuncs> G4eBremsstrahlungRelModel::gLPMFuncs()
|
||||
{
|
||||
// We have to use shared pointer for the LPMFuncs as it is manipulated (content deleted)
|
||||
// by the G4eBremsstrahlungRelModel used in the main thread and this
|
||||
// model is owned (well deleted) by (at least in some cases)
|
||||
// a G4SeltzerBergerModel which is owned by the G4LossTableManager
|
||||
// which owned by a G4ThreadLocalSingleton<G4LossTableManager>
|
||||
// which is a static global and thus deleted after this instance
|
||||
// is deleted.
|
||||
static auto _instance = std::make_shared<G4eBremsstrahlungRelModel::LPMFuncs>();
|
||||
return _instance;
|
||||
}
|
||||
|
||||
// special data structure per element i.e. per Z
|
||||
std::vector<G4eBremsstrahlungRelModel::ElementData*> G4eBremsstrahlungRelModel::gElementData;
|
||||
std::shared_ptr<std::vector<G4eBremsstrahlungRelModel::ElementData*>> G4eBremsstrahlungRelModel::gElementData()
|
||||
{
|
||||
// Same code comment as for gLPMFuncs.
|
||||
static auto _instance = std::make_shared<std::vector<G4eBremsstrahlungRelModel::ElementData*>>();
|
||||
return _instance;
|
||||
}
|
||||
|
||||
static std::once_flag applyOnce;
|
||||
|
||||
@@ -127,7 +143,7 @@ namespace
|
||||
|
||||
G4eBremsstrahlungRelModel::G4eBremsstrahlungRelModel(const G4ParticleDefinition* p,
|
||||
const G4String& nam)
|
||||
: G4VEmModel(nam)
|
||||
: G4VEmModel(nam), fLPMFuncs(gLPMFuncs()), fElementData(gElementData())
|
||||
{
|
||||
fGammaParticle = G4Gamma::Gamma();
|
||||
//
|
||||
@@ -147,13 +163,13 @@ G4eBremsstrahlungRelModel::~G4eBremsstrahlungRelModel()
|
||||
{
|
||||
if (fIsInitializer) {
|
||||
// clear ElementData container
|
||||
for (auto const & ptr : gElementData) { delete ptr; }
|
||||
gElementData.clear();
|
||||
for (auto const & ptr : *fElementData) { delete ptr; }
|
||||
fElementData->clear();
|
||||
// clear LPMFunctions (if any)
|
||||
if (gLPMFuncs.fIsInitialized) {
|
||||
gLPMFuncs.fLPMFuncG.clear();
|
||||
gLPMFuncs.fLPMFuncPhi.clear();
|
||||
gLPMFuncs.fIsInitialized = false;
|
||||
if (fLPMFuncs->fIsInitialized) {
|
||||
fLPMFuncs->fLPMFuncG.clear();
|
||||
fLPMFuncs->fLPMFuncPhi.clear();
|
||||
fLPMFuncs->fIsInitialized = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -172,10 +188,10 @@ void G4eBremsstrahlungRelModel::Initialise(const G4ParticleDefinition* p,
|
||||
std::call_once(applyOnce, [this]() { fIsInitializer = true; });
|
||||
|
||||
// for all treads and derived classes
|
||||
if (fIsInitializer || gElementData.empty()) {
|
||||
if (fIsInitializer || fElementData->empty()) {
|
||||
G4AutoLock l(&theBremRelMutex);
|
||||
if (gElementData.empty()) {
|
||||
gElementData.resize(gMaxZet+1, nullptr);
|
||||
if (fElementData->empty()) {
|
||||
fElementData->resize(gMaxZet+1, nullptr);
|
||||
}
|
||||
InitialiseElementData();
|
||||
InitLPMFunctions();
|
||||
@@ -447,7 +463,7 @@ G4eBremsstrahlungRelModel::ComputeRelDXSectionPerAtom(G4double gammaEnergy)
|
||||
// evaluate LPM functions (combined with the Ter-Mikaelian effect)
|
||||
G4double funcGS, funcPhiS, funcXiS;
|
||||
ComputeLPMfunctions(funcXiS, funcGS, funcPhiS, gammaEnergy);
|
||||
const ElementData* elDat = gElementData[fCurrentIZ];
|
||||
const ElementData* elDat = (*fElementData)[fCurrentIZ];
|
||||
const G4double term1 = funcXiS*(dum0*funcGS+(onemy+2.0*dum0)*funcPhiS);
|
||||
dxsec = term1*elDat->fZFactor1+onemy*elDat->fZFactor2;
|
||||
//
|
||||
@@ -491,7 +507,7 @@ G4eBremsstrahlungRelModel::ComputeDXSectionPerAtom(G4double gammaEnergy)
|
||||
const G4double y = gammaEnergy/fPrimaryTotalEnergy;
|
||||
const G4double onemy = 1.-y;
|
||||
const G4double dum0 = onemy+0.75*y*y;
|
||||
const ElementData* elDat = gElementData[fCurrentIZ];
|
||||
const ElementData* elDat = (*fElementData)[fCurrentIZ];
|
||||
// use complete screening and L_el, L_inel from Dirac-Fock model instead of TF
|
||||
if (fCurrentIZ < 5 || fIsUseCompleteScreening) {
|
||||
dxsec = dum0*elDat->fZFactor1;
|
||||
@@ -568,7 +584,7 @@ G4eBremsstrahlungRelModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vd
|
||||
dp->GetLogKineticEnergy(),tmin,tmax);
|
||||
//
|
||||
fCurrentIZ = elm->GetZasInt();
|
||||
const ElementData* elDat = gElementData[fCurrentIZ];
|
||||
const ElementData* elDat = (*fElementData)[fCurrentIZ];
|
||||
const G4double funcMax = elDat->fZFactor1+elDat->fZFactor2;
|
||||
// get the random engine
|
||||
G4double rndm[2];
|
||||
@@ -638,7 +654,7 @@ void G4eBremsstrahlungRelModel::InitialiseElementData()
|
||||
for (auto const & elem : *elemTable) {
|
||||
const G4double zet = elem->GetZ();
|
||||
const G4int izet = std::min(elem->GetZasInt(), gMaxZet);
|
||||
if (nullptr == gElementData[izet]) {
|
||||
if (nullptr == (*fElementData)[izet]) {
|
||||
auto elemData = new ElementData();
|
||||
const G4double fc = elem->GetfCoulomb();
|
||||
G4double Fel = 1.;
|
||||
@@ -662,7 +678,7 @@ void G4eBremsstrahlungRelModel::InitialiseElementData()
|
||||
elemData->fILVarS1 = 1./G4Log(elemData->fVarS1);
|
||||
elemData->fGammaFactor = 100.0*electron_mass_c2/z13;
|
||||
elemData->fEpsilonFactor = 100.0*electron_mass_c2/z23;
|
||||
gElementData[izet] = elemData;
|
||||
(*fElementData)[izet] = elemData;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -676,7 +692,7 @@ void G4eBremsstrahlungRelModel::ComputeLPMfunctions(G4double& funcXiS,
|
||||
const G4double redegamma = egamma/fPrimaryTotalEnergy;
|
||||
const G4double varSprime = std::sqrt(0.125*redegamma*fLPMEnergy/
|
||||
((1.0-redegamma)*fPrimaryTotalEnergy));
|
||||
const ElementData* elDat = gElementData[fCurrentIZ];
|
||||
const ElementData* elDat = (*fElementData)[fCurrentIZ];
|
||||
const G4double varS1 = elDat->fVarS1;
|
||||
const G4double condition = sqrt2*varS1;
|
||||
G4double funcXiSprime = 2.0;
|
||||
@@ -751,15 +767,15 @@ void G4eBremsstrahlungRelModel::ComputeLPMGsPhis(G4double& funcGS,
|
||||
// s goes up to 2 with ds = 0.01 to be the default bining
|
||||
void G4eBremsstrahlungRelModel::InitLPMFunctions()
|
||||
{
|
||||
if (!gLPMFuncs.fIsInitialized) {
|
||||
const G4int num = gLPMFuncs.fSLimit*gLPMFuncs.fISDelta+1;
|
||||
gLPMFuncs.fLPMFuncG.resize(num);
|
||||
gLPMFuncs.fLPMFuncPhi.resize(num);
|
||||
if (!fLPMFuncs->fIsInitialized) {
|
||||
const G4int num = fLPMFuncs->fSLimit*fLPMFuncs->fISDelta+1;
|
||||
fLPMFuncs->fLPMFuncG.resize(num);
|
||||
fLPMFuncs->fLPMFuncPhi.resize(num);
|
||||
for (G4int i = 0; i < num; ++i) {
|
||||
const G4double sval=i/gLPMFuncs.fISDelta;
|
||||
ComputeLPMGsPhis(gLPMFuncs.fLPMFuncG[i],gLPMFuncs.fLPMFuncPhi[i],sval);
|
||||
const G4double sval=i/fLPMFuncs->fISDelta;
|
||||
ComputeLPMGsPhis(fLPMFuncs->fLPMFuncG[i],fLPMFuncs->fLPMFuncPhi[i],sval);
|
||||
}
|
||||
gLPMFuncs.fIsInitialized = true;
|
||||
fLPMFuncs->fIsInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,14 +783,14 @@ void G4eBremsstrahlungRelModel::GetLPMFunctions(G4double& lpmGs,
|
||||
G4double& lpmPhis,
|
||||
const G4double sval)
|
||||
{
|
||||
if (sval < gLPMFuncs.fSLimit) {
|
||||
G4double val = sval*gLPMFuncs.fISDelta;
|
||||
if (sval < fLPMFuncs->fSLimit) {
|
||||
G4double val = sval*fLPMFuncs->fISDelta;
|
||||
const G4int ilow = (G4int)val;
|
||||
val -= ilow;
|
||||
lpmGs = (gLPMFuncs.fLPMFuncG[ilow+1]-gLPMFuncs.fLPMFuncG[ilow])*val
|
||||
+ gLPMFuncs.fLPMFuncG[ilow];
|
||||
lpmPhis = (gLPMFuncs.fLPMFuncPhi[ilow+1]-gLPMFuncs.fLPMFuncPhi[ilow])*val
|
||||
+ gLPMFuncs.fLPMFuncPhi[ilow];
|
||||
lpmGs = (fLPMFuncs->fLPMFuncG[ilow+1]-fLPMFuncs->fLPMFuncG[ilow])*val
|
||||
+ fLPMFuncs->fLPMFuncG[ilow];
|
||||
lpmPhis = (fLPMFuncs->fLPMFuncPhi[ilow+1]-fLPMFuncs->fLPMFuncPhi[ilow])*val
|
||||
+ fLPMFuncs->fLPMFuncPhi[ilow];
|
||||
} else {
|
||||
G4double ss = sval*sval;
|
||||
ss *= ss;
|
||||
|
||||
@@ -691,8 +691,11 @@ void G4eDPWAElasticDCS::ComputeMParams(const G4Material* mat, G4double& theBc,
|
||||
}
|
||||
const G4double density = mat->GetDensity()*CLHEP::cm3/CLHEP::g; // [g/cm3]
|
||||
//
|
||||
theBc = const1*density*zs/sa*G4Exp(ze/zs)/G4Exp(zx/zs); //[1/cm]
|
||||
theXc2 = const2*density*zs/sa; // [MeV2/cm]
|
||||
G4double z0 = (0.0 == sa) ? 0.0 : zs/sa;
|
||||
G4double z1 = (0.0 == zs) ? 0.0 : (ze - zx)/zs;
|
||||
|
||||
theBc = const1*density*z0*G4Exp(z1); //[1/cm]
|
||||
theXc2 = const2*density*z0; // [MeV2/cm]
|
||||
// change to Geant4 internal units of 1/length and energ2/length
|
||||
theBc *= 1.0/CLHEP::cm;
|
||||
theXc2 *= CLHEP::MeV*CLHEP::MeV/CLHEP::cm;
|
||||
|
||||
@@ -61,6 +61,8 @@
|
||||
#include "G4eplusAnnihilationEntanglementClipBoard.hh"
|
||||
#include "G4SimplePositronAtRestModel.hh"
|
||||
#include "G4AllisonPositronAtRestModel.hh"
|
||||
#include "G4OrePowellAtRestModel.hh"
|
||||
#include "G4PolarizedOrePowellAtRestModel.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4PhysicsModelCatalog.hh"
|
||||
|
||||
@@ -83,7 +85,8 @@ G4eplusAnnihilation::G4eplusAnnihilation(const G4String& name)
|
||||
|
||||
G4eplusAnnihilation::~G4eplusAnnihilation()
|
||||
{
|
||||
delete fAtRestModel;
|
||||
delete f2GammaAtRestModel;
|
||||
delete f3GammaAtRestModel;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -115,13 +118,19 @@ void G4eplusAnnihilation::InitialiseProcess(const G4ParticleDefinition*)
|
||||
}
|
||||
auto param = G4EmParameters::Instance();
|
||||
|
||||
// AtRest model should be chosen only once
|
||||
if (nullptr == fAtRestModel) {
|
||||
// AtRest models should be chosen only once
|
||||
if (nullptr == f2GammaAtRestModel) {
|
||||
auto type = param->PositronAtRestModelType();
|
||||
if (type == fAllisonPositronium) {
|
||||
fAtRestModel = new G4AllisonPositronAtRestModel();
|
||||
f2GammaAtRestModel = new G4AllisonPositronAtRestModel();
|
||||
} else if (type == fOrePowell) {
|
||||
f2GammaAtRestModel = new G4AllisonPositronAtRestModel();
|
||||
f3GammaAtRestModel = new G4OrePowellAtRestModel();
|
||||
} else if (type == fOrePowellPolar) {
|
||||
f2GammaAtRestModel = new G4AllisonPositronAtRestModel();
|
||||
f3GammaAtRestModel = new G4PolarizedOrePowellAtRestModel();
|
||||
} else {
|
||||
fAtRestModel = new G4SimplePositronAtRestModel();
|
||||
f2GammaAtRestModel = new G4SimplePositronAtRestModel();
|
||||
}
|
||||
}
|
||||
// Check that entanglement is switched on
|
||||
@@ -158,20 +167,24 @@ G4VParticleChange* G4eplusAnnihilation::AtRestDoIt(const G4Track& track,
|
||||
|
||||
// sample secondaries
|
||||
secParticles.clear();
|
||||
|
||||
G4double edep = 0.0;
|
||||
fAtRestModel->SampleSecondaries(secParticles, edep, couple->GetMaterial());
|
||||
if (nullptr != f3GammaAtRestModel &&
|
||||
G4UniformRand() < currentMaterial->GetIonisation()->GetOrtoPositroniumFraction()) {
|
||||
f3GammaAtRestModel->SampleSecondaries(secParticles, edep, couple->GetMaterial());
|
||||
} else {
|
||||
f2GammaAtRestModel->SampleSecondaries(secParticles, edep, couple->GetMaterial());
|
||||
}
|
||||
|
||||
// define new weight for primary and secondaries
|
||||
G4double weight = fParticleChange.GetParentWeight();
|
||||
std::size_t num0 = secParticles.size();
|
||||
|
||||
// splitting or Russian roulette
|
||||
// Russian roulette
|
||||
if (nullptr != biasManager) {
|
||||
G4int idx = couple->GetIndex();
|
||||
if (biasManager->SecondaryBiasingRegion(idx) &&
|
||||
!biasManager->GetDirectionalSplitting()) {
|
||||
G4VEmModel* mod = nullptr;
|
||||
G4VEmModel* mod = EmModel(0);
|
||||
G4double eloss = 0.0;
|
||||
weight *= biasManager->ApplySecondaryBiasing(secParticles, track, mod,
|
||||
&fParticleChange, eloss,
|
||||
@@ -204,10 +217,12 @@ G4VParticleChange* G4eplusAnnihilation::AtRestDoIt(const G4Track& track,
|
||||
if (fEntangled && i < 2) {
|
||||
// entangledgammagamma is only true when there are only two gammas
|
||||
// (See code above where entangledgammagamma is calculated.)
|
||||
if (i == 0) { // First gamma
|
||||
clipBoard->SetTrackA(t);
|
||||
} else if (i == 1) { // Second gamma
|
||||
clipBoard->SetTrackB(t);
|
||||
if (nullptr != clipBoard) {
|
||||
if (i == 0) { // First gamma
|
||||
clipBoard->SetTrackA(t);
|
||||
} else if (i == 1) { // Second gamma
|
||||
clipBoard->SetTrackB(t);
|
||||
}
|
||||
}
|
||||
t->SetAuxiliaryTrackInformation
|
||||
(fEntanglementModelID, new G4EntanglementAuxInfo(clipBoard));
|
||||
|
||||
+12
-12
@@ -29,7 +29,7 @@
|
||||
// GEANT4 Class file
|
||||
//
|
||||
//
|
||||
// File name: G4eplusTo2GammaOKVIModel
|
||||
// File name: G4eplusTo2or3GammaModel
|
||||
//
|
||||
// Author: Vladimir Ivanchenko and Omrame Kadri
|
||||
//
|
||||
@@ -42,7 +42,7 @@
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
|
||||
#include "G4eplusTo2GammaOKVIModel.hh"
|
||||
#include "G4eplusTo2or3GammaModel.hh"
|
||||
#include "G4eplusTo3GammaOKVIModel.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
@@ -62,11 +62,11 @@
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4PhysicsVector* G4eplusTo2GammaOKVIModel::fCrossSection = nullptr;
|
||||
G4PhysicsVector* G4eplusTo2GammaOKVIModel::f3GProbability = nullptr;
|
||||
G4PhysicsVector* G4eplusTo2or3GammaModel::fCrossSection = nullptr;
|
||||
G4PhysicsVector* G4eplusTo2or3GammaModel::f3GProbability = nullptr;
|
||||
|
||||
G4eplusTo2GammaOKVIModel::G4eplusTo2GammaOKVIModel()
|
||||
: G4VEmModel("eplus2ggOKVI"),
|
||||
G4eplusTo2or3GammaModel::G4eplusTo2or3GammaModel()
|
||||
: G4VEmModel("eplusTo2or3gamma"),
|
||||
fDeltaMin(0.001),
|
||||
fDelta(fDeltaMin),
|
||||
fGammaTh(CLHEP::MeV)
|
||||
@@ -88,7 +88,7 @@ G4eplusTo2GammaOKVIModel::G4eplusTo2GammaOKVIModel()
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4eplusTo2GammaOKVIModel::~G4eplusTo2GammaOKVIModel()
|
||||
G4eplusTo2or3GammaModel::~G4eplusTo2or3GammaModel()
|
||||
{
|
||||
if (IsMaster()) {
|
||||
delete fCrossSection;
|
||||
@@ -100,7 +100,7 @@ G4eplusTo2GammaOKVIModel::~G4eplusTo2GammaOKVIModel()
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4eplusTo2GammaOKVIModel::Initialise(const G4ParticleDefinition* p,
|
||||
void G4eplusTo2or3GammaModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector& cuts)
|
||||
{
|
||||
// here particle change is set for the triplet model
|
||||
@@ -131,7 +131,7 @@ void G4eplusTo2GammaOKVIModel::Initialise(const G4ParticleDefinition* p,
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double
|
||||
G4eplusTo2GammaOKVIModel::ComputeCrossSectionPerElectron(G4double kinEnergy)
|
||||
G4eplusTo2or3GammaModel::ComputeCrossSectionPerElectron(G4double kinEnergy)
|
||||
{
|
||||
// Calculates the cross section per electron of annihilation into two
|
||||
// photons from the Heilter formula with the radiation correction to 3 gamma
|
||||
@@ -158,7 +158,7 @@ G4eplusTo2GammaOKVIModel::ComputeCrossSectionPerElectron(G4double kinEnergy)
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4eplusTo2GammaOKVIModel::ComputeCrossSectionPerAtom(
|
||||
G4double G4eplusTo2or3GammaModel::ComputeCrossSectionPerAtom(
|
||||
const G4ParticleDefinition*,
|
||||
G4double kineticEnergy, G4double Z,
|
||||
G4double, G4double, G4double)
|
||||
@@ -170,7 +170,7 @@ G4double G4eplusTo2GammaOKVIModel::ComputeCrossSectionPerAtom(
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4eplusTo2GammaOKVIModel::CrossSectionPerVolume(
|
||||
G4double G4eplusTo2or3GammaModel::CrossSectionPerVolume(
|
||||
const G4Material* material,
|
||||
const G4ParticleDefinition*,
|
||||
G4double kineticEnergy,
|
||||
@@ -187,7 +187,7 @@ G4double G4eplusTo2GammaOKVIModel::CrossSectionPerVolume(
|
||||
// Polarisation of gamma according to M.H.L.Pryce and J.C.Ward,
|
||||
// Nature 4065 (1947) 435.
|
||||
|
||||
void G4eplusTo2GammaOKVIModel::SampleSecondaries(
|
||||
void G4eplusTo2or3GammaModel::SampleSecondaries(
|
||||
std::vector<G4DynamicParticle*>* vdp,
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dp,
|
||||
@@ -137,7 +137,13 @@ void G4ionIonisation::InitialiseEnergyLossProcess(
|
||||
SetFluctModel(G4EmStandUtil::ModelOfFluctuations(true));
|
||||
}
|
||||
|
||||
if (nullptr == EmModel(0)) { SetEmModel(new G4BraggIonModel()); }
|
||||
if (nullptr == EmModel(0)) {
|
||||
if (pdg == 1000020040) {
|
||||
SetEmModel(new G4BraggIonModel());
|
||||
} else {
|
||||
SetEmModel(new G4BraggModel());
|
||||
}
|
||||
}
|
||||
// to compute ranges correctly we have to use low-energy
|
||||
// model even if activation limit is high
|
||||
EmModel(0)->SetLowEnergyLimit(emin);
|
||||
|
||||
Reference in New Issue
Block a user