Import Geant4 11.1.2 source tree

This commit is contained in:
Gabriele Cosmo
2023-06-19 17:17:14 +02:00
parent 84a556a9dc
commit aef78ca386
309 changed files with 35572 additions and 34678 deletions
@@ -6,6 +6,10 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2023-06-02 Vladimir Ivanchenko (emhighenergy-V11-00-05)
- G4GammaConversionToMuons - fixed FPE exception in compound, when selected
element and address issue of cross section factor reported in #2543
## 2022-11-23 Gabriele Cosmo (emhighenergy-V11-00-04)
- Fixed more compilation warnings for implicit type conversions.
@@ -51,6 +51,7 @@
#include "G4ParticleDefinition.hh"
#include "G4Element.hh"
#include "G4Step.hh"
#include <vector>
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -137,6 +138,7 @@ private:
const G4ParticleDefinition* theGamma;
const G4ParticleDefinition* theMuonPlus;
const G4ParticleDefinition* theMuonMinus;
std::vector<G4double> fTemp;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -91,9 +91,17 @@ G4bool G4GammaConversionToMuons::IsApplicable(const G4ParticleDefinition& part)
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4GammaConversionToMuons::BuildPhysicsTable(const G4ParticleDefinition& p)
// Build cross section and mean free path tables
{ //here no tables, just calling PrintInfoDefinition
{
Energy5DLimit = G4EmParameters::Instance()->MaxEnergyFor5DMuPair();
auto table = G4Material::GetMaterialTable();
std::size_t nelm = 0;
for(auto const & mat : *table) {
std::size_t n = mat->GetNumberOfElements();
nelm = std::max(nelm, n);
}
fTemp.resize(nelm, 0);
if(Energy5DLimit > 0.0 && nullptr != f5Dmodel) {
f5Dmodel = new G4BetheHeitler5DModel();
f5Dmodel->SetLeptonPair(theMuonPlus, theMuonMinus);
@@ -108,15 +116,12 @@ void G4GammaConversionToMuons::BuildPhysicsTable(const G4ParticleDefinition& p)
G4double G4GammaConversionToMuons::GetMeanFreePath(const G4Track& aTrack,
G4double, G4ForceCondition*)
// returns the photon mean free path in GEANT4 internal units
// (MeanFreePath is a private member of the class)
{
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
const G4Material* aMaterial = aTrack.GetMaterial();
return ComputeMeanFreePath(GammaEnergy, aMaterial);
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
const G4Material* aMaterial = aTrack.GetMaterial();
return ComputeMeanFreePath(GammaEnergy, aMaterial);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -192,12 +197,11 @@ G4double G4GammaConversionToMuons::ComputeCrossSectionPerAtom(
sigfac=4.*fine_structure_const*Z*Z*Rc*Rc;
PowThres=1.479+0.00799*Dn;
Ecor=-18.+4347./(B*Zthird);
G4double CorFuc=1.+.04*G4Log(1.+Ecor/Egam);
//G4double Eg=pow(1.-4.*Mmuon/Egam,PowThres)*pow( pow(Wsatur,PowSat)+
// pow(Egam,PowSat),1./PowSat); // threshold and saturation
G4double Eg=G4Exp(G4Log(1.-4.*Mmuon/Egam)*PowThres)*
G4Exp(G4Log( G4Exp(G4Log(Wsatur)*PowSat)+G4Exp(G4Log(Egam)*PowSat))/PowSat);
G4Exp(G4Log(G4Exp(G4Log(Wsatur)*PowSat) + G4Exp(G4Log(Egam)*PowSat))/PowSat);
G4double CrossSection=7./9.*sigfac*G4Log(1.+WMedAppr*CorFuc*Eg);
CrossSection *= CrossSecFactor; // increase the CrossSection by (by default 1)
return CrossSection;
@@ -210,8 +214,10 @@ void G4GammaConversionToMuons::SetCrossSecFactor(G4double fac)
{
if(fac < 0.0) return;
CrossSecFactor=fac;
G4cout << "The cross section for GammaConversionToMuons is artificially "
<< "increased by the CrossSecFactor=" << CrossSecFactor << G4endl;
if (verboseLevel > 0) {
G4cout << "The cross section for GammaConversionToMuons is artificially "
<< "increased by the CrossSecFactor=" << CrossSecFactor << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
@@ -243,7 +249,6 @@ G4VParticleChange* G4GammaConversionToMuons::PostStepDoIt(
std::vector<G4DynamicParticle*> fvect;
f5Dmodel->SampleSecondaries(&fvect, aTrack.GetMaterialCutsCouple(),
aTrack.GetDynamicParticle(), 0.0, DBL_MAX);
aParticleChange.SetNumberOfSecondaries((G4int)fvect.size());
for(auto dp : fvect) { aParticleChange.AddSecondary(dp); }
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
@@ -276,33 +281,41 @@ G4VParticleChange* G4GammaConversionToMuons::PostStepDoIt(
G4double GammaMuonInv=Mmuon/Egam;
// generate xPlus according to the differential cross section by rejection
G4double xmin=(Egam < LimitEnergy) ? GammaMuonInv : .5-sqrt(.25-GammaMuonInv);
G4double xmin=(Egam <= LimitEnergy) ? 0.5 : 0.5 - std::sqrt(0.25 - GammaMuonInv);
G4double xmax=1.-xmin;
G4double Ds2=(Dn*sqrte-2.);
G4double sBZ=sqrte*B*Zthird/electron_mass_c2;
G4double LogWmaxInv=1./G4Log(Winfty*(1.+2.*Ds2*GammaMuonInv)
/(1.+2.*sBZ*Mmuon*GammaMuonInv));
G4double xPlus,xMinus,xPM,result,W;
G4double xPlus = 0.5;
G4double xMinus = 0.5;
G4double xPM = 0.25;
G4int nn = 0;
const G4int nmax = 1000;
do {
xPlus=xmin+G4UniformRand()*(xmax-xmin);
xMinus=1.-xPlus;
xPM=xPlus*xMinus;
G4double del=Mmuon*Mmuon/(2.*Egam*xPM);
W=Winfty*(1.+Ds2*del/Mmuon)/(1.+sBZ*del);
G4double xxp=1.-4./3.*xPM; // the main xPlus dependence
result=(xxp > 0.) ? xxp*G4Log(W)*LogWmaxInv : 0.0;
if(result>1.) {
G4cout << "G4GammaConversionToMuons::PostStepDoIt WARNING:"
<< " in dSigxPlusGen, result=" << result << " > 1" << G4endl;
// sampling for Egam > LimitEnergy
if (xmin < 0.5) {
G4double result,W;
do {
xPlus=xmin+G4UniformRand()*(xmax-xmin);
xMinus=1.-xPlus;
xPM=xPlus*xMinus;
G4double del=Mmuon*Mmuon/(2.*Egam*xPM);
W=Winfty*(1.+Ds2*del/Mmuon)/(1.+sBZ*del);
G4double xxp=1.-4./3.*xPM; // the main xPlus dependence
result=(xxp > 0.) ? xxp*G4Log(W)*LogWmaxInv : 0.0;
if(result>1.) {
G4cout << "G4GammaConversionToMuons::PostStepDoIt WARNING:"
<< " in dSigxPlusGen, result=" << result << " > 1" << G4endl;
}
++nn;
if(nn >= nmax) { break; }
}
++nn;
if(nn >= nmax) { break; }
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
while (G4UniformRand() > result);
}
// Loop checking, 07-Aug-2015, Vladimir Ivanchenko
while (G4UniformRand() > result);
// now generate the angular variables via the auxilary variables t,psi,rho
G4double t;
@@ -406,7 +419,7 @@ G4VParticleChange* G4GammaConversionToMuons::PostStepDoIt(
// rotate to actual gamma direction
MuPlusDirection.rotateUz(GammaDirection);
MuMinusDirection.rotateUz(GammaDirection);
aParticleChange.SetNumberOfSecondaries(2);
// create G4DynamicParticle object for the particle1
G4DynamicParticle* aParticle1 =
new G4DynamicParticle(theMuonPlus,MuPlusDirection,EPlus-Mmuon);
@@ -431,18 +444,24 @@ const G4Element* G4GammaConversionToMuons::SelectRandomAtom(
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
const G4Element* elm = (*theElementVector)[0];
if (NumberOfElements > 1) {
const G4double* NbOfAtomsPerVolume = aMaterial->GetVecNbOfAtomsPerVolume();
G4double PartialSumSigma = 0.;
G4double rval = G4UniformRand()/MeanFreePath;
if (NumberOfElements > 1) {
G4double e = std::max(aDynamicGamma->GetKineticEnergy(), LimitEnergy);
const G4double* natom = aMaterial->GetVecNbOfAtomsPerVolume();
G4double sum = 0.;
for (std::size_t i=0; i<NumberOfElements; ++i)
{
elm = (*theElementVector)[i];
PartialSumSigma += NbOfAtomsPerVolume[i]
*GetCrossSectionPerAtom(aDynamicGamma, elm);
if (rval <= PartialSumSigma) { break; }
sum += natom[i]*ComputeCrossSectionPerAtom(e, elm->GetZasInt());
fTemp[i] = sum;
}
sum *= G4UniformRand();
for (std::size_t i=0; i<NumberOfElements; ++i)
{
if(sum <= fTemp[i]) {
elm = (*theElementVector)[i];
break;
}
}
}
return elm;
@@ -458,6 +477,7 @@ void G4GammaConversionToMuons::PrintInfoDefinition()
G4cout << " good cross section parametrization from "
<< G4BestUnit(LowestEnergyLimit,"Energy")
<< " to " << HighestEnergyLimit/GeV << " GeV for all Z." << G4endl;
G4cout << " cross section factor: " << CrossSecFactor << G4endl;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -6,6 +6,15 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2023-04-10 V.Ivanchenko (emmuons-V11-00-08)
- G4MuBremsstrahlung, G4MuPairProduction - fix problem #2531, spline flag
was lost for mu-, pi-, K-, and pbar dedx and range tables, the max observed
problem was for mu- with momentum ~50 MeV/c, ~5 % biased range
- G4MuBetheBlochModel - enable option to use angular generator for sampling
of delta-electron direction
- G4MuIonisation - implement full schema of selection of the model of
energy loss fluctuation
## 2022-11-23 Gabriele Cosmo (emmuons-V11-00-07)
- Fixed compilation warnings for implicit type conversions on macOS/XCode 14.1.
@@ -126,6 +126,7 @@ private:
G4ParticleChangeForLoss* fParticleChange = nullptr;
G4EmCorrections* corr = nullptr;
G4double limitRadCorrection;
G4double limitKinEnergy;
G4double logLimitKinEnergy;
G4double mass = 1.0;
@@ -64,6 +64,7 @@
#include "G4ParticleChangeForLoss.hh"
#include "G4Log.hh"
#include "G4Exp.hh"
#include "G4DeltaAngle.hh"
G4double G4MuBetheBlochModel::xgi[]={ 0.0199, 0.1017, 0.2372, 0.4083, 0.5917,
0.7628, 0.8983, 0.9801 };
@@ -76,6 +77,7 @@ G4double G4MuBetheBlochModel::wgi[]={ 0.0506, 0.1112, 0.1569, 0.1813, 0.1813,
G4MuBetheBlochModel::G4MuBetheBlochModel(const G4ParticleDefinition* p,
const G4String& nam)
: G4VEmModel(nam),
limitRadCorrection(250.*CLHEP::MeV),
limitKinEnergy(100.*CLHEP::keV),
logLimitKinEnergy(G4Log(limitKinEnergy)),
twoln10(2.0*G4Log(10.0)),
@@ -125,6 +127,9 @@ void G4MuBetheBlochModel::Initialise(const G4ParticleDefinition* p,
SetParticle(p);
if(nullptr == fParticleChange) {
fParticleChange = GetParticleChangeForLoss();
if(UseAngularGeneratorFlag() && nullptr == GetAngularDistribution()) {
SetAngularDistribution(new G4DeltaAngle());
}
}
}
@@ -150,7 +155,7 @@ G4double G4MuBetheBlochModel::ComputeCrossSectionPerElectron(
0.5*(maxEnergy - cutEnergy)/energy2;
// radiative corrections of R. Kokoulin
if (maxEnergy > limitKinEnergy) {
if (maxEnergy > limitKinEnergy && kineticEnergy > limitRadCorrection) {
G4double logtmax = G4Log(maxEnergy);
G4double logtmin = G4Log(std::max(cutEnergy,limitKinEnergy));
@@ -231,12 +236,11 @@ G4double G4MuBetheBlochModel::ComputeDEDXPerVolume(const G4Material* material,
G4double x = G4Log(bg2)/twoln10;
dedx -= material->GetIonisation()->DensityCorrection(x);
// shell correction
// shell and high order corrections
dedx -= 2.0*corr->ShellCorrection(p,material,kineticEnergy);
dedx = std::max(dedx, 0.0);
// radiative corrections of R. Kokoulin
if (cutEnergy > limitKinEnergy) {
if (cutEnergy > limitKinEnergy && kineticEnergy > limitRadCorrection) {
G4double logtmax = G4Log(cutEnergy);
G4double logstep = logtmax - logLimitKinEnergy;
@@ -251,7 +255,6 @@ G4double G4MuBetheBlochModel::ComputeDEDXPerVolume(const G4Material* material,
}
dedx += dloss*logstep*alphaprime;
}
dedx *= CLHEP::twopi_mc2_rcl2*eDensity/beta2;
//High order corrections
@@ -264,7 +267,7 @@ G4double G4MuBetheBlochModel::ComputeDEDXPerVolume(const G4Material* material,
void G4MuBetheBlochModel::SampleSecondaries(
std::vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple*,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double minKinEnergy,
G4double maxEnergy)
@@ -279,7 +282,8 @@ void G4MuBetheBlochModel::SampleSecondaries(
G4double beta2 = kineticEnergy*(kineticEnergy + 2.0*mass)/etot2;
G4double grej = 1.;
if(tmax > limitKinEnergy) {
G4bool radC = (tmax > limitKinEnergy && kineticEnergy > limitRadCorrection);
if(radC) {
G4double a0 = G4Log(2.*totEnergy/mass);
grej += alphaprime*a0*a0;
}
@@ -292,7 +296,7 @@ void G4MuBetheBlochModel::SampleSecondaries(
tkin = minKinEnergy*maxKinEnergy/(minKinEnergy*(1.0 - q) + maxKinEnergy*q);
f = 1.0 - beta2*tkin/tmax + 0.5*tkin*tkin/etot2;
if(tkin > limitKinEnergy) {
if(radC && tkin > limitKinEnergy) {
G4double a1 = G4Log(1.0 + 2.0*tkin/CLHEP::electron_mass_c2);
G4double a3 = G4Log(4.0*totEnergy*(totEnergy - tkin)/massSquare);
f *= (1. + alphaprime*a1*(a3 - a1));
@@ -308,29 +312,35 @@ void G4MuBetheBlochModel::SampleSecondaries(
// Loop checking, 03-Aug-2015, Vladimir Ivanchenko
} while( grej*G4UniformRand() > f );
G4double deltaMomentum =
std::sqrt(tkin * (tkin + 2.0*CLHEP::electron_mass_c2));
G4double totalMomentum = totEnergy*std::sqrt(beta2);
G4double cost = tkin * (totEnergy + CLHEP::electron_mass_c2) /
(deltaMomentum * totalMomentum);
G4ThreeVector deltaDirection;
G4double sint = std::sqrt(1.0 - cost*cost);
G4double phi = CLHEP::twopi * G4UniformRand();
G4ThreeVector deltaDirection(sint*std::cos(phi), sint*std::sin(phi), cost);
G4ThreeVector direction = dp->GetMomentumDirection();
deltaDirection.rotateUz(direction);
if(UseAngularGeneratorFlag()) {
const G4Material* mat = couple->GetMaterial();
deltaDirection = GetAngularDistribution()->SampleDirection(dp, tkin,
SelectRandomAtomNumber(mat), mat);
} else {
G4double deltaMom = std::sqrt(tkin * (tkin + 2.0*CLHEP::electron_mass_c2));
G4double totalMom = totEnergy*std::sqrt(beta2);
G4double cost = tkin * (totEnergy + CLHEP::electron_mass_c2) /
(deltaMom * totalMom);
cost = std::min(cost, 1.0);
const G4double sint = std::sqrt((1.0 - cost)*(1.0 + cost));
const G4double phi = twopi*G4UniformRand();
deltaDirection.set(sint*std::cos(phi),sint*std::sin(phi), cost) ;
deltaDirection.rotateUz(dp->GetMomentumDirection());
}
// create G4DynamicParticle object for delta ray
auto delta = new G4DynamicParticle(theElectron, deltaDirection, tkin);
vdp->push_back(delta);
// primary change
kineticEnergy -= tkin;
G4ThreeVector dir = totalMomentum*direction - deltaMomentum*deltaDirection;
direction = dir.unit();
G4ThreeVector dir = dp->GetMomentum() - delta->GetMomentum();
dir = dir.unit();
fParticleChange->SetProposedKineticEnergy(kineticEnergy);
fParticleChange->SetProposedMomentumDirection(direction);
// create G4DynamicParticle object for delta ray
G4DynamicParticle* delta =
new G4DynamicParticle(theElectron, deltaDirection, tkin);
vdp->push_back(delta);
fParticleChange->SetProposedMomentumDirection(dir);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -79,7 +79,6 @@ G4MuBremsstrahlung::G4MuBremsstrahlung(const G4String& name)
SetProcessSubType(fBremsstrahlung);
SetSecondaryParticle(G4Gamma::Gamma());
SetIonisation(false);
SetSpline(false);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -124,6 +124,7 @@ G4MuIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* part,
theBaseParticle = bpart;
mass = theParticle->GetPDGMass();
ratio = CLHEP::electron_mass_c2/mass;
G4double q = theParticle->GetPDGCharge();
G4EmParameters* param = G4EmParameters::Instance();
@@ -138,13 +139,11 @@ G4MuIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* part,
EmModel(0)->SetLowEnergyLimit(param->MinKinEnergy());
EmModel(0)->SetHighEnergyLimit(elow);
// high energy fluctuation model
// fluctuation model
if (nullptr == FluctModel()) {
SetFluctModel(G4EmStandUtil::ModelOfFluctuations());
}
// low-energy fluctuation model
G4VEmFluctuationModel* f = G4EmStandUtil::ModelOfFluctuations(true);
AddEmModel(1, EmModel(0), f);
AddEmModel(1, EmModel(0), FluctModel());
// high energy model
if (nullptr == EmModel(1)) { SetEmModel(new G4MuBetheBlochModel()); }
@@ -152,7 +151,6 @@ G4MuIonisation::InitialiseEnergyLossProcess(const G4ParticleDefinition* part,
EmModel(1)->SetHighEnergyLimit(emax);
AddEmModel(1, EmModel(1), FluctModel());
ratio = CLHEP::electron_mass_c2/mass;
isInitialised = true;
}
}
@@ -85,7 +85,6 @@ G4MuPairProduction::G4MuPairProduction(const G4String& name)
SetProcessSubType(fPairProdByCharged);
SetSecondaryParticle(G4Positron::Positron());
SetIonisation(false);
SetSpline(false);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -6,6 +6,23 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2023-06-13 V.Ivanchenko (emstand-V11-00-24)
- G4LindhardSorensenIonModel - do not try to use ICRU73 data for projectile Z>80
## 2023-04-20 V.Ivanchenko (emstand-V11-00-23)
- G4LindhardSorensenIonModel - updated effective charge of an ion at each
step of simulation or at each call to G4EmCalculator
## 2023-04-17 V.Ivanchenko
- G4LinhardSorensenModel - added extra protection and improved debug printout
## 2023-02-24 V.Ivanchenko
- G4WentzelOKandVIxSection - fix numeric instability for the extreme case of
very small kinetic energy (< 1 eV)
## 2023-02-21 V.Ivanchenko
- G4WentzelOKandVIxSection - fix #2530, improved comments
## 2022-12-21 V.Ivanchenko (emstand-V11-00-22)
- G4GoudsmithSoundersonMscModel - fixed warning when build CMSSW
@@ -74,7 +74,7 @@ class G4WentzelOKandVIxSection
public:
explicit G4WentzelOKandVIxSection(G4bool comb=true);
explicit G4WentzelOKandVIxSection(G4bool combined=true);
virtual ~G4WentzelOKandVIxSection();
@@ -139,7 +139,10 @@ protected:
G4double coeff;
G4double cosTetMaxElec = 1.0;
G4double cosTetMaxNuc = 1.0;
G4double cosThetaMax = -1.0;
// for the combined mode it is cos(thetaMax)
// for single scattering it is cos(thetaMin)
G4double cosThetaMax = 1.0;
G4double chargeSquare = 0.0;
G4double charge3 = 0.0;
@@ -121,7 +121,8 @@ G4LindhardSorensenIonModel::GetChargeSquareRatio(const G4ParticleDefinition* p,
const G4Material* mat,
G4double kinEnergy)
{
return corr->EffectiveChargeSquareRatio(p,mat,kinEnergy);
chargeSquare = corr->EffectiveChargeSquareRatio(p,mat,kinEnergy);
return chargeSquare;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -258,15 +259,17 @@ void G4LindhardSorensenIonModel::CorrectionsAlongStep(
const G4double q2 = corr->EffectiveChargeSquareRatio(p, mat, e);
const G4int Z = p->GetAtomicNumber();
G4double res;
G4double res = 0.0;
if(escaled <= fElimit) {
// data from ICRU73 or ICRU90
res = fIonData->GetDEDX(mat, Z, escaled, G4Log(escaled));
/*
G4cout << "GetDEDX for Z=" << Z << " in " << mat->GetName()
<< " Escaled=" << escaled << " E="
<< e << " dEdx=" << res << G4endl;
*/
if(Z > 2 && Z <= 80) {
res = fIonData->GetDEDX(mat, Z, escaled, G4Log(escaled));
/*
G4cout << "GetDEDX for Z=" << Z << " in " << mat->GetName()
<< " Escaled=" << escaled << " E="
<< e << " dEdx=" << res << G4endl;
*/
}
if(res > 0.0) {
auto pcuts = couple->GetProductionCuts();
G4double cut = (nullptr == pcuts) ? tmax : pcuts->GetProductionCut(1);
@@ -310,16 +313,16 @@ void G4LindhardSorensenIonModel::CorrectionsAlongStep(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4LindhardSorensenIonModel::SampleSecondaries(
vector<G4DynamicParticle*>* vdp,
std::vector<G4DynamicParticle*>* vdp,
const G4MaterialCutsCouple* couple,
const G4DynamicParticle* dp,
G4double minKinEnergy,
G4double cut,
G4double maxEnergy)
{
G4double kineticEnergy = dp->GetKineticEnergy();
// take into account formfactor
G4double tmax = MaxSecondaryEnergy(dp->GetDefinition(),kineticEnergy);
G4double minKinEnergy = std::min(cut, tmax);
G4double maxKinEnergy = std::min(maxEnergy,tmax);
if(minKinEnergy >= maxKinEnergy) { return; }
@@ -346,34 +346,32 @@ G4WentzelOKandVIxSection::SampleSingleScattering(G4double cosTMin,
}
}
if(cost1 > cost2) {
G4double w1 = 1. - cost1 + screenZ;
G4double w2 = 1. - cost2 + screenZ;
G4double z1 = w1*w2/(w1 + rndmEngineMod->flat()*(w2 - w1)) - screenZ;
G4double w1 = 1. - cost1;
G4double w2 = 1. - cost2;
G4double w3 = rndmEngineMod->flat()*(w2 - w1);
G4double z1 = ((w2 - w3)*screenZ + w1*w2)/(screenZ + w1 + w3);
G4double fm = 1.0;
if(fNucFormfactor == fExponentialNF) {
fm += formf*z1;
fm = 1.0/(fm*fm);
} else if(fNucFormfactor == fGaussianNF) {
fm = G4Exp(-2*formf*z1);
} else if(fNucFormfactor == fFlatNF) {
static const G4double ccoef = 0.00508/MeV;
static const G4double ccoef = 0.00508/CLHEP::MeV;
G4double x = std::sqrt(2.*mom2*z1)*ccoef*2.;
fm = FlatFormfactor(x);
fm *= FlatFormfactor(x*0.6
*fG4pow->A13(fNistManager->GetAtomicMassAmu(targetZ)));
fm *= FlatFormfactor(x*0.6*fG4pow->A13(fNistManager->GetAtomicMassAmu(targetZ)));
}
// G4cout << " fm=" << fm << " " << fMottXSection << G4endl;
G4double grej;
if(fMottXSection) {
if(nullptr != fMottXSection) {
fMottXSection->SetupKinematic(tkin, targetZ);
grej = fMottXSection->RatioMottRutherfordCosT(std::sqrt(z1))*fm*fm;
} else {
grej = (1. - z1*factB + factB1*targetZ*sqrt(z1*factB)*(2. - z1))
*fm*fm/(1.0 + z1*factD);
}
// G4cout << "SampleSingleScattering: E= " << tkin << " z1= "
// << z1 << " grej= "<< grej << " mottFact= "<< fMottFactor<< G4endl;
if(fMottFactor*rndmEngineMod->flat() <= grej ) {
// exclude "false" scattering due to formfactor and spin effect
G4double cost = 1.0 - z1;
@@ -6,6 +6,25 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2023-06-02 J.Hahnfeld (emutils-V11-00-40)
- Fixes to `G4TransportationWithMsc`:
* Protect code for MultipleScattering
* Fix type of particle change
## 2023-04-08 V.Ivanchenko
- G4LossTableManager - improved debug printout and removed unused lines of code
## 2023-03-20 V.Ivanchenko
- G4VEnergyLossProcess - fixed static analyzer warning
- G4EmTableUtil - fixed verbose output and class comments
## 2023-03-06 J.Allison
- Allow /process/em/QuantumEntanglement in G4State_Idle.
## 2023-02-21 V.Ivanchenko
- G4EmExtraParameters - fixed AddPAIModel(...) method and improved comments
- G4EmExtraParametersMessenger - fixed broadcasting
## 2022-12-11 V.Ivanchenko (emutils-V11-00-39)
- G4EmParameters, G4EmParametersMessenger, added parameter, UI command,
GetSet methods - MscPositronCorrection
@@ -41,6 +41,7 @@
class G4EmModelManager;
class G4LossTableManager;
class G4ParticleChangeForMSC;
class G4ParticleDefinition;
class G4Region;
class G4VMscModel;
@@ -84,6 +85,9 @@ class G4TransportationWithMsc : public G4Transportation
G4EmModelManager* fModelManager;
const G4ParticleDefinition* fFirstParticle = nullptr;
// For ScatteringType::MultipleScattering
G4ParticleChangeForMSC* fParticleChangeForMSC = nullptr;
G4DynamicParticle* fSubStepDynamicParticle;
G4Track* fSubStepTrack;
G4Step* fSubStep;
@@ -225,20 +225,22 @@ void G4EmExtraParameters::AddPAIModel(const G4String& particle,
{
G4String r = CheckRegion(region);
std::size_t nreg = m_regnamesPAI.size();
for(std::size_t i=0; i<nreg; ++i) {
if((m_particlesPAI[i] == particle ||
m_particlesPAI[i] == "all" ||
particle == "all") &&
(m_regnamesPAI[i] == r ||
m_regnamesPAI[i] == "DefaultRegionForTheWorld" ||
r == "DefaultRegionForTheWorld") ) {
m_typesPAI[i] = type;
if(particle == "all") { m_particlesPAI[i] = particle; }
if(r == "DefaultRegionForTheWorld") { m_regnamesPAI[i] = r; }
return;
// in previously defined region other particles may be already defined
// type should be overrided for the same region and particle
for(std::size_t i=0; i<nreg; ++i) {
if(m_regnamesPAI[i] == r) {
if (particle == "all") {
m_particlesPAI[i] = particle;
m_typesPAI[i] = type;
return;
} else if(m_particlesPAI[i] == particle || m_particlesPAI[i] == "all") {
m_typesPAI[i] = type;
return;
}
}
}
// new regions and/or particles
m_particlesPAI.push_back(particle);
m_regnamesPAI.push_back(r);
m_typesPAI.push_back(type);
@@ -81,6 +81,7 @@ G4EmExtraParametersMessenger::G4EmExtraParametersMessenger(G4EmExtraParameters*
mscoCmd->SetGuidance(" regName : G4Region name");
mscoCmd->SetGuidance(" emType : G4EmStandard, G4EmStandard_opt1, ...");
mscoCmd->AvailableForStates(G4State_PreInit);
mscoCmd->SetToBeBroadcasted(false);
auto mregName = new G4UIparameter("regName",'s',false);
mscoCmd->SetParameter(mregName);
@@ -250,7 +251,7 @@ G4EmExtraParametersMessenger::G4EmExtraParametersMessenger(G4EmExtraParameters*
qeCmd = new G4UIcmdWithABool("/process/em/QuantumEntanglement",this);
qeCmd->SetGuidance("Enable quantum entanglement");
qeCmd->AvailableForStates(G4State_PreInit);
qeCmd->AvailableForStates(G4State_PreInit,G4State_Idle);
qeCmd->SetToBeBroadcasted(false);
dirSplitTargetCmd = new G4UIcmdWith3VectorAndUnit("/process/em/setDirectionalSplittingTarget",this);
@@ -98,7 +98,7 @@ G4EmTableUtil::PrepareEmProcess(G4VEmProcess* proc,
const G4DataVector* cuts = modelManager->Initialise(part, secPart, verb);
if(1 < verb) {
G4cout << "### G4VEmProcess::PreparePhysicsTable() done for "
G4cout << "### G4EmTableUtil::PreparePhysicsTable() done for "
<< proc->GetProcessName()
<< " and particle " << part->GetParticleName()
<< G4endl;
@@ -118,7 +118,7 @@ void G4EmTableUtil::BuildEmProcess(G4VEmProcess* proc,
{
G4String num = part->GetParticleName();
if(1 < verb) {
G4cout << "### G4VEmProcess::BuildPhysicsTable() for "
G4cout << "### G4EmTableUtil::BuildPhysicsTable() for "
<< proc->GetProcessName() << " and particle " << num
<< " buildLambdaTable=" << toBuild << " master= " << master
<< G4endl;
@@ -178,7 +178,7 @@ void G4EmTableUtil::BuildEmProcess(G4VEmProcess* proc,
}
if(1 < verb) {
G4cout << "### G4VEmProcess::BuildPhysicsTable() done for "
G4cout << "### G4EmTableUtil::BuildPhysicsTable() done for "
<< proc->GetProcessName() << " and particle " << num
<< " baseMat=" << baseMat << G4endl;
}
@@ -201,7 +201,7 @@ void G4EmTableUtil::BuildLambdaTable(G4VEmProcess* proc,
const G4bool splineFlag)
{
if(1 < verboseLevel) {
G4cout << "G4EmProcess::BuildLambdaTable() for process "
G4cout << "G4EmTableUtil::BuildLambdaTable() for process "
<< proc->GetProcessName() << " and particle "
<< part->GetParticleName() << G4endl;
}
@@ -290,7 +290,7 @@ void G4EmTableUtil::BuildLambdaTable(G4VEnergyLossProcess* proc,
const G4bool splineFlag)
{
if(1 < verboseLevel) {
G4cout << "G4EnergyLossProcess::BuildLambdaTable() for process "
G4cout << "G4EmTableUtil::BuildLambdaTable() for process "
<< proc->GetProcessName() << " and particle "
<< part->GetParticleName() << G4endl;
}
@@ -340,8 +340,9 @@ G4EmTableUtil::CheckIon(G4VEnergyLossProcess* proc,
const G4int verb, G4bool& isIon)
{
if(1 < verb) {
G4cout << "G4VEnergyLossProcess::PreparePhysicsTable for "
G4cout << "G4EmTableUtil::CheckIon for "
<< proc->GetProcessName() << " for " << part->GetParticleName()
<< " should be called from G4VEnergyLossProcess::PreparePhysicsTable"
<< G4endl;
}
const G4ParticleDefinition* particle = partLocal;
@@ -356,6 +357,8 @@ G4EmTableUtil::CheckIon(G4VEnergyLossProcess* proc,
const G4ParticleDefinition* theGIon = G4GenericIon::GenericIon();
isIon = true;
// this is a loop to compare pointers of G4GenericIon processes in order
// to confirm that for given particle the G4GenericIon physics is used
if(particle != theGIon) {
G4ProcessManager* pm = theGIon->GetProcessManager();
G4ProcessVector* v = pm->GetAlongStepProcessVector();
@@ -465,7 +468,7 @@ void G4EmTableUtil::BuildDEDXTable(G4VEnergyLossProcess* proc,
for(std::size_t i=0; i<numOfCouples; ++i) {
if(1 < verbose) {
G4cout << "G4VEnergyLossProcess::BuildDEDXVector idx= " << i
G4cout << "G4EmTableUtil::BuildDEDXVector idx= " << i
<< " flagTable=" << table->GetFlag(i)
<< " flagBuilder=" << bld->GetFlag(i) << G4endl;
}
@@ -491,7 +494,7 @@ void G4EmTableUtil::BuildDEDXTable(G4VEnergyLossProcess* proc,
}
if(1 < verbose) {
G4cout << "G4VEnergyLossProcess::BuildDEDXTable(): table is built for "
G4cout << "G4EmTableUtil::BuildDEDXTable(): table is built for "
<< part->GetParticleName()
<< " and process " << proc->GetProcessName()
<< G4endl;
@@ -517,7 +520,7 @@ void G4EmTableUtil::PrepareMscProcess(G4VMultipleScattering* proc,
part.GetParticleName() == "GenericIon") { isIon = true; }
if(1 < verb) {
G4cout << "### G4VMultipleScattering::PrepearPhysicsTable() for "
G4cout << "### G4EmTableUtil::PrepearPhysicsTable() for "
<< proc->GetProcessName()
<< " and particle " << part.GetParticleName()
<< " isIon: " << isIon << " isMaster: " << master
@@ -590,7 +593,7 @@ void G4EmTableUtil::BuildMscProcess(G4VMultipleScattering* proc,
}
}
if(1 < verb) {
G4cout << "### G4VMultipleScattering::BuildPhysicsTable() done for "
G4cout << "### G4EmTableUtil::BuildPhysicsTable() done for "
<< proc->GetProcessName()
<< " and particle " << part.GetParticleName() << G4endl;
}
@@ -651,7 +654,7 @@ G4bool G4EmTableUtil::StoreTable(G4VProcess* ptr,
if (1 < verb) G4cout << "Stored: " << name << G4endl;
} else {
res = false;
G4cout << "Fail to store: " << name << G4endl;
G4cout << "G4EmTableUtil::StoreTable fail to store: " << name << G4endl;
}
}
return res;
@@ -668,8 +671,10 @@ G4bool G4EmTableUtil::RetrieveTable(G4VProcess* ptr,
{
G4bool res = true;
if (nullptr == aTable) { return res; }
G4cout << tname << " table for " << part->GetParticleName()
<< " will be retrieved " << G4endl;
if (0 < verb) {
G4cout << tname << " table for " << part->GetParticleName()
<< " will be retrieved " << G4endl;
}
const G4String& name =
ptr->GetPhysicsTableFileName(part, dir, tname, ascii);
if(G4PhysicsTableHelper::RetrievePhysicsTable(aTable, name, ascii, spline)) {
@@ -685,8 +690,8 @@ G4bool G4EmTableUtil::RetrieveTable(G4VProcess* ptr,
}
} else {
res = false;
G4cout << "Fail to retrieve: " << tname << " from " << name << " for "
<< part->GetParticleName() << G4endl;
G4cout << "G4EmTableUtil::RetrieveTable fail to retrieve: " << tname
<< " from " << name << " for " << part->GetParticleName() << G4endl;
}
return res;
}
@@ -667,11 +667,6 @@ void G4LossTableManager::BuildPhysicsTable(
base_part_vector[i] = el->BaseParticle();
tables_are_built[i] = false;
all_tables_are_built= false;
if(!isActive[i]) {
el->SetIonisation(false);
tables_are_built[i] = true;
}
if(1 < verbose) {
G4cout << i <<". "<< el->GetProcessName();
if(el->Particle()) {
@@ -900,7 +895,6 @@ G4VEnergyLossProcess* G4LossTableManager::BuildTables(
// if(1<verbose) G4cout << *range << G4endl;
std::vector<G4PhysicsTable*> listSub;
std::vector<G4PhysicsTable*> listCSDA;
for (i=0; i<n_dedx; ++i) {
@@ -44,6 +44,8 @@
#include "G4EmConfigurator.hh"
#include "G4VMscModel.hh"
#include "G4ParticleChangeForMSC.hh"
#include "G4DynamicParticle.hh"
#include "G4Step.hh"
#include "G4StepPoint.hh"
@@ -72,6 +74,11 @@ G4TransportationWithMsc::G4TransportationWithMsc(ScatteringType type,
fEmManager = G4LossTableManager::Instance();
fModelManager = new G4EmModelManager;
if(type == ScatteringType::MultipleScattering)
{
fParticleChangeForMSC = new G4ParticleChangeForMSC;
}
G4ThreeVector zero;
fSubStepDynamicParticle =
new G4DynamicParticle(G4Electron::Definition(), zero);
@@ -85,6 +92,8 @@ G4TransportationWithMsc::G4TransportationWithMsc(ScatteringType type,
G4TransportationWithMsc::~G4TransportationWithMsc()
{
delete fModelManager;
delete fParticleChangeForMSC;
// fSubStepDynamicParticle is owned and also deleted by fSubStepTrack!
delete fSubStepTrack;
delete fSubStep;
@@ -103,7 +112,7 @@ void G4TransportationWithMsc::AddMscModel(G4VMscModel* mscModel, G4int order,
}
fModelManager->AddEmModel(order, mscModel, nullptr, region);
mscModel->SetParticleChange(&fParticleChange);
mscModel->SetParticleChange(fParticleChangeForMSC);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -136,15 +145,18 @@ void G4TransportationWithMsc::PreparePhysicsTable(
}
const G4int numberOfModels = fModelManager->NumberOfModels();
for(G4int i = 0; i < numberOfModels; ++i)
if(fType == ScatteringType::MultipleScattering)
{
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
msc->SetMasterThread(master);
msc->SetPolarAngleLimit(theParameters->MscThetaLimit());
G4double emax =
std::min(msc->HighEnergyLimit(), theParameters->MaxKinEnergy());
msc->SetHighEnergyLimit(emax);
msc->SetUseBaseMaterials(baseMat);
for(G4int i = 0; i < numberOfModels; ++i)
{
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
msc->SetMasterThread(master);
msc->SetPolarAngleLimit(theParameters->MscThetaLimit());
G4double emax =
std::min(msc->HighEnergyLimit(), theParameters->MaxKinEnergy());
msc->SetHighEnergyLimit(emax);
msc->SetUseBaseMaterials(baseMat);
}
}
fModelManager->Initialise(fFirstParticle, G4Electron::Electron(),
@@ -168,13 +180,16 @@ void G4TransportationWithMsc::BuildPhysicsTable(
// Initialisation of models.
const G4int numberOfModels = fModelManager->NumberOfModels();
for(G4int i = 0; i < numberOfModels; ++i)
if(fType == ScatteringType::MultipleScattering)
{
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
auto msc0 =
static_cast<G4VMscModel*>(masterProcess->fModelManager->GetModel(i));
msc->SetCrossSectionTable(msc0->GetCrossSectionTable(), false);
msc->InitialiseLocal(fFirstParticle, msc0);
for(G4int i = 0; i < numberOfModels; ++i)
{
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
auto msc0 =
static_cast<G4VMscModel*>(masterProcess->fModelManager->GetModel(i));
msc->SetCrossSectionTable(msc0->GetCrossSectionTable(), false);
msc->InitialiseLocal(fFirstParticle, msc0);
}
}
}
}
@@ -202,11 +217,14 @@ void G4TransportationWithMsc::StartTracking(G4Track* track)
fSubStepDynamicParticle->SetDefinition(currParticle);
const G4int numberOfModels = fModelManager->NumberOfModels();
for(G4int i = 0; i < numberOfModels; ++i)
if(fType == ScatteringType::MultipleScattering)
{
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
msc->StartTracking(track);
msc->SetIonisation(ionisation, currParticle);
for(G4int i = 0; i < numberOfModels; ++i)
{
auto msc = static_cast<G4VMscModel*>(fModelManager->GetModel(i));
msc->StartTracking(track);
msc->SetIonisation(ionisation, currParticle);
}
}
// Ensure that field propagation state is also cleared / prepared
@@ -348,15 +366,15 @@ G4double G4TransportationWithMsc::AlongStepGetPhysicalInteractionLength(
static constexpr G4double sFact = 0.99;
// The call to SampleScattering() *may* directly fill in the changed
// direction into fParticleChange, so we have to:
// direction into fParticleChangeForMSC, so we have to:
// 1) Make sure the momentum direction is initialized.
fParticleChange.ProposeMomentumDirection(fTransportEndMomentumDir);
fParticleChangeForMSC->ProposeMomentumDirection(fTransportEndMomentumDir);
// 2) Call SampleScattering(), which *may* change it.
const G4ThreeVector displacement =
mscModel->SampleScattering(fTransportEndMomentumDir, minSafety);
// 3) Get the changed direction and inform G4Transportation.
fMomentumChanged = true;
fTransportEndMomentumDir = *fParticleChange.GetMomentumDirection();
fTransportEndMomentumDir = *fParticleChangeForMSC->GetProposedMomentumDirection();
const G4double r2 = displacement.mag2();
if(r2 > kMinDisplacement2)
@@ -551,13 +551,10 @@ void G4VEnergyLossProcess::StartTracking(G4Track* track)
if(nullptr != baseParticle) {
massRatio = baseParticle->GetPDGMass()/newmass;
logMassRatio = G4Log(massRatio);
} else if(isIon) {
} else {
massRatio = CLHEP::proton_mass_c2/newmass;
logMassRatio = G4Log(massRatio);
} else {
massRatio = 1.0;
logMassRatio = 0.0;
}
}
}
// forced biasing only for primary particles
if(nullptr != biasManager) {