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
+21
View File
@@ -16,6 +16,27 @@ committal in the CVS repository !
* Reverse chronological order (last date on top), please *
----------------------------------------------------------
October. 12th, 2021 - V.Ivanchenko (proccuts-V10-07-05)
- G4PhysicsTableHelper - fixed Coverity warning due to index type,
removed G4ThreadLocal variable, substitute old cerr by
G4Exception (old printouts are kept), removed unused headers
- G4MCCIndexConversionTable - changed inline functions -only one
return is left instead of two
September. 1th, 2021 - V.Ivanchenko (proccuts-V10-07-04)
- G4VRangeToEnergyConverter, G4RToEConvForPositron,
G4RToEConvForElectron, G4RToEConvForGamma, G4RToEConvForProton
Simplified the design - do not use G4PhysicsTable and
G4PhysicsVector but convert range cut to production threshold
directly; expected memory reduction for big detectors and
some speed-up of initialisation
July. 18th, 2021 - V.Ivanchenko (proccuts-V10-07-03)
- G4VRangeToEnergyConverter - updated interfaces to G4PhysicsVector
July. 11th, 2021 - V.Ivanchenko (proccuts-V10-07-02)
- G4PhysicsTableHelper - fixed minor Coverity report
May. 26th, 2021 - V.Ivanchenko (proccuts-V10-07-01)
- G4PhysicsTableHelper - updated interface to Retrieve(..) method
@@ -81,32 +81,26 @@ class G4MCCIndexConversionTable
inline
G4bool G4MCCIndexConversionTable::IsUsed(std::size_t index) const
{
if (index >= vecNewIndex.size()) return false;
// returns 'true' if the indicated MCC in the file
// is used in the current production cut table
return (vecNewIndex[index] >= 0);
return ((index < vecNewIndex.size()) && (vecNewIndex[index] >= 0));
}
inline
void G4MCCIndexConversionTable::SetNewIndex(std::size_t index,
std::size_t new_value)
{
if (index >= vecNewIndex.size()) return;
// set the index in the current production cut table
// for the indicated MCC in the file
vecNewIndex[index]=G4int(new_value);
if (index < vecNewIndex.size()) vecNewIndex[index] = new_value;
}
inline
G4int G4MCCIndexConversionTable::GetIndex(std::size_t index) const
{
if (index >= vecNewIndex.size()) return -1;
// get the index in the current production cut table
// for the indicated MCC in the file
return (vecNewIndex[index]);
return (index < vecNewIndex.size()) ? vecNewIndex[index] : -1;
}
inline
@@ -35,13 +35,9 @@
#ifndef G4PhysicsTableHelper_hh
#define G4PhysicsTableHelper_hh 1
#include <vector>
#include "globals.hh"
#include "G4ios.hh"
#include "G4PhysicsVector.hh"
#include "G4PhysicsTable.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4Region.hh"
class G4PhysicsTableHelper
{
@@ -78,7 +74,7 @@ class G4PhysicsTableHelper
G4PhysicsTableHelper();
~G4PhysicsTableHelper();
static G4ThreadLocal G4int verboseLevel;
static G4int verboseLevel;
// Control flag for output message
};
@@ -42,25 +42,16 @@
class G4RToEConvForElectron : public G4VRangeToEnergyConverter
{
public:
public:
G4RToEConvForElectron();
// Constructor
explicit G4RToEConvForElectron();
virtual ~G4RToEConvForElectron();
// Destructor
virtual ~G4RToEConvForElectron();
protected:
protected:
virtual G4double ComputeLoss(G4double AtomicNumber,
G4double KineticEnergy);
G4double ComputeValue(const G4int Z, const G4double kinEnergy) final;
G4double Mass = 0.0;
G4double Z = -1.0;
G4double taul = 0.0;
G4double ionpot = 0.0;
G4double ionpotlog = -1.0e-10;
G4double bremfactor = 0.1;
};
#endif
@@ -34,62 +34,21 @@
#ifndef G4RToEConvForGamma_hh
#define G4RToEConvForGamma_hh 1
#include <vector>
#include "globals.hh"
#include "G4ios.hh"
#include "G4VRangeToEnergyConverter.hh"
class G4RToEConvForGamma : public G4VRangeToEnergyConverter
{
public:
public:
G4RToEConvForGamma();
// Constructor
explicit G4RToEConvForGamma();
virtual ~G4RToEConvForGamma();
// Destructor
virtual ~G4RToEConvForGamma();
protected:
protected:
using G4CrossSectionTable = G4LossTable;
G4double ComputeValue(const G4int Z, const G4double kinEnergy) final;
virtual G4double ComputeLoss( G4double AtomicNumber,
G4double KineticEnergy );
virtual void BuildRangeVector( const G4Material* aMaterial,
G4RangeVector* rangeVector );
// The Range Table
void BuildAbsorptionLengthVector( const G4Material* aMaterial,
G4RangeVector* rangeVector );
G4double ComputeCrossSection( G4double AtomicNumber,
G4double KineticEnergy );
G4double Z = -1.0;
G4double s200keV = 0.0, s1keV = 0.0;
G4double tmin = 0.0, tlow = 0.0;
G4double smin = 0.0, slow = 0.0;
G4double cmin = 0.0, clow = 0.0, chigh = 0.0;
};
// ------------------
// Inline methods
// ------------------
inline
G4double G4RToEConvForGamma::ComputeLoss(G4double AtomicNumber,
G4double KineticEnergy)
{
return ComputeCrossSection(AtomicNumber,KineticEnergy);
}
inline
void G4RToEConvForGamma::BuildRangeVector(const G4Material* aMaterial,
G4RangeVector* rangeVector)
{
BuildAbsorptionLengthVector(aMaterial, rangeVector);
}
#endif
@@ -34,33 +34,21 @@
#ifndef G4RToEConvForPositron_hh
#define G4RToEConvForPositron_hh 1
#include <vector>
#include "globals.hh"
#include "G4ios.hh"
#include "G4VRangeToEnergyConverter.hh"
class G4RToEConvForPositron : public G4VRangeToEnergyConverter
{
public:
public:
G4RToEConvForPositron();
// Constructor
explicit G4RToEConvForPositron();
virtual ~G4RToEConvForPositron();
// Destructor
protected:
protected:
virtual G4double ComputeLoss(G4double AtomicNumber,
G4double KineticEnergy);
G4double ComputeValue(const G4int Z, const G4double kinEnergy) final;
G4double Mass = 0.0;
G4double Z = -1.0;
G4double taul = 0.0;
G4double ionpot = 0.0;
G4double ionpotlog = -1.0e-10;
G4double bremfactor = 0.1;
};
@@ -34,41 +34,24 @@
#ifndef G4RToEConvForProton_hh
#define G4RToEConvForProton_hh 1
#include <vector>
#include "globals.hh"
#include "G4ios.hh"
#include "G4VRangeToEnergyConverter.hh"
class G4RToEConvForProton : public G4VRangeToEnergyConverter
{
public:
public:
G4RToEConvForProton();
// Constructor
explicit G4RToEConvForProton();
virtual ~G4RToEConvForProton();
// Destructor
virtual ~G4RToEConvForProton();
virtual G4double Convert(G4double rangeCut, const G4Material* material);
// Calculate energy cut from given range cut for the material
G4double Convert(const G4double rangeCut, const G4Material* material) final;
virtual void Reset();
// Reset Loss Table and Range Vectors
protected:
protected:
G4double ComputeValue(const G4int Z, const G4double kinEnergy) final;
virtual G4double ComputeLoss(G4double AtomicNumber,
G4double KineticEnergy);
G4double Mass = 0.0;
G4double Z = -1.0;
G4double tau0 = 0.0;
G4double taul = 0.0;
G4double taum = 0.0;
G4double ionpot = 0.0;
G4double ca = 0.0;
G4double cba = 0.0;
G4double cc = 0.0;
};
#endif
@@ -36,109 +36,87 @@
#ifndef G4VRangeToEnergyConverter_hh
#define G4VRangeToEnergyConverter_hh 1
#include <cmath>
#include <vector>
#include "globals.hh"
#include "G4ios.hh"
#include "G4ParticleDefinition.hh"
#include "G4PhysicsTable.hh"
#include "G4Element.hh"
#include "G4Material.hh"
class G4PhysicsLogVector;
#include "G4Threading.hh"
class G4VRangeToEnergyConverter
{
public:
public:
G4VRangeToEnergyConverter();
// Constructor
explicit G4VRangeToEnergyConverter();
G4VRangeToEnergyConverter(const G4VRangeToEnergyConverter& r);
// Copy constructor
virtual ~G4VRangeToEnergyConverter();
G4VRangeToEnergyConverter& operator=(const G4VRangeToEnergyConverter &r);
// Assignment operator
// operators are not used
G4VRangeToEnergyConverter(const G4VRangeToEnergyConverter& r) = delete;
G4VRangeToEnergyConverter& operator=
(const G4VRangeToEnergyConverter &r) = delete;
G4bool operator==(const G4VRangeToEnergyConverter& r) const = delete;
G4bool operator!=(const G4VRangeToEnergyConverter& r) const = delete;
virtual ~G4VRangeToEnergyConverter();
// Destructor
// Calculate energy cut from given range cut for the material
virtual G4double Convert(const G4double rangeCut, const G4Material* material);
G4bool operator==(const G4VRangeToEnergyConverter& r) const;
G4bool operator!=(const G4VRangeToEnergyConverter& r) const;
// Equality operators
// Set energy range for all particle type
// if highedge > 10 GeV, highedge value is not changed
static void SetEnergyRange(const G4double lowedge, const G4double highedge);
virtual G4double Convert(G4double rangeCut, const G4Material* material);
// Calculate energy cut from given range cut for the material
// Get energy range for all particle type
static G4double GetLowEdgeEnergy();
static G4double GetHighEdgeEnergy();
static void SetEnergyRange(G4double lowedge, G4double highedge);
// Set energy range for all particle type
static G4double GetLowEdgeEnergy();
static G4double GetHighEdgeEnergy();
// Get energy range for all particle type
static G4double GetMaxEnergyCut();
static void SetMaxEnergyCut(G4double value);
// Get/set max cut energy for all particle type
// Get/set max cut energy for all particle type
// No check on the value
static G4double GetMaxEnergyCut();
static void SetMaxEnergyCut(const G4double value);
inline const G4ParticleDefinition* GetParticleType() const;
// Return pointer to the particle type which this converter takes care of
// Return pointer to the particle type which this converter takes care of
inline const G4ParticleDefinition* GetParticleType() const;
const G4PhysicsTable* GetLossTable() const;
// theLossTable is a collection of loss vectors for all elements.
// Each loss vector has energy loss values (cross-section values
// for neutral particles) which are calculated by
// ComputeLoss(G4double AtomicNumber, G4double KineticEnergy).
// ComputeLoss method is pure virtual and should be provided
// for each particle type
virtual void Reset();
// Reset Loss Table and Range Vectors
inline void SetVerboseLevel(G4int value);
inline G4int GetVerboseLevel() const;
inline void SetVerboseLevel(G4int value);
inline G4int GetVerboseLevel() const;
// control flag for output message
// 0: Silent
// 1: Warning message
// 2: More
protected:
protected:
virtual void BuildLossTable();
virtual G4double ComputeValue(const G4int Z, const G4double kinEnergy) = 0;
virtual G4double ComputeLoss(G4double AtomicNumber,
G4double KineticEnergy) = 0;
private:
// ------------- Range Table --------------------------------------
static void FillEnergyVector(const G4double emin, const G4double emax);
using G4LossVector = G4PhysicsLogVector;
using G4RangeVector = G4PhysicsLogVector;
using G4LossTable = G4PhysicsTable;
G4double ConvertForGamma(const G4double rangeCut, const G4Material* material);
virtual void BuildRangeVector(const G4Material* aMaterial,
G4RangeVector* rangeVector);
G4double ConvertForElectron(const G4double rangeCut,
const G4Material* material);
G4double ConvertCutToKineticEnergy(G4RangeVector* theRangeVector,
G4double theCutInLength,
std::size_t materialIndex ) const;
protected:
inline G4double LiniearInterpolation(const G4double e1, const G4double e2,
const G4double r1, const G4double r2,
const G4double r);
static G4double LowestEnergy, HighestEnergy;
static G4double MaxEnergyCut;
G4double fMaxEnergyCut = 0.0;
const G4ParticleDefinition* theParticle = nullptr;
G4LossTable* theLossTable = nullptr;
G4int NumberOfElements = 0;
const G4int TotBin = 300;
protected:
std::vector< G4RangeVector* > fRangeVectorStore;
#ifdef G4MULTITHREADED
static G4Mutex theMutex;
#endif
private:
static G4double Emin;
static G4double Emax;
static std::vector<G4double>* Energy;
static G4int NbinPerDecade;
static G4int Nbin;
G4int verboseLevel = 1;
const G4ParticleDefinition* theParticle = nullptr;
G4int fPDG = 0;
G4int verboseLevel = 1;
};
// ------------------
@@ -163,4 +141,11 @@ const G4ParticleDefinition* G4VRangeToEnergyConverter::GetParticleType() const
return theParticle;
}
inline G4double G4VRangeToEnergyConverter::LiniearInterpolation(
const G4double e1, const G4double e2,
const G4double r1, const G4double r2, const G4double r)
{
return (r1 == r2) ? e1 : e1 + (e2 - e1)*(r - r1)/(r2 - r1);
}
#endif
@@ -29,9 +29,12 @@
// --------------------------------------------------------------------
#include "G4PhysicsTableHelper.hh"
#include "G4ProductionCutsTable.hh"
#include "G4ProductionCutsTable.hh"
#include "G4MCCIndexConversionTable.hh"
#include "G4Threading.hh"
#include "G4ios.hh"
G4ThreadLocal G4int G4PhysicsTableHelper::verboseLevel = 1;
G4int G4PhysicsTableHelper::verboseLevel = 1;
// --------------------------------------------------------------------
G4PhysicsTableHelper::G4PhysicsTableHelper()
@@ -51,68 +54,47 @@ G4PhysicsTableHelper::PreparePhysicsTable(G4PhysicsTable* physTable)
= G4ProductionCutsTable::GetProductionCutsTable();
std::size_t numberOfMCC = cutTable->GetTableSize();
if ( physTable != nullptr)
if ( physTable != nullptr )
{
// compare size of physics table and number of material-cuts-couple
if ( physTable->size() < numberOfMCC)
if ( physTable->size() < numberOfMCC )
{
// enlarge physics table
physTable->resize(numberOfMCC, nullptr);
#ifdef G4VERBOSE
if (verboseLevel>2)
{
G4cerr << "G4PhysicsTableHelper::PreparePhysicsTable ";
G4cerr << "Physics Table "<< physTable ;
G4cerr << " is resized to " << numberOfMCC << G4endl;
G4cout << "G4PhysicsTableHelper::PreparePhysicsTable: "
<< " the table " << physTable << " size="
<< physTable->size()
<< " will be is resized to " << numberOfMCC << G4endl;
}
#endif
// enlarge physics table
physTable->resize(numberOfMCC, nullptr);
}
else if ( physTable->size() > numberOfMCC)
else if ( physTable->size() > numberOfMCC )
{
// ERROR: this situation should not occur
// size of physics table is shorter than number of material-cuts-couple
physTable->resize(numberOfMCC);
#ifdef G4VERBOSE
if (verboseLevel>0)
{
G4cerr << "G4PhysicsTableHelper::PreparePhysicsTable ";
G4cerr << "Physics Table "<< physTable ;
G4cerr << " is longer than number of material-cuts-couple " << G4endl;
}
#endif
// size of physics table is larger than number of material-cuts-couple
G4ExceptionDescription ed;
ed << "table " << physTable << " size=" << physTable->size()
<< " is longer than number of material-cuts-couple " << numberOfMCC;
G4Exception( "G4PhysicsTableHelper::PreparePhysicsTable()",
"ProcCuts001", FatalException,
"Physics Table is inconsistent with material-cuts-couple");
"ProcCuts001", FatalException, ed);
}
}
else
{
// create PhysicsTable is given poitner is null
physTable = new G4PhysicsTable(numberOfMCC);
if (physTable != nullptr)
{
physTable->resize(numberOfMCC, nullptr);
}
else
{
G4Exception( "G4PhysicsTableHelper::PreparePhysicsTable()",
"ProcCuts002", FatalException,
"Can't create Physics Table");
}
physTable = new G4PhysicsTable();
physTable->resize(numberOfMCC, nullptr);
}
#ifdef G4VERBOSE
if (verboseLevel>2)
{
if ( physTable != nullptr)
{
G4cerr << "Physics Table size "<< physTable->size();
}
else
{
G4cerr << "Physics Table does not exist ";
}
G4cerr << ": number of material-cuts-couple " << numberOfMCC << G4endl;
G4cout << "G4PhysicsTableHelper::PreparePhysicsTable: "
<< " the table "<< physTable
<< " size=" << numberOfMCC << G4endl;
}
#endif
@@ -145,16 +127,10 @@ G4bool G4PhysicsTableHelper::RetrievePhysicsTable(G4PhysicsTable* physTable,
G4PhysicsTable* tempTable = new G4PhysicsTable();
if (! tempTable->RetrievePhysicsTable(fileName,ascii,spline) )
{
#ifdef G4VERBOSE
if (verboseLevel>1)
{
G4cerr << "G4PhysicsTableHelper::RetrievePhysicsTable ";
G4cerr << "Fail to retrieve from "<< fileName << G4endl;
}
#endif
G4ExceptionDescription ed;
ed << "Cannot retrieve physics table from the file <" << fileName << ">";
G4Exception( "G4ProductionCutsTable::RetrievePhysicsTable()",
"ProcCuts105",
JustWarning, "Can not retrieve physics tables from file");
"ProcCuts105", JustWarning, ed);
delete tempTable;
return false;
}
@@ -167,20 +143,13 @@ G4bool G4PhysicsTableHelper::RetrievePhysicsTable(G4PhysicsTable* physTable,
// check physics table size
if ( tempTable->size() != converter->size())
{
#ifdef G4VERBOSE
if (verboseLevel>0)
{
G4cerr << "G4PhysicsTableHelper::RetrievePhysicsTable ";
G4cerr << "Size of the physics table in "<< fileName;
G4cerr << "( size =" << tempTable->size() << ")";
G4cerr << " is inconsistent with material-cut info";
G4cerr << "( size =" << converter->size() << ")";
G4cerr << G4endl;
}
#endif
G4ExceptionDescription ed;
ed << "Physics table in " << fileName
<< "\n size=" << tempTable->size() << " "
<< " is inconsistent with material-cut-couple "
<< "size=" << converter->size() << " the table is not retrieved!";
G4Exception("G4ProductionCutsTable::RetrievePhysicsTable()",
"ProcCuts106", JustWarning,
"Retrieved file is inconsistent with current physics tables!");
"ProcCuts106", JustWarning, ed);
delete tempTable;
return false;
}
@@ -190,8 +159,13 @@ G4bool G4PhysicsTableHelper::RetrievePhysicsTable(G4PhysicsTable* physTable,
{
if (converter->IsUsed(idx))
{
if (converter->GetIndex(idx)<0) continue;
std::size_t i = converter->GetIndex(idx);
G4int i = converter->GetIndex(idx);
if(i < 0)
{
tempTable->clearAndDestroy();
delete tempTable;
return false;
}
G4PhysicsVector* vec = (*physTable)[i];
if (vec != nullptr ) delete vec;
(*physTable)[i] = (*tempTable)[idx];
@@ -213,19 +187,13 @@ void G4PhysicsTableHelper::SetPhysicsVector(G4PhysicsTable* physTable,
if ( physTable->size() <= idx)
{
#ifdef G4VERBOSE
if (verboseLevel>0)
{
G4cerr << "G4PhysicsTableHelper::SetPhysicsVector ";
G4cerr << "Given index (" << idx << ") exceeds ";
G4cerr << "size of the physics table ";
G4cerr << "( size =" << physTable->size()<< ")";
G4cerr << G4endl;
}
#endif
G4ExceptionDescription ed;
ed << "Given index (" << idx << ") exceeds "
<< "the size of the physics table "
<< "( size =" << physTable->size() << ") the vector is not added!";
G4Exception("G4ProductionCutsTable::SetPhysicsVector()",
"ProcCuts107",
JustWarning, "Illegal index!");
JustWarning, ed);
return;
}
@@ -236,9 +204,9 @@ void G4PhysicsTableHelper::SetPhysicsVector(G4PhysicsTable* physTable,
}
// --------------------------------------------------------------------
void G4PhysicsTableHelper::SetVerboseLevel(G4int value)
void G4PhysicsTableHelper::SetVerboseLevel(G4int value)
{
verboseLevel = value;
if( !G4Threading::IsWorkerThread() ) verboseLevel = value;
}
// --------------------------------------------------------------------
@@ -351,12 +351,7 @@ G4double G4ProductionCutsTable::ConvertRangeToEnergy(
// --------------------------------------------------------------------
void G4ProductionCutsTable::ResetConverters()
{
for(std::size_t i=0; i< NumberOfG4CutIndex; ++i)
{
if (converters[i]!=0) converters[i]->Reset();
}
}
{}
// --------------------------------------------------------------------
void G4ProductionCutsTable::SetEnergyRange(G4double lowedge, G4double highedge)
@@ -31,12 +31,12 @@
#include "G4RToEConvForElectron.hh"
#include "G4ParticleDefinition.hh"
#include "G4ParticleTable.hh"
#include "G4Material.hh"
#include "G4PhysicsLogVector.hh"
#include "G4ios.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4Pow.hh"
#include "G4Log.hh"
#include "G4Exp.hh"
// --------------------------------------------------------------------
G4RToEConvForElectron::G4RToEConvForElectron()
@@ -55,35 +55,32 @@ G4RToEConvForElectron::G4RToEConvForElectron()
}
else
{
Mass = theParticle->GetPDGMass();
fPDG = theParticle->GetPDGEncoding();
}
}
// --------------------------------------------------------------------
G4RToEConvForElectron::~G4RToEConvForElectron()
{
}
G4RToEConvForElectron::~G4RToEConvForElectron()
{}
// ***********************************************************************
// ************************** ComputeLoss ********************************
// ***********************************************************************
G4double G4RToEConvForElectron::ComputeLoss(G4double AtomicNumber,
G4double KineticEnergy)
// --------------------------------------------------------------------
G4double G4RToEConvForElectron::ComputeValue(const G4int Z,
const G4double kinEnergy)
{
const G4double cbr1=0.02, cbr2=-5.7e-5, cbr3=1., cbr4=0.072;
const G4double Tlow=10.*keV, Thigh=1.*GeV;
const G4double Tlow=10.*CLHEP::keV, Thigh=1.*CLHEP::GeV;
const G4double taul = Tlow/CLHEP::electron_mass_c2;
const G4double log05 = G4Log(0.5);
const G4double taul12 = std::sqrt(taul);
const G4double bremfactor = 0.1;
// calculate dE/dx for electrons
if( std::fabs(AtomicNumber-Z)>0.1 )
{
Z = AtomicNumber;
taul = Tlow/Mass;
ionpot = 1.6e-5*MeV*std::exp(0.9*std::log(Z))/Mass;
ionpotlog = std::log(ionpot);
}
const G4double Zlog = G4Pow::GetInstance()->logZ(Z);
const G4double ionpot =
1.6e-5*CLHEP::MeV*G4Exp(0.9*Zlog)/CLHEP::electron_mass_c2;
const G4double ionpotlog = G4Log(ionpot);
G4double tau = KineticEnergy/Mass;
G4double dEdx;
const G4double tau = kinEnergy/CLHEP::electron_mass_c2;
G4double dEdx = 0.0;
if(tau<taul)
{
@@ -91,12 +88,10 @@ G4double G4RToEConvForElectron::ComputeLoss(G4double AtomicNumber,
G4double t2 = taul+2.;
G4double tsq = taul*taul;
G4double beta2 = taul*t2/(t1*t1);
G4double f = 1.-beta2+std::log(tsq/2.)
+(0.5+0.25*tsq+(1.+2.*taul)*std::log(0.5))/(t1*t1);
dEdx = (std::log(2.*taul+4.)-2.*ionpotlog+f)/beta2;
dEdx = twopi_mc2_rcl2*Z*dEdx;
G4double clow = dEdx*std::sqrt(taul);
dEdx = clow/std::sqrt(KineticEnergy/Mass);
G4double f = 1.-beta2+G4Log(tsq/2.)
+(0.5+0.25*tsq+(1.+2.*taul)*log05)/(t1*t1);
dEdx = Z*(G4Log(2.*taul+4.)-2.*ionpotlog+f)/beta2;
dEdx *= taul12/std::sqrt(tau);
}
else
{
@@ -104,20 +99,16 @@ G4double G4RToEConvForElectron::ComputeLoss(G4double AtomicNumber,
G4double t2 = tau+2.;
G4double tsq = tau*tau;
G4double beta2 = tau*t2/(t1*t1);
G4double f = 1.-beta2+std::log(tsq/2.)
+(0.5+0.25*tsq+(1.+2.*tau)*std::log(0.5))/(t1*t1);
dEdx = (std::log(2.*tau+4.)-2.*ionpotlog+f)/beta2;
dEdx = twopi_mc2_rcl2*Z*dEdx;
G4double f = 1.-beta2+G4Log(tsq/2.)
+(0.5+0.25*tsq+(1.+2.*tau)*log05)/(t1*t1);
dEdx = Z*(G4Log(2.*tau+4.)-2.*ionpotlog+f)/beta2;
// loss from bremsstrahlung follows
G4double cbrem = (cbr1+cbr2*Z)
*(cbr3+cbr4*std::log(KineticEnergy/Thigh));
cbrem = Z*(Z+1.)*cbrem*tau/beta2;
cbrem *= bremfactor ;
dEdx += twopi_mc2_rcl2*cbrem;
G4double cbrem = (cbr1+cbr2*Z)*(cbr3+cbr4*G4Log(kinEnergy/Thigh));
dEdx += Z*(Z+1)*cbrem*bremfactor*tau/beta2;
}
return dEdx;
return dEdx*CLHEP::twopi_mc2_rcl2;
}
// --------------------------------------------------------------------
+45 -83
View File
@@ -31,11 +31,10 @@
#include "G4RToEConvForGamma.hh"
#include "G4ParticleDefinition.hh"
#include "G4ParticleTable.hh"
#include "G4Material.hh"
#include "G4PhysicsLogVector.hh"
#include "G4ios.hh"
#include "G4SystemOfUnits.hh"
#include "G4Log.hh"
#include "G4Exp.hh"
#include "G4Pow.hh"
// --------------------------------------------------------------------
G4RToEConvForGamma::G4RToEConvForGamma()
@@ -52,106 +51,69 @@ G4RToEConvForGamma::G4RToEConvForGamma()
}
#endif
}
}
G4RToEConvForGamma::~G4RToEConvForGamma()
{
}
// ***********************************************************************
// ******************* BuildAbsorptionLengthVector ***********************
// ***********************************************************************
void G4RToEConvForGamma::BuildAbsorptionLengthVector(
const G4Material* aMaterial,
G4RangeVector* absorptionLengthVector )
{
// fill the absorption length vector for this material
// absorption length is defined here as:
// absorption length = 5./ macroscopic absorption cross section
//
const G4CrossSectionTable* aCrossSectionTable
= (G4CrossSectionTable*)(theLossTable);
const G4ElementVector* elementVector
= aMaterial->GetElementVector();
const G4double* atomicNumDensityVector
= aMaterial->GetAtomicNumDensityVector();
// fill absorption length vector
G4int NumEl = aMaterial->GetNumberOfElements();
G4double absorptionLengthMax = 0.0;
for (std::size_t ibin=0; ibin<size_t(TotBin); ++ibin)
else
{
G4double SIGMA = 0.;
for (std::size_t iel=0; iel<size_t(NumEl); ++iel)
{
G4int IndEl = (*elementVector)[iel]->GetIndex();
SIGMA += atomicNumDensityVector[iel]
* (*((*aCrossSectionTable)[IndEl]))[ibin];
}
// absorption length=5./SIGMA
absorptionLengthVector->PutValue(ibin, 5./SIGMA);
if (absorptionLengthMax < 5./SIGMA )
absorptionLengthMax = 5./SIGMA;
fPDG = theParticle->GetPDGEncoding();
}
}
// ***********************************************************************
// ********************** ComputeCrossSection ****************************
// ***********************************************************************
G4double G4RToEConvForGamma::ComputeCrossSection(G4double AtomicNumber,
G4double KineticEnergy)
// --------------------------------------------------------------------
G4RToEConvForGamma::~G4RToEConvForGamma()
{}
// --------------------------------------------------------------------
G4double G4RToEConvForGamma::ComputeValue(const G4int Z,
const G4double energy)
{
// Compute the "absorption" cross-section of the photon "absorption".
// Cross-section means here the sum of the cross-sections of the
// pair production, Compton scattering and photoelectric processes
const G4double t1keV = 1.*keV;
const G4double t200keV = 200.*keV;
const G4double t100MeV = 100.*MeV;
const G4double t1keV = 1.*CLHEP::keV;
const G4double t200keV = 200.*CLHEP::keV;
const G4double t100MeV = 100.*CLHEP::MeV;
// Compute Z dependent quantities in the case of a new AtomicNumber
if(std::abs(AtomicNumber-Z)>0.1)
{
Z = AtomicNumber;
G4double Zsquare = Z*Z;
G4double Zlog = std::log(Z);
G4double Zlogsquare = Zlog*Zlog;
G4double Zsquare = Z*Z;
G4double Zlog = G4Pow::GetInstance()->logZ(Z);
G4double Zlogsquare = Zlog*Zlog;
s200keV = (0.2651-0.1501*Zlog+0.02283*Zlogsquare)*Zsquare;
tmin = (0.552+218.5/Z+557.17/Zsquare)*MeV;
smin = (0.01239+0.005585*Zlog-0.000923*Zlogsquare)*std::exp(1.5*Zlog);
cmin = std::log(s200keV/smin)
/(std::log(tmin/t200keV)*std::log(tmin/t200keV));
tlow = 0.2*std::exp(-7.355/std::sqrt(Z))*MeV;
slow = s200keV
* std::exp(0.042*Z*std::log(t200keV/tlow)*std::log(t200keV/tlow));
s1keV = 300.*Zsquare;
clow = std::log(s1keV/slow)/std::log(tlow/t1keV);
chigh = (7.55e-5-0.0542e-5*Z)*Zsquare*Z/std::log(t100MeV/tmin);
}
G4double tmin = (0.552+218.5/Z+557.17/Zsquare)*CLHEP::MeV;
G4double tlow = 0.2*G4Exp(-7.355/std::sqrt(Z))*CLHEP::MeV;
G4double smin = (0.01239+0.005585*Zlog-0.000923*Zlogsquare)*G4Exp(1.5*Zlog);
G4double s200keV = (0.2651-0.1501*Zlog+0.02283*Zlogsquare)*Zsquare;
G4double cminlog = G4Log(tmin/t200keV);
G4double cmin = G4Log(s200keV/smin)/(cminlog*cminlog);
G4double slowlog = G4Log(t200keV/tlow);
G4double slow = s200keV * G4Exp(0.042*Z*slowlog*slowlog);
G4double logtlow = G4Log(tlow/t1keV);
G4double clow = G4Log(300.*Zsquare/slow)/logtlow;
G4double chigh = (7.55e-5 - 0.0542e-5*Z)*Zsquare*Z/G4Log(t100MeV/tmin);
// Calculate the cross-section (using an approximate empirical formula)
G4double xs;
if ( KineticEnergy<tlow )
if ( energy < tlow )
{
if(KineticEnergy<t1keV) xs = slow*std::exp(clow*std::log(tlow/t1keV));
else xs = slow*std::exp(clow*std::log(tlow/KineticEnergy));
xs = (energy < t1keV) ? slow*G4Exp(clow*logtlow) :
slow*G4Exp(clow*G4Log(tlow/energy));
}
else if ( KineticEnergy<t200keV )
else if ( energy < t200keV )
{
xs = s200keV
* std::exp(0.042*Z*std::log(t200keV/KineticEnergy)
*std::log(t200keV/KineticEnergy));
G4double x = G4Log(t200keV/energy);
xs = s200keV * G4Exp(0.042*Z*x*x);
}
else if( KineticEnergy<tmin )
else if( energy<tmin )
{
xs = smin
* std::exp(cmin*std::log(tmin/KineticEnergy)
*std::log(tmin/KineticEnergy));
const G4double x = G4Log(tmin/energy);
xs = smin * G4Exp(cmin*x*x);
}
else
{
xs = smin + chigh*std::log(KineticEnergy/tmin);
xs = smin + chigh*G4Log(energy/tmin);
}
return xs * barn;
return xs * CLHEP::barn;
}
// --------------------------------------------------------------------
@@ -31,12 +31,12 @@
#include "G4RToEConvForPositron.hh"
#include "G4ParticleDefinition.hh"
#include "G4ParticleTable.hh"
#include "G4Material.hh"
#include "G4PhysicsLogVector.hh"
#include "G4ios.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4Pow.hh"
#include "G4Log.hh"
#include "G4Exp.hh"
// --------------------------------------------------------------------
G4RToEConvForPositron::G4RToEConvForPositron()
@@ -55,35 +55,33 @@ G4RToEConvForPositron::G4RToEConvForPositron()
}
else
{
Mass = theParticle->GetPDGMass();
fPDG = theParticle->GetPDGEncoding();
}
}
// --------------------------------------------------------------------
G4RToEConvForPositron::~G4RToEConvForPositron()
{
}
G4RToEConvForPositron::~G4RToEConvForPositron()
{}
// **********************************************************************
// ************************* ComputeLoss ********************************
// **********************************************************************
G4double G4RToEConvForPositron::ComputeLoss(G4double AtomicNumber,
G4double KineticEnergy)
// --------------------------------------------------------------------
G4double G4RToEConvForPositron::ComputeValue(const G4int Z,
const G4double kinEnergy)
{
const G4double cbr1=0.02, cbr2=-5.7e-5, cbr3=1., cbr4=0.072;
const G4double Tlow=10.*keV, Thigh=1.*GeV;
const G4double Tlow=10.*CLHEP::keV, Thigh=1.*CLHEP::GeV;
const G4double taul = Tlow/CLHEP::electron_mass_c2;
const G4double logtaul = G4Log(taul);
const G4double taul12 = std::sqrt(taul);
const G4double bremfactor = 0.1;
// calculate dE/dx for electrons
if( std::fabs(AtomicNumber-Z)>0.1 )
{
Z = AtomicNumber;
taul = Tlow/Mass;
ionpot = 1.6e-5*MeV*std::exp(0.9*std::log(Z))/Mass;
ionpotlog = std::log(ionpot);
}
G4double Zlog = G4Pow::GetInstance()->logZ(Z);
G4double ionpot =
1.6e-5*CLHEP::MeV*G4Exp(0.9*Zlog)/CLHEP::electron_mass_c2;
G4double ionpotlog = G4Log(ionpot);
G4double tau = kinEnergy/CLHEP::electron_mass_c2;
G4double dEdx = 0.0;
G4double tau = KineticEnergy/Mass;
G4double dEdx;
if(tau<taul)
{
@@ -91,13 +89,11 @@ G4double G4RToEConvForPositron::ComputeLoss(G4double AtomicNumber,
G4double t2 = taul+2.;
G4double tsq = taul*taul;
G4double beta2 = taul*t2/(t1*t1);
G4double f = 2.*std::log(taul)
-(6.*taul+1.5*tsq-taul*(1.-tsq/3.)/t2
-tsq*(0.5-tsq/12.)/(t2*t2))/(t1*t1);
dEdx = (std::log(2.*taul+4.)-2.*ionpotlog+f)/beta2;
dEdx = twopi_mc2_rcl2*Z*dEdx;
G4double clow = dEdx*std::sqrt(taul);
dEdx = clow/std::sqrt(KineticEnergy/Mass);
G4double f = 2.*logtaul -
(6.*taul+1.5*tsq-taul*(1.-tsq/3.)/t2
-tsq*(0.5-tsq/12.)/(t2*t2))/(t1*t1);
dEdx = (G4Log(2.*taul+4.)-2.*ionpotlog+f)/beta2;
dEdx *= Z*taul12/std::sqrt(tau);
}
else
{
@@ -105,18 +101,16 @@ G4double G4RToEConvForPositron::ComputeLoss(G4double AtomicNumber,
G4double t2 = tau+2.;
G4double tsq = tau*tau;
G4double beta2 = tau*t2/(t1*t1);
G4double f = 2.*std::log(tau)
- (6.*tau+1.5*tsq-tau*(1.-tsq/3.)/t2
-tsq*(0.5-tsq/12.)/(t2*t2))/(t1*t1);
dEdx = (std::log(2.*tau+4.)-2.*ionpotlog+f)/beta2;
dEdx = twopi_mc2_rcl2*Z*dEdx;
G4double f = 2.*G4Log(tau) - (6.*tau+1.5*tsq-tau*(1.-tsq/3.)/t2
-tsq*(0.5-tsq/12.)/(t2*t2))/(t1*t1);
dEdx = Z*(G4Log(2.*tau+4.)-2.*ionpotlog+f)/beta2;
// loss from bremsstrahlung follows
G4double cbrem = (cbr1+cbr2*Z)
* (cbr3+cbr4*std::log(KineticEnergy/Thigh));
cbrem = Z*(Z+1.)*cbrem*tau/beta2;
cbrem *= bremfactor;
dEdx += twopi_mc2_rcl2*cbrem;
* (cbr3+cbr4*G4Log(kinEnergy/Thigh));
dEdx += cbrem*Z*(Z+1.)*bremfactor*tau/beta2;
}
return dEdx;
return dEdx*CLHEP::twopi_mc2_rcl2;
}
// --------------------------------------------------------------------
@@ -30,10 +30,7 @@
#include "G4RToEConvForProton.hh"
#include "G4ParticleTable.hh"
#include "G4Material.hh"
#include "G4PhysicsLogVector.hh"
#include "G4ios.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
@@ -52,79 +49,35 @@ G4RToEConvForProton::G4RToEConvForProton()
}
#endif
}
else
else
{
Mass = theParticle->GetPDGMass();
}
fPDG = theParticle->GetPDGEncoding();
}
}
// --------------------------------------------------------------------
G4RToEConvForProton::~G4RToEConvForProton()
{
{}
// --------------------------------------------------------------------
G4double G4RToEConvForProton::Convert(const G4double rangeCut,
const G4Material* )
{
#ifdef G4VERBOSE
if (GetVerboseLevel()>3)
{
G4cout << "G4RToEConvForProton::Convert() - ";
G4cout << " with Range Cut " << rangeCut/mm << "[mm]" << G4endl;
}
#endif
// Simple formula - range = Ekin/(100*keV)*(1*mm);
return (rangeCut/(1.0*CLHEP::mm)) * (100.0*CLHEP::keV);
}
// --------------------------------------------------------------------
G4double G4RToEConvForProton::Convert(G4double rangeCut, const G4Material* )
G4double G4RToEConvForProton::ComputeValue(const G4int, const G4double)
{
// Simple formula - range = Ekin/(100*keV)*(1*mm);
return (rangeCut/(1.0*mm)) * (100.0*keV);
return 0.0;
}
// **********************************************************************
// ************************* ComputeLoss ********************************
// **********************************************************************
G4double G4RToEConvForProton::ComputeLoss(G4double AtomicNumber,
G4double KineticEnergy)
{
// calculate dE/dx
const G4double z2Particle = 1.0;
if( std::fabs(AtomicNumber-Z)>0.1 )
{
// recalculate constants
Z = AtomicNumber;
G4double Z13 = std::exp(std::log(Z)/3.);
tau0 = 0.1*Z13*MeV/proton_mass_c2;
taum = 0.035*Z13*MeV/proton_mass_c2;
taul = 2.*MeV/proton_mass_c2;
ionpot = 1.6e-5*MeV*std::exp(0.9*std::log(Z));
cc = (taul+1.)*(taul+1.)*std::log(2.*electron_mass_c2*taul*(taul+2.)/ionpot)
/ (taul*(taul+2.))-1.;
cc = 2.*twopi_mc2_rcl2*Z*cc*std::sqrt(taul);
ca = cc/((1.-0.5*std::sqrt(tau0/taum))*tau0);
cba = -0.5/std::sqrt(taum);
}
G4double tau = KineticEnergy/Mass;
G4double dEdx;
if ( tau <= tau0 )
{
dEdx = ca*(std::sqrt(tau)+cba*tau);
}
else
{
if( tau <= taul )
{
dEdx = cc/std::sqrt(tau);
}
else
{
dEdx = (tau+1.)*(tau+1.)
* std::log(2.*electron_mass_c2*tau*(tau+2.)/ionpot)
/ (tau*(tau+2.))-1.;
dEdx = 2.*twopi_mc2_rcl2*Z*dEdx;
}
}
return dEdx*z2Particle ;
}
// **********************************************************************
// ************************* Reset ********************************
// **********************************************************************
void G4RToEConvForProton::Reset()
{
// do nothing because loss tables and range vectors are not used
return;
}
// --------------------------------------------------------------------
@@ -30,443 +30,218 @@
#include "G4VRangeToEnergyConverter.hh"
#include "G4ParticleTable.hh"
#include "G4Material.hh"
#include "G4MaterialTable.hh"
#include "G4PhysicsLogVector.hh"
#include "G4ios.hh"
#include "G4Element.hh"
#include "G4SystemOfUnits.hh"
#include "G4Log.hh"
#include "G4Exp.hh"
G4double G4VRangeToEnergyConverter::LowestEnergy = 0.99e-3*MeV;
G4double G4VRangeToEnergyConverter::HighestEnergy = 100.0e6*MeV;
G4double G4VRangeToEnergyConverter::MaxEnergyCut = 10.0*GeV;
#ifdef G4MULTITHREADED
G4Mutex G4VRangeToEnergyConverter::theMutex = G4MUTEX_INITIALIZER;
#endif
G4double G4VRangeToEnergyConverter::Emin = 0.0;
G4double G4VRangeToEnergyConverter::Emax = 0.0;
std::vector<G4double>* G4VRangeToEnergyConverter::Energy = nullptr;
G4int G4VRangeToEnergyConverter::NbinPerDecade = 50;
G4int G4VRangeToEnergyConverter::Nbin = 350;
// --------------------------------------------------------------------
G4VRangeToEnergyConverter::G4VRangeToEnergyConverter()
{
}
// --------------------------------------------------------------------
G4VRangeToEnergyConverter::
G4VRangeToEnergyConverter(const G4VRangeToEnergyConverter& right)
{
*this = right;
}
// --------------------------------------------------------------------
G4VRangeToEnergyConverter&
G4VRangeToEnergyConverter::operator=(const G4VRangeToEnergyConverter& right)
{
if (this == &right) return *this;
if (theLossTable != nullptr)
if(nullptr == Energy)
{
theLossTable->clearAndDestroy();
delete theLossTable;
Energy = new std::vector<G4double>(Nbin + 1);
FillEnergyVector(1*CLHEP::keV, 10.0*CLHEP::GeV);
}
fMaxEnergyCut = right.fMaxEnergyCut;
NumberOfElements = right.NumberOfElements;
theParticle = right.theParticle;
verboseLevel = right.verboseLevel;
// create the loss table
theLossTable = new G4LossTable();
theLossTable->reserve(G4Element::GetNumberOfElements());
// fill the loss table
for (std::size_t j=0; j<std::size_t(NumberOfElements); ++j)
{
G4LossVector* aVector = new G4LossVector(LowestEnergy,MaxEnergyCut,TotBin);
for (std::size_t i=0; i<=std::size_t(TotBin); ++i)
{
G4double Value = (*((*right.theLossTable)[j]))[i];
aVector->PutValue(i,Value);
}
theLossTable->insert(aVector);
}
// clean up range vector store
for (std::size_t idx=0; idx<fRangeVectorStore.size(); ++idx)
{
delete fRangeVectorStore.at(idx);
}
fRangeVectorStore.clear();
// copy range vector store
for (std::size_t j=0; j<((right.fRangeVectorStore).size()); ++j)
{
G4RangeVector* vector = (right.fRangeVectorStore).at(j);
G4RangeVector* rangeVector = nullptr;
if (vector != nullptr )
{
rangeVector = new G4RangeVector(LowestEnergy, MaxEnergyCut, TotBin);
fMaxEnergyCut = MaxEnergyCut;
for (std::size_t i=0; i<=std::size_t(TotBin); ++i)
{
G4double Value = (*vector)[i];
rangeVector->PutValue(i,Value);
}
}
fRangeVectorStore.push_back(rangeVector);
}
return *this;
}
// --------------------------------------------------------------------
G4VRangeToEnergyConverter::~G4VRangeToEnergyConverter()
{
Reset();
{
if(nullptr != Energy)
{
delete Energy;
Energy = nullptr;
}
}
// --------------------------------------------------------------------
G4bool
G4VRangeToEnergyConverter::operator==(const G4VRangeToEnergyConverter& r) const
{
return this == &r;
}
// --------------------------------------------------------------------
G4bool
G4VRangeToEnergyConverter::operator!=(const G4VRangeToEnergyConverter &r) const
{
return this != &r;
}
// **********************************************************************
// ************************* Convert ***********************************
// **********************************************************************
G4double G4VRangeToEnergyConverter::Convert(G4double rangeCut,
G4double G4VRangeToEnergyConverter::Convert(const G4double rangeCut,
const G4Material* material)
{
#ifdef G4VERBOSE
if (GetVerboseLevel()>3)
{
G4cout << "G4VRangeToEnergyConverter::Convert() - ";
G4cout << "Convert for " << material->GetName()
<< " with Range Cut " << rangeCut/mm << "[mm]" << G4endl;
}
if (GetVerboseLevel()>3)
{
G4cout << "G4VRangeToEnergyConverter::Convert() - ";
G4cout << "Convert for " << material->GetName()
<< " with Range Cut " << rangeCut/mm << "[mm]" << G4endl;
}
#endif
G4double theKineticEnergyCuts = 0.;
if (fMaxEnergyCut != MaxEnergyCut)
{
fMaxEnergyCut = MaxEnergyCut;
// clear loss table and range vectors
Reset();
G4double cut = 0.0;
if(fPDG == 22)
{
cut = ConvertForGamma(rangeCut, material);
}
// Build the energy loss table
BuildLossTable();
// Build range vector for every material, convert cut into energy-cut,
// fill theKineticEnergyCuts and delete the range vector
static const G4double tune = 0.025*mm*g/cm3, lowen = 30.*keV ;
// check density
G4double density = material->GetDensity() ;
if(density <= 0.)
else
{
#ifdef G4VERBOSE
if (GetVerboseLevel()>0)
cut = ConvertForElectron(rangeCut, material);
const G4double tune = 0.025*CLHEP::mm*CLHEP::g/CLHEP::cm3;
const G4double lowen = 30.*CLHEP::keV;
if(cut < lowen)
{
G4cout << "G4VRangeToEnergyConverter::Convert() - ";
G4cout << material->GetName() << "has zero density "
<< "( " << density << ")" << G4endl;
// corr. should be switched on smoothly
cut /= (1.+(1.-cut/lowen)*tune/(rangeCut*material->GetDensity()));
}
#endif
return 0.;
}
// initialise RangeVectorStore
const G4MaterialTable* table = G4Material::GetMaterialTable();
G4int ext_size = table->size() - fRangeVectorStore.size();
for (G4int i=0; i<ext_size; ++i) fRangeVectorStore.push_back(nullptr);
// Build Range Vector
G4int idx = material->GetIndex();
G4RangeVector* rangeVector = fRangeVectorStore.at(idx);
if (rangeVector == nullptr)
{
rangeVector = new G4RangeVector(LowestEnergy, MaxEnergyCut, TotBin);
BuildRangeVector(material, rangeVector);
fRangeVectorStore.at(idx) = rangeVector;
}
// Convert Range Cut ro Kinetic Energy Cut
theKineticEnergyCuts = ConvertCutToKineticEnergy(rangeVector, rangeCut, idx);
if( ((theParticle->GetParticleName()=="e-")
||(theParticle->GetParticleName()=="e+"))
&&(theKineticEnergyCuts < lowen) )
{
// corr. should be switched on smoothly
theKineticEnergyCuts /= (1.+(1.-theKineticEnergyCuts/lowen)
* tune/(rangeCut*density));
}
if(theKineticEnergyCuts < LowestEnergy)
{
theKineticEnergyCuts = LowestEnergy;
}
else if(theKineticEnergyCuts > MaxEnergyCut)
{
theKineticEnergyCuts = MaxEnergyCut;
}
return theKineticEnergyCuts;
cut = std::max(Emin, std::min(cut, Emax));
return cut;
}
// **********************************************************************
// ************************ SetEnergyRange *****************************
// **********************************************************************
void G4VRangeToEnergyConverter::SetEnergyRange(G4double lowedge,
G4double highedge)
// --------------------------------------------------------------------
void G4VRangeToEnergyConverter::SetEnergyRange(const G4double lowedge,
const G4double highedge)
{
// check LowestEnergy/ HighestEnergy
if ( (lowedge<0.0)||(highedge<=lowedge) )
G4double ehigh = std::min(Emax, highedge);
if(ehigh > lowedge)
{
#ifdef G4VERBOSE
G4cerr << "Error in G4VRangeToEnergyConverter::SetEnergyRange()";
G4cerr << ": illegal energy range" << "(" << lowedge/GeV;
G4cerr << "," << highedge/GeV << ") [GeV]" << G4endl;
#endif
G4Exception( "G4VRangeToEnergyConverter::SetEnergyRange()",
"ProcCuts101", JustWarning, "Illegal energy range");
}
else
{
LowestEnergy = lowedge;
HighestEnergy = highedge;
}
FillEnergyVector(lowedge, ehigh);
}
}
// --------------------------------------------------------------------
G4double G4VRangeToEnergyConverter::GetLowEdgeEnergy()
{
return LowestEnergy;
return Emin;
}
// --------------------------------------------------------------------
G4double G4VRangeToEnergyConverter::GetHighEdgeEnergy()
{
return HighestEnergy;
}
// **********************************************************************
// ******************* Get/SetMaxEnergyCut *****************************
// **********************************************************************
G4double G4VRangeToEnergyConverter::GetMaxEnergyCut()
{
return MaxEnergyCut;
return Emax;
}
// --------------------------------------------------------------------
void G4VRangeToEnergyConverter::SetMaxEnergyCut(G4double value)
G4double G4VRangeToEnergyConverter::GetMaxEnergyCut()
{
MaxEnergyCut = value;
return Emax;
}
// **********************************************************************
// ************************ Reset **************************************
// **********************************************************************
void G4VRangeToEnergyConverter::Reset()
// --------------------------------------------------------------------
void G4VRangeToEnergyConverter::SetMaxEnergyCut(const G4double value)
{
// delete loss table
if (theLossTable != nullptr)
{
theLossTable->clearAndDestroy();
delete theLossTable;
}
theLossTable = nullptr;
NumberOfElements = 0;
// clear RangeVectorStore
for (std::size_t idx=0; idx<fRangeVectorStore.size(); ++idx)
if(value > Emin)
{
delete fRangeVectorStore.at(idx);
FillEnergyVector(Emin, value);
}
fRangeVectorStore.clear();
}
}
// **********************************************************************
// ************************ BuildLossTable ******************************
// **********************************************************************
void G4VRangeToEnergyConverter::BuildLossTable()
// --------------------------------------------------------------------
void G4VRangeToEnergyConverter::FillEnergyVector(const G4double emin,
const G4double emax)
{
// Create Energy Loss Table for charged particles
// (cross-section table for neutral)
if (std::size_t(NumberOfElements) == G4Element::GetNumberOfElements()) return;
// clear Loss table and Range vectors
Reset();
// Build dE/dx tables for elements
NumberOfElements = G4Element::GetNumberOfElements();
theLossTable = new G4LossTable();
theLossTable->reserve(G4Element::GetNumberOfElements());
#ifdef G4VERBOSE
if (GetVerboseLevel()>3)
{
G4cout << "G4VRangeToEnergyConverter::BuildLossTable() - ";
G4cout << "Create theLossTable[" << theLossTable << "]";
G4cout << " NumberOfElements=" << NumberOfElements << G4endl;
}
if(emin == Emin && emax == Emax) { return; }
#ifdef G4MULTITHREADED
G4MUTEXLOCK(&theMutex);
if(emin == Emin && emax == Emax) { return; }
#endif
// fill the loss table
for (std::size_t j=0; j<std::size_t(NumberOfElements); ++j)
Emin = emin;
Emax = emax;
Nbin = NbinPerDecade*static_cast<G4int>(std::log10(emax/emin));
Energy->resize(Nbin + 1);
(*Energy)[0] = emin;
(*Energy)[Nbin] = emax;
G4double fact = G4Log(emax/emin)/Nbin;
for(G4int i=1; i<Nbin; ++i)
{
G4double Value;
G4LossVector* aVector = nullptr;
aVector = new G4LossVector(LowestEnergy, MaxEnergyCut, TotBin);
for (std::size_t i=0; i<=std::size_t(TotBin); ++i)
{
Value = ComputeLoss( (*G4Element::GetElementTable())[j]->GetZ(),
aVector->Energy(i) );
aVector->PutValue(i,Value);
}
theLossTable->insert(aVector);
(*Energy)[i] = emin*G4Exp(i * fact);
}
#ifdef G4MULTITHREADED
G4MUTEXUNLOCK(&theMutex);
#endif
}
// **********************************************************************
// ************************ BuildRangeVector ****************************
// **********************************************************************
void G4VRangeToEnergyConverter::BuildRangeVector(const G4Material* aMaterial,
G4PhysicsLogVector* rangeVector)
// --------------------------------------------------------------------
G4double
G4VRangeToEnergyConverter::ConvertForGamma(const G4double rangeCut,
const G4Material* material)
{
// create range vector for a material
const G4ElementVector* elm = material->GetElementVector();
const G4double* dens = material->GetAtomicNumDensityVector();
const G4ElementVector* elementVector
= aMaterial->GetElementVector();
const G4double* atomicNumDensityVector
= aMaterial->GetAtomicNumDensityVector();
G4int NumEl = aMaterial->GetNumberOfElements();
// calculate parameters of the low energy part first
std::size_t i;
std::vector<G4double> lossV;
for ( std::size_t ib=0; ib<=std::size_t(TotBin); ++ib)
// fill absorption length vector
G4int nelm = material->GetNumberOfElements();
G4double range1 = 0.0;
G4double range2 = 0.0;
G4double e1 = 0.0;
G4double e2 = 0.0;
for (G4int i=0; i<Nbin; ++i)
{
G4double loss=0.;
for (i=0; i<std::size_t(NumEl); ++i)
{
G4int IndEl = (*elementVector)[i]->GetIndex();
loss += atomicNumDensityVector[i]*
(*((*theLossTable)[IndEl]))[ib];
}
lossV.push_back(loss);
}
// Integrate with Simpson formula with logarithmic binning
G4double dltau = 1.0;
if (LowestEnergy>0.)
{
G4double ltt =std::log(MaxEnergyCut/LowestEnergy);
dltau = ltt/TotBin;
}
G4double s0 = 0.;
G4double Value;
for ( i=0; i<=std::size_t(TotBin); ++i )
{
G4double t = rangeVector->GetLowEdgeEnergy(i);
G4double q = t/lossV[i];
if (i==0) s0 += 0.5*q;
else s0 += q;
e2 = (*Energy)[i];
G4double sig = 0.;
if (i==0)
for (G4int j=0; j<nelm; ++j)
{
Value = (s0 + 0.5*q)*dltau ;
sig += dens[j]*ComputeValue((*elm)[j]->GetZasInt(), e2);
}
range2 = (sig > 0.0) ? 5./sig : DBL_MAX;
if(i == 0 || range2 < rangeCut)
{
e1 = e2;
range1 = range2;
}
else
{
Value = (s0 - 0.5*q)*dltau ;
}
rangeVector->PutValue(i,Value);
}
}
// **********************************************************************
// ****************** ConvertCutToKineticEnergy *************************
// **********************************************************************
G4double G4VRangeToEnergyConverter::ConvertCutToKineticEnergy(
G4RangeVector* rangeVector,
G4double theCutInLength,
#ifdef G4VERBOSE
std::size_t materialIndex
#else
std::size_t
#endif
) const
{
const G4double epsilon = 0.01;
// find max. range and the corresponding energy (rmax,Tmax)
G4double rmax= -1.e10*mm;
G4double T1 = LowestEnergy;
G4double r1 =(*rangeVector)[0] ;
G4double T2 = MaxEnergyCut;
// check theCutInLength < r1
if ( theCutInLength <= r1 ) { return T1; }
// scan range vector to find nearest bin
// ( suppose that r(Ti) > r(Tj) if Ti >Tj )
for (std::size_t ibin=0; ibin<=std::size_t(TotBin); ++ibin)
{
G4double T=rangeVector->GetLowEdgeEnergy(ibin);
G4double r=(*rangeVector)[ibin];
if ( r>rmax ) rmax=r;
if (r <theCutInLength )
{
T1 = T;
r1 = r;
}
else if (r >theCutInLength )
{
T2 = T;
break;
}
}
return LiniearInterpolation(e1, e2, range1, range2, rangeCut);
}
// check cut in length is smaller than range max
if ( theCutInLength >= rmax )
// --------------------------------------------------------------------
G4double
G4VRangeToEnergyConverter::ConvertForElectron(const G4double rangeCut,
const G4Material* material)
{
const G4ElementVector* elm = material->GetElementVector();
const G4double* dens = material->GetAtomicNumDensityVector();
// fill absorption length vector
G4int nelm = material->GetNumberOfElements();
G4double dedx1 = 0.0;
G4double dedx2 = 0.0;
G4double range1 = 0.0;
G4double range2 = 0.0;
G4double e1 = 0.0;
G4double e2 = 0.0;
G4double range = 0.;
for (G4int i=0; i<Nbin; ++i)
{
#ifdef G4VERBOSE
if (GetVerboseLevel()>2)
e2 = (*Energy)[i];
dedx2 = 0.0;
for (G4int j=0; j<nelm; ++j)
{
G4cout << "G4VRangeToEnergyConverter::ConvertCutToKineticEnergy ";
G4cout << " for " << theParticle->GetParticleName() << G4endl;
G4cout << "The cut in range [" << theCutInLength/mm << " (mm)] ";
G4cout << " is too big " ;
G4cout << " for material idx=" << materialIndex <<G4endl;
dedx2 += dens[j]*ComputeValue((*elm)[j]->GetZasInt(), e2);
}
#endif
return MaxEnergyCut;
}
// convert range to energy
G4double T3 = std::sqrt(T1*T2);
G4double r3 = rangeVector->Value(T3);
const std::size_t MAX_LOOP = 1000;
for (std::size_t loop_count=0; loop_count<MAX_LOOP; ++loop_count)
{
if (std::fabs(1.-r3/theCutInLength)<epsilon ) break;
if ( theCutInLength <= r3 )
range += (dedx1 + dedx2 > 0.0) ? 2*(e2 - e1)/(dedx1 + dedx2) : 0.0;
range2 = range;
if(range2 < rangeCut)
{
T2 = T3;
e1 = e2;
dedx1 = dedx2;
range1 = range2;
}
else
{
T1 = T3;
break;
}
T3 = std::sqrt(T1*T2);
r3 = rangeVector->Value(T3);
}
return T3;
return LiniearInterpolation(e1, e2, range1, range2, rangeCut);
}
// --------------------------------------------------------------------