Import Geant4 11.2.0 source tree
This commit is contained in:
@@ -6,6 +6,50 @@ It must **not** be used as a substitute for writing good git commit messages!
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
## 2023-11-03 Ben Morgan (emstand-V11-01-24)
|
||||
- Use "G4" prefixed version of EXPAT/ZLIB CMake variables
|
||||
|
||||
## 2023-10-19 V.Ivanchenko (emstand-V11-01-23)
|
||||
- G4UrbanMscModel - (L. Urban) tuned step limit parameterisation for
|
||||
the case of enabled optional algorithm of lateral displacement.
|
||||
The default tracking is not affected.
|
||||
|
||||
## 2023-10-07 V.Ivanchenko (emstand-V11-01-22)
|
||||
- G4ASTARStopping, G4PSTARStopping, G4IonICRU73Data - use logarithmic search
|
||||
of bin for free vectors
|
||||
|
||||
## 2023-10-05 V.Ivanchenko (emstand-V11-01-21)
|
||||
- G4UrbanMscModel - (L. Urban) optional method SampleDisplacementNew(..) is
|
||||
rewritten. This method is not used so far in any EM physics configurations
|
||||
by default but may be enabled via UI command and/or C++ interface
|
||||
|
||||
## 2023-10-02 V.Ivanchenko (emstand-V11-01-20)
|
||||
- G4eBremsstrahlungRelModel - fixed potential division by zero if advanced
|
||||
compiler options are used, use G4Pow
|
||||
|
||||
## 2023-08-21 V.Ivanchenko (emstand-V11-01-19)
|
||||
- G4SeltzerBergerModel - implement inheritance from G4VEmModel instead of
|
||||
G4eBremsstrahlungRelModel, which means re-implementing common methods
|
||||
by cut and paster from G4eBremsstrahlungRelModel and removal LPM
|
||||
computations; use std::applyOnce approach to initilize static data;
|
||||
upplied code format.
|
||||
- G4eBremsstrahlungRelModel - use std::applyOncy approach to initilize
|
||||
static data. This MR is a continuation of implementing a general
|
||||
solution for initialisation of static data proposed by Stephan
|
||||
Hageboeck
|
||||
|
||||
## 2023-06-18 V.Ivanchenko (emstand-V11-01-18)
|
||||
- G4BetheHeitlerModel, G4PairProductionRelModel, G4eBremsstrahlungRelModel,
|
||||
G4SeltzerBergerModel - further reorganized initialisation for #2543 and
|
||||
considered neccesity to fix, Initilise(..) method described by Stephan
|
||||
Hageboeck, to have thread safe check if a model is the first
|
||||
instance of the class, set lock and perform initilisation of all static
|
||||
data. Results of standard EM tests are unchanged.
|
||||
|
||||
## 2023-06-17 V.Ivanchenko (emstand-V11-01-17)
|
||||
- G4UrbanMscModel - reduced number of re-computations of safety,
|
||||
results of EM tests unchanged
|
||||
|
||||
## 2023-06-13 V.Ivanchenko (emstand-V11-01-16)
|
||||
- G4LindHardSorensenIonModel - do not try to use ICRU73 data for projectile Z>80
|
||||
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
// 1. S.M. Seltzer and M.J. Berger Nucl. Instr. Meth. B12 (1985) 95
|
||||
// 2. S.M. Seltzer and M.J. Berger Atomic data and Nuclear Data
|
||||
// Tables 35 (1986) 345
|
||||
// Cross section computation in the base class G4eBremsstrahlungRelModel
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
//
|
||||
@@ -59,13 +58,15 @@
|
||||
#ifndef G4SeltzerBergerModel_h
|
||||
#define G4SeltzerBergerModel_h 1
|
||||
|
||||
#include "G4VEmModel.hh"
|
||||
#include "G4eBremsstrahlungRelModel.hh"
|
||||
#include "globals.hh"
|
||||
|
||||
class G4Physics2DVector;
|
||||
class G4SBBremTable;
|
||||
class G4ParticleChangeForLoss;
|
||||
|
||||
class G4SeltzerBergerModel : public G4eBremsstrahlungRelModel
|
||||
class G4SeltzerBergerModel : public G4VEmModel
|
||||
{
|
||||
|
||||
public:
|
||||
@@ -77,6 +78,21 @@ public:
|
||||
|
||||
void Initialise(const G4ParticleDefinition*, const G4DataVector&) override;
|
||||
|
||||
void InitialiseLocal(const G4ParticleDefinition*,
|
||||
G4VEmModel* masterModel) override;
|
||||
|
||||
G4double ComputeDEDXPerVolume(const G4Material*,
|
||||
const G4ParticleDefinition*,
|
||||
G4double ekin,
|
||||
G4double cutEnergy) override;
|
||||
|
||||
G4double ComputeCrossSectionPerAtom(const G4ParticleDefinition*,
|
||||
G4double ekin,
|
||||
G4double zet,
|
||||
G4double,
|
||||
G4double cutEnergy,
|
||||
G4double maxEnergy = DBL_MAX) override;
|
||||
|
||||
void SampleSecondaries(std::vector<G4DynamicParticle*>*,
|
||||
const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle*,
|
||||
@@ -86,6 +102,10 @@ public:
|
||||
void SetupForMaterial(const G4ParticleDefinition*,
|
||||
const G4Material*, G4double) override;
|
||||
|
||||
G4double MinPrimaryEnergy(const G4Material*,
|
||||
const G4ParticleDefinition*,
|
||||
G4double cutEnergy) override;
|
||||
|
||||
inline void SetBicubicInterpolationFlag(G4bool val)
|
||||
{ fIsUseBicubicInterpolation = val; };
|
||||
|
||||
@@ -93,33 +113,58 @@ public:
|
||||
G4SeltzerBergerModel & operator=(const G4SeltzerBergerModel &right) = delete;
|
||||
G4SeltzerBergerModel(const G4SeltzerBergerModel&) = delete;
|
||||
|
||||
protected:
|
||||
|
||||
G4double ComputeDXSectionPerAtom(G4double gammaEnergy) override;
|
||||
|
||||
private:
|
||||
|
||||
void SetParticle(const G4ParticleDefinition* p);
|
||||
|
||||
void ReadData(G4int Z);
|
||||
|
||||
G4double ComputeBremLoss(G4double cutEnergy);
|
||||
|
||||
G4double ComputeXSectionPerAtom(G4double cutEnergy);
|
||||
|
||||
G4double ComputeDXSectionPerAtom(G4double gammaEnergy);
|
||||
|
||||
G4double SampleEnergyTransfer(const G4double kineticEnergy,
|
||||
const G4double logKineticEnergy,
|
||||
const G4double cut,
|
||||
const G4double emax);
|
||||
|
||||
static constexpr G4int gMaxZet = 101;
|
||||
static constexpr G4double gExpNumLimit = -12.;
|
||||
static G4double gYLimitData[gMaxZet];
|
||||
protected:
|
||||
|
||||
G4ParticleChangeForLoss* fParticleChange{nullptr};
|
||||
|
||||
private:
|
||||
|
||||
static constexpr G4int gMaxZet{101};
|
||||
static constexpr G4double gExpNumLimit{-12.};
|
||||
static G4double gYLimitData[gMaxZet];
|
||||
static G4Physics2DVector* gSBDCSData[gMaxZet];
|
||||
static G4SBBremTable* gSBSamplingTable;
|
||||
static G4SBBremTable* gSBSamplingTable;
|
||||
static const G4double gBremFactor;
|
||||
static const G4double gMigdalConstant;
|
||||
|
||||
G4bool fIsUseBicubicInterpolation;
|
||||
G4bool fIsUseSamplingTables;
|
||||
G4bool fIsUseBicubicInterpolation{false};
|
||||
G4bool fIsUseSamplingTables{true};
|
||||
G4bool fIsElectron{true};
|
||||
G4bool fIsScatOffElectron{false};
|
||||
G4bool isInitializer{false};
|
||||
//
|
||||
G4int fCurrentIZ{0};
|
||||
G4int fNumWarnings{0};
|
||||
|
||||
G4int fNumWarnings;
|
||||
const G4ParticleDefinition* fPrimaryParticle{nullptr};
|
||||
G4ParticleDefinition* fGammaParticle;
|
||||
|
||||
size_t fIndx;
|
||||
size_t fIndy;
|
||||
G4bool isFirstInstance{false};
|
||||
// cash
|
||||
G4double fPrimaryKinEnergy{0.};
|
||||
G4double fPrimaryTotalEnergy{0.};
|
||||
G4double fDensityFactor{0.};
|
||||
G4double fDensityCorr{0.};
|
||||
G4double fLowestKinEnergy;
|
||||
|
||||
std::size_t fIndx{0};
|
||||
std::size_t fIndy{0};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -179,7 +179,7 @@ private:
|
||||
G4double rndmarray[2];
|
||||
|
||||
struct mscData {
|
||||
G4double Z23, sqrtZ;
|
||||
G4double Z23, sqrtZ, factmin;
|
||||
G4double coeffth1, coeffth2;
|
||||
G4double coeffc1, coeffc2, coeffc3, coeffc4;
|
||||
G4double stepmina, stepminb;
|
||||
@@ -233,8 +233,8 @@ inline G4double G4UrbanMscModel::SimpleScattering()
|
||||
{
|
||||
// 'large angle scattering'
|
||||
// 2 model functions with correct xmean and x2mean
|
||||
G4double a = (2.*xmeanth+9.*x2meanth-3.)/(2.*xmeanth-3.*x2meanth+1.);
|
||||
G4double prob = (a+2.)*xmeanth/a;
|
||||
const G4double a = (2.*xmeanth+9.*x2meanth-3.)/(2.*xmeanth-3.*x2meanth+1.);
|
||||
const G4double prob = (a+2.)*xmeanth/a;
|
||||
|
||||
// sampling
|
||||
rndmEngineMod->flatArray(2, rndmarray);
|
||||
@@ -248,8 +248,9 @@ inline G4double G4UrbanMscModel::ComputeStepmin()
|
||||
{
|
||||
// define stepmin using estimation of the ratio
|
||||
// of lambda_elastic/lambda_transport
|
||||
G4double rat = currentKinEnergy*invmev;
|
||||
return lambda0*1.e-3/(2.e-3+rat*(msc[idx]->stepmina+msc[idx]->stepminb*rat));
|
||||
const G4double rat = currentKinEnergy*invmev;
|
||||
return lambda0*msc[idx]->factmin/
|
||||
(0.002 + rat*(msc[idx]->stepmina + msc[idx]->stepminb*rat));
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
@@ -143,7 +143,7 @@ private:
|
||||
private:
|
||||
|
||||
G4bool fIsUseCompleteScreening = false;
|
||||
G4bool fIsFirstInstance = false;
|
||||
G4bool fIsInitializer = false;
|
||||
G4bool fUseLPM = true;
|
||||
|
||||
protected:
|
||||
|
||||
@@ -179,4 +179,4 @@ geant4_module_link_libraries(G4emstandard
|
||||
G4ions
|
||||
G4mesons
|
||||
G4procman
|
||||
${ZLIB_LIBRARIES})
|
||||
${G4ZLIB_LIBRARIES})
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
|
||||
#include "G4ASTARStopping.hh"
|
||||
#include "G4NISTStoppingData.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
@@ -356,6 +357,7 @@ void G4ASTARStopping::AddData(const G4float* stop, const G4Material* mat)
|
||||
v->PutValues(i, T0[i], stop[i]*fac);
|
||||
}
|
||||
v->FillSecondDerivatives();
|
||||
v->EnableLogBinSearch(G4EmParameters::Instance()->NumberForFreeVector());
|
||||
materials.push_back(mat);
|
||||
sdata.push_back(v);
|
||||
++nvectors;
|
||||
|
||||
@@ -86,18 +86,15 @@ void G4BetheHeitlerModel::Initialise(const G4ParticleDefinition* p,
|
||||
{
|
||||
if (!fParticleChange) { fParticleChange = GetParticleChangeForGamma(); }
|
||||
|
||||
if (gElementData.empty()) {
|
||||
if (isFirstInstance || gElementData.empty()) {
|
||||
G4AutoLock l(&theBetheHMutex);
|
||||
if (gElementData.empty()) {
|
||||
isFirstInstance = true;
|
||||
gElementData.resize(gMaxZet+1, nullptr);
|
||||
}
|
||||
l.unlock();
|
||||
}
|
||||
|
||||
// static data should be initialised only in the one instance
|
||||
if(isFirstInstance) {
|
||||
// static data should be initialised only in the one instance
|
||||
InitialiseElementData();
|
||||
l.unlock();
|
||||
}
|
||||
// element selectors should be initialised in the master thread
|
||||
if(IsMaster()) {
|
||||
|
||||
@@ -407,6 +407,7 @@ G4IonICRU73Data::RetrieveVector(std::ostringstream& ost, G4bool warn)
|
||||
FatalException, ed, "Check G4LEDATA");
|
||||
} else {
|
||||
if(fSpline) { fVector->FillSecondDerivatives(); }
|
||||
fVector->EnableLogBinSearch(G4EmParameters::Instance()->NumberForFreeVector());
|
||||
v = new G4PhysicsLogVector(fEmin, fEmax, fNbins, fSpline);
|
||||
for(G4int i=0; i<=fNbins; ++i) {
|
||||
G4double e = v->Energy(i);
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
|
||||
#include "G4PSTARStopping.hh"
|
||||
#include "G4NISTStoppingData.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
@@ -357,6 +358,7 @@ void G4PSTARStopping::AddData(const G4float* stop, const G4Material* mat)
|
||||
v->PutValues(i, T0[i], ((G4double)stop[i])*fac);
|
||||
}
|
||||
v->FillSecondDerivatives();
|
||||
v->EnableLogBinSearch(G4EmParameters::Instance()->NumberForFreeVector());
|
||||
materials.push_back(mat);
|
||||
sdata.push_back(v);
|
||||
++nvectors;
|
||||
|
||||
@@ -124,7 +124,7 @@ G4PairProductionRelModel::G4PairProductionRelModel(const G4ParticleDefinition*,
|
||||
fTheElectron(G4Electron::Electron()), fThePositron(G4Positron::Positron()),
|
||||
fParticleChange(nullptr)
|
||||
{
|
||||
// gamma energy below which the parametrized atomic x-section is used (80 GeV)
|
||||
// gamma energy below which the parametrized atomic x-section is used (30 GeV)
|
||||
fParametrizedXSectionThreshold = 30.0*CLHEP::GeV;
|
||||
// gamma energy below the Coulomb correction is turned off (50 MeV)
|
||||
fCoulombCorrectionThreshold = 50.0*CLHEP::MeV;
|
||||
@@ -153,21 +153,19 @@ void G4PairProductionRelModel::Initialise(const G4ParticleDefinition* p,
|
||||
{
|
||||
if(nullptr == fParticleChange) { fParticleChange = GetParticleChangeForGamma(); }
|
||||
|
||||
if (gElementData.empty()) {
|
||||
if (isFirstInstance || gElementData.empty()) {
|
||||
// init element data and LPM funcs
|
||||
G4AutoLock l(&thePairProdRelMutex);
|
||||
if (gElementData.empty()) {
|
||||
isFirstInstance = true;
|
||||
gElementData.resize(gMaxZet+1, nullptr);
|
||||
}
|
||||
l.unlock();
|
||||
}
|
||||
// static data should be initialised only in the one instance
|
||||
if(isFirstInstance) {
|
||||
// static data should be initialised only in the one instance
|
||||
InitialiseElementData();
|
||||
if (fIsUseLPMCorrection) {
|
||||
InitLPMFunctions();
|
||||
}
|
||||
l.unlock();
|
||||
}
|
||||
// element selectors should be initialised in the master thread
|
||||
if (IsMaster()) {
|
||||
|
||||
@@ -62,6 +62,8 @@
|
||||
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4ProductionCutsTable.hh"
|
||||
#include "G4Gamma.hh"
|
||||
#include "G4Electron.hh"
|
||||
|
||||
#include "G4Physics2DVector.hh"
|
||||
#include "G4Exp.hh"
|
||||
@@ -73,33 +75,56 @@
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
G4Physics2DVector* G4SeltzerBergerModel::gSBDCSData[] = { nullptr };
|
||||
G4SBBremTable* G4SeltzerBergerModel::gSBSamplingTable = nullptr;
|
||||
G4double G4SeltzerBergerModel::gYLimitData[] = { 0.0 };
|
||||
G4double G4SeltzerBergerModel::gYLimitData[] = { 0.0 };
|
||||
G4Physics2DVector* G4SeltzerBergerModel::gSBDCSData[] = { nullptr };
|
||||
G4SBBremTable* G4SeltzerBergerModel::gSBSamplingTable = nullptr;
|
||||
|
||||
// constant DCS factor: 16\alpha r_0^2/3
|
||||
const G4double G4SeltzerBergerModel::gBremFactor
|
||||
= 16. * CLHEP::fine_structure_const * CLHEP::classic_electr_radius
|
||||
* CLHEP::classic_electr_radius/3.;
|
||||
|
||||
// Migdal's constant: 4\pi r_0*electron_reduced_compton_wavelength^2
|
||||
const G4double G4SeltzerBergerModel::gMigdalConstant
|
||||
= 4. * CLHEP::pi * CLHEP::classic_electr_radius
|
||||
* CLHEP::electron_Compton_length * CLHEP::electron_Compton_length;
|
||||
|
||||
static constexpr G4double twoMass = 2* CLHEP::electron_mass_c2;
|
||||
static constexpr G4double kAlpha = CLHEP::twopi*CLHEP::fine_structure_const;
|
||||
static std::once_flag applyOnce;
|
||||
|
||||
namespace
|
||||
{
|
||||
G4Mutex theSBMutex = G4MUTEX_INITIALIZER;
|
||||
}
|
||||
|
||||
static const G4double kMC2 = CLHEP::electron_mass_c2;
|
||||
static const G4double kAlpha = CLHEP::twopi*CLHEP::fine_structure_const;
|
||||
// for numerical integration on [0,1]
|
||||
const G4double gXGL[8] = {
|
||||
1.98550718e-02, 1.01666761e-01, 2.37233795e-01, 4.08282679e-01,
|
||||
5.91717321e-01, 7.62766205e-01, 8.98333239e-01, 9.80144928e-01
|
||||
};
|
||||
const G4double gWGL[8] = {
|
||||
5.06142681e-02, 1.11190517e-01, 1.56853323e-01, 1.81341892e-01,
|
||||
1.81341892e-01, 1.56853323e-01, 1.11190517e-01, 5.06142681e-02
|
||||
};
|
||||
}
|
||||
|
||||
G4SeltzerBergerModel::G4SeltzerBergerModel(const G4ParticleDefinition* p,
|
||||
const G4String& nam)
|
||||
: G4eBremsstrahlungRelModel(p,nam), fIsUseBicubicInterpolation(false),
|
||||
fIsUseSamplingTables(true), fNumWarnings(0), fIndx(0), fIndy(0)
|
||||
: G4VEmModel(nam),
|
||||
fGammaParticle(G4Gamma::Gamma()),
|
||||
fLowestKinEnergy(1.0*CLHEP::keV)
|
||||
{
|
||||
fLowestKinEnergy = 1.0*keV;
|
||||
SetLowEnergyLimit(fLowestKinEnergy);
|
||||
SetAngularDistribution(new G4ModifiedTsai());
|
||||
if (fPrimaryParticle != p) { SetParticle(p); }
|
||||
}
|
||||
|
||||
G4SeltzerBergerModel::~G4SeltzerBergerModel()
|
||||
{
|
||||
// delete SB-DCS data per Z
|
||||
if (isFirstInstance) {
|
||||
if (isInitializer) {
|
||||
for (std::size_t iz = 0; iz < gMaxZet; ++iz) {
|
||||
if (gSBDCSData[iz]) {
|
||||
delete gSBDCSData[iz];
|
||||
@@ -116,23 +141,20 @@ G4SeltzerBergerModel::~G4SeltzerBergerModel()
|
||||
void G4SeltzerBergerModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector& cuts)
|
||||
{
|
||||
// parameters in each thread
|
||||
if (fPrimaryParticle != p) {
|
||||
SetParticle(p);
|
||||
}
|
||||
fIsUseSamplingTables = G4EmParameters::Instance()->EnableSamplingTable();
|
||||
fCurrentIZ = 0;
|
||||
|
||||
// initialise static tables for the Seltzer-Berger model
|
||||
if (0.0 == gYLimitData[0]) {
|
||||
std::call_once(applyOnce, [this]() { isInitializer = true; });
|
||||
|
||||
if (isInitializer) {
|
||||
G4AutoLock l(&theSBMutex);
|
||||
if (0.0 == gYLimitData[0]) {
|
||||
isFirstInstance = true;
|
||||
gYLimitData[0] = 1.0;
|
||||
}
|
||||
l.unlock();
|
||||
}
|
||||
|
||||
// initialise base class
|
||||
G4eBremsstrahlungRelModel::Initialise(p, cuts);
|
||||
|
||||
// initialisation per element is done only once
|
||||
if (isFirstInstance) {
|
||||
// initialisation per element is done only once
|
||||
auto elemTable = G4Element::GetElementTable();
|
||||
for (auto const & elm : *elemTable) {
|
||||
G4int Z = std::max(1,std::min(elm->GetZasInt(), gMaxZet-1));
|
||||
@@ -148,7 +170,33 @@ void G4SeltzerBergerModel::Initialise(const G4ParticleDefinition* p,
|
||||
gSBSamplingTable->Initialize(std::max(fLowestKinEnergy, LowEnergyLimit()),
|
||||
HighEnergyLimit());
|
||||
}
|
||||
l.unlock();
|
||||
}
|
||||
// element selectors are initialized in the master thread
|
||||
if (IsMaster()) {
|
||||
InitialiseElementSelectors(p, cuts);
|
||||
}
|
||||
// initialisation in all threads
|
||||
if (nullptr == fParticleChange) {
|
||||
fParticleChange = GetParticleChangeForLoss();
|
||||
}
|
||||
auto trmodel = GetTripletModel();
|
||||
if (nullptr != trmodel) {
|
||||
trmodel->Initialise(p, cuts);
|
||||
fIsScatOffElectron = true;
|
||||
}
|
||||
}
|
||||
|
||||
void G4SeltzerBergerModel::InitialiseLocal(const G4ParticleDefinition*,
|
||||
G4VEmModel* masterModel)
|
||||
{
|
||||
SetElementSelectors(masterModel->GetElementSelectors());
|
||||
}
|
||||
|
||||
void G4SeltzerBergerModel::SetParticle(const G4ParticleDefinition* p)
|
||||
{
|
||||
fPrimaryParticle = p;
|
||||
fIsElectron = (p == G4Electron::Electron());
|
||||
}
|
||||
|
||||
void G4SeltzerBergerModel::ReadData(G4int Z) {
|
||||
@@ -174,7 +222,7 @@ void G4SeltzerBergerModel::ReadData(G4int Z) {
|
||||
v->SetBicubicInterpolation(fIsUseBicubicInterpolation);
|
||||
static const G4double emaxlog = 4*G4Log(10.);
|
||||
gYLimitData[Z] = v->Value(0.97, emaxlog, fIndx, fIndy);
|
||||
gSBDCSData[Z] = v;
|
||||
gSBDCSData[Z] = v;
|
||||
} else {
|
||||
G4ExceptionDescription ed;
|
||||
ed << "Bremsstrahlung data file <" << ost.str().c_str()
|
||||
@@ -186,6 +234,191 @@ void G4SeltzerBergerModel::ReadData(G4int Z) {
|
||||
}
|
||||
}
|
||||
|
||||
// minimum primary (e-/e+) energy at which discrete interaction is possible
|
||||
G4double G4SeltzerBergerModel::MinPrimaryEnergy(const G4Material*,
|
||||
const G4ParticleDefinition*,
|
||||
G4double cut)
|
||||
{
|
||||
return std::max(fLowestKinEnergy, cut);
|
||||
}
|
||||
|
||||
// Sets kinematical variables like E_kin, E_t and some material dependent
|
||||
// for characteristic photon energy k_p (more exactly
|
||||
// k_p^2) for the Ter-Mikaelian suppression effect.
|
||||
void G4SeltzerBergerModel::SetupForMaterial(const G4ParticleDefinition*,
|
||||
const G4Material* mat,
|
||||
G4double kinEnergy)
|
||||
{
|
||||
fDensityFactor = gMigdalConstant*mat->GetElectronDensity();
|
||||
// calculate threshold for density effect: k_p = sqrt(fDensityCorr)
|
||||
fPrimaryKinEnergy = kinEnergy;
|
||||
fPrimaryTotalEnergy = kinEnergy + CLHEP::electron_mass_c2;
|
||||
fDensityCorr = fDensityFactor*fPrimaryTotalEnergy*fPrimaryTotalEnergy;
|
||||
}
|
||||
|
||||
// Computes the restricted dE/dx as the appropriate weight of the individual
|
||||
// element contributions that are computed by numerically integrating the DCS.
|
||||
G4double
|
||||
G4SeltzerBergerModel::ComputeDEDXPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double cutEnergy)
|
||||
{
|
||||
G4double dedx = 0.0;
|
||||
if (nullptr == fPrimaryParticle) {
|
||||
SetParticle(p);
|
||||
}
|
||||
if (kineticEnergy <= fLowestKinEnergy) {
|
||||
return dedx;
|
||||
}
|
||||
// maximum value of the dE/dx integral (the minimum is 0 of course)
|
||||
G4double tmax = std::min(cutEnergy, kineticEnergy);
|
||||
if (tmax == 0.0) {
|
||||
return dedx;
|
||||
}
|
||||
// sets kinematical and material related variables
|
||||
SetupForMaterial(fPrimaryParticle, material, kineticEnergy);
|
||||
// get element compositions of the material
|
||||
const G4ElementVector* theElemVector = material->GetElementVector();
|
||||
const G4double* theAtomNumDensVector = material->GetAtomicNumDensityVector();
|
||||
const std::size_t numberOfElements = theElemVector->size();
|
||||
// loop over the elements of the material and compute their contributions to
|
||||
// the restricted dE/dx by numerical integration of the dependent part of DCS
|
||||
for (std::size_t ie = 0; ie < numberOfElements; ++ie) {
|
||||
G4VEmModel::SetCurrentElement((*theElemVector)[ie]);
|
||||
G4int Z = (*theElemVector)[ie]->GetZasInt();
|
||||
fCurrentIZ = std::min(Z, gMaxZet);
|
||||
dedx += (Z*Z)*theAtomNumDensVector[ie]*ComputeBremLoss(tmax);
|
||||
}
|
||||
// apply the constant factor C/Z = 16\alpha r_0^2/3
|
||||
dedx *= gBremFactor;
|
||||
return std::max(dedx, 0.);
|
||||
}
|
||||
|
||||
// Computes the integral part of the restricted dE/dx contribution from a given
|
||||
// element (Z) by numerically integrating the k dependent DCS between
|
||||
// k_min=0 and k_max = tmax = min[gamma-cut, electron-kinetic-energy].
|
||||
// The numerical integration is done by dividing the integration range into 'n'
|
||||
// subintervals and an 8 pint GL integral (on [0,1]) is performed on each sub-
|
||||
// inteval by tranforming k to alpha=k/E_t (E_t is the total energy of the e-)
|
||||
// and each sub-interavl is transformed to [0,1]. So the integrastion is done
|
||||
// in xi(alpha) = xi(k) = [k/E_t-alpha_i]/delta where alpha_i=(i-1)*delta for
|
||||
// the i = 1,2,..,n-th sub-interval so xi(k) in [0,1] on each sub-intevals.
|
||||
// This transformation from 'k' to 'xi(k)' results in a multiplicative factor
|
||||
// of E_t*delta at each step.
|
||||
// The restricted dE/dx = N int_{0}^{k_max} k*ds/dk dk. In this case not
|
||||
// the ds/dk(Z,k) but ds/dk(Z,k)*[F*k/C] is computed since:
|
||||
// (i) what we need here is ds/dk*k and not k so this multiplication is done
|
||||
// (ii) the Ter-Mikaelian suppression i.e. F related factor is done here
|
||||
// (iii) the constant factor C (includes Z^2 as well)is accounted in the caller
|
||||
G4double G4SeltzerBergerModel::ComputeBremLoss(G4double tmax)
|
||||
{
|
||||
// number of intervals and integration step
|
||||
const G4double alphaMax = tmax/fPrimaryTotalEnergy;
|
||||
const G4int nSub = (G4int)(20*alphaMax)+3;
|
||||
const G4double delta = alphaMax/((G4double)nSub);
|
||||
// set minimum value of the first sub-inteval
|
||||
G4double alpha_i = 0.0;
|
||||
G4double dedxInteg = 0.0;
|
||||
for (G4int l = 0; l < nSub; ++l) {
|
||||
for (G4int igl = 0; igl < 8; ++igl) {
|
||||
// compute the emitted photon energy k
|
||||
const G4double k = (alpha_i+gXGL[igl]*delta)*fPrimaryTotalEnergy;
|
||||
// compute the DCS value at k (without the constant, the 1/k, 1/F factors)
|
||||
const G4double dcs = ComputeDXSectionPerAtom(k);
|
||||
// account Ter-Mikaelian suppression: times 1/F with F = 1+(k_p/k)^2
|
||||
dedxInteg += gWGL[igl]*dcs/(1.0+fDensityCorr/(k*k));
|
||||
}
|
||||
// update sub-interval minimum value
|
||||
alpha_i += delta;
|
||||
}
|
||||
// apply corrections due to variable transformation i.e. E_t*delta
|
||||
dedxInteg *= delta*fPrimaryTotalEnergy;
|
||||
return std::max(dedxInteg,0.);
|
||||
}
|
||||
|
||||
// Computes restrected atomic cross section by numerically integrating the
|
||||
// DCS between the proper kinematical limits accounting the gamma production cut
|
||||
G4double
|
||||
G4SeltzerBergerModel::ComputeCrossSectionPerAtom(const G4ParticleDefinition* p,
|
||||
G4double kineticEnergy,
|
||||
G4double Z,
|
||||
G4double,
|
||||
G4double cut,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
G4double crossSection = 0.0;
|
||||
if (nullptr == fPrimaryParticle) {
|
||||
SetParticle(p);
|
||||
}
|
||||
if (kineticEnergy <= fLowestKinEnergy) {
|
||||
return crossSection;
|
||||
}
|
||||
// min/max kinetic energy limits of the DCS integration:
|
||||
const G4double tmin = std::min(cut, kineticEnergy);
|
||||
const G4double tmax = std::min(maxEnergy, kineticEnergy);
|
||||
// zero restricted x-section if e- kinetic energy is below gamma cut
|
||||
if (tmin >= tmax) {
|
||||
return crossSection;
|
||||
}
|
||||
fCurrentIZ = std::min(G4lrint(Z), gMaxZet);
|
||||
// integrate numerically (dependent part of) the DCS between the kin. limits:
|
||||
// a. integrate between tmin and kineticEnergy of the e-
|
||||
crossSection = ComputeXSectionPerAtom(tmin);
|
||||
// allow partial integration: only if maxEnergy < kineticEnergy
|
||||
// b. integrate between tmax and kineticEnergy (tmax=maxEnergy in this case)
|
||||
// (so the result in this case is the integral of DCS between tmin and
|
||||
// maxEnergy)
|
||||
if (tmax < kineticEnergy) {
|
||||
crossSection -= ComputeXSectionPerAtom(tmax);
|
||||
}
|
||||
// multiply with the constant factors: 16\alpha r_0^2/3 Z^2
|
||||
crossSection *= Z*Z*gBremFactor;
|
||||
return std::max(crossSection, 0.);
|
||||
}
|
||||
|
||||
// Numerical integral of the (k dependent part of) DCS between k_min=tmin and
|
||||
// k_max = E_k (where E_k is the kinetic energy of the e- and tmin is the
|
||||
// minimum of energy of the emitted photon). The integration is done in the
|
||||
// transformed alpha(k) = ln(k/E_t) variable (with E_t being the total energy of
|
||||
// the primary e-). The integration range is divided into n sub-intervals with
|
||||
// delta = [ln(k_min/E_t)-ln(k_max/E_t)]/n width each. An 8 point GL integral
|
||||
// on [0,1] is applied on each sub-inteval so alpha is transformed to
|
||||
// xi(alpha) = xi(k) = [ln(k/E_t)-alpha_i]/delta where alpha_i = ln(k_min/E_t) +
|
||||
// (i-1)*delta for the i = 1,2,..,n-th sub-interval and xi(k) in [0,1] on each
|
||||
// sub-intevals. From the transformed xi, k(xi) = E_t exp[xi*delta+alpha_i].
|
||||
// Since the integration is done in variable xi instead of k this
|
||||
// transformation results in a multiplicative factor of k*delta at each step.
|
||||
// However, DCS differential in k is ~1/k so the multiplicative factor is simple
|
||||
// becomes delta and the 1/k factor is dropped from the DCS computation.
|
||||
// Ter-Mikaelian suppression is always accounted
|
||||
G4double G4SeltzerBergerModel::ComputeXSectionPerAtom(G4double tmin)
|
||||
{
|
||||
G4double xSection = 0.0;
|
||||
const G4double alphaMin = G4Log(tmin/fPrimaryTotalEnergy);
|
||||
const G4double alphaMax = G4Log(fPrimaryKinEnergy/fPrimaryTotalEnergy);
|
||||
const G4int nSub = (G4int)(0.45*(alphaMax-alphaMin))+4;
|
||||
const G4double delta = (alphaMax-alphaMin)/((G4double)nSub);
|
||||
// set minimum value of the first sub-inteval
|
||||
G4double alpha_i = alphaMin;
|
||||
for (G4int l = 0; l < nSub; ++l) {
|
||||
for (G4int igl = 0; igl < 8; ++igl) {
|
||||
// compute the emitted photon energy k
|
||||
const G4double k = G4Exp(alpha_i+gXGL[igl]*delta)*fPrimaryTotalEnergy;
|
||||
// compute the DCS value at k (without the constant, the 1/k, 1/F factors)
|
||||
const G4double dcs = ComputeDXSectionPerAtom(k);
|
||||
// account Ter-Mikaelian suppression: times 1/F with F = 1+(k_p/k)^2
|
||||
xSection += gWGL[igl]*dcs/(1.0+fDensityCorr/(k*k));
|
||||
}
|
||||
// update sub-interval minimum value
|
||||
alpha_i += delta;
|
||||
}
|
||||
// apply corrections due to variable transformation
|
||||
xSection *= delta;
|
||||
// final check
|
||||
return std::max(xSection, 0.);
|
||||
}
|
||||
|
||||
G4double G4SeltzerBergerModel::ComputeDXSectionPerAtom(G4double gammaEnergy)
|
||||
{
|
||||
G4double dxsec = 0.0;
|
||||
@@ -205,17 +438,18 @@ G4double G4SeltzerBergerModel::ComputeDXSectionPerAtom(G4double gammaEnergy)
|
||||
l.unlock();
|
||||
}
|
||||
// NOTE: SetupForMaterial should have been called before!
|
||||
const G4double pt2 = fPrimaryKinEnergy*(fPrimaryKinEnergy+2.*kMC2);
|
||||
const G4double pt2 = fPrimaryKinEnergy*(fPrimaryKinEnergy + twoMass);
|
||||
const G4double invb2 = fPrimaryTotalEnergy*fPrimaryTotalEnergy/pt2;
|
||||
G4double val = gSBDCSData[fCurrentIZ]->Value(x,y,fIndx,fIndy);
|
||||
dxsec = val*invb2*CLHEP::millibarn/gBremFactor;
|
||||
// e+ correction
|
||||
if (!fIsElectron) {
|
||||
const G4double invbeta1 = std::sqrt(invb2);
|
||||
const G4double e2 = fPrimaryKinEnergy-gammaEnergy;
|
||||
const G4double e2 = fPrimaryKinEnergy - gammaEnergy;
|
||||
if (e2 > 0.0) {
|
||||
const G4double invbeta2 = (e2+kMC2)/std::sqrt(e2*(e2+2.0*kMC2));
|
||||
const G4double dum0 = kAlpha*fCurrentIZ*(invbeta1-invbeta2);
|
||||
const G4double invbeta2 =
|
||||
(e2 + CLHEP::electron_mass_c2)/std::sqrt(e2*(e2 + twoMass));
|
||||
const G4double dum0 = kAlpha*fCurrentIZ*(invbeta1-invbeta2);
|
||||
if (dum0 < gExpNumLimit) {
|
||||
dxsec = 0.0;
|
||||
} else {
|
||||
@@ -235,7 +469,7 @@ G4SeltzerBergerModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
|
||||
G4double cutEnergy,
|
||||
G4double maxEnergy)
|
||||
{
|
||||
const G4double kinEnergy = dp->GetKineticEnergy();
|
||||
const G4double kinEnergy = dp->GetKineticEnergy();
|
||||
const G4double logKinEnergy = dp->GetLogKineticEnergy();
|
||||
const G4double tmin = std::min(cutEnergy, kinEnergy);
|
||||
const G4double tmax = std::min(maxEnergy, kinEnergy);
|
||||
@@ -246,9 +480,9 @@ G4SeltzerBergerModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
|
||||
SetupForMaterial(fPrimaryParticle, couple->GetMaterial(), kinEnergy);
|
||||
const G4Element* elm = SelectTargetAtom(couple, fPrimaryParticle, kinEnergy,
|
||||
logKinEnergy, tmin, tmax);
|
||||
fCurrentIZ = std::max(std::min(elm->GetZasInt(),gMaxZet-1), 1);
|
||||
fCurrentIZ = std::max(std::min(elm->GetZasInt(), gMaxZet-1), 1);
|
||||
//
|
||||
const G4double totMomentum = std::sqrt(kinEnergy*(fPrimaryTotalEnergy+kMC2));
|
||||
const G4double totMomentum = std::sqrt(kinEnergy*(kinEnergy + twoMass));
|
||||
/*
|
||||
G4cout << "G4SeltzerBergerModel::SampleSecondaries E(MeV)= "
|
||||
<< kinEnergy/MeV
|
||||
@@ -268,14 +502,14 @@ G4SeltzerBergerModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
|
||||
// angles of the emitted gamma. ( Z - axis along the parent particle) use
|
||||
// general interface
|
||||
G4ThreeVector gamDir = GetAngularDistribution()->SampleDirection(dp,
|
||||
fPrimaryTotalEnergy-gammaEnergy, fCurrentIZ, couple->GetMaterial());
|
||||
fPrimaryTotalEnergy-gammaEnergy, fCurrentIZ, couple->GetMaterial());
|
||||
// create G4DynamicParticle object for the emitted Gamma
|
||||
auto gamma = new G4DynamicParticle(fGammaParticle, gamDir, gammaEnergy);
|
||||
vdp->push_back(gamma);
|
||||
//
|
||||
// compute post-interaction kinematics of the primary e-/e+
|
||||
G4ThreeVector dir =
|
||||
(totMomentum*dp->GetMomentumDirection()-gammaEnergy*gamDir).unit();
|
||||
(totMomentum*dp->GetMomentumDirection() - gammaEnergy*gamDir).unit();
|
||||
const G4double finalE = kinEnergy - gammaEnergy;
|
||||
/*
|
||||
G4cout << "### G4SBModel: v= "
|
||||
@@ -291,7 +525,7 @@ G4SeltzerBergerModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vdp,
|
||||
fParticleChange->ProposeTrackStatus(fStopAndKill);
|
||||
fParticleChange->SetProposedKineticEnergy(0.0);
|
||||
auto el = new G4DynamicParticle(
|
||||
const_cast<G4ParticleDefinition*>(fPrimaryParticle), dir, finalE);
|
||||
const_cast<G4ParticleDefinition*>(fPrimaryParticle), dir, finalE);
|
||||
vdp->push_back(el);
|
||||
} else { // continue tracking the primary e-/e+ otherwise
|
||||
fParticleChange->SetProposedMomentumDirection(dir);
|
||||
@@ -344,10 +578,12 @@ G4SeltzerBergerModel::SampleEnergyTransfer(const G4double kinEnergy,
|
||||
v = gSBDCSData[fCurrentIZ]->Value(gammaEnergy/kinEnergy, y, fIndx, fIndy);
|
||||
// e+ correction
|
||||
if (!fIsElectron) {
|
||||
const G4double e1 = kinEnergy - tmin;
|
||||
const G4double invbeta1 = (e1+kMC2)/std::sqrt(e1*(e1+2.*kMC2));
|
||||
const G4double e1 = kinEnergy - tmin;
|
||||
const G4double invbeta1 =
|
||||
(e1 + CLHEP::electron_mass_c2)/std::sqrt(e1*(e1 + twoMass));
|
||||
const G4double e2 = kinEnergy-gammaEnergy;
|
||||
const G4double invbeta2 = (e2+kMC2)/std::sqrt(e2*(e2+2.*kMC2));
|
||||
const G4double invbeta2 =
|
||||
(e2 + CLHEP::electron_mass_c2)/std::sqrt(e2*(e2 + twoMass));
|
||||
const G4double dum0 = kAlpha*fCurrentIZ*(invbeta1-invbeta2);
|
||||
if (dum0 < gExpNumLimit) {
|
||||
v = 0.0;
|
||||
@@ -377,17 +613,3 @@ G4SeltzerBergerModel::SampleEnergyTransfer(const G4double kinEnergy,
|
||||
}
|
||||
return gammaEnergy;
|
||||
}
|
||||
|
||||
void G4SeltzerBergerModel::SetupForMaterial(const G4ParticleDefinition*,
|
||||
const G4Material* mat,
|
||||
G4double kineticEnergy)
|
||||
{
|
||||
fDensityFactor = gMigdalConstant*mat->GetElectronDensity();
|
||||
// calculate threshold for density effect: gamma*k_p = sqrt(fDensityCorr)
|
||||
fPrimaryKinEnergy = kineticEnergy;
|
||||
fPrimaryTotalEnergy = kineticEnergy+CLHEP::electron_mass_c2;
|
||||
fDensityCorr = fDensityFactor*fPrimaryTotalEnergy*fPrimaryTotalEnergy;
|
||||
// flag for the base class
|
||||
fIsLPMActive = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -454,6 +454,12 @@ G4double G4UrbanMscModel::ComputeTruePathLengthLimit(
|
||||
<< " range= " <<currentRange<< " lambda= "<<lambda0
|
||||
<<G4endl;
|
||||
*/
|
||||
// extreme small step
|
||||
if(tPathLength < tlimitminfix) {
|
||||
latDisplasment = false;
|
||||
return ConvertTrueToGeom(tPathLength, currentMinimalStep);
|
||||
}
|
||||
|
||||
presafety = (stepStatus == fGeomBoundary) ? sp->GetSafety()
|
||||
: ComputeSafety(sp->GetPosition(), tPathLength);
|
||||
|
||||
@@ -1046,123 +1052,42 @@ void G4UrbanMscModel::SampleDisplacement(G4double, G4double phi)
|
||||
|
||||
void G4UrbanMscModel::SampleDisplacementNew(G4double, G4double phi)
|
||||
{
|
||||
// best sampling based on single scattering results
|
||||
G4double rmax =
|
||||
// simple and fast sampling
|
||||
// based on single scattering results
|
||||
// u = (r/rmax)**2 : distribution from ss simulations
|
||||
const G4double eps = 1.e-3;
|
||||
const G4double rmax =
|
||||
std::sqrt((tPathLength-zPathLength)*(tPathLength+zPathLength));
|
||||
G4double r(0.0);
|
||||
G4double u(0.0);
|
||||
static const G4double reps = 5.e-3;
|
||||
|
||||
|
||||
if(rmax > 0.)
|
||||
{
|
||||
static const G4double umax = 0.855;
|
||||
static const G4double wlow = 0.750;
|
||||
const G4double x0 = 0.73 ;
|
||||
const G4double alpha = G4Log(7.33)/x0 ;
|
||||
const G4double a1 = 1.-x0 ;
|
||||
const G4double a2 = 1.-G4Exp(-alpha*x0) ;
|
||||
const G4double a3 = G4Exp(alpha*x0)-1. ;
|
||||
const G4double w1 = 2.*a2/(alpha*a1+2.*a2) ;
|
||||
|
||||
static const G4double ralpha = 6.83e+0;
|
||||
static const G4double ra1 =-4.16179e+1;
|
||||
static const G4double ra2 = 1.12548e+2;
|
||||
static const G4double ra3 =-8.66665e+1;
|
||||
static const G4double ralpha1 = 0.751*ralpha;
|
||||
static const G4double ralpha2 =ralpha-ralpha1;
|
||||
static const G4double rwa1 = G4Exp(ralpha1*reps);
|
||||
static const G4double rwa2 = G4Exp(ralpha1*umax)-rwa1;
|
||||
static const G4double rejamax = 1.16456;
|
||||
|
||||
static const G4double rbeta = 2.18e+1;
|
||||
static const G4double rb0 = 4.81382e+2;
|
||||
static const G4double rb1 =-1.12842e+4;
|
||||
static const G4double rb2 = 4.57745e+4;
|
||||
static const G4double rbeta1 = 0.732*rbeta;
|
||||
static const G4double rbeta2 = rbeta-rbeta1;
|
||||
static const G4double rwb1 = G4Exp(-rbeta1*umax);
|
||||
static const G4double rwb2 = rwb1-G4Exp(-rbeta1*(1.-reps));
|
||||
static const G4double rejbmax = 1.62651;
|
||||
|
||||
G4int count = 0;
|
||||
G4double uc,rej;
|
||||
|
||||
if(rndmEngineMod->flat() < wlow)
|
||||
G4double r, sqx;
|
||||
if (rmax/currentRange < eps)
|
||||
{
|
||||
do {
|
||||
rndmEngineMod->flatArray(2, rndmarray);
|
||||
u = G4Log(rwa1+rwa2*rndmarray[0])/ralpha1;
|
||||
uc = umax-u;
|
||||
rej = G4Exp(-ralpha2*uc)*
|
||||
(1.+ralpha*uc+ra1*uc*uc+ra2*uc*uc*uc+ra3*uc*uc*uc*uc);
|
||||
} while (rejamax*rndmarray[1] > rej && ++count < 1000);
|
||||
r = 0.73*rmax ;
|
||||
sqx = 1.;
|
||||
}
|
||||
else
|
||||
{
|
||||
do {
|
||||
rndmEngineMod->flatArray(2, rndmarray);
|
||||
u = -G4Log(rwb1-rwb2*rndmarray[0])/rbeta1;
|
||||
uc = u-umax;
|
||||
rej = G4Exp(-rbeta2*uc)*
|
||||
(1.+rbeta*uc+rb0*uc*uc+rb1*uc*uc*uc+rb2*uc*uc*uc*uc);
|
||||
} while (rejbmax*rndmarray[1] > rej && ++count < 1000);
|
||||
rndmEngineMod->flatArray(2,rndmarray);
|
||||
const G4double x = (rndmarray[0] < w1) ? G4Log(1. + a3*rndmarray[1])/alpha :
|
||||
1. - a1*std::sqrt(1.-rndmarray[1]);
|
||||
|
||||
sqx = std::sqrt(x);
|
||||
r = sqx*rmax;
|
||||
}
|
||||
r = rmax*u;
|
||||
}
|
||||
|
||||
if(r > 0.)
|
||||
{
|
||||
// sample Phi using lateral correlation
|
||||
// and r/rmax - (Phi-phi) correlation
|
||||
// v = Phi-phi = acos(latcorr/(r*sth))
|
||||
// from SS simulation f(v)*g(v)
|
||||
// f(v) ~ exp(-a1*v) normalized distribution
|
||||
// g(v) rejection function (0 < g(v) <= 1)
|
||||
G4double v, rej;
|
||||
|
||||
static const G4double peps = 1.e-4;
|
||||
static const G4double palpha[10] = {2.300e+0,2.490e+0,2.610e+0,2.820e+0,2.710e+0,
|
||||
2.750e+0,2.910e+0,3.400e+0,4.150e+0,5.400e+0};
|
||||
static const G4double palpha1[10]= {4.600e-2,1.245e-1,2.610e-1,2.820e-1,2.710e-1,
|
||||
6.875e-1,1.019e+0,1.360e+0,1.660e+0,2.430e+0};
|
||||
static const G4double pejmax[10] = {3.513,1.968,1.479,1.239,1.116,
|
||||
1.081,1.064,1.073,1.103,1.158};
|
||||
|
||||
static const G4double pa1[10] = { 3.218e+0, 2.412e+0, 2.715e+0, 2.787e+0, 2.541e+0,
|
||||
2.508e+0, 2.600e+0, 3.231e+0, 4.588e+0, 6.584e+0};
|
||||
static const G4double pa2[10] = {-5.528e-1, 2.523e+0, 1.738e+0, 2.082e+0, 1.423e+0,
|
||||
4.682e-1,-6.883e-1,-2.147e+0,-5.127e+0,-1.054e+1};
|
||||
static const G4double pa3[10] = { 3.618e+0, 2.032e+0, 2.341e+0, 2.172e+0, 7.205e-1,
|
||||
4.655e-1, 6.318e-1, 1.255e+0, 2.425e+0, 4.938e+0};
|
||||
static const G4double pa4[10] = { 2.437e+0, 9.450e-1, 4.349e-1, 2.221e-1, 1.130e-1,
|
||||
5.405e-2, 2.245e-2, 7.370e-3, 1.456e-3, 1.508e-4};
|
||||
static const G4double pw1[10] = {G4Exp(-palpha1[0]*peps),G4Exp(-palpha1[1]*peps),
|
||||
G4Exp(-palpha1[2]*peps),G4Exp(-palpha1[3]*peps),
|
||||
G4Exp(-palpha1[4]*peps),G4Exp(-palpha1[5]*peps),
|
||||
G4Exp(-palpha1[6]*peps),G4Exp(-palpha1[7]*peps),
|
||||
G4Exp(-palpha1[8]*peps),G4Exp(-palpha1[9]*peps)};
|
||||
static const G4double pw2[10] = {pw1[0]-G4Exp(-palpha1[0]*(CLHEP::pi-peps)),
|
||||
pw1[1]-G4Exp(-palpha1[1]*(CLHEP::pi-peps)),
|
||||
pw1[2]-G4Exp(-palpha1[2]*(CLHEP::pi-peps)),
|
||||
pw1[3]-G4Exp(-palpha1[3]*(CLHEP::pi-peps)),
|
||||
pw1[4]-G4Exp(-palpha1[4]*(CLHEP::pi-peps)),
|
||||
pw1[5]-G4Exp(-palpha1[5]*(CLHEP::pi-peps)),
|
||||
pw1[6]-G4Exp(-palpha1[6]*(CLHEP::pi-peps)),
|
||||
pw1[7]-G4Exp(-palpha1[7]*(CLHEP::pi-peps)),
|
||||
pw1[8]-G4Exp(-palpha1[8]*(CLHEP::pi-peps)),
|
||||
pw1[9]-G4Exp(-palpha1[9]*(CLHEP::pi-peps))};
|
||||
|
||||
G4int iphi = (G4int)(u*10.);
|
||||
if(iphi < 0) { iphi = 0; }
|
||||
else if(iphi > 9) { iphi = 9; }
|
||||
G4int count = 0;
|
||||
|
||||
do {
|
||||
rndmEngineMod->flatArray(2, rndmarray);
|
||||
v = -G4Log(pw1[iphi]-pw2[iphi]*rndmarray[0])/palpha1[iphi];
|
||||
rej = (G4Exp(-palpha[iphi]*v)*
|
||||
(1+pa1[iphi]*v+pa2[iphi]*v*v+pa3[iphi]*v*v*v)+pa4[iphi])/
|
||||
G4Exp(-pw1[iphi]*v);
|
||||
}
|
||||
// Loop checking, 5-March-2018, Vladimir Ivanchenko
|
||||
while (pejmax[iphi]*rndmarray[1] > rej && ++count < 1000);
|
||||
|
||||
G4double Phi = (rndmEngineMod->flat() < 0.5) ? phi+v : phi-v;
|
||||
fDisplacement.set(r*std::cos(Phi),r*std::sin(Phi),0.0);
|
||||
// Gaussian distribution for Phi-phi=psi
|
||||
const G4double sigma = 0.1+0.9*sqx;
|
||||
const G4double psi = G4RandGauss::shoot(0.,sigma);
|
||||
const G4double Phi = phi+psi;
|
||||
fDisplacement.set(r*std::cos(Phi), r*std::sin(Phi), 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1182,7 +1107,10 @@ void G4UrbanMscModel::InitialiseModelCache()
|
||||
// new couple
|
||||
msc[j] = new mscData();
|
||||
G4double Zeff = aCouple->GetMaterial()->GetIonisation()->GetZeffective();
|
||||
msc[j]->sqrtZ = std::sqrt(Zeff);
|
||||
G4double sqrz = std::sqrt(Zeff);
|
||||
msc[j]->sqrtZ = sqrz;
|
||||
// parameterisation of step limitation
|
||||
msc[j]->factmin = dispAlg96 ? 0.001 : 0.001/(1.+0.028*sqrz);
|
||||
G4double lnZ = G4Log(Zeff);
|
||||
// correction in theta0 formula
|
||||
G4double w = G4Exp(lnZ/6.);
|
||||
|
||||
@@ -70,8 +70,10 @@
|
||||
#include "G4ModifiedTsai.hh"
|
||||
#include "G4Exp.hh"
|
||||
#include "G4Log.hh"
|
||||
#include "G4Pow.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4AutoLock.hh"
|
||||
#include <thread>
|
||||
|
||||
const G4int G4eBremsstrahlungRelModel::gMaxZet = 120;
|
||||
|
||||
@@ -116,6 +118,8 @@ G4eBremsstrahlungRelModel::LPMFuncs G4eBremsstrahlungRelModel::gLPMFuncs;
|
||||
// special data structure per element i.e. per Z
|
||||
std::vector<G4eBremsstrahlungRelModel::ElementData*> G4eBremsstrahlungRelModel::gElementData;
|
||||
|
||||
static std::once_flag applyOnce;
|
||||
|
||||
namespace
|
||||
{
|
||||
G4Mutex theBremRelMutex = G4MUTEX_INITIALIZER;
|
||||
@@ -127,7 +131,7 @@ G4eBremsstrahlungRelModel::G4eBremsstrahlungRelModel(const G4ParticleDefinition*
|
||||
{
|
||||
fGammaParticle = G4Gamma::Gamma();
|
||||
//
|
||||
fLowestKinEnergy = 1.0*MeV;
|
||||
fLowestKinEnergy = 1.0*CLHEP::MeV;
|
||||
SetLowEnergyLimit(fLowestKinEnergy);
|
||||
//
|
||||
fLPMEnergyThreshold = 1.e+39;
|
||||
@@ -141,12 +145,12 @@ G4eBremsstrahlungRelModel::G4eBremsstrahlungRelModel(const G4ParticleDefinition*
|
||||
|
||||
G4eBremsstrahlungRelModel::~G4eBremsstrahlungRelModel()
|
||||
{
|
||||
if (fIsFirstInstance) {
|
||||
if (fIsInitializer) {
|
||||
// clear ElementData container
|
||||
for (auto const & ptr : gElementData) { delete ptr; }
|
||||
gElementData.clear();
|
||||
// clear LPMFunctions (if any)
|
||||
if (fUseLPM) {
|
||||
if (gLPMFuncs.fIsInitialized) {
|
||||
gLPMFuncs.fLPMFuncG.clear();
|
||||
gLPMFuncs.fLPMFuncPhi.clear();
|
||||
gLPMFuncs.fIsInitialized = false;
|
||||
@@ -165,18 +169,17 @@ void G4eBremsstrahlungRelModel::Initialise(const G4ParticleDefinition* p,
|
||||
fCurrentIZ = 0;
|
||||
|
||||
// init static element data and precompute LPM functions only once
|
||||
std::call_once(applyOnce, [this]() { fIsInitializer = true; });
|
||||
|
||||
// for all treads and derived classes
|
||||
if (gElementData.empty()) {
|
||||
if (fIsInitializer || gElementData.empty()) {
|
||||
G4AutoLock l(&theBremRelMutex);
|
||||
if (gElementData.empty()) {
|
||||
fIsFirstInstance = true;
|
||||
gElementData.resize(gMaxZet+1, nullptr);
|
||||
}
|
||||
l.unlock();
|
||||
}
|
||||
if (fIsFirstInstance) {
|
||||
InitialiseElementData();
|
||||
if (fUseLPM) { InitLPMFunctions(); }
|
||||
InitLPMFunctions();
|
||||
l.unlock();
|
||||
}
|
||||
|
||||
// element selectors are initialized in the master thread
|
||||
@@ -383,11 +386,11 @@ G4double G4eBremsstrahlungRelModel::ComputeXSectionPerAtom(G4double tmin)
|
||||
{
|
||||
G4double xSection = 0.0;
|
||||
const G4double alphaMin = G4Log(tmin/fPrimaryTotalEnergy);
|
||||
const G4double alphaMax = G4Log(fPrimaryKinEnergy/fPrimaryTotalEnergy);
|
||||
const G4int nSub = (G4int)(0.45*(alphaMax-alphaMin))+4;
|
||||
const G4double delta = (alphaMax-alphaMin)/((G4double)nSub);
|
||||
const G4double alphaMax = G4Log(fPrimaryKinEnergy/tmin);
|
||||
const G4int nSub = std::max((G4int)(0.45*alphaMax), 0) + 4;
|
||||
const G4double delta = alphaMax/((G4double)nSub);
|
||||
// set minimum value of the first sub-inteval
|
||||
G4double alpha_i = alphaMin;
|
||||
G4double alpha_i = alphaMin;
|
||||
for (G4int l = 0; l < nSub; ++l) {
|
||||
for (G4int igl = 0; igl < 8; ++igl) {
|
||||
// compute the emitted photon energy k
|
||||
@@ -550,7 +553,6 @@ G4eBremsstrahlungRelModel::SampleSecondaries(std::vector<G4DynamicParticle*>* vd
|
||||
G4double maxEnergy)
|
||||
{
|
||||
const G4double kineticEnergy = dp->GetKineticEnergy();
|
||||
// const G4double logKineticEnergy = dp->GetLogKineticEnergy();
|
||||
if (kineticEnergy < LowEnergyLimit()) {
|
||||
return;
|
||||
}
|
||||
@@ -650,8 +652,8 @@ void G4eBremsstrahlungRelModel::InitialiseElementData()
|
||||
Fel = G4Log(184.15) - elemData->fLogZ/3.;
|
||||
Finel = G4Log(1194) - 2.*elemData->fLogZ/3.;
|
||||
}
|
||||
const G4double z23 = std::pow(zet,2./3.);
|
||||
const G4double z13 = std::pow(zet,1./3.);
|
||||
const G4double z13 = G4Pow::GetInstance()->Z13(izet);
|
||||
const G4double z23 = z13*z13;
|
||||
elemData->fZFactor1 = (Fel-fc)+Finel/zet;
|
||||
elemData->fZFactor11 = (Fel-fc); // used only for the triplet
|
||||
elemData->fZFactor2 = (1.+1./zet)/12.;
|
||||
|
||||
Reference in New Issue
Block a user