77G4SBBremTable* G4SeltzerBergerModel::gSBSamplingTable =
nullptr;
78G4double G4SeltzerBergerModel::gYLimitData[] = { 0.0 };
79G4String G4SeltzerBergerModel::gDataDirectory =
"";
85static const G4double kMC2 = CLHEP::electron_mass_c2;
86static const G4double kAlpha = CLHEP::twopi*CLHEP::fine_structure_const;
91 fIsUseSamplingTables(true), fNumWarnings(0), fIndx(0), fIndy(0)
103 for (
size_t iz = 0; iz < gMaxZet; ++iz) {
104 if (gSBDCSData[iz]) {
105 delete gSBDCSData[iz];
106 gSBDCSData[iz] =
nullptr;
109 if (gSBSamplingTable) {
110 delete gSBSamplingTable;
111 gSBSamplingTable =
nullptr;
127 size_t numOfCouples = theCoupleTable->GetTableSize();
128 for(
size_t j=0; j<numOfCouples; ++j) {
129 auto mat = theCoupleTable->GetMaterialCutsCouple(j)->GetMaterial();
130 auto elmVec = mat->GetElementVector();
131 for (
auto & elm : *elmVec) {
132 G4int Z = std::max(1,std::min(elm->GetZasInt(), gMaxZet-1));
134 if (gSBDCSData[Z] ==
nullptr) ReadData(Z);
142 if (fIsUseSamplingTables) {
143 if (!gSBSamplingTable) {
158const G4String& G4SeltzerBergerModel::FindDirectoryPath()
162 if(gDataDirectory.empty()) {
163 const char* path = std::getenv(
"G4LEDATA");
165 std::ostringstream ost;
166 ost << path <<
"/brem_SB/br";
167 gDataDirectory = ost.str();
169 G4Exception(
"G4SeltzerBergerModel::FindDirectoryPath()",
"em0006",
171 "Environment variable G4LEDATA not defined");
174 return gDataDirectory;
177void G4SeltzerBergerModel::ReadData(
G4int Z) {
179 if (gSBDCSData[Z] !=
nullptr)
return;
181#ifdef G4MULTITHREADED
183 if (gSBDCSData[Z] !=
nullptr)
return;
186 std::ostringstream ost;
187 ost << FindDirectoryPath() << Z;
188 std::ifstream fin(ost.str().c_str());
189 if (!fin.is_open()) {
191 ed <<
"Bremsstrahlung data file <" << ost.str().c_str()
192 <<
"> is not opened!";
194 ed,
"G4LEDATA version should be G4EMLOW6.23 or later.");
203 gYLimitData[Z] = v->
Value(0.97, emaxlog, fIndx, fIndy);
207 ed <<
"Bremsstrahlung data file <" << ost.str().c_str()
208 <<
"> is not retrieved!";
210 ed,
"G4LEDATA version should be G4EMLOW6.23 or later.");
213#ifdef G4MULTITHREADED
241 const G4double invbeta1 = std::sqrt(invb2);
244 const G4double invbeta2 = (e2+kMC2)/std::sqrt(e2*(e2+2.0*kMC2));
246 if (dum0 < gExpNumLimit) {
249 dxsec *=
G4Exp(dum0);
267 const G4double tmin = std::min(cutEnergy, kinEnergy);
268 const G4double tmax = std::min(maxEnergy, kinEnergy);
275 logKinEnergy, tmin, tmax);
286 const G4double gammaEnergy = !fIsUseSamplingTables
287 ? SampleEnergyTransfer(kinEnergy, logKinEnergy, tmin, tmax)
291 if (gammaEnergy <= 0.) {
302 vdp->push_back(gamma);
307 const G4double finalE = kinEnergy - gammaEnergy;
332G4SeltzerBergerModel::SampleEnergyTransfer(
const G4double kinEnergy,
350 static const G4double kEPeakLim = 300.*CLHEP::MeV;
351 static const G4double kELowLim = 20.*CLHEP::keV;
354 ((kinEnergy>kEPeakLim) || (kinEnergy<kELowLim))) {
357 vmax = std::max(vmax, ylim);
364 static const G4int kNCountMax = 100;
368 for (
G4int nn = 0;
nn < kNCountMax; ++
nn) {
372 v = gSBDCSData[
fCurrentIZ]->
Value(gammaEnergy/kinEnergy, y, fIndx, fIndy);
375 const G4double e1 = kinEnergy - tmin;
376 const G4double invbeta1 = (e1+kMC2)/std::sqrt(e1*(e1+2.*kMC2));
377 const G4double e2 = kinEnergy-gammaEnergy;
378 const G4double invbeta2 = (e2+kMC2)/std::sqrt(e2*(e2+2.*kMC2));
380 if (dum0 < gExpNumLimit) {
386 if (v > 1.05*vmax && fNumWarnings < 11) {
389 ed <<
"### G4SeltzerBergerModel Warning: Majoranta exceeded! "
390 << v <<
" > " << vmax <<
" by " << v/vmax
392 <<
" Egamma(MeV)= " << gammaEnergy
393 <<
" Ee(MeV)= " << kinEnergy
396 if (10 == fNumWarnings) {
397 ed <<
"\n ### G4SeltzerBergerModel Warnings stopped";
399 G4Exception(
"G4SeltzerBergerModel::SampleScattering",
"em0044",
402 if (v >= vmax*rndm[1]) {
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::ostringstream G4ExceptionDescription
G4double G4Exp(G4double initial_x)
Exponential Function double precision.
G4double G4Log(G4double x)
#define G4MUTEX_INITIALIZER
#define G4MUTEXLOCK(mutex)
#define G4MUTEXUNLOCK(mutex)
virtual void flatArray(const int size, double *vect)=0
const G4ThreeVector & GetMomentumDirection() const
G4double GetLogKineticEnergy() const
G4double GetKineticEnergy() const
static G4EmParameters * Instance()
G4bool EnableSamplingTable() const
const G4Material * GetMaterial() const
G4double GetElectronDensity() const
void SetProposedKineticEnergy(G4double proposedKinEnergy)
void SetProposedMomentumDirection(const G4ThreeVector &dir)
const G4String & GetParticleName() const
G4bool Retrieve(std::ifstream &fIn)
G4double Value(G4double x, G4double y, std::size_t &lastidx, std::size_t &lastidy) const
void SetBicubicInterpolation(G4bool)
static G4ProductionCutsTable * GetProductionCutsTable()
double SampleEnergyTransfer(const G4double eekin, const G4double leekin, const G4double gcut, const G4double dielSupConst, const G4int izet, const G4int matCutIndx, const bool iselectron)
void Initialize(const G4double lowe, const G4double highe)
void Initialise(const G4ParticleDefinition *, const G4DataVector &) override
void SetupForMaterial(const G4ParticleDefinition *, const G4Material *, G4double) override
void SampleSecondaries(std::vector< G4DynamicParticle * > *, const G4MaterialCutsCouple *, const G4DynamicParticle *, G4double cutEnergy, G4double maxEnergy) override
G4double ComputeDXSectionPerAtom(G4double gammaEnergy) override
~G4SeltzerBergerModel() override
G4SeltzerBergerModel(const G4ParticleDefinition *p=nullptr, const G4String &nam="eBremSB")
virtual G4ThreeVector & SampleDirection(const G4DynamicParticle *dp, G4double finalTotalEnergy, G4int Z, const G4Material *)=0
G4VEmAngularDistribution * GetAngularDistribution()
G4double LowEnergyLimit() const
G4VEmModel * GetTripletModel()
void SetLPMFlag(G4bool val)
virtual G4double Value(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy)
G4double HighEnergyLimit() const
void SetLowEnergyLimit(G4double)
void SetAngularDistribution(G4VEmAngularDistribution *)
const G4Element * SelectTargetAtom(const G4MaterialCutsCouple *, const G4ParticleDefinition *, G4double kineticEnergy, G4double logKineticEnergy, G4double cutEnergy=0.0, G4double maxEnergy=DBL_MAX)
void InitialiseElementSelectors(const G4ParticleDefinition *, const G4DataVector &)
virtual void Initialise(const G4ParticleDefinition *, const G4DataVector &)=0
G4double SecondaryThreshold() const
G4ParticleChangeForLoss * GetParticleChangeForLoss()
void ProposeTrackStatus(G4TrackStatus status)
void SetParticle(const G4ParticleDefinition *p)
G4double fPrimaryKinEnergy
const G4ParticleDefinition * fPrimaryParticle
static const G4double gBremFactor
G4bool fIsScatOffElectron
G4double fPrimaryTotalEnergy
G4double fLowestKinEnergy
G4ParticleDefinition * fGammaParticle
G4ParticleChangeForLoss * fParticleChange
static const G4double gMigdalConstant