Import Geant4 11.3.0 source tree

This commit is contained in:
Gabriele Cosmo
2024-12-06 11:11:40 +01:00
parent e58e650b32
commit 32390e802b
1984 changed files with 98713 additions and 83996 deletions
@@ -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));
@@ -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);