Import Geant4 11.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2021-12-10 14:46:44 +01:00
committed by Ben Morgan
parent 6399a014b6
commit 80e2389dd8
3932 changed files with 202519 additions and 246221 deletions
+35
View File
@@ -14,6 +14,41 @@ code and to keep track of all tags.
* Please list in reverse chronological order (last date on top)
---------------------------------------------------------------
05 November 2021 Alberto Ribon (hadr-util-V10-07-08)
--------------------------------------------------------
- G4Nucleus : the method GetBiasedThermalNucleus has been rewritten
(by Loic Thulliez and Eric Dumonteil of CEA Saclay) according to the
Sampling of the Velocity of the Target nucleus (SVT) algorithm.
27 October 2021 Alberto Ribon (hadr-util-V10-07-07)
---------------------------------------------------
- G4Nucleon, G4Nucleus, G4V3DNucleus, G4Fancy3DNucleus, G4Fragment:
extended for hypernuclei and anti-hypernuclei.
22 October 2021 Vladimir Ivanchenko (hadr-util-V10-07-06)
--------------------------------------------------------
- G4HadronicParameters - added hyper-nuclei flag
04 August 2021 Alberto Ribon (hadr-util-V10-07-05)
--------------------------------------------------------
- G4Fragment, G4KineticTrack, G4HadSecondary, G4ReactionProduct :
introduced consistent naming of the Set/Get methods for the
creator model ID.
- G4DecayKineticTracks, G4KineticTrack, G4DecayStrongResonances :
propagate correctly the information regarding the creator model ID.
19 July 2021 Alberto Ribon (hadr-util-V10-07-04)
--------------------------------------------------------
- G4SampleResonance : bug-fix in the method GetMinimumMass in the case
that users include rare and light decay channels (e.g. e+ e-) for
hadronic resonances.
Thanks to Thomas Ruf (SHiP Collaboration) for pointing out this issue
(Bug #2299).
09 July 2021 Vladimir Ivanchenko (hadr-util-V10-07-03)
--------------------------------------------------------
- G4Nucleus - use const pointer to G4Element
16 April 2021 Ben Morgan (hadr-util-V10-07-02)
--------------------------------------------------------
- Migrate build to modular CMake API
@@ -40,7 +40,7 @@
#include "globals.hh"
#include "G4DynamicParticle.hh"
#include "G4Nucleon.hh" /* FIXME: This should be forward decl! */
#include "G4Nucleon.hh"
#include "G4V3DNucleus.hh"
#include "G4VNuclearDensity.hh"
#include "G4FermiMomentum.hh"
@@ -74,15 +74,16 @@ class G4Fancy3DNucleus : public G4V3DNucleus
public:
#if defined(NON_INTEGER_A_Z)
void Init(G4double theA, G4double theZ);
void Init(G4double theA, G4double theZ, G4int numberOfLambdas = 0);
#endif
void Init(G4int theA, G4int theZ);
void Init(G4int theA, G4int theZ, G4int numberOfLambdas = 0);
G4bool StartLoop();
G4Nucleon * GetNextNucleon();
const std::vector<G4Nucleon> & GetNucleons();
G4int GetMassNumber();
G4double GetMass();
G4int GetCharge();
G4int GetNumberOfLambdas(); // Non-negative number of Lambdas (for hypernuclei) or anti-Lambdas (for anti-hypernuclei)
G4double GetNuclearRadius();
G4double GetNuclearRadius(const G4double maxRelativeDensity);
G4double GetOuterRadius();
@@ -103,13 +104,13 @@ class G4Fancy3DNucleus : public G4V3DNucleus
G4int myA;
G4int myZ;
G4int myL; // Non-negative number of Lambdas (for hypernuclei) or anti-Lambdas (for anti-hypernuclei)
std::vector<G4Nucleon> theNucleons;
G4int currentNucleon;
G4VNuclearDensity * theDensity;
G4FermiMomentum theFermi;
//const G4double nucleondistance; // Uzhi Dec. 2017
G4double nucleondistance; // Uzhi Dec. 2017
G4double nucleondistance;
G4double excitationEnergy;
std::vector<G4ThreeVector> places; // For selecting locations
@@ -128,6 +129,12 @@ inline G4int G4Fancy3DNucleus::GetMassNumber()
{
return myA;
}
inline G4int G4Fancy3DNucleus::GetNumberOfLambdas()
{
return myL;
}
inline G4double G4Fancy3DNucleus::AddExcitationEnergy(G4double anE)
{
excitationEnergy +=anE;
@@ -43,6 +43,7 @@
// removed not needed 'const'; removed old debug staff and unused
// private methods; add comments and reorder methods for
// better reading
// 27.10.2021 A.Ribon extension for hypernuclei.
#ifndef G4Fragment_h
#define G4Fragment_h 1
@@ -53,6 +54,7 @@
#include "G4ThreeVector.hh"
#include "G4NuclearPolarization.hh"
#include "G4NucleiProperties.hh"
#include "G4HyperNucleiProperties.hh"
#include "G4Proton.hh"
#include "G4Neutron.hh"
#include <vector>
@@ -80,6 +82,9 @@ public:
// A,Z and 4-momentum - main constructor for fragment
G4Fragment(G4int A, G4int Z, const G4LorentzVector& aMomentum, G4bool warning=true);
// A,Z,numberOfLambdas and 4-momentum
G4Fragment(G4int A, G4int Z, G4int numberOfLambdas, const G4LorentzVector& aMomentum, G4bool warning=true);
// 4-momentum and pointer to G4particleDefinition (for gammas, e-)
G4Fragment(const G4LorentzVector& aMomentum,
const G4ParticleDefinition* aParticleDefinition);
@@ -101,7 +106,11 @@ public:
inline G4int GetZ_asInt() const;
inline G4int GetA_asInt() const;
inline void SetZandA_asInt(G4int Znew, G4int Anew);
inline G4int GetNumberOfLambdas() const;
inline void SetNumberOfLambdas(G4int numberOfLambdas);
// Non-negative number of lambdas/anti-lambdas inside the nucleus/anti-nucleus
inline G4double GetExcitationEnergy() const;
inline void SetExcEnergyAndMomentum(G4double eexc, const G4LorentzVector&);
@@ -112,15 +121,15 @@ public:
inline const G4LorentzVector& GetMomentum() const;
inline void SetMomentum(const G4LorentzVector& value);
// computation of mass for any Z and A
inline G4double ComputeGroundStateMass(G4int Z, G4int A) const;
// computation of mass for any Z, A and numberOfLambdas
inline G4double ComputeGroundStateMass(G4int Z, G4int A, G4int numberOfLambdas = 0) const;
// extra methods
inline G4double GetSpin() const;
inline void SetSpin(G4double value);
inline G4int GetCreatorModelType() const;
inline void SetCreatorModelType(G4int value);
inline G4int GetCreatorModelID() const;
inline void SetCreatorModelID(G4int value);
// obsolete methods
@@ -185,6 +194,8 @@ private:
G4int theA;
G4int theZ;
G4int theL; // Non-negative number of lambdas/anti-lambdas inside the nucleus/anti-nucleus
G4double theExcitationEnergy;
@@ -245,14 +256,16 @@ inline void G4Fragment::CalculateExcitationEnergy(G4bool warning)
}
inline G4double
G4Fragment::ComputeGroundStateMass(G4int Z, G4int A) const
G4Fragment::ComputeGroundStateMass(G4int Z, G4int A, G4int numberOfLambdas) const
{
return G4NucleiProperties::GetNuclearMass(A, Z);
if ( numberOfLambdas <= 0 ) return G4NucleiProperties::GetNuclearMass(A, Z);
else return G4HyperNucleiProperties::GetNuclearMass(A, Z, numberOfLambdas);
}
inline void G4Fragment::CalculateGroundStateMass()
{
theGroundStateMass = G4NucleiProperties::GetNuclearMass(theA, theZ);
if ( theL <= 0 ) theGroundStateMass = G4NucleiProperties::GetNuclearMass(theA, theZ);
else theGroundStateMass = G4HyperNucleiProperties::GetNuclearMass(theA, theZ, theL);
}
inline G4int G4Fragment::GetA_asInt() const
@@ -272,6 +285,17 @@ inline void G4Fragment::SetZandA_asInt(G4int Znew, G4int Anew)
CalculateGroundStateMass();
}
inline G4int G4Fragment::GetNumberOfLambdas() const
{
return theL;
}
inline void G4Fragment::SetNumberOfLambdas(G4int numberOfLambdas)
{
theL = std::max( numberOfLambdas, 0 ); // Cannot be negative
CalculateGroundStateMass();
}
inline G4double G4Fragment::GetExcitationEnergy() const
{
return theExcitationEnergy;
@@ -396,12 +420,12 @@ inline void G4Fragment::SetNumberOfElectrons(G4int value)
numberOfShellElectrons = value;
}
inline G4int G4Fragment::GetCreatorModelType() const
inline G4int G4Fragment::GetCreatorModelID() const
{
return creatorModel;
}
inline void G4Fragment::SetCreatorModelType(G4int value)
inline void G4Fragment::SetCreatorModelID(G4int value)
{
creatorModel = value;
}
@@ -45,8 +45,8 @@ public:
inline void SetWeight(G4double aW) {theWeight= aW;}
inline void SetTime(G4double aT) {theTime = aT;}
inline G4double GetTime() const {return theTime;}
inline void SetCreatorModelType(G4int idx) {theCreatorModel = idx;}
inline G4int GetCreatorModelType() const {return theCreatorModel;}
inline void SetCreatorModelID(G4int id) {theCreatorModel = id;}
inline G4int GetCreatorModelID() const {return theCreatorModel;}
private:
@@ -107,6 +107,11 @@ class G4HadronicParameters {
// Baryons and mesons with c- and b- quarks may be enabled/disabled
// This flag is used both by EM and hadronic physics constructors
G4bool EnableHyperNuclei() const;
void SetEnableHyperNuclei( G4bool val );
// Light hyper-nuclei may be enabled/disabled
// This flag is used both by EM and hadronic physics constructors
G4bool ApplyFactorXS() const;
void SetApplyFactorXS( G4bool val );
// Flag enabling cross section factor definition
@@ -149,6 +154,7 @@ class G4HadronicParameters {
G4int fVerboseLevel = 1;
G4bool fEnableBC = false;
G4bool fEnableHyperNuclei = false;
G4bool fApplyFactorXS = false;
G4bool fEnableCRCoalescence = false;
};
@@ -212,6 +218,10 @@ inline G4bool G4HadronicParameters::EnableBCParticles() const {
return fEnableBC;
}
inline G4bool G4HadronicParameters::EnableHyperNuclei() const {
return fEnableHyperNuclei;
}
inline G4bool G4HadronicParameters::ApplyFactorXS() const {
return fApplyFactorXS;
}
@@ -123,6 +123,8 @@ class G4KineticTrack : public G4VKineticNucleon
void SetProjectilePotential(const G4double aPotential);
G4double GetProjectilePotential() const;
void SetCreatorModelID(G4int id);
G4int GetCreatorModelID() const;
private:
@@ -186,6 +188,8 @@ public:
CascadeState theStateToNucleus;
G4double theProjectilePotential;
G4int theCreatorModel;
};
// extern G4Allocator<G4KineticTrack> theKTAllocator;
@@ -422,6 +426,17 @@ G4double G4KineticTrack::GetProjectilePotential() const
return theProjectilePotential;
}
inline
void G4KineticTrack::SetCreatorModelID(G4int id)
{
theCreatorModel = id;
}
inline
G4int G4KineticTrack::GetCreatorModelID() const
{
return theCreatorModel;
}
#endif
@@ -42,10 +42,10 @@
#include "G4ParticleDefinition.hh"
#include "G4Proton.hh"
#include "G4Neutron.hh"
#include "G4AntiProton.hh" // Uzhi Feb. 2011
#include "G4AntiNeutron.hh" // Uzhi Feb. 2011
#include "G4Lambda.hh"
#include "G4AntiProton.hh"
#include "G4AntiNeutron.hh"
#include "G4AntiLambda.hh"
#include "G4VKineticNucleon.hh"
//#include "G4VSplitableHadron.hh"
@@ -74,11 +74,13 @@ class G4Nucleon : public G4VKineticNucleon
inline void SetBindingEnergy(G4double anEnergy) {theBindingE = anEnergy;}
inline G4double GetBindingEnergy() const {return theBindingE;}
inline void SetParticleType(G4Proton * aProton) {theParticleType = aProton;}
inline void SetParticleType(G4Neutron *aNeutron){theParticleType = aNeutron;}
inline void SetParticleType(G4Proton* aProton) {theParticleType = aProton;}
inline void SetParticleType(G4Neutron* aNeutron){theParticleType = aNeutron;}
inline void SetParticleType(G4Lambda* aLambda) {theParticleType = aLambda;}
inline void SetParticleType(G4AntiProton * aAntiProton) {theParticleType =aAntiProton;}
inline void SetParticleType(G4AntiNeutron *aAntiNeutron){theParticleType =aAntiNeutron;}
inline void SetParticleType(G4AntiProton* aAntiProton) {theParticleType = aAntiProton;}
inline void SetParticleType(G4AntiNeutron* aAntiNeutron){theParticleType = aAntiNeutron;}
inline void SetParticleType(G4AntiLambda* aAntiLambda) {theParticleType = aAntiLambda;}
inline const G4ParticleDefinition* GetParticleType() const {return theParticleType;}
virtual const G4ParticleDefinition* GetDefinition() const {return theParticleType;}
@@ -30,7 +30,8 @@
// M.G. Pia, 2 Oct 1998: modified GetFermiMomentum (original design was
// the source of memory leaks)
// G.Folger, spring 2010: add integer A/Z interface
// A. Ribon, autumn 2021: extended to hypernuclei
#ifndef G4Nucleus_h
#define G4Nucleus_h 1
// Class Description
@@ -52,8 +53,8 @@ class G4Nucleus
public:
G4Nucleus();
G4Nucleus(const G4double A, const G4double Z);
G4Nucleus(const G4int A, const G4int Z);
G4Nucleus(const G4double A, const G4double Z, const G4int numberOfLambdas = 0);
G4Nucleus(const G4int A, const G4int Z, const G4int numberOfLambdas = 0);
G4Nucleus(const G4Material* aMaterial);
~G4Nucleus();
@@ -66,6 +67,7 @@ class G4Nucleus
if (this != &right) {
theA=right.theA;
theZ=right.theZ;
theL=right.theL;
aEff=right.aEff;
zEff=right.zEff;
fIsotope = right.fIsotope;
@@ -91,21 +93,9 @@ class G4Nucleus
void ChooseParameters( const G4Material *aMaterial );
void SetParameters( const G4double A, const G4double Z );
void SetParameters( const G4int A, const G4int Z );
void SetParameters( const G4double A, const G4double Z, const G4int numberOfLambdas = 0 );
void SetParameters( const G4int A, const G4int Z, const G4int numberOfLambdas = 0 );
/*
#ifndef G4Hadr_Nucleus_IntegerAZ
//deprecated Jan 2010, GF
inline G4double GetN() const
{ return aEff; }
inline G4double GetZ() const
{ return zEff; }
#endif
//to be replaced by new
*/
inline G4int GetA_asInt() const
{ return theA; }
@@ -114,7 +104,9 @@ class G4Nucleus
inline G4int GetZ_asInt() const
{ return theZ; }
//... \GF
inline G4int GetL() const // Number of Lambdas (in the case of a hypernucleus)
{ return theL; }
inline const G4Isotope* GetIsotope()
{ return fIsotope; }
@@ -125,6 +117,7 @@ class G4Nucleus
if(iso) {
theZ = iso->GetZ();
theA = iso->GetN();
theL = 0;
aEff = theA;
zEff = theZ;
}
@@ -132,9 +125,9 @@ class G4Nucleus
G4DynamicParticle *ReturnTargetParticle() const;
G4double AtomicMass( const G4double A, const G4double Z ) const;
G4double AtomicMass( const G4int A, const G4int Z ) const;
G4double AtomicMass( const G4double A, const G4double Z, const G4int numberOfLambdas = 0 ) const;
G4double AtomicMass( const G4int A, const G4int Z, const G4int numberOfLambdas = 0 ) const;
G4double GetThermalPz( const G4double mass, const G4double temp ) const;
G4ReactionProduct GetThermalNucleus(G4double aMass, G4double temp=-1) const;
@@ -192,6 +185,7 @@ class G4Nucleus
G4int theA;
G4int theZ;
G4int theL; // Number of Lambdas (in the case of hypernucleus)
G4double aEff; // effective atomic weight
G4double zEff; // effective atomic number
@@ -162,10 +162,10 @@ class G4ReactionProduct
inline G4int GetSide() const
{ return side; }
inline void SetCreatorModel( const G4int mod )
inline void SetCreatorModelID( const G4int mod )
{ theCreatorModel = mod; }
inline G4int GetCreatorModel() const
inline G4int GetCreatorModelID() const
{ return theCreatorModel; }
inline void SetNewlyAdded( const G4bool f )
@@ -51,13 +51,14 @@ class G4V3DNucleus
G4bool operator!=(const G4V3DNucleus &right) const;
public:
virtual void Init(G4int theA, G4int theZ) = 0;
virtual void Init(G4int theA, G4int theZ, G4int numberOfLambdas = 0) = 0;
virtual G4bool StartLoop() = 0;
virtual G4Nucleon * GetNextNucleon() = 0;
virtual const std::vector<G4Nucleon> & GetNucleons() = 0;
virtual G4int GetMassNumber() = 0;
virtual G4double GetMass() = 0;
virtual G4int GetCharge() = 0;
virtual G4int GetNumberOfLambdas() = 0;
virtual G4double GetNuclearRadius() = 0;
virtual G4double GetNuclearRadius(const G4double maxRelativeDensity) = 0;
virtual G4double GetOuterRadius() = 0;
@@ -52,8 +52,14 @@ void G4DecayKineticTracks::Decay(G4KineticTrackVector *tracks) const {
// Select decay of current track, put daughters at end of vector
daughters = track->GetDefinition()->IsShortLived() ? track->Decay() : 0;
if (daughters) {
// Assign to the daughters the creator model ID of their parent
for (size_t k=0; k<daughters->size(); ++k) {
G4KineticTrack* aDaughter = (*daughters)[k];
if (aDaughter) aDaughter->SetCreatorModelID(track->GetCreatorModelID());
}
tracks->insert(tracks->end(), daughters->begin(), daughters->end());
delete track; // Remove parent track
delete daughters;
@@ -73,6 +73,7 @@ G4DecayStrongResonances::Propagate(G4KineticTrackVector* theSecondaries,
it->SetMass(aSecondary->GetDefinition()->GetPDGMass());
it->SetTotalEnergy(aSecondary->Get4Momentum().t());
it->SetMomentum(aSecondary->Get4Momentum().vect());
it->SetCreatorModelID(aSecondary->GetCreatorModelID());
delete aSecondary;
try { theResult->push_back(it); }
catch(...){
@@ -42,6 +42,7 @@
#include "G4NuclearFermiDensity.hh"
#include "G4NuclearShellModelDensity.hh"
#include "G4NucleiProperties.hh"
#include "G4HyperNucleiProperties.hh"
#include "G4Nucleon.hh"
#include "G4SystemOfUnits.hh"
#include "Randomize.hh"
@@ -57,7 +58,7 @@
#include "G4PhysicalConstants.hh"
G4Fancy3DNucleus::G4Fancy3DNucleus()
: myA(0), myZ(0), theNucleons(250), currentNucleon(-1), theDensity(0),
: myA(0), myZ(0), myL(0), theNucleons(250), currentNucleon(-1), theDensity(0),
nucleondistance(0.8*fermi),excitationEnergy(0.),
places(250), momentum(250), fermiM(250), testSums(250)
{
@@ -69,17 +70,17 @@ G4Fancy3DNucleus::~G4Fancy3DNucleus()
}
#if defined(NON_INTEGER_A_Z)
void G4Fancy3DNucleus::Init(G4double theA, G4double theZ)
void G4Fancy3DNucleus::Init(G4double theA, G4double theZ, G4int numberOfLambdas)
{
G4int intZ = G4int(theZ);
G4int intA= ( G4UniformRand()>theA-G4int(theA) ) ? G4int(theA) : G4int(theA)+1;
// forward to integer Init()
Init(intA, intZ);
Init(intA, intZ, std::max(numberOfLambdas, 0));
}
#endif
void G4Fancy3DNucleus::Init(G4int theA, G4int theZ)
void G4Fancy3DNucleus::Init(G4int theA, G4int theZ, G4int numberOfLambdas)
{
currentNucleon=-1;
theNucleons.clear();
@@ -90,10 +91,14 @@ void G4Fancy3DNucleus::Init(G4int theA, G4int theZ)
testSums.clear();
myZ = theZ;
myA= theA;
myA = theA;
myL = std::max(numberOfLambdas, 0); // Cannot be negative
excitationEnergy=0;
theNucleons.resize(myA); // Pre-loads vector with empty elements
// For simplicity, we neglect eventual Lambdas in the nucleus as far as the
// density of nucler levels and the Fermi level are concerned.
if(theDensity) delete theDensity;
if ( myA < 17 ) {
@@ -197,9 +202,10 @@ G4double G4Fancy3DNucleus::GetOuterRadius()
G4double G4Fancy3DNucleus::GetMass()
{
return myZ*G4Proton::Proton()->GetPDGMass() +
(myA-myZ)*G4Neutron::Neutron()->GetPDGMass() -
BindingEnergy();
if ( myL <= 0 ) return myZ*G4Proton::Proton()->GetPDGMass() +
(myA-myZ)*G4Neutron::Neutron()->GetPDGMass() -
BindingEnergy();
else return G4HyperNucleiProperties::GetNuclearMass(myA, myZ, myL);
}
@@ -273,22 +279,28 @@ const G4VNuclearDensity * G4Fancy3DNucleus::GetNuclearDensity() const
void G4Fancy3DNucleus::ChooseNucleons()
{
G4int protons=0,nucleons=0;
while (nucleons < myA ) /* Loop checking, 30-Oct-2015, G.Folger */
{
if ( protons < myZ && G4UniformRand() < (G4double)(myZ-protons)/(G4double)(myA-nucleons) )
{
protons++;
theNucleons[nucleons++].SetParticleType(G4Proton::Proton());
}
else if ( (nucleons-protons) < (myA-myZ) )
{
theNucleons[nucleons++].SetParticleType(G4Neutron::Neutron());
}
else G4cout << "G4Fancy3DNucleus::ChooseNucleons not efficient" << G4endl;
}
return;
G4int protons=0, nucleons=0, lambdas=0;
G4double probProton = ( G4double(myZ) )/( G4double(myA) );
G4double probLambda = myL > 0 ? ( G4double(myL) )/( G4double(myA) ) : 0.0;
while ( nucleons < myA ) { /* Loop checking, 30-Oct-2015, G.Folger */
G4double rnd = G4UniformRand();
if ( rnd < probProton ) {
if ( protons < myZ ) {
protons++;
theNucleons[nucleons++].SetParticleType(G4Proton::Proton());
}
} else if ( rnd < probProton + probLambda ) {
if ( lambdas < myL ) {
lambdas++;
theNucleons[nucleons++].SetParticleType(G4Lambda::Lambda());
}
} else {
if ( (nucleons - protons - lambdas) < (myA - myZ - myL) ) {
theNucleons[nucleons++].SetParticleType(G4Neutron::Neutron());
}
}
}
return;
}
void G4Fancy3DNucleus::ChoosePositions()
@@ -36,6 +36,7 @@
// inline to source
// 25.09.2010 M. Kelsey -- Change "setprecision" to "setwidth" in printout,
// add null pointer check.
// 27.10.2021 A.Ribon extension for hypernuclei.
#include "G4Fragment.hh"
#include "G4HadronicException.hh"
@@ -54,6 +55,7 @@ const G4double G4Fragment::minFragExcitation = 10.*CLHEP::eV;
G4Fragment::G4Fragment() :
theA(0),
theZ(0),
theL(0),
theExcitationEnergy(0.0),
theGroundStateMass(0.0),
theMomentum(G4LorentzVector(0,0,0,0)),
@@ -74,6 +76,7 @@ G4Fragment::G4Fragment() :
G4Fragment::G4Fragment(const G4Fragment &right) :
theA(right.theA),
theZ(right.theZ),
theL(right.theL),
theExcitationEnergy(right.theExcitationEnergy),
theGroundStateMass(right.theGroundStateMass),
theMomentum(right.theMomentum),
@@ -96,6 +99,32 @@ G4Fragment::~G4Fragment()
G4Fragment::G4Fragment(G4int A, G4int Z, const G4LorentzVector& aMomentum, G4bool warning) :
theA(A),
theZ(Z),
theL(0),
theExcitationEnergy(0.0),
theGroundStateMass(0.0),
theMomentum(aMomentum),
thePolarization(nullptr),
creatorModel(-1),
numberOfParticles(0),
numberOfCharged(0),
numberOfHoles(0),
numberOfChargedHoles(0),
numberOfShellElectrons(0),
xLevel(0),
theParticleDefinition(nullptr),
spin(0.0),
theCreationTime(0.0)
{
if(theA > 0) {
CalculateGroundStateMass();
CalculateExcitationEnergy(warning);
}
}
G4Fragment::G4Fragment(G4int A, G4int Z, G4int numberOfLambdas, const G4LorentzVector& aMomentum, G4bool warning) :
theA(A),
theZ(Z),
theL(std::max(numberOfLambdas,0)),
theExcitationEnergy(0.0),
theGroundStateMass(0.0),
theMomentum(aMomentum),
@@ -122,6 +151,7 @@ G4Fragment::G4Fragment(const G4LorentzVector& aMomentum,
const G4ParticleDefinition * aParticleDefinition) :
theA(0),
theZ(0),
theL(0),
theExcitationEnergy(0.0),
theMomentum(aMomentum),
thePolarization(nullptr),
@@ -150,6 +180,7 @@ G4Fragment & G4Fragment::operator=(const G4Fragment &right)
if (this != &right) {
theA = right.theA;
theZ = right.theZ;
theL = right.theL;
theExcitationEnergy = right.theExcitationEnergy;
theGroundStateMass = right.theGroundStateMass;
theMomentum = right.theMomentum;
@@ -184,7 +215,8 @@ std::ostream& operator << (std::ostream &out, const G4Fragment &theFragment)
out.setf(std::ios::floatfield);
out << "Fragment: A = " << std::setw(3) << theFragment.theA
<< ", Z = " << std::setw(3) << theFragment.theZ ;
<< ", Z = " << std::setw(3) << theFragment.theZ
<< ", numberOfLambdas = " << std::setw(3) << theFragment.theL ;
out.setf(std::ios::scientific,std::ios::floatfield);
// Store user's precision setting and reset to (3) here: back-compatibility
@@ -193,8 +225,8 @@ std::ostream& operator << (std::ostream &out, const G4Fragment &theFragment)
out << std::setprecision(3)
<< ", U = " << theFragment.GetExcitationEnergy()/CLHEP::MeV
<< " MeV ";
if(theFragment.GetCreatorModelType() >= 0) {
out << " creatorModelType= " << theFragment.GetCreatorModelType();
if(theFragment.GetCreatorModelID() >= 0) {
out << " creatorModelID= " << theFragment.GetCreatorModelID();
}
if(theFragment.GetCreationTime() > 0.0) {
out << " Time= " << theFragment.GetCreationTime()/CLHEP::ns << " ns";
@@ -101,6 +101,7 @@ void G4HadronicParameters::SetMinEnergyTransitionFTF_Cascade( const G4double val
}
}
void G4HadronicParameters::SetMaxEnergyTransitionFTF_Cascade( const G4double val ) {
if ( ! IsLocked() && val > fMinEnergyTransitionFTF_Cascade ) {
fMaxEnergyTransitionFTF_Cascade = val;
@@ -120,12 +121,16 @@ void G4HadronicParameters::SetMaxEnergyTransitionQGS_FTF( const G4double val ) {
}
}
void G4HadronicParameters::SetEnableBCParticles( G4bool val ) {
if ( ! IsLocked() ) fEnableBC = val;
}
void G4HadronicParameters::SetEnableHyperNuclei( G4bool val ) {
if ( ! IsLocked() ) fEnableHyperNuclei = val;
}
void G4HadronicParameters::SetVerboseLevel( const G4int val ) {
if ( ! IsLocked() && val >= 0 ) fVerboseLevel = val;
}
@@ -78,7 +78,8 @@ G4KineticTrack::G4KineticTrack() :
theDaughterMass(0),
theDaughterWidth(0),
theStateToNucleus(undefined),
theProjectilePotential(0)
theProjectilePotential(0),
theCreatorModel(-1)
{
////////////////
// DEBUG //
@@ -117,7 +118,7 @@ G4KineticTrack::G4KineticTrack(const G4KineticTrack &right) : G4VKineticNucleon(
theDaughterWidth = 0;
theStateToNucleus=right.theStateToNucleus;
theProjectilePotential=right.theProjectilePotential;
theCreatorModel = right.GetCreatorModelID();
////////////////
// DEBUG //
////////////////
@@ -146,7 +147,8 @@ G4KineticTrack::G4KineticTrack(const G4ParticleDefinition* aDefinition,
theTotal4Momentum(a4Momentum),
theNucleon(0),
theStateToNucleus(undefined),
theProjectilePotential(0)
theProjectilePotential(0),
theCreatorModel(-1)
{
if(G4KaonZero::KaonZero() == theDefinition ||
G4AntiKaonZero::AntiKaonZero() == theDefinition)
@@ -412,8 +414,8 @@ G4KineticTrack::G4KineticTrack(const G4ParticleDefinition* aDefinition,
}
G4KineticTrack::G4KineticTrack(G4Nucleon * nucleon,
const G4ThreeVector& aPosition,
const G4LorentzVector& a4Momentum)
const G4ThreeVector& aPosition,
const G4LorentzVector& a4Momentum)
: theDefinition(nucleon->GetDefinition()),
theFormationTime(0),
thePosition(aPosition),
@@ -426,7 +428,8 @@ G4KineticTrack::G4KineticTrack(G4Nucleon * nucleon,
theDaughterMass(0),
theDaughterWidth(0),
theStateToNucleus(undefined),
theProjectilePotential(0)
theProjectilePotential(0),
theCreatorModel(-1)
{
theFermi3Momentum.setE(0);
Set4Momentum(a4Momentum);
@@ -458,6 +461,7 @@ G4KineticTrack& G4KineticTrack::operator=(const G4KineticTrack& right)
nChannels = right.GetnChannels();
theActualWidth = new G4double[nChannels];
for (G4int i = 0; i < nChannels; ++i) theActualWidth[i] = right.theActualWidth[i];
theCreatorModel = right.GetCreatorModelID();
}
return *this;
}
@@ -694,7 +698,9 @@ G4KineticTrackVector* G4KineticTrack::Decay()
//
// Create the kinetic track List associated to the decay products
//
//
// For the decay products of hadronic resonances, we assign as creator model ID
// the same as their parent
G4LorentzRotation toMoving(Get4Momentum().boostVector());
G4DynamicParticle* theDynamicParticle;
G4double formationTime = 0.0;
@@ -713,10 +719,12 @@ G4KineticTrackVector* G4KineticTrack::Decay()
momentumBalanceCMS += theDynamicParticle->Get4Momentum();
momentum = toMoving*theDynamicParticle->Get4Momentum();
energyMomentumBalance -= momentum;
theDecayProductList->push_back(new G4KineticTrack (aProduct,
G4KineticTrack* aDaughter = new G4KineticTrack (aProduct,
formationTime,
position,
momentum));
momentum);
if (aDaughter != nullptr) aDaughter->SetCreatorModelID(GetCreatorModelID());
theDecayProductList->push_back(aDaughter);
delete theDynamicParticle;
}
delete theDecayProducts;
+355 -238
View File
@@ -25,20 +25,21 @@
//
//
//
// original by H.P. Wellisch
// modified by J.L. Chuma, TRIUMF, 19-Nov-1996
// last modified: 27-Mar-1997
// J.P.Wellisch: 23-Apr-97: minor simplifications
// modified by J.L.Chuma 24-Jul-97 to set the total momentum in Cinema and
// EvaporationEffects
// modified by J.L.Chuma 21-Oct-97 put std::abs() around the totalE^2-mass^2
// in calculation of total momentum in
// Cinema and EvaporationEffects
// Chr. Volcker, 10-Nov-1997: new methods and class variables.
// HPW added utilities for low energy neutron transport. (12.04.1998)
// M.G. Pia, 2 Oct 1998: modified GetFermiMomentum to avoid memory leaks
// G.Folger, spring 2010: add integer A/Z interface
// A. Ribon, 6 August 2015: migrated to G4Exp and G4Log.
// original by H.P. Wellisch
// modified by J.L. Chuma, TRIUMF, 19-Nov-1996
// last modified: 27-Mar-1997
// J.P.Wellisch: 23-Apr-97: minor simplifications
// modified by J.L.Chuma 24-Jul-97 to set the total momentum in Cinema and
// EvaporationEffects
// modified by J.L.Chuma 21-Oct-97 put std::abs() around the totalE^2-mass^2
// in calculation of total momentum in
// Cinema and EvaporationEffects
// Chr. Volcker, 10-Nov-1997: new methods and class variables.
// HPW added utilities for low energy neutron transport. (12.04.1998)
// M.G. Pia, 2 Oct 1998: modified GetFermiMomentum to avoid memory leaks
// G.Folger, spring 2010: add integer A/Z interface
// A. Ribon, summer 2015: migrated to G4Exp and G4Log
// A. Ribon, autumn 2021: extended to hypernuclei
#include "G4Nucleus.hh"
#include "G4NucleiProperties.hh"
@@ -46,13 +47,13 @@
#include "G4SystemOfUnits.hh"
#include "Randomize.hh"
#include "G4HadronicException.hh"
#include "G4Exp.hh"
#include "G4Log.hh"
#include "G4HyperNucleiProperties.hh"
G4Nucleus::G4Nucleus()
: theA(0), theZ(0), aEff(0.0), zEff(0)
: theA(0), theZ(0), theL(0), aEff(0.0), zEff(0)
{
pnBlackTrackEnergy = 0.0;
dtaBlackTrackEnergy = 0.0;
@@ -65,9 +66,9 @@ G4Nucleus::G4Nucleus()
fIsotope = 0;
}
G4Nucleus::G4Nucleus( const G4double A, const G4double Z )
G4Nucleus::G4Nucleus( const G4double A, const G4double Z, const G4int numberOfLambdas )
{
SetParameters( A, Z );
SetParameters( A, Z, std::max(numberOfLambdas, 0) );
pnBlackTrackEnergy = 0.0;
dtaBlackTrackEnergy = 0.0;
pnBlackTrackEnergyfromAnnihilation = 0.0;
@@ -79,9 +80,9 @@ G4Nucleus::G4Nucleus( const G4double A, const G4double Z )
fIsotope = 0;
}
G4Nucleus::G4Nucleus( const G4int A, const G4int Z )
G4Nucleus::G4Nucleus( const G4int A, const G4int Z, const G4int numberOfLambdas )
{
SetParameters( A, Z );
SetParameters( A, Z, std::max(numberOfLambdas, 0) );
pnBlackTrackEnergy = 0.0;
dtaBlackTrackEnergy = 0.0;
pnBlackTrackEnergyfromAnnihilation = 0.0;
@@ -109,36 +110,128 @@ G4Nucleus::G4Nucleus( const G4Material *aMaterial )
G4Nucleus::~G4Nucleus() {}
G4ReactionProduct G4Nucleus::
GetBiasedThermalNucleus(G4double aMass, G4ThreeVector aVelocity, G4double temp) const
//-------------------------------------------------------------------------------------------------
// SVT (Sampling of the Velocity of the Target nucleus) method, L. Thulliez (CEA-Saclay) 2021/05/04
//-------------------------------------------------------------------------------------------------
G4ReactionProduct
G4Nucleus::GetBiasedThermalNucleus(G4double aMass, G4ThreeVector aVelocity, G4double temp) const
{
G4double velMag = aVelocity.mag();
// If E_neutron <= 400*kB*T (400 is a common value encounter in MC neutron transport code)
// Then apply the Sampling ot the Velocity of the Target (SVT) method
// Else consider the target nucleus being without motion
G4double E_threshold = 400.0*8.617333262E-11*temp; // 400*kBoltzman*T
G4double E_neutron = 0.5*aVelocity.mag2()*G4Neutron::Neutron()->GetPDGMass(); // E=0.5*m*v2
G4ReactionProduct result;
G4double value = 0;
G4double random = 1;
G4double norm = 3.*std::sqrt(k_Boltzmann*temp*aMass*G4Neutron::Neutron()->GetPDGMass());
norm /= G4Neutron::Neutron()->GetPDGMass();
norm *= 5.;
norm += velMag;
norm /= velMag;
const G4int maxNumberOfLoops = 1000000;
G4int loopCounter = -1;
while ( (value/norm<random) && ++loopCounter < maxNumberOfLoops ) /* Loop checking, 02.11.2015, A.Ribon */
{
result = GetThermalNucleus(aMass, temp);
G4ThreeVector targetVelocity = 1./result.GetMass()*result.GetMomentum();
value = (targetVelocity+aVelocity).mag()/velMag;
random = G4UniformRand();
}
if ( loopCounter >= maxNumberOfLoops ) {
G4ExceptionDescription ed;
ed << " Failed sampling after maxNumberOfLoops attempts : forced exit! " << G4endl;
G4Exception( " G4Nucleus::GetBiasedThermalNucleus ", "HAD_NUCLEUS_001", JustWarning, ed );
result = GetThermalNucleus(aMass, temp);
result.SetMass(aMass*G4Neutron::Neutron()->GetPDGMass());
if ( E_neutron <= E_threshold ) {
// Beta = sqrt(m/2kT)
G4double beta = std::sqrt(result.GetMass()/(2.*8.617333262E-11*temp)); // kT E-5[eV] mass E-11[MeV] => beta in [m/s]-1
// Neutron speed vn
G4double vN_norm = aVelocity.mag();
G4double vN_norm2 = vN_norm*vN_norm;
G4double y = beta*vN_norm;
// Normalize neutron velocity
aVelocity = (1./vN_norm)*aVelocity;
// Sample target speed
G4double x2;
G4double randThreshold;
G4double vT_norm, vT_norm2, mu; //theta, val1, val2,
G4double acceptThreshold;
G4double vRelativeSpeed;
G4double cdf0 = 2./(2.+std::sqrt(CLHEP::pi)*y);
do {
// Sample the target velocity vT in the laboratory frame
if ( G4UniformRand() < cdf0 ) {
// Sample in C45 from https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-9721.pdf
x2 = -std::log(G4UniformRand()*G4UniformRand());
} else {
// Sample in C61 from https://laws.lanl.gov/vhosts/mcnp.lanl.gov/pdf_files/la-9721.pdf
G4double ampl = std::cos(CLHEP::pi/2.0 * G4UniformRand());
x2 = -std::log(G4UniformRand()) - std::log(G4UniformRand())*ampl*ampl;
}
vT_norm = std::sqrt(x2)/beta;
vT_norm2 = vT_norm*vT_norm;
// Sample cosine between the incident neutron and the target in the laboratory frame
mu = 2*G4UniformRand() - 1;
// Define acceptance threshold
vRelativeSpeed = std::sqrt(vN_norm2 + vT_norm2 - 2*vN_norm*vT_norm*mu);
acceptThreshold = vRelativeSpeed/(vN_norm + vT_norm);
randThreshold = G4UniformRand();
} while ( randThreshold >= acceptThreshold );
// Get target nucleus direction from the neutron direction and the relative angle between target nucleus and neutron (mu)
G4double cosTh = mu;
G4ThreeVector uNorm = aVelocity;
G4double sinTh = std::sqrt(1. - cosTh*cosTh);
// Sample randomly the phi angle between the neutron veloicty and the target velocity
G4double phi = CLHEP::twopi*G4UniformRand();
G4double sinPhi = std::sin(phi);
G4double cosPhi = std::cos(phi);
// Find orthogonal vector to aVelocity - solve equation xx' + yy' + zz' = 0
G4ThreeVector ortho(1,1,1);
if ( uNorm[0] ) ortho[0] = -(uNorm[1]+uNorm[2])/uNorm[0];
else if ( uNorm[1] ) ortho[1] = -(uNorm[0]+uNorm[2])/uNorm[1];
else if ( uNorm[2] ) ortho[2] = -(uNorm[0]+uNorm[1])/uNorm[2];
// Normalize the vector
ortho = (1/ortho.mag())*ortho;
// Find vector to draw a plan perpendicular to uNorm (i.e neutron velocity) with vectors ortho & orthoComp
G4ThreeVector orthoComp( uNorm[1]*ortho[2] - ortho[1]*uNorm[2],
uNorm[2]*ortho[0] - ortho[2]*uNorm[0],
uNorm[0]*ortho[1] - ortho[0]*uNorm[1] );
// Find the direction of the target velocity in the laboratory frame
G4ThreeVector directionTarget( cosTh*uNorm[0] + sinTh*(cosPhi*orthoComp[0] + sinPhi*ortho[0]),
cosTh*uNorm[1] + sinTh*(cosPhi*orthoComp[1] + sinPhi*ortho[1]),
cosTh*uNorm[2] + sinTh*(cosPhi*orthoComp[2] + sinPhi*ortho[2]) );
// Normalize directionTarget
directionTarget = (1/directionTarget.mag())*directionTarget;
// Set momentum
G4double px = result.GetMass()*vT_norm*directionTarget[0];
G4double py = result.GetMass()*vT_norm*directionTarget[1];
G4double pz = result.GetMass()*vT_norm*directionTarget[2];
result.SetMomentum(px, py, pz);
G4double tMom = std::sqrt(px*px+py*py+pz*pz);
G4double tEtot = std::sqrt((tMom+result.GetMass())*(tMom+result.GetMass())
- 2.*tMom*result.GetMass());
if ( tEtot/result.GetMass() - 1. > 0.001 ) {
// use relativistic energy for higher energies
result.SetTotalEnergy(tEtot);
} else {
// use p**2/2M for lower energies (to preserve precision?)
result.SetKineticEnergy(tMom*tMom/(2.*result.GetMass()));
}
} else { // target nucleus considered as being without motion
result.SetMomentum(0., 0., 0.);
result.SetKineticEnergy(0.);
}
return result;
}
G4ReactionProduct
G4Nucleus::GetThermalNucleus(G4double targetMass, G4double temp) const
{
@@ -176,7 +269,7 @@ G4Nucleus::ChooseParameters(const G4Material* aMaterial)
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
G4double running(0);
// G4Element* element(0);
G4Element* element = (*theElementVector)[aMaterial->GetNumberOfElements()-1];
const G4Element* element = (*theElementVector)[aMaterial->GetNumberOfElements()-1];
for (unsigned int i = 0; i < aMaterial->GetNumberOfElements(); ++i) {
running += aMaterial->GetVecNbOfAtomsPerVolume()[i];
@@ -197,22 +290,25 @@ G4Nucleus::ChooseParameters(const G4Material* aMaterial)
}
theA=element->GetIsotope(iso)->GetN();
theZ=element->GetIsotope(iso)->GetZ();
theL=0;
aEff=theA;
zEff=theZ;
} else {
aEff = element->GetN();
zEff = element->GetZ();
theZ = G4int(zEff + 0.5);
theA = G4int(aEff + 0.5);
theA = G4int(aEff + 0.5);
theL=0;
}
}
void
G4Nucleus::SetParameters(G4double A, G4double Z)
G4Nucleus::SetParameters( const G4double A, const G4double Z, const G4int numberOfLambdas )
{
theZ = G4lrint(Z);
theA = G4lrint(A);
theA = G4lrint(A);
theL = std::max(numberOfLambdas, 0);
if (theA<1 || theZ<0 || theZ>theA) {
throw G4HadronicException(__FILE__, __LINE__,
"G4Nucleus::SetParameters called with non-physical parameters");
@@ -222,11 +318,13 @@ G4Nucleus::SetParameters(G4double A, G4double Z)
fIsotope = 0;
}
void
G4Nucleus::SetParameters(G4int A, const G4int Z )
G4Nucleus::SetParameters( const G4int A, const G4int Z, const G4int numberOfLambdas )
{
theZ = Z;
theA = A;
theA = A;
theL = std::max(numberOfLambdas, 0);
if( theA<1 || theZ<0 || theZ>theA )
{
throw G4HadronicException(__FILE__, __LINE__,
@@ -237,219 +335,238 @@ G4Nucleus::SetParameters(G4int A, const G4int Z )
fIsotope = 0;
}
G4DynamicParticle *
G4Nucleus::ReturnTargetParticle() const
{
// choose a proton or a neutron as the target particle
G4DynamicParticle *targetParticle = new G4DynamicParticle;
if( G4UniformRand() < zEff/aEff )
targetParticle->SetDefinition( G4Proton::Proton() );
else
targetParticle->SetDefinition( G4Neutron::Neutron() );
return targetParticle;
G4DynamicParticle *
G4Nucleus::ReturnTargetParticle() const
{
// choose a proton or a neutron (or a lamba if a hypernucleus) as the target particle
G4DynamicParticle *targetParticle = new G4DynamicParticle;
const G4double rnd = G4UniformRand();
if ( rnd < zEff/aEff ) {
targetParticle->SetDefinition( G4Proton::Proton() );
} else if ( rnd < (zEff + theL*1.0)/aEff ) {
targetParticle->SetDefinition( G4Lambda::Lambda() );
} else {
targetParticle->SetDefinition( G4Neutron::Neutron() );
}
return targetParticle;
}
G4double
G4Nucleus::AtomicMass( const G4double A, const G4double Z ) const
{
// Now returns (atomic mass - electron masses)
G4double
G4Nucleus::AtomicMass( const G4double A, const G4double Z, const G4int numberOfLambdas ) const
{
// Now returns (atomic mass - electron masses)
if ( numberOfLambdas > 0 ) {
return G4HyperNucleiProperties::GetNuclearMass(G4int(A), G4int(Z), numberOfLambdas);
} else {
return G4NucleiProperties::GetNuclearMass(A, Z);
}
}
G4double
G4Nucleus::AtomicMass( const G4int A, const G4int Z ) const
{
// Now returns (atomic mass - electron masses)
G4double
G4Nucleus::AtomicMass( const G4int A, const G4int Z, const G4int numberOfLambdas ) const
{
// Now returns (atomic mass - electron masses)
if ( numberOfLambdas > 0 ) {
return G4HyperNucleiProperties::GetNuclearMass(A, Z, numberOfLambdas);
} else {
return G4NucleiProperties::GetNuclearMass(A, Z);
}
}
G4double
G4Nucleus::GetThermalPz( const G4double mass, const G4double temp ) const
{
G4double result = G4RandGauss::shoot();
result *= std::sqrt(k_Boltzmann*temp*mass); // Das ist impuls (Pz),
// nichtrelativistische rechnung
// Maxwell verteilung angenommen
return result;
}
G4double
G4Nucleus::EvaporationEffects( G4double kineticEnergy )
{
// derived from original FORTRAN code EXNU by H. Fesefeldt (10-Dec-1986)
//
// Nuclear evaporation as function of atomic number
// and kinetic energy (MeV) of primary particle
//
// returns kinetic energy (MeV)
//
if( aEff < 1.5 )
{
pnBlackTrackEnergy = dtaBlackTrackEnergy = 0.0;
return 0.0;
}
G4double ek = kineticEnergy/GeV;
G4float ekin = std::min( 4.0, std::max( 0.1, ek ) );
const G4float atno = std::min( 120., aEff );
const G4float gfa = 2.0*((aEff-1.0)/70.)*G4Exp(-(aEff-1.0)/70.);
//
// 0.35 value at 1 GeV
// 0.05 value at 0.1 GeV
//
G4float cfa = std::max( 0.15, 0.35 + ((0.35-0.05)/2.3)*G4Log(ekin) );
G4float exnu = 7.716 * cfa * G4Exp(-cfa)
* ((atno-1.0)/120.)*G4Exp(-(atno-1.0)/120.);
G4float fpdiv = std::max( 0.5, 1.0-0.25*ekin*ekin );
//
// pnBlackTrackEnergy is the kinetic energy (in GeV) available for
// proton/neutron black track particles
// dtaBlackTrackEnergy is the kinetic energy (in GeV) available for
// deuteron/triton/alpha black track particles
//
pnBlackTrackEnergy = exnu*fpdiv;
dtaBlackTrackEnergy = exnu*(1.0-fpdiv);
if( G4int(zEff+0.1) != 82 )
{
G4double ran1 = -6.0;
G4double ran2 = -6.0;
for( G4int i=0; i<12; ++i )
{
ran1 += G4UniformRand();
ran2 += G4UniformRand();
}
pnBlackTrackEnergy *= 1.0 + ran1*gfa;
dtaBlackTrackEnergy *= 1.0 + ran2*gfa;
}
pnBlackTrackEnergy = std::max( 0.0, pnBlackTrackEnergy );
dtaBlackTrackEnergy = std::max( 0.0, dtaBlackTrackEnergy );
while( pnBlackTrackEnergy+dtaBlackTrackEnergy >= ek ) /* Loop checking, 02.11.2015, A.Ribon */
{
pnBlackTrackEnergy *= 1.0 - 0.5*G4UniformRand();
dtaBlackTrackEnergy *= 1.0 - 0.5*G4UniformRand();
}
// G4cout << "EvaporationEffects "<<kineticEnergy<<" "
// <<pnBlackTrackEnergy+dtaBlackTrackEnergy<<endl;
return (pnBlackTrackEnergy+dtaBlackTrackEnergy)*GeV;
}
G4double
G4Nucleus::GetThermalPz( const G4double mass, const G4double temp ) const
{
G4double result = G4RandGauss::shoot();
result *= std::sqrt(k_Boltzmann*temp*mass); // Das ist impuls (Pz),
// nichtrelativistische rechnung
// Maxwell verteilung angenommen
return result;
}
G4double G4Nucleus::AnnihilationEvaporationEffects(G4double kineticEnergy, G4double ekOrg)
{
// Nuclear evaporation as a function of atomic number and kinetic
// energy (MeV) of primary particle. Modified for annihilation effects.
//
if( aEff < 1.5 || ekOrg < 0.)
{
pnBlackTrackEnergyfromAnnihilation = 0.0;
dtaBlackTrackEnergyfromAnnihilation = 0.0;
return 0.0;
}
G4double ek = kineticEnergy/GeV;
G4float ekin = std::min( 4.0, std::max( 0.1, ek ) );
const G4float atno = std::min( 120., aEff );
const G4float gfa = 2.0*((aEff-1.0)/70.)*G4Exp(-(aEff-1.0)/70.);
G4float cfa = std::max( 0.15, 0.35 + ((0.35-0.05)/2.3)*G4Log(ekin) );
G4float exnu = 7.716 * cfa * G4Exp(-cfa)
* ((atno-1.0)/120.)*G4Exp(-(atno-1.0)/120.);
G4float fpdiv = std::max( 0.5, 1.0-0.25*ekin*ekin );
pnBlackTrackEnergyfromAnnihilation = exnu*fpdiv;
dtaBlackTrackEnergyfromAnnihilation = exnu*(1.0-fpdiv);
G4double
G4Nucleus::EvaporationEffects( G4double kineticEnergy )
{
// derived from original FORTRAN code EXNU by H. Fesefeldt (10-Dec-1986)
//
// Nuclear evaporation as function of atomic number
// and kinetic energy (MeV) of primary particle
//
// returns kinetic energy (MeV)
//
if( aEff < 1.5 )
{
pnBlackTrackEnergy = dtaBlackTrackEnergy = 0.0;
return 0.0;
}
G4double ek = kineticEnergy/GeV;
G4float ekin = std::min( 4.0, std::max( 0.1, ek ) );
const G4float atno = std::min( 120., aEff );
const G4float gfa = 2.0*((aEff-1.0)/70.)*G4Exp(-(aEff-1.0)/70.);
//
// 0.35 value at 1 GeV
// 0.05 value at 0.1 GeV
//
G4float cfa = std::max( 0.15, 0.35 + ((0.35-0.05)/2.3)*G4Log(ekin) );
G4float exnu = 7.716 * cfa * G4Exp(-cfa)
* ((atno-1.0)/120.)*G4Exp(-(atno-1.0)/120.);
G4float fpdiv = std::max( 0.5, 1.0-0.25*ekin*ekin );
//
// pnBlackTrackEnergy is the kinetic energy (in GeV) available for
// proton/neutron black track particles
// dtaBlackTrackEnergy is the kinetic energy (in GeV) available for
// deuteron/triton/alpha black track particles
//
pnBlackTrackEnergy = exnu*fpdiv;
dtaBlackTrackEnergy = exnu*(1.0-fpdiv);
if( G4int(zEff+0.1) != 82 )
{
G4double ran1 = -6.0;
G4double ran2 = -6.0;
for( G4int i=0; i<12; ++i ) {
for( G4int i=0; i<12; ++i )
{
ran1 += G4UniformRand();
ran2 += G4UniformRand();
}
pnBlackTrackEnergyfromAnnihilation *= 1.0 + ran1*gfa;
dtaBlackTrackEnergyfromAnnihilation *= 1.0 + ran2*gfa;
pnBlackTrackEnergyfromAnnihilation = std::max( 0.0, pnBlackTrackEnergyfromAnnihilation);
dtaBlackTrackEnergyfromAnnihilation = std::max( 0.0, dtaBlackTrackEnergyfromAnnihilation);
G4double blackSum = pnBlackTrackEnergyfromAnnihilation+dtaBlackTrackEnergyfromAnnihilation;
if (blackSum >= ekOrg/GeV) {
pnBlackTrackEnergyfromAnnihilation *= ekOrg/GeV/blackSum;
dtaBlackTrackEnergyfromAnnihilation *= ekOrg/GeV/blackSum;
}
return (pnBlackTrackEnergyfromAnnihilation+dtaBlackTrackEnergyfromAnnihilation)*GeV;
pnBlackTrackEnergy *= 1.0 + ran1*gfa;
dtaBlackTrackEnergy *= 1.0 + ran2*gfa;
}
G4double
G4Nucleus::Cinema( G4double kineticEnergy )
pnBlackTrackEnergy = std::max( 0.0, pnBlackTrackEnergy );
dtaBlackTrackEnergy = std::max( 0.0, dtaBlackTrackEnergy );
while( pnBlackTrackEnergy+dtaBlackTrackEnergy >= ek ) /* Loop checking, 02.11.2015, A.Ribon */
{
// derived from original FORTRAN code CINEMA by H. Fesefeldt (14-Oct-1987)
//
// input: kineticEnergy (MeV)
// returns modified kinetic energy (MeV)
//
static const G4double expxu = 82.; // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
G4double ek = kineticEnergy/GeV;
G4double ekLog = G4Log( ek );
G4double aLog = G4Log( aEff );
G4double em = std::min( 1.0, 0.2390 + 0.0408*aLog*aLog );
G4double temp1 = -ek * std::min( 0.15, 0.0019*aLog*aLog*aLog );
G4double temp2 = G4Exp( std::max( expxl, std::min( expxu, -(ekLog-em)*(ekLog-em)*2.0 ) ) );
G4double result = 0.0;
if( std::abs( temp1 ) < 1.0 )
{
if( temp2 > 1.0e-10 )result = temp1*temp2;
}
else result = temp1*temp2;
if( result < -ek )result = -ek;
return result*GeV;
pnBlackTrackEnergy *= 1.0 - 0.5*G4UniformRand();
dtaBlackTrackEnergy *= 1.0 - 0.5*G4UniformRand();
}
//G4cout << "EvaporationEffects "<<kineticEnergy<<" "
// <<pnBlackTrackEnergy+dtaBlackTrackEnergy<< G4endl;
return (pnBlackTrackEnergy+dtaBlackTrackEnergy)*GeV;
}
G4double
G4Nucleus::AnnihilationEvaporationEffects(G4double kineticEnergy, G4double ekOrg)
{
// Nuclear evaporation as a function of atomic number and kinetic
// energy (MeV) of primary particle. Modified for annihilation effects.
//
if( aEff < 1.5 || ekOrg < 0.)
{
pnBlackTrackEnergyfromAnnihilation = 0.0;
dtaBlackTrackEnergyfromAnnihilation = 0.0;
return 0.0;
}
G4double ek = kineticEnergy/GeV;
G4float ekin = std::min( 4.0, std::max( 0.1, ek ) );
const G4float atno = std::min( 120., aEff );
const G4float gfa = 2.0*((aEff-1.0)/70.)*G4Exp(-(aEff-1.0)/70.);
G4float cfa = std::max( 0.15, 0.35 + ((0.35-0.05)/2.3)*G4Log(ekin) );
G4float exnu = 7.716 * cfa * G4Exp(-cfa)
* ((atno-1.0)/120.)*G4Exp(-(atno-1.0)/120.);
G4float fpdiv = std::max( 0.5, 1.0-0.25*ekin*ekin );
pnBlackTrackEnergyfromAnnihilation = exnu*fpdiv;
dtaBlackTrackEnergyfromAnnihilation = exnu*(1.0-fpdiv);
G4double ran1 = -6.0;
G4double ran2 = -6.0;
for( G4int i=0; i<12; ++i ) {
ran1 += G4UniformRand();
ran2 += G4UniformRand();
}
pnBlackTrackEnergyfromAnnihilation *= 1.0 + ran1*gfa;
dtaBlackTrackEnergyfromAnnihilation *= 1.0 + ran2*gfa;
pnBlackTrackEnergyfromAnnihilation = std::max( 0.0, pnBlackTrackEnergyfromAnnihilation);
dtaBlackTrackEnergyfromAnnihilation = std::max( 0.0, dtaBlackTrackEnergyfromAnnihilation);
G4double blackSum = pnBlackTrackEnergyfromAnnihilation+dtaBlackTrackEnergyfromAnnihilation;
if (blackSum >= ekOrg/GeV) {
pnBlackTrackEnergyfromAnnihilation *= ekOrg/GeV/blackSum;
dtaBlackTrackEnergyfromAnnihilation *= ekOrg/GeV/blackSum;
}
//
// methods for class G4Nucleus ... by Christian Volcker
//
return (pnBlackTrackEnergyfromAnnihilation+dtaBlackTrackEnergyfromAnnihilation)*GeV;
}
G4ThreeVector G4Nucleus::GetFermiMomentum()
{
// chv: .. we assume zero temperature!
// momentum is equally distributed in each phasespace volume dpx, dpy, dpz.
G4double ranflat1=
G4RandFlat::shoot((G4double)0.,(G4double)fermiMomentum);
G4double ranflat2=
G4RandFlat::shoot((G4double)0.,(G4double)fermiMomentum);
G4double ranflat3=
G4RandFlat::shoot((G4double)0.,(G4double)fermiMomentum);
G4double ranmax = (ranflat1>ranflat2? ranflat1: ranflat2);
ranmax = (ranmax>ranflat3? ranmax : ranflat3);
// Isotropic momentum distribution
G4double costheta = 2.*G4UniformRand() - 1.0;
G4double sintheta = std::sqrt(1.0 - costheta*costheta);
G4double phi = 2.0*pi*G4UniformRand();
G4double pz=costheta*ranmax;
G4double px=sintheta*std::cos(phi)*ranmax;
G4double py=sintheta*std::sin(phi)*ranmax;
G4ThreeVector p(px,py,pz);
return p;
}
G4ReactionProductVector* G4Nucleus::Fragmentate()
G4double
G4Nucleus::Cinema( G4double kineticEnergy )
{
// derived from original FORTRAN code CINEMA by H. Fesefeldt (14-Oct-1987)
//
// input: kineticEnergy (MeV)
// returns modified kinetic energy (MeV)
//
static const G4double expxu = 82.; // upper bound for arg. of exp
static const G4double expxl = -expxu; // lower bound for arg. of exp
G4double ek = kineticEnergy/GeV;
G4double ekLog = G4Log( ek );
G4double aLog = G4Log( aEff );
G4double em = std::min( 1.0, 0.2390 + 0.0408*aLog*aLog );
G4double temp1 = -ek * std::min( 0.15, 0.0019*aLog*aLog*aLog );
G4double temp2 = G4Exp( std::max( expxl, std::min( expxu, -(ekLog-em)*(ekLog-em)*2.0 ) ) );
G4double result = 0.0;
if( std::abs( temp1 ) < 1.0 )
{
// needs implementation!
return NULL;
if( temp2 > 1.0e-10 )result = temp1*temp2;
}
else result = temp1*temp2;
if( result < -ek )result = -ek;
return result*GeV;
}
G4ThreeVector G4Nucleus::GetFermiMomentum()
{
// chv: .. we assume zero temperature!
// momentum is equally distributed in each phasespace volume dpx, dpy, dpz.
G4double ranflat1=
G4RandFlat::shoot((G4double)0.,(G4double)fermiMomentum);
G4double ranflat2=
G4RandFlat::shoot((G4double)0.,(G4double)fermiMomentum);
G4double ranflat3=
G4RandFlat::shoot((G4double)0.,(G4double)fermiMomentum);
G4double ranmax = (ranflat1>ranflat2? ranflat1: ranflat2);
ranmax = (ranmax>ranflat3? ranmax : ranflat3);
// Isotropic momentum distribution
G4double costheta = 2.*G4UniformRand() - 1.0;
G4double sintheta = std::sqrt(1.0 - costheta*costheta);
G4double phi = 2.0*pi*G4UniformRand();
G4double pz=costheta*ranmax;
G4double px=sintheta*std::cos(phi)*ranmax;
G4double py=sintheta*std::sin(phi)*ranmax;
G4ThreeVector p(px,py,pz);
return p;
}
void G4Nucleus::AddMomentum(const G4ThreeVector aMomentum)
{
momentum+=(aMomentum);
}
G4ReactionProductVector* G4Nucleus::Fragmentate()
{
// needs implementation!
return nullptr;
}
void G4Nucleus::AddExcitationEnergy( G4double anEnergy )
{
excitationEnergy+=anEnergy;
}
void G4Nucleus::AddMomentum(const G4ThreeVector aMomentum)
{
momentum+=(aMomentum);
}
void G4Nucleus::AddExcitationEnergy( G4double anEnergy )
{
excitationEnergy+=anEnergy;
}
/* end of file */
@@ -62,23 +62,51 @@ G4double G4SampleResonance::GetMinimumMass(const G4ParticleDefinition* p) const
const G4DecayTable* theDecays = p->GetDecayTable();
const G4int nDecays = theDecays->entries();
// To find the minimum mass of the resonance, consider only the
// decay channels whose branching ratio is above a given threshold.
// This is needed to avoid that rare and light decay channels
// (e.g. e+ e-) can set a very small minimum mass of the resonance.
// In the case that no channel with branching ratio above the
// threshold has been found, consider the channel with the highest
// branching ratio (whatever its values).
// Note that this solution works also when rare decays are artificially
// enhanced if both of the following conditions hold:
// 1. The enhanced rare decays have branching ratios below the threshold
// 2. The decay with the highest branching ratio is a "natural" decay,
// i.e. not a rare decay which has been artificially enhanced.
const G4double thresholdChannelProbability = 0.10;
G4double foundChannelAboveThresholdProbability = false;
G4double minMassMostProbableChannel = 0.0;
G4double highestChannelProbability = 0.0;
for (G4int i=0; i<nDecays; i++)
{
const G4VDecayChannel* aDecay = theDecays->GetDecayChannel(i);
const G4int nDaughters = aDecay->GetNumberOfDaughters();
G4double minChannelMass = 0;
for (G4int j=0; j<nDaughters; j++)
G4double decayBr = aDecay->GetBR();
if (decayBr > std::min(highestChannelProbability, thresholdChannelProbability))
{
const G4int nDaughters = aDecay->GetNumberOfDaughters();
G4double minChannelMass = 0;
for (G4int j=0; j<nDaughters; j++)
{
const G4ParticleDefinition* aDaughter = const_cast<G4VDecayChannel*>(aDecay)->GetDaughter(j);
G4double minMass = GetMinimumMass(aDaughter);
if (!minMass) minMass = DBL_MAX; // exclude gamma channel;
minChannelMass+=minMass;
}
// G4cout << "channel mass for the above is " << minChannelMass/MeV << G4endl;
if (minChannelMass < minResonanceMass) minResonanceMass = minChannelMass;
}
if (decayBr > highestChannelProbability)
{
highestChannelProbability = decayBr;
minMassMostProbableChannel = minChannelMass;
}
if (decayBr > thresholdChannelProbability)
{
foundChannelAboveThresholdProbability = true;
if (minChannelMass < minResonanceMass) minResonanceMass = minChannelMass;
}
}
}
if ( ! foundChannelAboveThresholdProbability ) {
minResonanceMass = minMassMostProbableChannel;
}
// replace this as soon as the compiler supports mutable!!
G4SampleResonance* self = const_cast<G4SampleResonance*>(this);