Import Geant4 11.2.1 source tree

This commit is contained in:
Gabriele Cosmo
2024-02-16 14:58:45 +01:00
parent 860a2b92bf
commit dda54bbdcf
331 changed files with 48457 additions and 50699 deletions
@@ -6,6 +6,10 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2023-12-09 Vladimir Ivanchenko (hadr-cross-V11-01-17)
- G4KokoulinMuonNuclearXS - use faster interface to G4PhysicsVector
- G4ElectroNuclearCrossSection - added low-energy limit 100 MeV for x-section
## 2023-11-18 I. Hrivnacova (hadr-cross-V11-01-16)
- G4PhotoNuclearCrossSection - fix memory leaks
@@ -61,6 +61,7 @@ G4_DECLARE_XS_FACTORY(G4ElectroNuclearCrossSection);
// removing all the static consts and putting them here
// Parametrization of the PhotoNucCS
static const G4double sLowEnergyLimit = 100.; // Low-energy limit for the process in MeV
static const G4double shd=1.0734; // HE PomShadowing(D)
static const G4double poc=0.0375; // HE Pomeron coefficient
static const G4double pos=16.5; // HE Pomeron shift
@@ -2254,17 +2255,16 @@ G4ElectroNuclearCrossSection::CrossSectionDescription(std::ostream& outFile) con
<< "all energies.\n";
}
G4bool G4ElectroNuclearCrossSection::IsElementApplicable(const G4DynamicParticle* /*aParticle*/, G4int Z, const G4Material*)
G4bool G4ElectroNuclearCrossSection::IsElementApplicable(const G4DynamicParticle*, G4int, const G4Material*)
{
return (Z>0 && Z<120);
return true;
}
G4double G4ElectroNuclearCrossSection::GetElementCrossSection(const G4DynamicParticle* aPart, G4int ZZ, const G4Material*)
{
const G4double Energy = aPart->GetKineticEnergy()/MeV; // Energy of the electron
const G4double Energy = aPart->GetKineticEnergy(); // Energy of the electron
if (Energy<=EMi) return 0.; // Energy is below the minimum energy in the table
if (Energy <= sLowEnergyLimit || ZZ >= 120) return 0.; // Energy is below the minimum energy of the process
if(ZZ!=lastZ) // This nucleus was not the last used element
{
@@ -219,11 +219,11 @@ ComputeDDMicroscopicCrossSection(G4double KineticEnergy, G4double,
G4double G4KokoulinMuonNuclearXS::
GetElementCrossSection(const G4DynamicParticle* aPart,
G4int Z, const G4Material*)
G4int ZZ, const G4Material*)
{
//AR-24Apr2018 Switch to treat transuranic elements as uranium
const G4bool isHeavyElementAllowed = true; if ( isHeavyElementAllowed && Z>92 ) Z=92;
return theCrossSection[Z]->Value(aPart->GetKineticEnergy());
G4int Z = std::min(ZZ, 92);
return theCrossSection[Z]->LogVectorValue(aPart->GetKineticEnergy(),
aPart->GetLogKineticEnergy());
}
@@ -6,6 +6,11 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2023-12-09 Vladimir Ivanchenko (hadr-man-V11-01-09)
- G4HadronicProcess - explicitly define cross section type per particle type,
this should improve CPU performance for hadronic showers for ~1%
## 2023-11-18 I. Hrivnacova (hadr-man-V11-01-08)
- G4HadronicProcess, G4HadXSHelper - fixed memory leak at exit
@@ -205,23 +205,28 @@ void G4HadronicProcess::BuildPhysicsTable(const G4ParticleDefinition& p)
// check particle for integral method
if(isMaster || nullptr == masterProcess) {
G4double charge = p.GetPDGCharge()/eplus;
G4bool isLepton = (p.GetLeptonNumber() != 0);
G4bool ok = (p.GetAtomicNumber() != 0 || p.GetPDGMass() < GeV);
// select cross section shape
if(charge != 0.0 && useIntegralXS && !isLepton && ok) {
if(charge != 0.0 && useIntegralXS) {
G4double tmax = param->GetMaxEnergy();
fXSType = (charge > 0.0) ? fHadIncreasing : fHadDecreasing;
currentParticle = firstParticle;
// initialisation in the master thread
G4int pdg = p.GetPDGEncoding();
if(std::abs(pdg) == 211) {
if (std::abs(pdg) == 211) {
fXSType = fHadTwoPeaks;
} else if(pdg == 321) {
} else if (pdg == 321) {
fXSType = fHadOnePeak;
} else if(pdg == 2212) {
} else if (pdg == -321) {
fXSType = fHadDecreasing;
} else if (pdg == 2212) {
fXSType = fHadTwoPeaks;
} else if (pdg == -2212 || pdg == -1000010020 || pdg == -1000010030 ||
pdg == -1000020030 || pdg == -1000020040) {
fXSType = fHadDecreasing;
} else if (charge > 0.0 || pdg == 11 || pdg == 13) {
fXSType = fHadIncreasing;
}
delete theEnergyOfCrossSectionMax;
theEnergyOfCrossSectionMax = nullptr;
if(fXSType == fHadTwoPeaks) {
@@ -280,18 +285,8 @@ G4double G4HadronicProcess::PostStepGetPhysicalInteractionLength(
mfpKinEnergy = DBL_MAX;
matIdx = (G4int)track.GetMaterial()->GetIndex();
}
/*
G4cout << GetProcessName() << " E=" << track.GetKineticEnergy()
<< " " << currentParticle->GetParticleName()
<< " lastxs=" << theLastCrossSection
<< " lastmfp=" << theMFP << G4endl;
*/
UpdateCrossSectionAndMFP(track.GetKineticEnergy());
/*
G4cout << " xs=" << theLastCrossSection
<< " mfp=" << theMFP << " nleft=" << theNumberOfInteractionLengthLeft
<< G4endl;
*/
// zero cross section
if(theLastCrossSection <= 0.0) {
theNumberOfInteractionLengthLeft = -1.0;
@@ -6,6 +6,17 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-01-29 Vladimir Ivanchenko (hadr-deex-V11-01-12)
- G4StatMFChannel - fixed compilation warnings at alma9-gcc131 seen in CMSSW
by substitution of C-arrays by std::vector
## 2024-01-25 Vladimir Ivanchenko
- G4FermiBreakUpVI, G4FermiFragmentsPoolVI - fixed problem 2584 (production
of fake excited isomeres) by moving the check on lifetime limit from the
pull (initialized once as a static object) to the Initialise() method of
the model allowing to change this limit in an application, do not consider
decay chains with no final state.
## 2023-11-15 Vladimir Ivanchenko (hadr-deex-V11-01-11)
- G4FermiChannels - fixed memory leak at exit
@@ -76,6 +76,7 @@ private:
G4double fTolerance{0.0};
G4double fElim{0.0};
G4double fTimeLim{1.0}; // in ns
G4bool isFirst{false};
@@ -71,7 +71,6 @@ private:
G4double fTolerance{0.0};
G4double fElim{0.0};
G4double fTimeLim{0.0};
const G4int maxZ{9};
const G4int maxA{17};
@@ -39,15 +39,9 @@
#include "G4PhysicsModelCatalog.hh"
#include "Randomize.hh"
#include "G4RandomDirection.hh"
#include "G4AutoLock.hh"
G4FermiFragmentsPoolVI* G4FermiBreakUpVI::fPool = nullptr;
namespace
{
G4Mutex theFBUMutex = G4MUTEX_INITIALIZER;
}
G4FermiBreakUpVI::G4FermiBreakUpVI()
{
frag.reserve(10);
@@ -55,13 +49,9 @@ G4FermiBreakUpVI::G4FermiBreakUpVI()
secID = G4PhysicsModelCatalog::GetModelID("model_G4FermiBreakUpVI");
prob.resize(12,0.0);
if (nullptr == fPool) {
G4AutoLock l(&theFBUMutex);
if (nullptr == fPool) {
fPool = new G4FermiFragmentsPoolVI();
fPool->Initialise();
isFirst = true;
}
l.unlock();
fPool = new G4FermiFragmentsPoolVI();
fPool->Initialise();
isFirst = true;
}
}
@@ -79,6 +69,7 @@ void G4FermiBreakUpVI::Initialise()
G4NuclearLevelData::GetInstance()->GetParameters();
fTolerance = param->GetMinExcitation();
fElim = param->GetFBUEnergyLimit();
fTimeLim = param->GetMaxLifeTime();
if (verbose > 1) {
G4cout << "### G4FermiBreakUpVI::Initialise(): the pool is initilized="
<< fPool->IsInitialized() << " fTolerance(eV)=" << fTolerance/CLHEP::eV
@@ -125,8 +116,8 @@ void G4FermiBreakUpVI::BreakFragment(G4FragmentVector* theResult,
A = frag[i]->GetA();
excitation = frag[i]->GetExcitationEnergy();
lv0 = lvect[i];
G4bool unstable = IsApplicable(Z, A, excitation);
if (unstable) {
G4bool unstable = (IsApplicable(Z, A, excitation) && frag[i]->GetLifeTime() < fTimeLim);
if (unstable) {
mass = frag[i]->GetTotalEnergy();
if (verbose > 1) {
G4cout << "# FermiFrag " << i << ". Z= " << Z << " A= " << A
@@ -43,7 +43,7 @@ G4FermiFragmentsPoolVI::G4FermiFragmentsPoolVI()
G4FermiFragmentsPoolVI::~G4FermiFragmentsPoolVI()
{
for (G4int i=1; i<maxA; ++i) {
for (G4int i=0; i<maxA; ++i) {
for (G4int j=0; j<maxZ; ++j) {
auto ptr = list_c[j][i];
if (nullptr != ptr) {
@@ -79,6 +79,7 @@ G4FermiFragmentsPoolVI::ClosestChannels(G4int Z, G4int A, G4double etot) const
G4double demax = 1.e+9;
for (auto const & ch : *chan) {
if (ch->NumberPairs() == 0) { continue; }
G4double de = etot - ch->GetFragment()->GetTotalEnergy();
// an excitation coincide with a level
if (std::abs(de) <= fTolerance) {
@@ -111,7 +112,6 @@ void G4FermiFragmentsPoolVI::Initialise()
G4NuclearLevelData::GetInstance()->GetParameters();
fTolerance = 2*CLHEP::eV;
fElim = param->GetFBUEnergyLimit();
fTimeLim = param->GetMaxLifeTime();
fragment_pool.reserve(991);
@@ -200,8 +200,7 @@ void G4FermiFragmentsPoolVI::Initialise()
auto ch = (*chan)[k];
const G4double e0 = ch->GetMass();
auto f0 = ch->GetFragment();
if (e0 > minE && f0->GetLifeTime() <= fTimeLim &&
G4FermiBreakUpUtil::CheckSpinParity(f1, f2, f0)) {
if (e0 > minE && G4FermiBreakUpUtil::CheckSpinParity(f1, f2, f0)) {
const G4double cb =
G4FermiBreakUpUtil::CoulombBarrier(Z1, A1, Z2, A2, ch->GetExcitation());
if (e0 >= minE + cb) {
@@ -32,6 +32,7 @@
#define G4StatMFChannel_h 1
#include <deque>
#include <vector>
#include "G4StatMFParameters.hh"
#include "G4StatMFFragment.hh"
@@ -93,6 +94,9 @@ private:
private:
std::deque<G4StatMFFragment*> _theFragments;
std::vector<G4ThreeVector> Pos;
std::vector<G4ThreeVector> Vel;
std::vector<G4ThreeVector> Accel;
G4int _NumOfNeutralFragments;
@@ -46,7 +46,11 @@
G4StatMFChannel::G4StatMFChannel() :
_NumOfNeutralFragments(0),
_NumOfChargedFragments(0)
{}
{
Pos.resize(8);
Vel.resize(8);
Accel.resize(8);
}
G4StatMFChannel::~G4StatMFChannel()
{
@@ -351,10 +355,11 @@ void G4StatMFChannel::SolveEqOfMotion(G4int anA, G4int anZ, G4double T)
G4double TimeN = 0.0;
G4double TimeS = 0.0;
G4double DeltaTime = 10.0;
G4ThreeVector * Pos = new G4ThreeVector[_NumOfChargedFragments];
G4ThreeVector * Vel = new G4ThreeVector[_NumOfChargedFragments];
G4ThreeVector * Accel = new G4ThreeVector[_NumOfChargedFragments];
if (_NumOfChargedFragments > (G4int)Pos.size()) {
Pos.resize(_NumOfChargedFragments);
Vel.resize(_NumOfChargedFragments);
Accel.resize(_NumOfChargedFragments);
}
G4int i;
for (i = 0; i < _NumOfChargedFragments; ++i)
@@ -412,12 +417,6 @@ void G4StatMFChannel::SolveEqOfMotion(G4int anA, G4int anZ, G4double T)
{
_theFragments[i]->SetMomentum((_theFragments[i]->GetNuclearMass()*Eta)*Vel[i]);
}
// garbage collection
delete [] Pos;
delete [] Vel;
delete [] Accel;
return;
}
@@ -5,6 +5,16 @@ which **must** added in reverse chronological order (newest at the top).
It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-01-29 Vladimir Ivanchenko (hadr-lend-V11-01-03)
- MCGIDI_product, MCGIDI_outputChannel, MCGIDI_distribution - fixed alma9-gcc131
compilation warnings seen in CMSSW
## 2023-12-18 Gabriele Cosmo
- Fixed compilation error on latest Windows VC++ compiler 17.8.3 for use of
std::isfinite() in nf_specialFunctions_h and in nf_floatToShortestString().
Addressing problem report #2582.
## 2023-11-03 Ben Morgan (hadr-lend-V11-01-02)
- Use "G4" prefixed version of EXPAT/ZLIB CMake variables
@@ -8,12 +8,11 @@
#include <math.h>
#include <float.h>
#include <nf_utilities.h>
#include "nf_utilities.h"
#ifdef WIN32
#define isfinite _finite
#define M_PI 3.141592653589793238463
/*#define INFINITY (DBL_MAX+DBL_MAX)*/
#endif
#if defined __cplusplus
@@ -61,7 +61,7 @@ int MCGIDI_distribution_release( statusMessageReporting *smr, MCGIDI_distributio
int MCGIDI_distribution_parseFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_product *product, MCGIDI_POPs * /*pops*/, ptwXYPoints *norms ) {
char const *nativeData, *gammaEnergy;
double gammaEnergy_MeV;
double gammaEnergy_MeV{0.0};
MCGIDI_distribution *distribution = &(product->distribution);
xDataTOM_element *distributionElement;
enum MCGIDI_energyType energyType = MCGIDI_energyType_unknown;
@@ -61,9 +61,9 @@ int MCGIDI_outputChannel_release( statusMessageReporting *smr, MCGIDI_outputChan
int MCGIDI_outputChannel_parseFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_POPs *pops, MCGIDI_outputChannel *outputChannel,
MCGIDI_reaction *reaction, MCGIDI_product *parent ) {
int n, delayedNeutronIndex = 0;
char const *genre, *Q;
xDataTOM_element *child;
int n{0}, delayedNeutronIndex{0};
char const *genre{""}, *Q{""};
xDataTOM_element *child{nullptr};
MCGIDI_outputChannel_initialize( smr, outputChannel );
@@ -82,9 +82,9 @@ int MCGIDI_product_release( statusMessageReporting *smr, MCGIDI_product *product
int MCGIDI_product_parseFromTOM( statusMessageReporting *smr, xDataTOM_element *element, MCGIDI_outputChannel *outputChannel,
MCGIDI_POPs *pops, MCGIDI_product *product, int *delayedNeutronIndex ) {
char const *name, *label, *delayedNeutron, *multiplicityStr, *multiplicityUnits[2] = { "MeV", "" };
xDataTOM_element *multiplicity, *multiplicityTOM, *decayChannelElement;
nfu_status status;
char const *name{""}, *label{""}, *delayedNeutron{""}, *multiplicityStr{""}, *multiplicityUnits[2] = { "MeV", "" };
xDataTOM_element *multiplicity{nullptr}, *multiplicityTOM{nullptr}, *decayChannelElement{nullptr};
nfu_status status{nfu_Okay};
ptwXYPoints *multiplicityVsEnergy = NULL, *norms1 = NULL, *norms2 = NULL;
MCGIDI_product_initialize( smr, product );
@@ -4,17 +4,11 @@
*/
#include <stdlib.h>
#include <float.h>
#include <cmath>
#include "nf_utilities.h"
#ifdef WIN32
#include <float.h>
#define isfinite _finite
#else
#define isfinite std::isfinite
#endif
#if defined __cplusplus
namespace GIDI {
using namespace GIDI;
@@ -71,7 +65,7 @@ char *nf_floatToShortestString( double value, int significantDigits, int favorEF
if( flags & nf_floatToShortestString_includeSign ) sign = "+";
if( !isfinite( value ) ) {
if( !std::isfinite( value ) ) {
snprintf( Fmt, sizeof Fmt, "%%%sf", sign );
snprintf( Str_e, sizeof Str_e, Fmt, value );
return( strdup( Str_e ) );
@@ -6,6 +6,16 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-01-30 Vladimir Ivanchenko (hadr-hpp-V11-01-25)
- G4ParticleHPFSFissionFS, G4ParticleHPFissionBaseFS - substitute
C-arrays with std::vector in order to reduce compilation warnings on gcc
with LTO settings.
## 2024-01-26 Vladimir Ivanchenko
- G4ParticleHPFissionFS, G4ParticleHPFFFissionFS - added extra protections
against cases when fission data are not available for some isotopes
(fixed problem #2590)
## 2023-11-04 Vladimir Ivanchenko (hadr-hpp-V11-01-24)
- G4ParticleHPManager - set default upper limit on Doppler broading
30 keV instead of 100 keV
@@ -164,8 +164,11 @@ void G4ParticleHPFFFissionFS::GetAFissionFragment(G4double energy, G4int& fragZ,
G4double rand = G4UniformRand();
// G4cout << rand << G4endl;
std::map<G4double, std::map<G4int, G4double>*>* mEnergyFSPData =
FissionProductYieldData.find(454)->second;
auto ptr = FissionProductYieldData.find(454);
if (ptr == FissionProductYieldData.end())
return;
auto mEnergyFSPData = ptr->second;
// It is not clear that the treatment of the scheme 2 on two-dimensional interpolation.
// So, here just use the closest energy point array of yield data.
@@ -108,8 +108,9 @@ G4DynamicParticleVector* G4ParticleHPFSFissionFS::ApplyYourself(G4int nPrompt, G
G4double eKinetic = boosted.GetKineticEnergy();
// Build neutrons
auto theNeutrons = new G4ReactionProduct[nPrompt + nDelayed];
std::vector<G4ReactionProduct> theNeutrons;
for (i = 0; i < nPrompt + nDelayed; ++i) {
theNeutrons.emplace_back();
theNeutrons[i].SetDefinition(G4Neutron::Neutron());
}
@@ -140,8 +141,6 @@ G4DynamicParticleVector* G4ParticleHPFSFissionFS::ApplyYourself(G4int nPrompt, G
dp->SetMomentum(theNeutrons[i].GetMomentum());
aResult->push_back(dp);
}
delete[] theNeutrons;
return aResult;
}
@@ -108,8 +108,9 @@ G4DynamicParticleVector* G4ParticleHPFissionBaseFS::ApplyYourself(G4int nPrompt)
G4double eKinetic = boosted.GetKineticEnergy();
// Build neutrons
auto theNeutrons = new G4ReactionProduct[nPrompt];
std::vector<G4ReactionProduct> theNeutrons;
for (i = 0; i < nPrompt; i++) {
theNeutrons.emplace_back();
theNeutrons[i].SetDefinition(G4Neutron::Neutron());
}
@@ -132,7 +133,6 @@ G4DynamicParticleVector* G4ParticleHPFissionBaseFS::ApplyYourself(G4int nPrompt)
it->SetMomentum(theNeutrons[i].GetMomentum());
aResult->push_back(it);
}
delete[] theNeutrons;
// return the result
return aResult;
@@ -251,6 +251,7 @@ G4HadFinalState* G4ParticleHPFissionFS::ApplyYourself(const G4HadProjectile& the
G4int fragA_M = 0;
// System is traget rest!
theFF.GetAFissionFragment(eKinetic, fragA_Z, fragA_A, fragA_M);
if (0 == fragA_A) { return theResult.Get(); }
G4int fragB_Z = (G4int)theBaseZ - fragA_Z;
G4int fragB_A = (G4int)theBaseA - fragA_A - Prompt;
@@ -6,6 +6,9 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2023-12-21 Yoshihide Sato (hadr-qmd-V11-01-04)
- G4LightIonQMDReaction.cc: Fix model ID (model_LightIonQMDModel).
## 2023-10-27 Yoshihide Sato (hadr-qmd-V11-01-03)
- Add files for the Light Ion QMD which is qmd optimized for light ion.
The name of the added files start with G4LightIonQMD.
@@ -111,7 +111,7 @@ G4LightIonQMDReaction::G4LightIonQMDReaction()
coulomb_collision_px_targ = 0.0;
coulomb_collision_pz_targ = 0.0;
secID = G4PhysicsModelCatalog::GetModelID( "model_QMDModel" );
secID = G4PhysicsModelCatalog::GetModelID( "model_LightIonQMDModel" );
}
@@ -6,6 +6,14 @@ It must **not** be used as a substitute for writing good git commit messages!
-------------------------------------------------------------------------------
## 2024-02-13 Vladimir Ivanchenko (radioactive_decay-V11-01-10)
- G4BetaPlusDecay, G4BetaMinusDecay - fixed sampling algorithm (problem #2588)
## 2024-01-13 Alexander Howard
- G4Radioactivation : added DBL_EPSILON check on transition energy for
metastables to prevent creation of zero energy levels which have no decay
products!
## 2023-11-16 Alberto Ribon (radioactive_decay-V11-01-09)
- G4RadioactiveDecay, G4Radioactivation : added an extra parameter in the
constructor of these classes, to be able to set, directly at the level
@@ -58,7 +58,7 @@ G4BetaMinusDecay::G4BetaMinusDecay(const G4ParticleDefinition* theParentNucleus,
const G4Ions::G4FloatLevelBase& flb,
const G4BetaDecayType& betaType)
: G4NuclearDecay("beta- decay", BetaMinus, excitationE, flb),
maxEnergy(e0),
maxEnergy(e0/eMass),
estep(maxEnergy/(G4double)(npti - 1))
{
SetParent(theParentNucleus); // Store name of parent nucleus, delete G4MT_parent
@@ -98,7 +98,7 @@ G4DecayProducts* G4BetaMinusDecay::DecayIt(G4double)
G4DynamicParticle prim(fPrimaryIon, G4ThreeVector(0,0,1), 0.0);
G4DecayProducts* products = new G4DecayProducts(prim);
// Generate positron isotropic in angle, with energy from stored spectrum
// Generate electron isotropic in angle, with energy from stored spectrum
const G4double eKE = eMass*G4BetaSpectrumSampler::shoot(npti, cdf, estep);
G4double eMomentum = std::sqrt(eKE*(eKE + 2.*eMass));
@@ -111,14 +111,14 @@ G4DecayProducts* G4BetaMinusDecay::DecayIt(G4double)
<< " + " << fNeutrino->GetParticleName() << " Ee(MeV)=" << eKE
<< G4endl;
*/
// Fill G4MT_parent with theParentNucleus (stored by SetParent in ctor)
// 4-momentum of residual ion and neutrino
G4LorentzVector lv(-eMomentum*dir.x(), -eMomentum*dir.y(), -eMomentum*dir.z(),
parentMass - eKE - eMass);
G4double edel = std::max(lv.e() - resMass, 0.0);
if (edel > CLHEP::eV) {
G4double edel = std::max(lv.e() - resMass, 0.0);
// Free energy should be above zero
if (edel > 0.0) {
// centrum of mass system
G4double M = lv.mag();
@@ -157,16 +157,17 @@ G4BetaMinusDecay::SetUpBetaSpectrumSampler(const G4int& daughterZ,
{
cdf[0] = 0.0;
// Check for cases in which Q < 2Me (e.g. z67.a162)
// Check for cases in which Q < 0
if (maxEnergy > 0.) {
G4BetaDecayCorrections corrections(daughterZ, daughterA);
// Fill array to store cumulative spectrum
G4double ex;
G4double p; // Positron momentum in units of electron mass
G4double ex; // Kinetic energy normalized on electron mass
G4double p; // Momentum in units of electron mass
G4double f; // Spectral shape function
G4double f0 = 0.0;
G4double sum = 0.0;
for (G4int i = 1; i < npti; ++i) {
for (G4int i = 1; i < npti-1; ++i) {
ex = estep*i;
p = std::sqrt(ex*(ex + 2.));
f = p*(1. + ex)*(maxEnergy - ex)*(maxEnergy - ex);
@@ -176,9 +177,11 @@ G4BetaMinusDecay::SetUpBetaSpectrumSampler(const G4int& daughterZ,
// Apply shape factor for forbidden transitions
f *= corrections.ShapeFactor(betaType, p, maxEnergy - ex);
sum += f;
sum += f + f0;
cdf[i] = sum;
f0 = f;
}
cdf[npti-1] = sum + f0;
} else {
for (G4int i = 1; i < npti; ++i) { cdf[i] = 0.0; }
}
@@ -59,7 +59,7 @@ G4BetaPlusDecay::G4BetaPlusDecay(const G4ParticleDefinition* theParentNucleus,
const G4Ions::G4FloatLevelBase& flb,
const G4BetaDecayType& betaType)
: G4NuclearDecay("beta+ decay", BetaPlus, excitationE, flb),
maxEnergy((e0 - 2*eMass)/eMass),
maxEnergy(e0/eMass - 2.0),
estep(maxEnergy/(G4double)(npti - 1))
{
SetParent(theParentNucleus); // Store name of parent nucleus, delete G4MT_parent
@@ -88,7 +88,7 @@ G4BetaPlusDecay::G4BetaPlusDecay(const G4ParticleDefinition* theParentNucleus,
// Fill G4MT_parent with theParentNucleus (stored by SetParent in ctor)
CheckAndFillParent();
// Fill G4MT_daughters with e-, nu and residual nucleus (stored by SetDaughter)
// Fill G4MT_daughters with e+, nu and residual nucleus (stored by SetDaughter)
CheckAndFillDaughters();
}
@@ -117,8 +117,9 @@ G4DecayProducts* G4BetaPlusDecay::DecayIt(G4double)
G4LorentzVector lv(-eMomentum*dir.x(), -eMomentum*dir.y(), -eMomentum*dir.z(),
parentMass - eKE - eMass);
G4double edel = std::max(lv.e() - resMass, 0.0);
if (edel > CLHEP::eV) {
G4double edel = std::max(lv.e() - resMass, 0.0);
// Free energy should be above zero
if (edel > 0.0) {
// centrum of mass system
G4double M = lv.mag();
@@ -155,17 +156,20 @@ G4BetaPlusDecay::SetUpBetaSpectrumSampler(const G4int& daughterZ,
const G4int& daughterA,
const G4BetaDecayType& betaType)
{
cdf[0] = 0.0;
// Check for cases in which Q < 2Me (e.g. z67.a162)
if (maxEnergy > 0.) {
G4BetaDecayCorrections corrections(-daughterZ, daughterA);
// Fill array to store cumulative spectrum
G4double ex;
G4double ex; // Positron kinetic energy
G4double p; // Positron momentum in units of electron mass
G4double f; // Spectral shape function
G4double f0 = 0.0;
G4double sum = 0.0;
for (G4int i = 0; i < npti; ++i) {
ex = (0 == i) ? maxEnergy*1.e-6 : estep*i;
for (G4int i = 1; i < npti-1; ++i) {
ex = estep*i;
p = std::sqrt(ex*(ex + 2.));
f = p*(1. + ex)*(maxEnergy - ex)*(maxEnergy - ex);
@@ -174,9 +178,11 @@ G4BetaPlusDecay::SetUpBetaSpectrumSampler(const G4int& daughterZ,
// Apply shape factor for forbidden transitions
f *= corrections.ShapeFactor(betaType, p, maxEnergy - ex);
sum += f;
sum += f + f0;
cdf[i] = sum;
f0 = f;
}
cdf[npti-1] = sum + f0;
} else {
for (G4int i = 0; i < npti; ++i) { cdf[i] = 0.0; }
}
@@ -459,7 +459,7 @@ CalculateChainsFromParent(const G4ParticleDefinition& theParentNucleus)
// summedDecayTable. If not, just add its BR to sum for that decay mode.
if (levelManager->NumberOfTransitions() ) {
nearestEnergy = levelManager->NearestLevelEnergy(daughterExcitation);
if (std::abs(daughterExcitation - nearestEnergy) < levelTolerance) {
if ((std::abs(daughterExcitation - nearestEnergy) < levelTolerance) && (std::abs(daughterExcitation - nearestEnergy) > DBL_EPSILON)) {
// Level half-life is in ns and the threshold is set to 1 micros
// by default, user can set it via the UI command
nearestLevelIndex = (G4int)levelManager->NearestLevelIndex(daughterExcitation);