Import Geant4 5.1.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 10:15:15 +02:00
parent 37fff30d2e
commit fbd4999cf7
4396 changed files with 56662 additions and 52446 deletions
@@ -22,7 +22,7 @@
//
//
// $Id: G4AtomicTransitionManager.hh,v 1.2 ????
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Authors: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
// Alfonso Mantero (Alfonso.Mantero@ge.infn.it)
@@ -50,7 +50,7 @@ G4AtomicDeexcitation::G4AtomicDeexcitation():
G4AtomicDeexcitation::~G4AtomicDeexcitation()
{}
G4std::vector<G4DynamicParticle*>* G4AtomicDeexcitation::GenerateParticles(G4int Z,G4int shellId)
G4std::vector<G4DynamicParticle*>* G4AtomicDeexcitation::GenerateParticles(G4int Z,G4int givenShellId)
{
G4std::vector<G4DynamicParticle*>* vectorOfParticles = new G4std::vector<G4DynamicParticle*>;
G4DynamicParticle* aParticle;
@@ -63,17 +63,17 @@ do
{
if (counter == 0)
// First call to GenerateParticles(...):
// shellId is given by the process
// givenShellId is given by the process
{
provShellId = SelectTypeOfTransition(Z, shellId);
provShellId = SelectTypeOfTransition(Z, givenShellId);
if ( provShellId >0)
{
aParticle = GenerateFluorescence(Z,shellId,provShellId);
aParticle = GenerateFluorescence(Z,givenShellId,provShellId);
}
else if ( provShellId == -1)
{
aParticle = GenerateAuger(Z, shellId);
aParticle = GenerateAuger(Z, givenShellId);
}
else
{
@@ -102,7 +102,9 @@ do
if (aParticle != 0) {vectorOfParticles->push_back(aParticle);}
else {provShellId = -2;}
}
while (provShellId >= 0);
// Look this in a particular way: only one auger emitted! //
while (provShellId >= -1);
return vectorOfParticles;
}
@@ -252,9 +254,9 @@ G4DynamicParticle* G4AtomicDeexcitation::GenerateAuger(G4int Z, G4int shellId)
transitionManager->ReachableAugerShell(Z,maxNumOfShells-1);
// This loop gives shellNum the value of the index of shellId
// in the vector storing the list of the shells reachable through
// a NON-radiative transition
// This loop gives to shellNum the value of the index of shellId
// in the vector storing the list of the vacancies in the variuos shells
// that can originate a NON-radiative transition
// ---- MGP ---- Next line commented out to remove compilation warning
// G4int p = refAugerTransition->FinalShellId();
@@ -262,20 +264,31 @@ G4DynamicParticle* G4AtomicDeexcitation::GenerateAuger(G4int Z, G4int shellId)
G4int shellNum = 0;
if ( shellId <= refAugerTransition->FinalShellId() )
if ( shellId <= refAugerTransition->FinalShellId() )
//"FinalShellId" is final from the point of view of the elctron who makes the transition,
// being the Id of the shell in which there is a vacancy
{
G4int pippo = transitionManager->ReachableAugerShell(Z,shellNum)->FinalShellId();
if (shellId != pippo ) {
do {
shellNum++;
if(shellNum == maxNumOfShells)
{
G4Exception("G4AtomicDeexcitation: No Auger transition found");
}
}
while (shellId != (transitionManager->ReachableAugerShell(Z,shellNum)->FinalShellId()) ) ;
}
/* {
do
if(shellNum == maxNumOfShells-1)
{
G4Exception("G4AtomicDeexcitation: No Auger tramsition found");
}
shellNum++;
}*/
{
if(shellNum == maxNumOfShells-1)
{
break;
}
shellNum++;
}
while (shellId != transitionManager->ReachableAugerShell(Z,shellNum)->FinalShellId());
// Now we have that shellnum is the shellIndex of the shell named ShellId
@@ -300,14 +313,21 @@ G4DynamicParticle* G4AtomicDeexcitation::GenerateAuger(G4int Z, G4int shellId)
G4int augerIndex = 0;
// G4int partSum2 = 0;
while (augerIndex < numberOfPossibleAuger) {
partSum += anAugerTransition->AugerTransitionProbability(augerIndex,
transitionLoopShellId);
augerIndex++;
}
if (augerIndex < numberOfPossibleAuger) {
do
{
G4double thisProb = anAugerTransition->AugerTransitionProbability(augerIndex,
transitionLoopShellId);
partSum += thisProb;
augerIndex++;
} while (augerIndex < numberOfPossibleAuger);
}
transitionLoopShellIndex++;
}
// Now we have the entire probability of an auger transition for the vacancy
@@ -338,8 +358,10 @@ G4DynamicParticle* G4AtomicDeexcitation::GenerateAuger(G4int Z, G4int shellId)
while (augerIndex < numberOfPossibleAuger) {
partSum += anAugerTransition->AugerTransitionProbability(augerIndex,
transitionRandomShellId);
G4double thisProb =anAugerTransition->AugerTransitionProbability(augerIndex,
transitionRandomShellId);
partSum += thisProb;
if (partSum >= (partialProb/totalVacancyAugerProbability) ) {break;}
augerIndex++;
@@ -361,46 +383,17 @@ G4DynamicParticle* G4AtomicDeexcitation::GenerateAuger(G4int Z, G4int shellId)
G4ThreeVector newElectronDirection(xDir,yDir,zDir);
/*
G4int shellNum = 0;
G4int maxNumOfShells = transitionManager->NumberOfReachableShells(Z);
// find the index of the shell named shellId
while (shellId != transitionManager->
ReachableShell(Z,shellNum)->FinalShellId())
{
if(shellNum == maxNumOfShells-1)
{
break;
}
shellNum++;
}
// number of shell from wich an electron can reach shellId
size_t transitionSize = transitionManager->
ReachableShell(Z,shellNum)->OriginatingShellIds().size();
size_t index = 0;
// find the index of the shell named provShellId in the vector
// storing the shells from which shellId can be reached
while (provShellId != transitionManager->
ReachableShell(Z,shellNum)->OriginatingShellId(index))
{
if(index == transitionSize-1)
{
break;
}
index++;
}
*/
// energy of the auger electron emitted
G4double transitionEnergy =
anAugerTransition->AugerTransitionEnergy(augerIndex, transitionRandomShellId);
/*
G4cout << "AUger TransitionId " << anAugerTransition->FinalShellId() << G4endl;
G4cout << "augerIndex: " << augerIndex << G4endl;
G4cout << "transitionShellId: " << transitionRandomShellId << G4endl;
*/
// This is the shell where the new vacancy is: it is the same
// shell where the electron came from
newShellId = transitionRandomShellId;
@@ -411,7 +404,7 @@ G4DynamicParticle* G4AtomicDeexcitation::GenerateAuger(G4int Z, G4int shellId)
transitionEnergy);
return newPart;
}
}
else
{
//G4Exception("G4AtomicDeexcitation: no auger transition found");
@@ -22,7 +22,7 @@
//
//
// $Id: G4AtomicShell.cc,v 1.2 ????
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Authors: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
// Alfonso Mantero (Alfonso.Mantero@ge.infn.it)
@@ -22,7 +22,7 @@
//
//
// $Id: G4AtomicTransition.cc,v 1.2 ????
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
//
@@ -22,7 +22,7 @@
//
//
// $Id: G4AtomicTransitionManager.cc,v 1.2 ????
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Authors: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
// Alfonso Mantero (Alfonso.Mantero@ge.infn.it)
@@ -173,24 +173,35 @@ G4AtomicShell* G4AtomicTransitionManager::Shell(G4int Z, size_t shellIndex) cons
pos = shellTable.find(Z);
if (pos!= shellTable.end()){
G4std::vector<G4AtomicShell*> v = (*pos).second;
if (shellIndex<v.size()){
return(v[shellIndex]);
if (pos!= shellTable.end())
{
G4std::vector<G4AtomicShell*> v = (*pos).second;
if (shellIndex<v.size())
{
return(v[shellIndex]);
}
else
{
size_t lastShell = v.size();
G4cout << "G4AtomicTransitionManager::Shell - Z = "
<< Z << ", shellIndex = " << shellIndex
<< " not found; number of shells = " << lastShell << G4endl;
// G4Exception("G4AtomicTransitionManager:shell not found");
if (lastShell > 0)
{
return v[lastShell - 1];
}
else
{
return 0;
}
}
}
else {
G4Exception("G4AtomicTransitionManager:shell not found");
else
{
G4Exception("G4AtomicTransitionManager:Z not found");
return 0;
}
}
else{
G4Exception("G4AtomicTransitionManager:Z not found");
return 0;
}
}
}
// This function gives, upon Z and the Index of the initial shell where te vacancy is,
@@ -65,17 +65,17 @@ const G4std::vector<G4int>* G4AugerTransition::AugerOriginatingShellIds(G4int st
{
G4std::map<G4int,G4std::vector<G4int>,G4std::less<G4int> >::const_iterator shellId = augerOriginatingShellIdsMap.find(startShellId);
const G4std::vector<G4int> dataSet = (*shellId).second;
const G4std::vector<G4int>* dataOut = 0;
const G4std::vector<G4int>* dataSet = &(*shellId).second;
//const G4std::vector<G4int>* dataOut = 0;
if (dataSet.size() == 0) {G4cout << "Error: no auger Id found"<< G4endl;}
if (dataSet->size() == 0) {G4cout << "Error: no auger Id found"<< G4endl;}
else {
dataOut = &dataSet;
// dataOut = &dataSet;
}
return dataOut;
return dataSet;
}
// Returns the ids of the shells from wich an electron cuuld fill the vacancy in finalShellId
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4BremsstrahlungCrossSectionHandler.cc,v 1.5 2001/10/25 14:31:20 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4BremsstrahlungCrossSectionHandler.cc,v 1.6 2003/01/22 18:47:26 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// -------------------------------------------------------------------
//
@@ -36,6 +36,7 @@
//
// Modifications:
// 10.10.2001 MGP Revision to improve code quality and consistency with design
// 21.01.2003 VI cut per region
//
// -------------------------------------------------------------------
@@ -48,9 +49,9 @@
#include "G4VEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4Material.hh"
#include "G4MaterialTable.hh"
#include "G4ProductionCutsTable.hh"
G4BremsstrahlungCrossSectionHandler::G4BremsstrahlungCrossSectionHandler(const G4VEnergySpectrum* spec,
G4BremsstrahlungCrossSectionHandler::G4BremsstrahlungCrossSectionHandler(const G4VEnergySpectrum* spec,
G4VDataSetAlgorithm* alg)
: theBR(spec)
{
@@ -58,14 +59,14 @@ G4BremsstrahlungCrossSectionHandler::G4BremsstrahlungCrossSectionHandler(const G
}
G4BremsstrahlungCrossSectionHandler::~G4BremsstrahlungCrossSectionHandler()
G4BremsstrahlungCrossSectionHandler::~G4BremsstrahlungCrossSectionHandler()
{
delete interp;
}
G4std::vector<G4VEMDataSet*>*
G4BremsstrahlungCrossSectionHandler::BuildCrossSectionsForMaterials(const G4DataVector& energyVector,
G4std::vector<G4VEMDataSet*>*
G4BremsstrahlungCrossSectionHandler::BuildCrossSectionsForMaterials(const G4DataVector& energyVector,
const G4DataVector* energyCuts)
{
G4std::vector<G4VEMDataSet*>* set = new G4std::vector<G4VEMDataSet*>;
@@ -74,15 +75,14 @@ G4BremsstrahlungCrossSectionHandler::BuildCrossSectionsForMaterials(const G4Data
G4DataVector* cs;
G4int nOfBins = energyVector.size();
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
if (materialTable == 0)
G4Exception("G4VCrossSectionHandler::G4VCrossSectionHandler - no MaterialTable found)");
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
G4int nMaterials = G4Material::GetNumberOfMaterials();
for (size_t m=0; m<numOfCouples; m++) {
for (G4int m=0; m<nMaterials; m++) {
const G4Material* material = (*materialTable)[m];
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(m);
const G4Material* material= couple->GetMaterial();
const G4ElementVector* elementVector = material->GetElementVector();
const G4double* nAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4int nElements = material->GetNumberOfElements();
@@ -93,7 +93,7 @@ G4BremsstrahlungCrossSectionHandler::BuildCrossSectionsForMaterials(const G4Data
G4VEMDataSet* setForMat = new G4CompositeEMDataSet(algo,1.,1.);
for (G4int i=0; i<nElements; i++) {
G4int Z = (G4int) ((*elementVector)[i]->GetZ());
energies = new G4DataVector;
cs = new G4DataVector;
@@ -107,19 +107,19 @@ G4BremsstrahlungCrossSectionHandler::BuildCrossSectionsForMaterials(const G4Data
if(e > tcut) {
G4double elemCs = FindValue(Z, e);
value = theBR->Probability(Z, tcut, e, e);
value *= elemCs*density;
}
cs->push_back(value);
}
}
G4VDataSetAlgorithm* algol = interp->Clone();
G4VEMDataSet* elSet = new G4EMDataSet(i,energies,cs,algol,1.,1.);
setForMat->AddComponent(elSet);
}
set->push_back(setForMat);
}
return set;
}
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4BremsstrahlungParameters.cc,v 1.14 2002/11/18 18:08:25 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4BremsstrahlungParameters.cc,v 1.16 2003/02/28 08:42:18 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
// V.Ivanchenko (Vladimir.Ivantchenko@cern.ch)
@@ -34,6 +34,8 @@
// 25.09.01 V.Ivanchenko Add parameter C and change interface to B
// 29.11.01 V.Ivanchenko Update parametrisation
// 18.11.02 V.Ivanchenko Fix problem of load
// 21.02.03 V.Ivanchenko Number of parameters is defined in the constructor
// 28.02.03 V.Ivanchenko Filename is defined in the constructor
//
// -------------------------------------------------------------------
@@ -46,18 +48,19 @@
#include "g4std/strstream"
G4BremsstrahlungParameters:: G4BremsstrahlungParameters(G4int minZ, G4int maxZ)
: zMin(minZ),
G4BremsstrahlungParameters:: G4BremsstrahlungParameters(const G4String& name,
size_t num, G4int minZ, G4int maxZ)
: zMin(minZ),
zMax(maxZ),
length(16)
length(num)
{
LoadData();
LoadData(name);
}
G4BremsstrahlungParameters::~G4BremsstrahlungParameters()
{
// Reset the map of data sets: remove the data sets from the map
{
// Reset the map of data sets: remove the data sets from the map
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::iterator pos;
for (pos = param.begin(); pos != param.end(); ++pos)
@@ -71,12 +74,12 @@ G4BremsstrahlungParameters::~G4BremsstrahlungParameters()
}
G4double G4BremsstrahlungParameters::Parameter(G4int parameterIndex,
G4int Z,
G4double G4BremsstrahlungParameters::Parameter(G4int parameterIndex,
G4int Z,
G4double energy) const
{
G4double value = 0.;
G4int id = Z*20 + parameterIndex;
G4int id = Z*length + parameterIndex;
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
pos = param.find(id);
@@ -86,7 +89,7 @@ G4double G4BremsstrahlungParameters::Parameter(G4int parameterIndex,
const G4DataVector ener = dataSet->GetEnergies(0);
G4double ee = G4std::max(ener.front(),G4std::min(ener.back(),energy));
value = dataSet->FindValue(ee);
} else {
G4cout << "WARNING: G4BremsstrahlungParameters::FindValue "
<< "did not find ID = "
@@ -96,7 +99,7 @@ G4double G4BremsstrahlungParameters::Parameter(G4int parameterIndex,
return value;
}
void G4BremsstrahlungParameters::LoadData()
void G4BremsstrahlungParameters::LoadData(const G4String& name)
{
// Build the complete string identifying the file with the data set
@@ -112,13 +115,13 @@ void G4BremsstrahlungParameters::LoadData()
for (G4int mm=0; mm<100; mm++) {
paramC.push_back(x);
}
for (G4int m=0; m<nMaterials; m++) {
const G4Material* material= (*materialTable)[m];
const G4Material* material= (*materialTable)[m];
const G4ElementVector* elementVector = material->GetElementVector();
const G4int nElements = material->GetNumberOfElements();
for (G4int iEl=0; iEl<nElements; iEl++) {
G4Element* element = (*elementVector)[iEl];
G4double Z = element->GetZ();
@@ -127,31 +130,30 @@ void G4BremsstrahlungParameters::LoadData()
paramC[iz] = 0.217635e-33*(material->GetTotNbOfElectPerVolume());
if (!(activeZ.contains(Z))) {
activeZ.push_back(Z);
}
}
}
}
// Read parameters
char* path = getenv("G4LEDATA");
if (path == 0)
{
{
G4String excep("G4BremsstrahlungParameters - G4LEDATA environment variable not set");
G4Exception(excep);
}
G4String pathString_a(path);
G4String stringConversion1("/brem/br-sp.dat");
G4String name_a = pathString_a + stringConversion1;
G4String name_a = pathString_a + name;
G4std::ifstream file_a(name_a);
G4std::filebuf* lsdp_a = file_a.rdbuf();
if (! (lsdp_a->is_open()) )
if (! (lsdp_a->is_open()) )
{
G4String stringConversion2("G4BremsstrahlungParameters: cannot open file ");
G4String excep = stringConversion2 + name_a;
G4Exception(excep);
}
}
// The file is organized into two columns:
// 1st column is the energy
@@ -163,15 +165,15 @@ void G4BremsstrahlungParameters::LoadData()
G4DataVector* data;
G4double ener = 0.0;
G4double sum = 0.0;
energies = new G4DataVector();
data = new G4DataVector();
energies = new G4DataVector();
data = new G4DataVector();
G4int z = 0;
G4std::vector<G4DataVector*> a;
for (size_t j=0; j<length; j++) {
G4DataVector* aa = new G4DataVector();
a.push_back(aa);
}
}
G4DataVector e;
e.clear();
@@ -179,21 +181,21 @@ void G4BremsstrahlungParameters::LoadData()
file_a >> ener >> sum;
// End of file
if (ener == -2) {
if (ener == (G4double)(-2)) {
break;
// End of next element
} else if (ener == -1) {
} else if (ener == (G4double)(-1)) {
z++;
G4double Z = (G4double)z;
// fill map if Z is used
if (activeZ.contains(Z)) {
for (size_t k=0; k<length; k++) {
G4int id = z*20 + k;
G4int id = z*length + k;
G4VDataSetAlgorithm* inter = new G4LogLogInterpolation();
G4DataVector* eVector = new G4DataVector;
size_t eSize = e.size();
@@ -207,14 +209,14 @@ void G4BremsstrahlungParameters::LoadData()
for (size_t j=0; j<length; j++) {
G4DataVector* aa = new G4DataVector();
a.push_back(aa);
}
}
} else {
for (size_t j=0; j<length; j++) {
a[j]->clear();
}
}
e.clear();
} else {
if(ener > 1000.) ener = 1000.;
@@ -225,11 +227,11 @@ void G4BremsstrahlungParameters::LoadData()
G4double qRead;
file_a >> qRead;
a[j]->push_back(qRead);
}
}
}
} while (ener != -2);
} while (ener != (G4double)(-2));
file_a.close();
}
@@ -238,7 +240,7 @@ void G4BremsstrahlungParameters::LoadData()
G4double G4BremsstrahlungParameters::ParameterC(G4int id) const
{
G4int n = paramC.size();
if (id < 0 || id >= n)
if (id < 0 || id >= n)
{
G4String stringConversion1("G4BremsstrahlungParameters::ParameterC - wrong id = ");
G4String stringConversion2(id);
@@ -252,7 +254,7 @@ G4double G4BremsstrahlungParameters::ParameterC(G4int id) const
void G4BremsstrahlungParameters::PrintData() const
{
G4cout << G4endl;
G4cout << "===== G4BremsstrahlungParameters =====" << G4endl;
G4cout << G4endl;
@@ -263,15 +265,15 @@ void G4BremsstrahlungParameters::PrintData() const
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
for (size_t j=0; j<nZ; j++) {
G4int Z = (G4int)activeZ[j];
G4int Z = (G4int)activeZ[j];
for (size_t i=0; i<length; i++) {
pos = param.find(Z*20 + i);
pos = param.find(Z*length + i);
if (pos!= param.end()) {
G4cout << "===== Z= " << Z
<< " parameter[" << i << "] ====="
G4cout << "===== Z= " << Z
<< " parameter[" << i << "] ====="
<< G4endl;
G4VEMDataSet* dataSet = (*pos).second;
dataSet->PrintData();
@@ -22,7 +22,7 @@
//
//
// $Id: G4CompositeEMDataSet.cc,v 1.6 2002/05/28 09:20:18 pia Exp $
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4CrossSectionHandler.cc,v 1.14 2002/07/19 17:32:48 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4CrossSectionHandler.cc,v 1.15 2003/04/24 14:19:37 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -30,6 +30,7 @@
// -----------
// 1 Aug 2001 MGP Created
// 19 Jul 2002 VI Create composite data set for material
// 24 Apr 2003 VI Cut per region mfpt
//
// -------------------------------------------------------------------
@@ -39,10 +40,10 @@
#include "G4EMDataSet.hh"
#include "G4CompositeEMDataSet.hh"
#include "G4ShellEMDataSet.hh"
#include "G4MaterialTable.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "Randomize.hh"
#include "Randomize.hh"
#include "g4std/map"
#include "g4std/vector"
#include "g4std/fstream"
@@ -56,7 +57,7 @@ G4CrossSectionHandler::G4CrossSectionHandler()
G4CrossSectionHandler::~G4CrossSectionHandler()
{ }
G4std::vector<G4VEMDataSet*>*
G4std::vector<G4VEMDataSet*>*
G4CrossSectionHandler::BuildCrossSectionsForMaterials(const G4DataVector& energyVector,
const G4DataVector*)
{
@@ -65,15 +66,17 @@ G4CrossSectionHandler::BuildCrossSectionsForMaterials(const G4DataVector& energy
G4std::vector<G4VEMDataSet*>* matCrossSections = new G4std::vector<G4VEMDataSet*>;
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
G4int nMaterials = G4Material::GetNumberOfMaterials();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
size_t nOfBins = energyVector.size();
const G4VDataSetAlgorithm* interpolationAlgo = CreateInterpolation();
for (G4int m=0; m<nMaterials; m++)
for (size_t m=0; m<numOfCouples; m++)
{
const G4Material* material= (*materialTable)[m];
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(m);
const G4Material* material= couple->GetMaterial();
G4int nElements = material->GetNumberOfElements();
const G4ElementVector* elementVector = material->GetElementVector();
const G4double* nAtomsPerVolume = material->GetAtomicNumDensityVector();
@@ -1,73 +0,0 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// $Id: G4CutsPerMaterialWarning.cc,v 1.1 2001/11/07 22:39:02 pia Exp $
// GEANT4 tag $Name: geant4-05-00 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// -----------
// 05 Oct 2001 MGP Created
//
// -------------------------------------------------------------------
#include "G4CutsPerMaterialWarning.hh"
#include "G4ParticleDefinition.hh"
#include "G4Material.hh"
#include "G4MaterialTable.hh"
void G4CutsPerMaterialWarning::PrintWarning(const G4ParticleDefinition* particle) const
{
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
size_t nMaterials = materialTable->size();
if (nMaterials > 1)
{
G4Material* material = (*materialTable)[0];
G4double cut0 = particle->GetRangeThreshold(material);
G4double cut = cut0;
G4bool different = false;
size_t mat = 0;
while ((!different) && mat < (nMaterials-1))
{
mat++;
G4Material* material = (*materialTable)[mat];
cut = particle->GetRangeThreshold(material);
if (cut != cut0) different = true;
}
if (different)
{
G4cout << "========================== W A R N I N G ============================ " << G4endl
<< " " << G4endl
<< "You are using different range thresholds for different materials" << G4endl
<< "This is an UNSUPPORTED feature temporarily implemented in Geant4" << G4endl
<< "Geant4 Low Energy Electromagnetic Physics Processes are not supported," << G4endl
<< "if this feature is activated and you may get inconsistent results" << G4endl
<< "Please define the same range threshold for all materials" << G4endl
<< " " << G4endl
<< "========================== W A R N I N G ============================ " << G4endl;
}
}
}
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4EMDataSet.cc,v 1.6 2002/05/28 09:20:19 pia Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4EMDataSet.cc,v 1.7 2003/02/24 00:36:10 pia Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -82,29 +82,30 @@ G4EMDataSet::~G4EMDataSet()
G4double G4EMDataSet::FindValue(G4double e, G4int id) const
{
G4double value;
G4double e0 = (*energies)[0];
// Protections
size_t bin = FindBinLocation(e);
if (bin == numberOfBins)
G4double value = 0.;
if ( !(energies->empty()) )
{
// G4cout << "WARNING - G4EMDataSet::FindValue: energy outside upper boundary"
// << G4endl;
value = (*data)[bin];
G4double e0 = (*energies)[0];
// Protections
size_t bin = FindBinLocation(e);
if (bin == numberOfBins)
{
// G4cout << "WARNING - G4EMDataSet::FindValue: energy outside upper boundary"
// << G4endl;
value = (*data)[bin];
}
else if (e <= e0)
{
// G4cout << "WARNING - G4EMDataSet::FindValue: energy outside lower boundary"
// << G4endl;
value = (*data)[0];
}
else
{
if (algorithm == 0) G4Exception("G4EMDataSet::FindValue - interpolation algorithm = 0");
value = algorithm->Calculate(e,bin,*energies,*data);
}
}
else if (e <= e0)
{
// G4cout << "WARNING - G4EMDataSet::FindValue: energy outside lower boundary"
// << G4endl;
value = (*data)[0];
}
else
{
if (algorithm == 0)
G4Exception("G4EMDataSet::FindValue - interpolation algorithm = 0");
value = algorithm->Calculate(e,bin,*energies,*data);
}
return value;
}
@@ -22,7 +22,7 @@
//
//
// $Id: G4FluoTransition.cc,v 1.2 ????
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
//
@@ -22,7 +22,7 @@
//
//
// $Id: G4LinInterpolation.cc,v 1.2 2002/05/28 09:20:19 pia Exp $
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -22,7 +22,7 @@
//
//
// $Id: G4LogLogInterpolation.cc,v 1.4 2002/05/28 09:20:19 pia Exp $
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -20,15 +20,15 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4LowEnergyBremsstrahlung.cc,v 1.55 2002/07/30 18:14:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4LowEnergyBremsstrahlung.cc,v 1.58 2003/02/28 08:42:17 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// --------------------------------------------------------------
//
// File name: G4LowEnergyBremsstrahlung
//
// Author: Alessandra Forti, Vladimir Ivanchenko
//
//
// Creation date: March 1999
//
// Modifications:
@@ -51,6 +51,9 @@
// 28.10.2001 VI Update printout
// 29.11.2001 VI New parametrisation
// 30.07.2002 VI Fix in restricted energy loss
// 21.01.2003 VI Cut per region
// 21.02.2003 V.Ivanchenko Energy bins for spectrum are defined here
// 28.02.03 V.Ivanchenko Filename is defined in the constructor
//
// --------------------------------------------------------------
@@ -64,11 +67,11 @@
#include "G4UnitsTable.hh"
#include "G4Electron.hh"
#include "G4Gamma.hh"
#include "G4ProductionCutsTable.hh"
#include "G4CutsPerMaterialWarning.hh"
G4LowEnergyBremsstrahlung::G4LowEnergyBremsstrahlung(const G4String& nam)
: G4eLowEnergyLoss(nam),
: G4eLowEnergyLoss(nam),
crossSectionHandler(0),
theMeanFreePath(0),
energySpectrum(0)
@@ -83,6 +86,7 @@ G4LowEnergyBremsstrahlung::~G4LowEnergyBremsstrahlung()
if(crossSectionHandler) delete crossSectionHandler;
if(energySpectrum) delete energySpectrum;
if(theMeanFreePath) delete theMeanFreePath;
energyBins.clear();
}
@@ -92,15 +96,24 @@ void G4LowEnergyBremsstrahlung::BuildPhysicsTable(const G4ParticleDefinition& aP
G4cout << "G4LowEnergyBremsstrahlung::BuildPhysicsTable start"
<< G4endl;
}
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&aParticleType);
cutForSecondaryPhotons.clear();
// Create and fill BremsstrahlungParameters once
if( energySpectrum != 0 ) delete energySpectrum;
energySpectrum = new G4eBremsstrahlungSpectrum();
energyBins.clear();
for(size_t i=0; i<15; i++) {
G4double x = 0.1*((G4double)i);
if(i == 0) x = 0.01;
if(i == 10) x = 0.95;
if(i == 11) x = 0.97;
if(i == 12) x = 0.99;
if(i == 13) x = 0.995;
if(i == 14) x = 1.0;
energyBins.push_back(x);
}
const G4String dataName("/brem/br-sp.dat");
energySpectrum = new G4eBremsstrahlungSpectrum(energyBins,dataName);
if(verboseLevel > 0) {
G4cout << "G4LowEnergyBremsstrahlungSpectrum is initialized"
@@ -119,11 +132,11 @@ void G4LowEnergyBremsstrahlung::BuildPhysicsTable(const G4ParticleDefinition& aP
crossSectionHandler->LoadShellData("brem/br-cs-");
if (verboseLevel > 0) {
G4cout << GetProcessName()
<< " is created; Cross section data: "
G4cout << GetProcessName()
<< " is created; Cross section data: "
<< G4endl;
crossSectionHandler->PrintData();
G4cout << "Parameters: "
G4cout << "Parameters: "
<< G4endl;
energySpectrum->PrintData();
}
@@ -161,7 +174,7 @@ void G4LowEnergyBremsstrahlung::BuildPhysicsTable(const G4ParticleDefinition& aP
}
// Build common DEDX table for all ionisation processes
BuildDEDXTable(aParticleType);
if(verboseLevel > 0) {
@@ -187,50 +200,52 @@ void G4LowEnergyBremsstrahlung::BuildLossTable(const G4ParticleDefinition& aPart
theLossTable->clearAndDestroy();
delete theLossTable;
}
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
const size_t numOfMaterials = G4Material::GetNumberOfMaterials();
theLossTable = new G4PhysicsTable(numOfMaterials);
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
theLossTable = new G4PhysicsTable(numOfCouples);
// Clean up the vector of cuts
cutForSecondaryPhotons.clear();
// Loop for materials
for (size_t j=0; j<numOfMaterials; j++) {
for (size_t j=0; j<numOfCouples; j++) {
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(lowKineticEnergy,
highKineticEnergy,
totBin);
// get material parameters needed for the energy loss calculation
const G4Material* material= (*theMaterialTable)[j];
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(j);
const G4Material* material= couple->GetMaterial();
// the cut cannot be below lowest limit
G4double tCut = G4std::min(highKineticEnergy,
((G4Gamma::Gamma())->GetEnergyThreshold(material)));
G4double tCut = (*(theCoupleTable->GetEnergyCutsVector(0)))[j];
tCut = G4std::min(highKineticEnergy, tCut);
cutForSecondaryPhotons.push_back(tCut);
const G4ElementVector* theElementVector = material->GetElementVector();
size_t NumberOfElements = material->GetNumberOfElements() ;
const G4double* theAtomicNumDensityVector =
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector();
if(verboseLevel > 1) {
G4cout << "Energy loss for material # " << j
<< " tCut(keV)= " << tCut/keV
<< G4endl;
}
// now comes the loop for the kinetic energy values
for (size_t i = 0; i<totBin; i++) {
G4double lowEdgeEnergy = aVector->GetLowEdgeEnergy(i);
G4double ionloss = 0.;
G4double ionloss = 0.;
// loop for elements in the material
for (size_t iel=0; iel<NumberOfElements; iel++ ) {
G4int Z = (G4int)((*theElementVector)[iel]->GetZ());
G4double e = energySpectrum->AverageEnergy(Z, 0.0, tCut, lowEdgeEnergy);
G4double e = energySpectrum->AverageEnergy(Z, 0.0, tCut, lowEdgeEnergy);
G4double cs= crossSectionHandler->FindValue(Z, lowEdgeEnergy);
ionloss += e * cs * theAtomicNumDensityVector[iel];
if(verboseLevel > 1) {
@@ -242,7 +257,7 @@ void G4LowEnergyBremsstrahlung::BuildLossTable(const G4ParticleDefinition& aPart
<< "; loss= " << ionloss
<< G4endl;
}
}
}
aVector->PutValue(i,ionloss);
}
theLossTable->insert(aVector);
@@ -255,38 +270,38 @@ G4VParticleChange* G4LowEnergyBremsstrahlung::PostStepDoIt(const G4Track& track,
{
aParticleChange.Initialize(track);
const G4Material* material = track.GetMaterial();
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
G4double kineticEnergy = track.GetKineticEnergy();
G4int index = material->GetIndex();
G4int index = couple->GetIndex();
G4double tCut = cutForSecondaryPhotons[index];
// Control limits
if(tCut >= kineticEnergy)
if(tCut >= kineticEnergy)
return G4VContinuousDiscreteProcess::PostStepDoIt(track, step);
G4int Z = crossSectionHandler->SelectRandomAtom(material, kineticEnergy);
G4int Z = crossSectionHandler->SelectRandomAtom(couple, kineticEnergy);
G4double tGamma = energySpectrum->SampleEnergy(Z, tCut, kineticEnergy, kineticEnergy);
// Sample gamma angle (Z - axis along the parent particle).
// Universal distribution suggested by L. Urban (Geant3 manual (1993)
// Universal distribution suggested by L. Urban (Geant3 manual (1993)
// Phys211) derived from Tsai distribution (Rev Mod Phys 49,421(1977))
G4double totalEnergy = kineticEnergy + electron_mass_c2;
G4double totalEnergy = kineticEnergy + electron_mass_c2;
const G4double a1 = 0.625, a2 = 3.*a1, d = 27.;
G4double u = - log(G4UniformRand()*G4UniformRand());
if (9./(9.+d) > G4UniformRand()) u /= a1;
else u /= a2;
G4double theta = u*electron_mass_c2/totalEnergy;
G4double phi = twopi * G4UniformRand();
G4double dirZ = cos(theta);
G4double sinTheta = sqrt(1. - dirZ*dirZ);
G4double dirX = sinTheta*cos(phi);
G4double dirY = sinTheta*sin(phi);
G4double dirY = sinTheta*sin(phi);
G4ThreeVector gammaDirection (dirX, dirY, dirZ);
G4ThreeVector electronDirection = track.GetMomentumDirection();
@@ -318,7 +333,7 @@ G4VParticleChange* G4LowEnergyBremsstrahlung::PostStepDoIt(const G4Track& track,
// create G4DynamicParticle object for the gamma
G4DynamicParticle* aGamma= new G4DynamicParticle (G4Gamma::Gamma(),
gammaDirection, tGamma);
aParticleChange.AddSecondary(aGamma);
aParticleChange.AddSecondary(aGamma);
return G4VContinuousDiscreteProcess::PostStepDoIt(track, step);
}
@@ -347,11 +362,11 @@ G4double G4LowEnergyBremsstrahlung::GetMeanFreePath(const G4Track& track,
G4ForceCondition* cond)
{
*cond = NotForced;
G4int index = (track.GetMaterial())->GetIndex();
G4int index = (track.GetMaterialCutsCouple())->GetIndex();
const G4VEMDataSet* data = theMeanFreePath->GetComponent(index);
G4double meanFreePath = data->FindValue(track.GetKineticEnergy());
return meanFreePath;
}
return meanFreePath;
}
void G4LowEnergyBremsstrahlung::SetCutForLowEnSecPhotons(G4double cut)
{
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4LowEnergyCompton.cc,v 1.33 2001/11/07 20:47:29 pia Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4LowEnergyCompton.cc,v 1.36 2003/04/24 14:19:37 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: A. Forti
// Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
@@ -33,8 +33,11 @@
// Modified PostStepDoIt to insert sampling with EPDL97 data A. Forti
// Added SelectRandomAtom A. Forti
// Added map of the elements A. Forti
// 24.04.2001 V.Ivanchenko - Remove RogueWave
// 24.04.2001 V.Ivanchenko - Remove RogueWave
// 06.08.2001 MGP - Revised according to a design iteration
// 22.01.2003 V.Ivanchenko - Cut per region
// 10.03.2003 V.Ivanchenko - Remove CutPerMaterial warning
// 24.04.2003 V.Ivanchenko - Cut per region mfpt
//
// -------------------------------------------------------------------
@@ -58,17 +61,17 @@
#include "G4LogLogInterpolation.hh"
#include "G4VRangeTest.hh"
#include "G4RangeTest.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4CutsPerMaterialWarning.hh"
G4LowEnergyCompton::G4LowEnergyCompton(const G4String& processName)
: G4VDiscreteProcess(processName),
lowEnergyLimit(250*eV),
lowEnergyLimit(250*eV),
highEnergyLimit(100*GeV),
intrinsicLowEnergyLimit(10*eV),
intrinsicHighEnergyLimit(100*GeV)
{
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
highEnergyLimit > intrinsicHighEnergyLimit)
{
G4Exception("G4LowEnergyCompton::G4LowEnergyCompton - energy outside intrinsic process validity range");
@@ -84,16 +87,16 @@ G4LowEnergyCompton::G4LowEnergyCompton(const G4String& processName)
rangeTest = new G4RangeTest;
if (verboseLevel > 0)
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / GeV << " GeV"
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
G4LowEnergyCompton::~G4LowEnergyCompton()
{
delete meanFreePathTable;
@@ -104,9 +107,6 @@ G4LowEnergyCompton::~G4LowEnergyCompton()
void G4LowEnergyCompton::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&photon);
crossSectionHandler->Clear();
G4String crossSectionFile = "comp/ce-cs-";
@@ -116,26 +116,26 @@ void G4LowEnergyCompton::BuildPhysicsTable(const G4ParticleDefinition& photon)
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
}
G4VParticleChange* G4LowEnergyCompton::PostStepDoIt(const G4Track& aTrack,
G4VParticleChange* G4LowEnergyCompton::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
// The scattered gamma energy is sampled according to Klein - Nishina formula.
// then accepted or rejected depending on the Scattering Function multiplied
// by factor from Klein - Nishina formula.
// Expression of the angular distribution as Klein Nishina
// then accepted or rejected depending on the Scattering Function multiplied
// by factor from Klein - Nishina formula.
// Expression of the angular distribution as Klein Nishina
// angular and energy distribution and Scattering fuctions is taken from
// D. E. Cullen "A simple model of photon transport" Nucl. Instr. Meth.
// Phys. Res. B 101 (1995). Method of sampling with form factors is different
// D. E. Cullen "A simple model of photon transport" Nucl. Instr. Meth.
// Phys. Res. B 101 (1995). Method of sampling with form factors is different
// data are interpolated while in the article they are fitted.
// Reference to the article is from J. Stepanek New Photon, Positron
// and Electron Interaction Data for GEANT in Energy Range from 1 eV to 10
// TeV (draft).
// The random number techniques of Butcher & Messel are used
// TeV (draft).
// The random number techniques of Butcher & Messel are used
// (Nucl Phys 20(1960),15).
aParticleChange.Initialize(aTrack);
// Dynamic particle quantities
// Dynamic particle quantities
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double photonEnergy0 = incidentPhoton->GetKineticEnergy();
@@ -151,8 +151,8 @@ G4VParticleChange* G4LowEnergyCompton::PostStepDoIt(const G4Track& aTrack,
G4ParticleMomentum photonDirection0 = incidentPhoton->GetMomentumDirection();
// Select randomly one element in the current material
G4Material* material = aTrack.GetMaterial();
G4int Z = crossSectionHandler->SelectRandomAtom(material,photonEnergy0);
const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
G4int Z = crossSectionHandler->SelectRandomAtom(couple,photonEnergy0);
G4double epsilon0 = 1. / (1. + 2. * e0m);
G4double epsilon0Sq = epsilon0 * epsilon0;
@@ -160,8 +160,8 @@ G4VParticleChange* G4LowEnergyCompton::PostStepDoIt(const G4Track& aTrack,
G4double alpha2 = 0.5 * (1. - epsilon0Sq);
G4double wlPhoton = h_Planck*c_light/photonEnergy0;
// Sample the energy of the scattered photon
// Sample the energy of the scattered photon
G4double epsilon;
G4double epsilonSq;
G4double oneCosT;
@@ -172,20 +172,20 @@ G4VParticleChange* G4LowEnergyCompton::PostStepDoIt(const G4Track& aTrack,
if ( alpha1/(alpha1+alpha2) > G4UniformRand())
{
epsilon = exp(-alpha1 * G4UniformRand()); // pow(epsilon0,G4UniformRand())
epsilonSq = epsilon * epsilon;
epsilonSq = epsilon * epsilon;
}
else
{
epsilonSq = epsilon0Sq + (1. - epsilon0Sq) * G4UniformRand();
epsilon = sqrt(epsilonSq);
}
oneCosT = (1. - epsilon) / ( epsilon * e0m);
sinT2 = oneCosT * (2. - oneCosT);
sinT2 = oneCosT * (2. - oneCosT);
G4double x = sqrt(oneCosT/2.) / (wlPhoton/cm);
G4double scatteringFunction = scatterFunctionData->FindValue(x,Z-1);
gReject = (1. - epsilon * sinT2 / (1. + epsilonSq)) * scatteringFunction;
} while(gReject < G4UniformRand()*Z);
G4double cosTheta = 1. - oneCosT;
@@ -195,8 +195,8 @@ G4VParticleChange* G4LowEnergyCompton::PostStepDoIt(const G4Track& aTrack,
G4double diry = sinTheta * sin(phi);
G4double dirz = cosTheta ;
// Update G4VParticleChange for the scattered photon
// Update G4VParticleChange for the scattered photon
G4ThreeVector photonDirection1(dirx,diry,dirz);
photonDirection1.rotateUz(photonDirection0);
aParticleChange.SetMomentumChange(photonDirection1) ;
@@ -207,28 +207,28 @@ G4VParticleChange* G4LowEnergyCompton::PostStepDoIt(const G4Track& aTrack,
aParticleChange.SetEnergyChange(photonEnergy1) ;
}
else
{
{
aParticleChange.SetEnergyChange(0.) ;
aParticleChange.SetStatusChange(fStopAndKill);
}
// Kinematics of the scattered electron
// Kinematics of the scattered electron
G4double eKineticEnergy = photonEnergy0 - photonEnergy1;
// Generate the electron only if with large enough range w.r.t. cuts and safety
G4double safety = aStep.GetPostStepPoint()->GetSafety();
if (rangeTest->Escape(G4Electron::Electron(),material,eKineticEnergy,safety))
if (rangeTest->Escape(G4Electron::Electron(),couple,eKineticEnergy,safety))
{
G4double eMomentum = sqrt(eKineticEnergy*(eKineticEnergy+2.*electron_mass_c2));
G4ThreeVector eDirection((photonEnergy0 * photonDirection0 -
photonEnergy1 * photonDirection1) * (1./eMomentum));
G4ThreeVector eDirection((photonEnergy0 * photonDirection0 -
photonEnergy1 * photonDirection1) * (1./eMomentum));
G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),
eDirection,eKineticEnergy) ;
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(electron);
aParticleChange.SetLocalEnergyDeposit(0.);
aParticleChange.SetLocalEnergyDeposit(0.);
}
else
{
@@ -241,17 +241,17 @@ G4VParticleChange* G4LowEnergyCompton::PostStepDoIt(const G4Track& aTrack,
G4bool G4LowEnergyCompton::IsApplicable(const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
return ( &particle == G4Gamma::Gamma() );
}
G4double G4LowEnergyCompton::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4double G4LowEnergyCompton::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition*)
{
const G4DynamicParticle* photon = track.GetDynamicParticle();
G4double energy = photon->GetKineticEnergy();
G4Material* material = track.GetMaterial();
size_t materialIndex = material->GetIndex();
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
size_t materialIndex = couple->GetIndex();
G4double meanFreePath;
if (energy > highEnergyLimit) meanFreePath = meanFreePathTable->FindValue(highEnergyLimit,materialIndex);
@@ -22,8 +22,8 @@
//
// --------------------------------------------------------------------
///
// $Id: G4LowEnergyGammaConversion.cc,v 1.27 2002/05/31 18:48:43 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4LowEnergyGammaConversion.cc,v 1.30 2003/04/24 14:19:37 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
//
// --------------------------------------------------------------
@@ -38,8 +38,11 @@
// Change initialisation of lowestEnergyLimit from 1.22 to 1.022.
// Note that the hard coded value 1.022 should be used instead of
// 2*electron_mass_c2 in order to agree with the value of the data bank EPDL97
// 24.04.01 V.Ivanchenko remove RogueWave
// 27.07.01 F.Longo correct bug in energy distribution
// 24.04.01 V.Ivanchenko remove RogueWave
// 27.07.01 F.Longo correct bug in energy distribution
// 21.01.03 V.Ivanchenko Cut per region
// 25.03.03 F.Longo fix in angular distribution of e+/e-
// 24.04.03 V.Ivanchenko - Cut per region mfpt
//
// --------------------------------------------------------------
@@ -65,11 +68,10 @@
#include "G4LogLogInterpolation.hh"
#include "G4VRangeTest.hh"
#include "G4RangeTest.hh"
#include "G4CutsPerMaterialWarning.hh"
#include "G4MaterialCutsCouple.hh"
G4LowEnergyGammaConversion::G4LowEnergyGammaConversion(const G4String& processName)
: G4VDiscreteProcess(processName),
: G4VDiscreteProcess(processName),
lowEnergyLimit(1.022000*MeV),
highEnergyLimit(100*GeV),
intrinsicLowEnergyLimit(1.022000*MeV),
@@ -109,9 +111,6 @@ G4LowEnergyGammaConversion::~G4LowEnergyGammaConversion()
void G4LowEnergyGammaConversion::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&photon);
crossSectionHandler->Clear();
G4String crossSectionFile = "pair/pp-cs-";
@@ -121,92 +120,92 @@ void G4LowEnergyGammaConversion::BuildPhysicsTable(const G4ParticleDefinition& p
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
}
G4VParticleChange* G4LowEnergyGammaConversion::PostStepDoIt(const G4Track& aTrack,
G4VParticleChange* G4LowEnergyGammaConversion::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
// The energies of the e+ e- secondaries are sampled using the Bethe - Heitler
// cross sections with Coulomb correction. A modified version of the random
// The energies of the e+ e- secondaries are sampled using the Bethe - Heitler
// cross sections with Coulomb correction. A modified version of the random
// number techniques of Butcher & Messel is used (Nuc Phys 20(1960),15).
// Note 1 : Effects due to the breakdown of the Born approximation at low
// Note 1 : Effects due to the breakdown of the Born approximation at low
// energy are ignored.
// Note 2 : The differential cross section implicitly takes account of
// pair creation in both nuclear and atomic electron fields. However triplet
// Note 2 : The differential cross section implicitly takes account of
// pair creation in both nuclear and atomic electron fields. However triplet
// prodution is not generated.
aParticleChange.Initialize(aTrack);
G4Material* material = aTrack.GetMaterial();
const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double photonEnergy = incidentPhoton->GetKineticEnergy();
G4ParticleMomentum photonDirection = incidentPhoton->GetMomentumDirection();
G4double epsilon ;
G4double epsilon0 = electron_mass_c2 / photonEnergy ;
// Do it fast if photon energy < 2. MeV
if (photonEnergy < smallEnergy )
{
epsilon = epsilon0 + (0.5 - epsilon0) * G4UniformRand();
if (photonEnergy < smallEnergy )
{
epsilon = epsilon0 + (0.5 - epsilon0) * G4UniformRand();
}
else
{
{
// Select randomly one element in the current material
const G4Element* element = crossSectionHandler->SelectRandomElement(material,photonEnergy);
const G4Element* element = crossSectionHandler->SelectRandomElement(couple,photonEnergy);
if (element == 0)
if (element == 0)
{
G4cout << "G4LowEnergyGammaConversion::PostStepDoIt - element = 0" << G4endl;
}
G4IonisParamElm* ionisation = element->GetIonisation();
if (ionisation == 0)
if (ionisation == 0)
{
G4cout << "G4LowEnergyGammaConversion::PostStepDoIt - ionisation = 0" << G4endl;
}
// Extract Coulomb factor for this Element
G4double fZ = 8. * (ionisation->GetlogZ3());
if (photonEnergy > 50. * MeV) fZ += 8. * (element->GetfCoulomb());
// Limits of the screening variable
G4double screenFactor = 136. * epsilon0 / (element->GetIonisation()->GetZ3()) ;
G4double screenMax = exp ((42.24 - fZ)/8.368) - 0.952 ;
G4double screenMin = G4std::min(4.*screenFactor,screenMax) ;
// Limits of the energy sampling
G4double epsilon1 = 0.5 - 0.5 * sqrt(1. - screenMin / screenMax) ;
G4double epsilonMin = G4std::max(epsilon0,epsilon1);
G4double epsilonRange = 0.5 - epsilonMin ;
// Sample the energy rate of the created electron (or positron)
// Sample the energy rate of the created electron (or positron)
G4double screen;
G4double gReject ;
G4double f10 = ScreenFunction1(screenMin) - fZ;
G4double f20 = ScreenFunction2(screenMin) - fZ;
G4double normF1 = G4std::max(f10 * epsilonRange * epsilonRange,0.);
G4double normF2 = G4std::max(1.5 * f20,0.);
do {
if (normF1 / (normF1 + normF2) > G4UniformRand() )
{
epsilon = 0.5 - epsilonRange * pow(G4UniformRand(), 0.3333) ;
screen = screenFactor / (epsilon * (1. - epsilon));
gReject = (ScreenFunction1(screen) - fZ) / f10 ;
}
else
{
}
else
{
epsilon = epsilonMin + epsilonRange * G4UniformRand();
screen = screenFactor / (epsilon * (1 - epsilon));
gReject = (ScreenFunction2(screen) - fZ) / f20 ;
}
} while ( gReject < G4UniformRand() );
} // End of epsilon sampling
// Fix charges randomly
// Fix charges randomly
G4double electronTotEnergy;
G4double positronTotEnergy;
@@ -220,7 +219,7 @@ G4VParticleChange* G4LowEnergyGammaConversion::PostStepDoIt(const G4Track& aTrac
positronTotEnergy = (1. - epsilon) * photonEnergy;
electronTotEnergy = epsilon * photonEnergy;
}
// Scattered electron (positron) angles. ( Z - axis along the parent photon)
// Universal distribution suggested by L. Urban (Geant3 manual (1993) Phys211),
// derived from Tsai distribution (Rev. Mod. Phys. 49, 421 (1977)
@@ -229,7 +228,7 @@ G4VParticleChange* G4LowEnergyGammaConversion::PostStepDoIt(const G4Track& aTrac
const G4double a1 = 0.625;
G4double a2 = 3. * a1;
// G4double d = 27. ;
// if (9. / (9. + d) > G4UniformRand())
if (0.25 > G4UniformRand())
{
@@ -240,51 +239,55 @@ G4VParticleChange* G4LowEnergyGammaConversion::PostStepDoIt(const G4Track& aTrac
u = - log(G4UniformRand() * G4UniformRand()) / a2 ;
}
G4double theta = u * electron_mass_c2 / photonEnergy ;
G4double phi = twopi * G4UniformRand() ;
G4double dirX = sin(theta) * cos(phi);
G4double dirY = sin(theta) * sin(phi);
G4double dirZ = cos(theta);
// Kinematics of the created pair:
// the electron and positron are assumed to have a symetric angular
// distribution with respect to the Z axis along the parent photon
G4double thetaEle = u*electron_mass_c2/electronTotEnergy;
G4double thetaPos = u*electron_mass_c2/positronTotEnergy;
G4double phi = twopi * G4UniformRand();
G4double dxEle= sin(thetaEle)*cos(phi),dyEle= sin(thetaEle)*sin(phi),dzEle=cos(thetaEle);
G4double dxPos=-sin(thetaPos)*cos(phi),dyPos=-sin(thetaPos)*sin(phi),dzPos=cos(thetaPos);
// Kinematics of the created pair:
// the electron and positron are assumed to have a symetric angular
// distribution with respect to the Z axis along the parent photon
G4double localEnergyDeposit = 0. ;
aParticleChange.SetNumberOfSecondaries(2) ;
G4double electronKineEnergy = G4std::max(0.,electronTotEnergy - electron_mass_c2) ;
// Generate the electron only if with large enough range w.r.t. cuts and safety
G4double safety = aStep.GetPostStepPoint()->GetSafety();
if (rangeTest->Escape(G4Electron::Electron(),material,electronKineEnergy,safety))
if (rangeTest->Escape(G4Electron::Electron(),couple,electronKineEnergy,safety))
{
G4ThreeVector electronDirection ( dirX, dirY, dirZ );
electronDirection.rotateUz(photonDirection);
G4ThreeVector electronDirection (dxEle, dyEle, dzEle);
electronDirection.rotateUz(photonDirection);
G4DynamicParticle* particle1 = new G4DynamicParticle (G4Electron::Electron(),
electronDirection,
electronDirection,
electronKineEnergy);
aParticleChange.AddSecondary(particle1) ;
aParticleChange.AddSecondary(particle1) ;
}
else
{
localEnergyDeposit += electronKineEnergy ;
{
localEnergyDeposit += electronKineEnergy ;
}
// The e+ is always created (even with kinetic energy = 0) for further annihilation
G4double positronKineEnergy = G4std::max(0.,positronTotEnergy - electron_mass_c2) ;
// Is the local energy deposit correct, if the positron is always created?
if (! (rangeTest->Escape(G4Positron::Positron(),material,positronKineEnergy,safety)))
if (! (rangeTest->Escape(G4Positron::Positron(),couple,positronKineEnergy,safety)))
{
localEnergyDeposit += positronKineEnergy ;
positronKineEnergy = 0. ;
}
G4ThreeVector positronDirection(-dirX,-dirY,dirZ);
G4ThreeVector positronDirection (dxPos, dyPos, dzPos);
positronDirection.rotateUz(photonDirection);
// Create G4DynamicParticle object for the particle2
G4DynamicParticle* particle2 = new G4DynamicParticle(G4Positron::Positron(),
positronDirection, positronKineEnergy);
@@ -312,8 +315,8 @@ G4double G4LowEnergyGammaConversion::GetMeanFreePath(const G4Track& track,
{
const G4DynamicParticle* photon = track.GetDynamicParticle();
G4double energy = photon->GetKineticEnergy();
G4Material* material = track.GetMaterial();
size_t materialIndex = material->GetIndex();
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
size_t materialIndex = couple->GetIndex();
G4double meanFreePath;
if (energy > highEnergyLimit) meanFreePath = meanFreePathTable->FindValue(highEnergyLimit,materialIndex);
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4LowEnergyIonisation.cc,v 1.90 2002/10/28 09:43:49 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4LowEnergyIonisation.cc,v 1.93 2003/04/12 16:40:29 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// --------------------------------------------------------------
//
@@ -77,7 +77,7 @@
// 10.10.01 MGP Revision to improve code quality and
// consistency with design
// 18.10.01 V.Ivanchenko Add fluorescence AlongStepDoIt
// 18.10.01 MGP Revision to improve code quality and
// 18.10.01 MGP Revision to improve code quality and
// consistency with design
// 19.10.01 V.Ivanchenko update according to new design, V.Ivanchenko
// 26.10.01 V.Ivanchenko clean up deexcitation
@@ -86,12 +86,15 @@
// 25.03.02 V.Ivanchneko Fix in fluorescence
// 28.03.02 V.Ivanchenko Add flag of fluorescence
// 28.05.02 V.Ivanchenko Remove flag fStopAndKill
// 31.05.02 V.Ivanchenko Add path of Fluo + Auger cuts to
// 31.05.02 V.Ivanchenko Add path of Fluo + Auger cuts to
// AtomicDeexcitation
// 03.06.02 MGP Restore fStopAndKill
// 19.06.02 VI Additional printout
// 30.07.02 VI Fix in restricted energy loss
// 20.09.02 VI Remove ActivateFlurescence from SetCut...
// 21.01.03 VI Cut per region
// 12.02.03 VI Change signature for Deexcitation
// 12.04.03 V.Ivanchenko Cut per region for fluo AlongStep
//
// --------------------------------------------------------------
@@ -111,8 +114,7 @@
#include "G4UnitsTable.hh"
#include "G4Electron.hh"
#include "G4Gamma.hh"
#include "G4CutsPerMaterialWarning.hh"
#include "G4ProductionCutsTable.hh"
G4LowEnergyIonisation::G4LowEnergyIonisation(const G4String& nam)
: G4eLowEnergyLoss(nam),
@@ -142,9 +144,6 @@ void G4LowEnergyIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParti
G4cout << "G4LowEnergyIonisation::BuildPhysicsTable start"
<< G4endl;
}
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&aParticleType);
cutForDelta.clear();
@@ -164,19 +163,19 @@ void G4LowEnergyIonisation::BuildPhysicsTable(const G4ParticleDefinition& aParti
G4double lowKineticEnergy = GetLowerBoundEloss();
G4double highKineticEnergy = GetUpperBoundEloss();
G4int totBin = GetNbinEloss();
crossSectionHandler = new G4eIonisationCrossSectionHandler(energySpectrum,
crossSectionHandler = new G4eIonisationCrossSectionHandler(energySpectrum,
interpolation,
lowKineticEnergy,
lowKineticEnergy,
highKineticEnergy,
totBin);
crossSectionHandler->LoadShellData("ioni/ion-ss-cs-");
if (verboseLevel > 0) {
G4cout << GetProcessName()
<< " is created; Cross section data: "
G4cout << GetProcessName()
<< " is created; Cross section data: "
<< G4endl;
crossSectionHandler->PrintData();
G4cout << "Parameters: "
G4cout << "Parameters: "
<< G4endl;
energySpectrum->PrintData();
}
@@ -236,14 +235,15 @@ void G4LowEnergyIonisation::BuildLossTable(
size_t totBin = GetNbinEloss();
// create table
if (theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
const size_t numOfMaterials = G4Material::GetNumberOfMaterials();
theLossTable = new G4PhysicsTable(numOfMaterials);
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
theLossTable = new G4PhysicsTable(numOfCouples);
if (shellVacancy != 0) delete shellVacancy;
shellVacancy = new G4ShellVacancy();
@@ -261,38 +261,39 @@ void G4LowEnergyIonisation::BuildLossTable(
cutForDelta.clear();
// Loop for materials
for (size_t m=0; m<numOfMaterials; m++) {
for (size_t m=0; m<numOfCouples; m++) {
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(lowKineticEnergy,
highKineticEnergy,
totBin);
// get material parameters needed for the energy loss calculation
const G4Material* material= (*theMaterialTable)[m];
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(m);
const G4Material* material= couple->GetMaterial();
// the cut cannot be below lowest limit
G4double tCut = G4Electron::Electron()->GetEnergyThreshold(material);
G4double tCut = (*(theCoupleTable->GetEnergyCutsVector(1)))[m];
if(tCut > highKineticEnergy) tCut = highKineticEnergy;
cutForDelta.push_back(tCut);
const G4ElementVector* theElementVector = material->GetElementVector();
size_t NumberOfElements = material->GetNumberOfElements() ;
const G4double* theAtomicNumDensityVector =
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector();
if(verboseLevel > 0) {
G4cout << "Energy loss for material # " << m
<< " tCut(keV)= " << tCut/keV
<< G4endl;
}
// now comes the loop for the kinetic energy values
for (size_t i = 0; i<totBin; i++) {
G4double lowEdgeEnergy = aVector->GetLowEdgeEnergy(i);
G4double ionloss = 0.;
G4double ionloss = 0.;
// loop for elements in the material
for (size_t iel=0; iel<NumberOfElements; iel++ ) {
@@ -302,7 +303,7 @@ void G4LowEnergyIonisation::BuildLossTable(
for (G4int n=0; n<nShells; n++) {
G4double e = energySpectrum->AverageEnergy(Z, 0.0, tCut,
G4double e = energySpectrum->AverageEnergy(Z, 0.0, tCut,
lowEdgeEnergy, n);
G4double cs= crossSectionHandler->FindValue(Z, lowEdgeEnergy, n);
ionloss += e * cs * theAtomicNumDensityVector[iel];
@@ -319,9 +320,9 @@ void G4LowEnergyIonisation::BuildLossTable(
}
G4double esp = energySpectrum->Excitation(Z, lowEdgeEnergy);
ionloss += esp * theAtomicNumDensityVector[iel];
}
}
if(verboseLevel > 1 || (m == 0 && lowEdgeEnergy>=1. && lowEdgeEnergy<=0.)) {
G4cout << "Sum: "
G4cout << "Sum: "
<< " E(keV)= " << lowEdgeEnergy/keV
<< " loss(MeV/mm)= " << ionloss*mm/MeV
<< G4endl;
@@ -349,9 +350,9 @@ void G4LowEnergyIonisation::BuildLossTable(
for (G4int n=0; n<nShells; n++) {
G4double e = energySpectrum->AverageEnergy(Z, 0.0, tCut,
G4double e = energySpectrum->AverageEnergy(Z, 0.0, tCut,
lowEdgeEnergy, n);
G4double pro = energySpectrum->Probability(Z, 0.0, tCut,
G4double pro = energySpectrum->Probability(Z, 0.0, tCut,
lowEdgeEnergy, n);
G4double cs= crossSectionHandler->FindValue(Z, lowEdgeEnergy, n);
eAverage += e * cs * theAtomicNumDensityVector[iel];
@@ -389,7 +390,7 @@ void G4LowEnergyIonisation::BuildLossTable(
xsis->AddComponent(set);
}
if(verboseLevel) xsis->PrintData();
shellVacancy->AddXsiTable(xsis);
shellVacancy->AddXsiTable(xsis);
}
delete bVector;
}
@@ -399,50 +400,50 @@ G4VParticleChange* G4LowEnergyIonisation::PostStepDoIt(const G4Track& track,
const G4Step& step)
{
// Delta electron production mechanism on base of the model
// J. Stepanek " A program to determine the radiation spectra due
// to a single atomic subshell ionisation by a particle or due to
// deexcitation or decay of radionuclides",
// J. Stepanek " A program to determine the radiation spectra due
// to a single atomic subshell ionisation by a particle or due to
// deexcitation or decay of radionuclides",
// Comp. Phys. Comm. 1206 pp 1-19 (1997)
aParticleChange.Initialize(track);
const G4Material* material = track.GetMaterial();
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
G4double kineticEnergy = track.GetKineticEnergy();
// Select atom and shell
G4int Z = crossSectionHandler->SelectRandomAtom(material, kineticEnergy);
G4int Z = crossSectionHandler->SelectRandomAtom(couple, kineticEnergy);
G4int shell = crossSectionHandler->SelectRandomShell(Z, kineticEnergy);
const G4AtomicShell* atomicShell =
const G4AtomicShell* atomicShell =
(G4AtomicTransitionManager::Instance())->Shell(Z, shell);
G4double bindingEnergy = atomicShell->BindingEnergy();
G4int shellId = atomicShell->ShellId();
// Sample delta energy
G4int index = material->GetIndex();
G4int index = couple->GetIndex();
G4double tCut = cutForDelta[index];
G4double tmax = energySpectrum->MaxEnergyOfSecondaries(kineticEnergy);
G4double tDelta = energySpectrum->SampleEnergy(Z, tCut, tmax,
G4double tDelta = energySpectrum->SampleEnergy(Z, tCut, tmax,
kineticEnergy, shell);
if(tDelta == 0.0)
if(tDelta == 0.0)
return G4VContinuousDiscreteProcess::PostStepDoIt(track, step);
// Transform to shell potential
G4double deltaKinE = tDelta + 2.0*bindingEnergy;
G4double primaryKinE = kineticEnergy + 2.0*bindingEnergy;
G4double deltaKinE = tDelta + 2.0*bindingEnergy;
G4double primaryKinE = kineticEnergy + 2.0*bindingEnergy;
// sampling of scattering angle neglecting atomic motion
G4double deltaMom = sqrt(deltaKinE*(deltaKinE + 2.0*electron_mass_c2));
G4double primaryMom = sqrt(primaryKinE*(primaryKinE + 2.0*electron_mass_c2));
G4double cost = deltaKinE * (primaryKinE + 2.0*electron_mass_c2)
/ (deltaMom * primaryMom);
if (cost > 1.) cost = 1.;
G4double sint = sqrt(1. - cost*cost);
G4double phi = twopi * G4UniformRand();
G4double phi = twopi * G4UniformRand();
G4double dirx = sint * cos(phi);
G4double diry = sint * sin(phi);
G4double dirz = cost;
@@ -461,7 +462,7 @@ G4VParticleChange* G4LowEnergyIonisation::PostStepDoIt(const G4Track& track,
cost = 2.0*G4UniformRand() - 1.0;
sint = sqrt(1. - cost*cost);
phi = twopi * G4UniformRand();
phi = twopi * G4UniformRand();
G4double del = sqrt(bindingEnergy *(bindingEnergy + 2.0*electron_mass_c2))
/ deltaMom;
dirx += del* sint * cos(phi);
@@ -469,9 +470,9 @@ G4VParticleChange* G4LowEnergyIonisation::PostStepDoIt(const G4Track& track,
dirz += del* cost;
// Find out new primary electron direction
G4double finalPx = primaryMom*primaryDirection.x() - deltaMom*dirx;
G4double finalPy = primaryMom*primaryDirection.y() - deltaMom*diry;
G4double finalPz = primaryMom*primaryDirection.z() - deltaMom*dirz;
G4double finalPx = primaryMom*primaryDirection.x() - deltaMom*dirx;
G4double finalPy = primaryMom*primaryDirection.y() - deltaMom*diry;
G4double finalPz = primaryMom*primaryDirection.z() - deltaMom*dirz;
// create G4DynamicParticle object for delta ray
G4DynamicParticle* theDeltaRay = new G4DynamicParticle();
@@ -480,19 +481,19 @@ G4VParticleChange* G4LowEnergyIonisation::PostStepDoIt(const G4Track& track,
dirx *= norm;
diry *= norm;
dirz *= norm;
theDeltaRay->SetMomentumDirection(dirx, diry, dirz);
theDeltaRay->SetMomentumDirection(dirx, diry, dirz);
theDeltaRay->SetDefinition(G4Electron::Electron());
G4double theEnergyDeposit = bindingEnergy;
// fill ParticleChange
// fill ParticleChange
// changed energy and momentum of the actual particle
G4double finalKinEnergy = kineticEnergy - tDelta - theEnergyDeposit;
if(finalKinEnergy < 0.0) {
theEnergyDeposit += finalKinEnergy;
finalKinEnergy = 0.0;
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetStatusChange(fStopAndKill);
} else {
@@ -511,10 +512,10 @@ G4VParticleChange* G4LowEnergyIonisation::PostStepDoIt(const G4Track& track,
G4std::vector<G4DynamicParticle*>* secondaryVector = 0;
G4DynamicParticle* aSecondary = 0;
G4ParticleDefinition* type = 0;
// Fluorescence data start from element 6
if (Fluorescence() && Z > 5 && (bindingEnergy >= cutForPhotons
if (Fluorescence() && Z > 5 && (bindingEnergy >= cutForPhotons
|| bindingEnergy >= cutForElectrons)) {
secondaryVector = deexcitationManager.GenerateParticles(Z, shellId);
@@ -526,11 +527,11 @@ G4VParticleChange* G4LowEnergyIonisation::PostStepDoIt(const G4Track& track,
aSecondary = (*secondaryVector)[i];
if (aSecondary) {
G4double e = aSecondary->GetKineticEnergy();
type = aSecondary->GetDefinition();
if (e < theEnergyDeposit &&
((type == G4Gamma::Gamma() && e > cutForPhotons ) ||
if (e < theEnergyDeposit &&
((type == G4Gamma::Gamma() && e > cutForPhotons ) ||
(type == G4Electron::Electron() && e > cutForElectrons ))) {
theEnergyDeposit -= e;
@@ -545,14 +546,14 @@ G4VParticleChange* G4LowEnergyIonisation::PostStepDoIt(const G4Track& track,
}
}
}
// Save delta-electrons
aParticleChange.SetNumberOfSecondaries(totalNumber);
aParticleChange.AddSecondary(theDeltaRay);
// Save Fluorescence and Auger
if (secondaryVector) {
for (size_t l = 0; l < nSecondaries; l++) {
@@ -562,13 +563,13 @@ G4VParticleChange* G4LowEnergyIonisation::PostStepDoIt(const G4Track& track,
if(aSecondary) {
aParticleChange.AddSecondary(aSecondary);
}
}
}
delete secondaryVector;
}
if(theEnergyDeposit < 0.) {
G4cout << "G4LowEnergyIonisation: Negative energy deposit: "
G4cout << "G4LowEnergyIonisation: Negative energy deposit: "
<< theEnergyDeposit/eV << " eV" << G4endl;
theEnergyDeposit = 0.0;
}
@@ -582,97 +583,98 @@ void G4LowEnergyIonisation::PrintInfoDefinition()
{
G4String comments = "Total cross sections from EEDL database.";
comments += "\n Gamma energy sampled from a parametrised formula.";
comments += "\n Implementation of the continuous dE/dx part.";
comments += "\n Implementation of the continuous dE/dx part.";
comments += "\n At present it can be used for electrons ";
comments += "in the energy range [250eV,100GeV].";
comments += "\n The process must work with G4LowEnergyBremsstrahlung.";
G4cout << G4endl << GetProcessName() << ": " << comments << G4endl;
}
}
G4bool G4LowEnergyIonisation::IsApplicable(const G4ParticleDefinition& particle)
{
return ( (&particle == G4Electron::Electron()) );
}
G4std::vector<G4DynamicParticle*>*
G4LowEnergyIonisation::DeexciteAtom(const G4Material* material,
G4std::vector<G4DynamicParticle*>*
G4LowEnergyIonisation::DeexciteAtom(const G4MaterialCutsCouple* couple,
G4double incidentEnergy,
G4double eLoss)
{
{
// create vector of secondary particles
G4std::vector<G4DynamicParticle*>* partVector =
const G4Material* material = couple->GetMaterial();
G4std::vector<G4DynamicParticle*>* partVector =
new G4std::vector<G4DynamicParticle*>;
if(eLoss > cutForPhotons && eLoss > cutForElectrons) {
const G4AtomicTransitionManager* transitionManager =
const G4AtomicTransitionManager* transitionManager =
G4AtomicTransitionManager::Instance();
size_t nElements = material->GetNumberOfElements();
const G4ElementVector* theElementVector = material->GetElementVector();
G4std::vector<G4DynamicParticle*>* secVector = 0;
G4std::vector<G4DynamicParticle*>* secVector = 0;
G4DynamicParticle* aSecondary = 0;
G4ParticleDefinition* type = 0;
G4double e;
G4ThreeVector position;
G4int shell, shellId;
// sample secondaries
G4double eTot = 0.0;
G4std::vector<G4int> n =
shellVacancy->GenerateNumberOfIonisations(material,
G4double eTot = 0.0;
G4std::vector<G4int> n =
shellVacancy->GenerateNumberOfIonisations(couple,
incidentEnergy,eLoss);
for (size_t i=0; i<nElements; i++) {
G4int Z = (G4int)((*theElementVector)[i]->GetZ());
size_t nVacancies = n[i];
G4double maxE = transitionManager->Shell(Z, 0)->BindingEnergy();
if (nVacancies && Z > 5 && (maxE>cutForPhotons || maxE>cutForElectrons)) {
for (size_t j=0; j<nVacancies; j++) {
shell = crossSectionHandler->SelectRandomShell(Z, incidentEnergy);
shellId = transitionManager->Shell(Z, shell)->ShellId();
G4double maxEShell =
G4double maxEShell =
transitionManager->Shell(Z, shell)->BindingEnergy();
if (maxEShell>cutForPhotons || maxEShell>cutForElectrons ) {
secVector = deexcitationManager.GenerateParticles(Z, shellId);
if (secVector != 0) {
if (secVector != 0) {
for (size_t l = 0; l<secVector->size(); l++) {
aSecondary = (*secVector)[l];
if (aSecondary != 0) {
e = aSecondary->GetKineticEnergy();
type = aSecondary->GetDefinition();
if ( eTot + e <= eLoss &&
(type == G4Gamma::Gamma() && e>cutForPhotons ) ||
(type == G4Gamma::Gamma() && e>cutForPhotons ) ||
(type == G4Electron::Electron() && e>cutForElectrons)) {
eTot += e;
eTot += e;
partVector->push_back(aSecondary);
} else {
delete aSecondary;
}
}
}
delete secVector;
}
}
}
}
}
}
}
}
}
@@ -684,17 +686,17 @@ G4double G4LowEnergyIonisation::GetMeanFreePath(const G4Track& track,
G4ForceCondition* cond)
{
*cond = NotForced;
G4int index = (track.GetMaterial())->GetIndex();
G4int index = (track.GetMaterialCutsCouple())->GetIndex();
const G4VEMDataSet* data = theMeanFreePath->GetComponent(index);
G4double meanFreePath = data->FindValue(track.GetKineticEnergy());
return meanFreePath;
}
return meanFreePath;
}
void G4LowEnergyIonisation::SetCutForLowEnSecPhotons(G4double cut)
{
cutForPhotons = cut;
deexcitationManager.SetCutForSecondaryPhotons(cut);
}
}
void G4LowEnergyIonisation::SetCutForLowEnSecElectrons(G4double cut)
{
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4LowEnergyPhotoElectric.cc,v 1.48 2002/06/14 17:39:09 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4LowEnergyPhotoElectric.cc,v 1.49 2003/01/22 18:47:28 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: A. Forti
// Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
@@ -52,10 +52,11 @@
// 06.10.2001 MGP Added protection to avoid negative electron energies
// when binding energy of selected shell > photon energy
// 18.04.2001 V.Ivanchenko Fix problem with low energy gammas from fluorescence
// MeanFreePath is calculated by crosSectionHandler directly
// MeanFreePath is calculated by crosSectionHandler directly
// 31.05.2002 V.Ivanchenko Add path of Fluo + Auger cuts to AtomicDeexcitation
// 14.06.2002 V.Ivanchenko By default do not cheak range of e-
//
// 21.01.2003 V.Ivanchenko Cut per region
//
// --------------------------------------------------------------
#include "G4LowEnergyPhotoElectric.hh"
@@ -79,8 +80,7 @@
#include "G4RangeNoTest.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4AtomicShell.hh"
#include "G4CutsPerMaterialWarning.hh"
#include "G4ProductionCutsTable.hh"
G4LowEnergyPhotoElectric::G4LowEnergyPhotoElectric(const G4String& processName)
: G4VDiscreteProcess(processName), lowEnergyLimit(250*eV), highEnergyLimit(100*GeV),
@@ -100,12 +100,12 @@ G4LowEnergyPhotoElectric::G4LowEnergyPhotoElectric(const G4String& processName)
meanFreePathTable = 0;
rangeTest = new G4RangeNoTest;
if (verboseLevel > 0)
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / GeV << " GeV"
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
@@ -120,9 +120,6 @@ G4LowEnergyPhotoElectric::~G4LowEnergyPhotoElectric()
void G4LowEnergyPhotoElectric::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&photon);
crossSectionHandler->Clear();
G4String crossSectionFile = "phot/pe-cs-";
@@ -136,11 +133,11 @@ void G4LowEnergyPhotoElectric::BuildPhysicsTable(const G4ParticleDefinition& pho
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
}
G4VParticleChange* G4LowEnergyPhotoElectric::PostStepDoIt(const G4Track& aTrack,
G4VParticleChange* G4LowEnergyPhotoElectric::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
// Fluorescence generated according to:
// J. Stepanek ,"A program to determine the radiation spectra due to a single atomic
// J. Stepanek ,"A program to determine the radiation spectra due to a single atomic
// subshell ionisation by a particle or due to deexcitation or decay of radionuclides",
// Comp. Phys. Comm. 1206 pp 1-1-9 (1997)
@@ -157,10 +154,10 @@ G4VParticleChange* G4LowEnergyPhotoElectric::PostStepDoIt(const G4Track& aTrack,
}
G4ParticleMomentum photonDirection = incidentPhoton->GetMomentumDirection();
// Select randomly one element in the current material
G4Material* material = aTrack.GetMaterial();
G4int Z = crossSectionHandler->SelectRandomAtom(material,photonEnergy);
const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
G4int Z = crossSectionHandler->SelectRandomAtom(couple,photonEnergy);
// Select the ionised shell in the current atom according to shell cross sections
size_t shellIndex = shellCrossSectionHandler->SelectRandomShell(Z,photonEnergy);
@@ -188,17 +185,17 @@ G4VParticleChange* G4LowEnergyPhotoElectric::PostStepDoIt(const G4Track& aTrack,
// Generate the electron only if with large enough range w.r.t. cuts and safety
G4double safety = aStep.GetPostStepPoint()->GetSafety();
if (rangeTest->Escape(G4Electron::Electron(),material,eKineticEnergy,safety))
if (rangeTest->Escape(G4Electron::Electron(),couple,eKineticEnergy,safety))
{
// The electron is created in the direction of the incident photon ...
G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),
photonDirection,
// The electron is created in the direction of the incident photon ...
G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),
photonDirection,
eKineticEnergy);
electronVector.push_back(electron);
}
else
}
else
{
energyDeposit += eKineticEnergy;
energyDeposit += eKineticEnergy;
}
}
else
@@ -209,19 +206,25 @@ G4VParticleChange* G4LowEnergyPhotoElectric::PostStepDoIt(const G4Track& aTrack,
G4int nElectrons = electronVector.size();
size_t nTotPhotons = 0;
G4int nPhotons=0;
G4double cutg = G4std::min(cutForLowEnergySecondaryPhotons,
G4Gamma::Gamma()->GetEnergyThreshold(material));
G4double cute = G4std::min(cutForLowEnergySecondaryElectrons,
G4Electron::Electron()->GetEnergyThreshold(material));
G4DynamicParticle* aPhoton;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t index = couple->GetIndex();
G4double cutg = (*(theCoupleTable->GetEnergyCutsVector(0)))[index];
cutg = G4std::min(cutForLowEnergySecondaryPhotons,cutg);
G4double cute = (*(theCoupleTable->GetEnergyCutsVector(1)))[index];
cute = G4std::min(cutForLowEnergySecondaryPhotons,cute);
G4DynamicParticle* aPhoton;
// Generation of fluorescence
// Data in EADL are available only for Z > 5
// Protection to avoid generating photons in the unphysical case of
// Protection to avoid generating photons in the unphysical case of
// shell binding energy > photon energy
if (Z > 5 && (bindingEnergy > cutg || bindingEnergy > cute))
{
photonVector = deexcitationManager.GenerateParticles(Z,shellId);
photonVector = deexcitationManager.GenerateParticles(Z,shellId);
nTotPhotons = photonVector->size();
for (size_t k=0; k<nTotPhotons; k++)
{
@@ -235,15 +238,15 @@ G4VParticleChange* G4LowEnergyPhotoElectric::PostStepDoIt(const G4Track& aTrack,
if (itsEnergy > itsCut && itsEnergy <= bindingEnergy)
{
nPhotons++;
// Local energy deposit is given as the sum of the
// Local energy deposit is given as the sum of the
// energies of incident photons minus the energies
// of the outcoming fluorescence photons
bindingEnergy -= itsEnergy;
}
else
{
delete aPhoton;
{
delete aPhoton;
(*photonVector)[k] = 0;
}
}
@@ -262,16 +265,16 @@ G4VParticleChange* G4LowEnergyPhotoElectric::PostStepDoIt(const G4Track& aTrack,
aParticleChange.AddSecondary(aPhoton);
}
}
for ( size_t ll = 0; ll < nTotPhotons; ll++)
for ( size_t ll = 0; ll < nTotPhotons; ll++)
{
aPhoton = (*photonVector)[ll];
if(aPhoton) {
aParticleChange.AddSecondary(aPhoton);
}
}
}
delete photonVector;
if (energyDeposit < 0)
{
G4cout << "WARNING - "
@@ -279,25 +282,25 @@ G4VParticleChange* G4LowEnergyPhotoElectric::PostStepDoIt(const G4Track& aTrack,
<< G4endl;
energyDeposit = 0;
}
// Kill the incident photon
// Kill the incident photon
aParticleChange.SetMomentumChange( 0., 0., 0. );
aParticleChange.SetEnergyChange( 0. );
aParticleChange.SetLocalEnergyDeposit(energyDeposit);
aParticleChange.SetStatusChange( fStopAndKill );
aParticleChange.SetLocalEnergyDeposit(energyDeposit);
aParticleChange.SetStatusChange( fStopAndKill );
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep );
}
G4bool G4LowEnergyPhotoElectric::IsApplicable(const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
return ( &particle == G4Gamma::Gamma() );
}
G4double G4LowEnergyPhotoElectric::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4double G4LowEnergyPhotoElectric::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition*)
{
const G4DynamicParticle* photon = track.GetDynamicParticle();
@@ -334,10 +337,3 @@ void G4LowEnergyPhotoElectric::ActivateAuger(G4bool val)
{
deexcitationManager.ActivateAugerElectronProduction(val);
}
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4LowEnergyPolarizedCompton.cc,v 1.13 2002/06/02 21:27:52 pia Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4LowEnergyPolarizedCompton.cc,v 1.15 2003/04/24 14:19:37 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// ------------------------------------------------------------
// GEANT 4 class implementation file
@@ -44,12 +44,14 @@
// 21 February 2002 - F.Longo Revisions with A.Zoglauer and G.Depaola
// - better description of parallelism
// - system of ref change method improved
// 22 January 2003 - V.Ivanchenko Cut per region
// 24 April 2003 - V.Ivanchenko Cut per region mfpt
//
//
// ************************************************************
//
// Corrections by Rui Curado da Silva (2000)
// New Implementation by G.Depaola & F.Longo
// New Implementation by G.Depaola & F.Longo
//
// - sampling of phi
// - polarization of scattered photon
@@ -75,8 +77,7 @@
#include "G4LogLogInterpolation.hh"
#include "G4VRangeTest.hh"
#include "G4RangeTest.hh"
#include "G4CutsPerMaterialWarning.hh"
#include "G4MaterialCutsCouple.hh"
// constructor
@@ -87,30 +88,30 @@ G4LowEnergyPolarizedCompton::G4LowEnergyPolarizedCompton(const G4String& process
intrinsicLowEnergyLimit(10*eV),
intrinsicHighEnergyLimit(100*GeV)
{
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
highEnergyLimit > intrinsicHighEnergyLimit)
{
G4Exception("G4LowEnergyPolarizedCompton::G4LowEnergyPolarizedCompton - energy outside intrinsic process validity range");
}
crossSectionHandler = new G4CrossSectionHandler;
G4VDataSetAlgorithm* scatterInterpolation = new G4LogLogInterpolation;
G4String scatterFile = "comp/ce-sf-";
scatterFunctionData = new
scatterFunctionData = new
G4CompositeEMDataSet(scatterFile,scatterInterpolation,1.,1.);
meanFreePathTable = 0;
rangeTest = new G4RangeTest;
if (verboseLevel > 0)
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / GeV << " GeV"
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
@@ -124,13 +125,10 @@ G4LowEnergyPolarizedCompton::~G4LowEnergyPolarizedCompton()
delete scatterFunctionData;
delete rangeTest;
}
void G4LowEnergyPolarizedCompton::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&photon);
crossSectionHandler->Clear();
G4String crossSectionFile = "comp/ce-cs-";
@@ -150,26 +148,26 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
aParticleChange.Initialize(aTrack);
// Dynamic particle quantities
// Dynamic particle quantities
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double gammaEnergy0 = incidentPhoton->GetKineticEnergy();
G4ThreeVector gammaPolarization0 = incidentPhoton->GetPolarization();
G4ThreeVector gammaPolarization0 = incidentPhoton->GetPolarization();
// gammaPolarization0 = gammaPolarization0.unit(); //
// gammaPolarization0 = gammaPolarization0.unit(); //
// Protection: a polarisation parallel to the
// direction causes problems;
// Protection: a polarisation parallel to the
// direction causes problems;
// in that case find a random polarization
G4ThreeVector gammaDirection0 = incidentPhoton->GetMomentumDirection();
// ---- MGP ---- Next two lines commented out to remove compilation warnings
// G4double scalarproduct = gammaPolarization0.dot(gammaDirection0);
// G4double angle = gammaPolarization0.angle(gammaDirection0);
// Make sure that the polarization vector is perpendicular to the
// gamma direction. If not
if(!(gammaPolarization0.isOrthogonal(gammaDirection0, 1e-6))||(gammaPolarization0.mag()==0))
// Make sure that the polarization vector is perpendicular to the
// gamma direction. If not
if(!(gammaPolarization0.isOrthogonal(gammaDirection0, 1e-6))||(gammaPolarization0.mag()==0))
{ // only for testing now
gammaPolarization0 = GetRandomPolarization(gammaDirection0);
}
@@ -184,7 +182,7 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
// End of Protection
// Within energy limit?
if(gammaEnergy0 <= lowEnergyLimit)
{
aParticleChange.SetStatusChange(fStopAndKill);
@@ -192,18 +190,18 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
aParticleChange.SetLocalEnergyDeposit(gammaEnergy0);
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
G4double E0_m = gammaEnergy0 / electron_mass_c2 ;
// Select randomly one element in the current material
G4Material* material = aTrack.GetMaterial();
G4int Z = crossSectionHandler->SelectRandomAtom(material,gammaEnergy0);
// Sample the energy and the polarization of the scattered photon
const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
G4int Z = crossSectionHandler->SelectRandomAtom(couple,gammaEnergy0);
// Sample the energy and the polarization of the scattered photon
G4double epsilon, epsilonSq, onecost, sinThetaSqr, greject ;
G4double epsilon0 = 1./(1. + 2*E0_m);
G4double epsilon0Sq = epsilon0*epsilon0;
G4double alpha1 = - log(epsilon0);
@@ -212,10 +210,10 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
G4double wlGamma = h_Planck*c_light/gammaEnergy0;
G4double gammaEnergy1;
G4ThreeVector gammaDirection1;
do {
if ( alpha1/(alpha1+alpha2) > G4UniformRand() )
{
{
epsilon = exp(-alpha1*G4UniformRand());
epsilonSq = epsilon*epsilon;
}
@@ -224,28 +222,28 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
epsilonSq = epsilon0Sq + (1.- epsilon0Sq)*G4UniformRand();
epsilon = sqrt(epsilonSq);
}
onecost = (1.- epsilon)/(epsilon*E0_m);
sinThetaSqr = onecost*(2.-onecost);
// Protection
if (sinThetaSqr > 1.)
{
if (verboseLevel>0) G4cout
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "sin(theta)**2 = "
<< "sin(theta)**2 = "
<< sinThetaSqr
<< "; set to 1"
<< "; set to 1"
<< G4endl;
sinThetaSqr = 1.;
}
if (sinThetaSqr < 0.)
{
if (verboseLevel>0) G4cout
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "sin(theta)**2 = "
<< "sin(theta)**2 = "
<< sinThetaSqr
<< "; set to 0"
<< "; set to 0"
<< G4endl;
sinThetaSqr = 0.;
}
@@ -253,32 +251,32 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
G4double x = sqrt(onecost/2.) / (wlGamma/cm);;
G4double scatteringFunction = scatterFunctionData->FindValue(x,Z-1);
greject = (1. - epsilon*sinThetaSqr/(1.+ epsilonSq))*scatteringFunction;
greject = (1. - epsilon*sinThetaSqr/(1.+ epsilonSq))*scatteringFunction;
} while(greject < G4UniformRand()*Z);
// ****************************************************
// Phi determination
// ****************************************************
G4double phi = SetPhi(epsilon,sinThetaSqr);
//
// scattered gamma angles. ( Z - axis along the parent gamma)
//
G4double cosTheta = 1. - onecost;
// Protection
if (cosTheta > 1.)
{
if (verboseLevel>0) G4cout
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "cosTheta = "
<< "cosTheta = "
<< cosTheta
<< "; set to 1"
<< "; set to 1"
<< G4endl;
cosTheta = 1.;
}
@@ -288,7 +286,7 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "cosTheta = "
<< cosTheta
<< "; set to -1"
<< "; set to -1"
<< G4endl;
cosTheta = -1.;
}
@@ -304,7 +302,7 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "sinTheta = "
<< sinTheta
<< "; set to 1"
<< "; set to 1"
<< G4endl;
sinTheta = 1.;
}
@@ -328,25 +326,25 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
//
// update G4VParticleChange for the scattered photon
//
gammaEnergy1 = epsilon*gammaEnergy0;
// New polarization
G4ThreeVector gammaPolarization1 = SetNewPolarization(epsilon,
sinThetaSqr,
phi,
cosTheta);
// Set new direction
// Set new direction
G4ThreeVector tmpDirection1( dirx,diry,dirz );
gammaDirection1 = tmpDirection1;
// Change reference frame.
SystemOfRefChange(gammaDirection0,gammaDirection1,
gammaPolarization0,gammaPolarization1);
gammaPolarization0,gammaPolarization1);
if (gammaEnergy1 > 0.)
{
aParticleChange.SetEnergyChange( gammaEnergy1 ) ;
@@ -354,26 +352,26 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
aParticleChange.SetPolarizationChange( gammaPolarization1 );
}
else
{
{
aParticleChange.SetEnergyChange(0.) ;
aParticleChange.SetStatusChange(fStopAndKill);
}
//
// kinematic of the scattered electron
//
G4double ElecKineEnergy = gammaEnergy0 - gammaEnergy1 ;
// Generate the electron only if with large enough range w.r.t. cuts and safety
G4double safety = aStep.GetPostStepPoint()->GetSafety();
if (rangeTest->Escape(G4Electron::Electron(),material,ElecKineEnergy,safety))
if (rangeTest->Escape(G4Electron::Electron(),couple,ElecKineEnergy,safety))
{
G4double ElecMomentum = sqrt(ElecKineEnergy*(ElecKineEnergy+2.*electron_mass_c2));
G4ThreeVector ElecDirection((gammaEnergy0 * gammaDirection0 -
gammaEnergy1 * gammaDirection1) * (1./ElecMomentum));
G4ThreeVector ElecDirection((gammaEnergy0 * gammaDirection0 -
gammaEnergy1 * gammaDirection1) * (1./ElecMomentum));
G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),ElecDirection.unit(),ElecKineEnergy) ;
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(electron);
@@ -398,7 +396,7 @@ G4double G4LowEnergyPolarizedCompton::SetPhi(G4double energyRate,
G4double phiProbability;
G4double phi;
G4double a, b;
do
{
rand1 = G4UniformRand();
@@ -476,7 +474,7 @@ G4ThreeVector G4LowEnergyPolarizedCompton::GetPerpendicularPolarization
}
G4ThreeVector G4LowEnergyPolarizedCompton::SetNewPolarization(G4double epsilon,
G4ThreeVector G4LowEnergyPolarizedCompton::SetNewPolarization(G4double epsilon,
G4double sinSqrTh,
G4double phi,
G4double costheta)
@@ -508,7 +506,7 @@ G4ThreeVector G4LowEnergyPolarizedCompton::SetNewPolarization(G4double epsilon,
a = 4*normalisation*normalisation;
b = (epsilon + 1/epsilon) - 2;
thetaProbability = (b + a*cos(theta)*cos(theta))/(a+b);
cosTheta = cos(theta);
cosTheta = cos(theta);
}
while ( rand2 > thetaProbability );
@@ -516,14 +514,14 @@ G4ThreeVector G4LowEnergyPolarizedCompton::SetNewPolarization(G4double epsilon,
G4double sinBeta = sqrt(1-cosBeta*cosBeta);
G4ThreeVector gammaPolarization1;
G4double xParallel = normalisation*cosBeta;
G4double yParallel = -(sinSqrTh*cosPhi*sinPhi)*cosBeta/normalisation;
G4double zParallel = -(costheta*sinTheta*cosPhi)*cosBeta/normalisation;
G4double xPerpendicular = 0.;
G4double yPerpendicular = (costheta)*sinBeta/normalisation;
G4double zPerpendicular = -(sinTheta*sinPhi)*sinBeta/normalisation;
G4double xTotal = (xParallel + xPerpendicular);
G4double yTotal = (yParallel + yPerpendicular);
G4double zTotal = (zParallel + zPerpendicular);
@@ -558,7 +556,7 @@ void G4LowEnergyPolarizedCompton::SystemOfRefChange
G4double polarization_x = polarization1.getX();
G4double polarization_y = polarization1.getY();
G4double polarization_z = polarization1.getZ();
polarization1 =(polarization_x*Axis_X0+polarization_y*Axis_Y0+polarization_z*Axis_Z0).unit();
}
@@ -570,14 +568,14 @@ G4bool G4LowEnergyPolarizedCompton::IsApplicable(const G4ParticleDefinition& par
}
G4double G4LowEnergyPolarizedCompton::GetMeanFreePath(const G4Track& track,
G4double G4LowEnergyPolarizedCompton::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition*)
{
const G4DynamicParticle* photon = track.GetDynamicParticle();
G4double energy = photon->GetKineticEnergy();
G4Material* material = track.GetMaterial();
size_t materialIndex = material->GetIndex();
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
size_t materialIndex = couple->GetIndex();
G4double meanFreePath;
if (energy > highEnergyLimit) meanFreePath = meanFreePathTable->FindValue(highEnergyLimit,materialIndex);
else if (energy < lowEnergyLimit) meanFreePath = DBL_MAX;
@@ -22,24 +22,26 @@
//
// --------------------------------------------------------------------
//
// $Id: G4LowEnergyRayleigh.cc,v 1.30 2002/11/08 07:59:05 flongo Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4LowEnergyRayleigh.cc,v 1.32 2003/04/24 14:19:37 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: A. Forti
// Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// --------
// --------
// Added Livermore data table construction methods A. Forti
// Added BuildMeanFreePath A. Forti
// Added PostStepDoIt A. Forti
// Added SelectRandomAtom A. Forti
// Added map of the elements A.Forti
// 24.04.01 V.Ivanchenko remove RogueWave
// 24.04.01 V.Ivanchenko remove RogueWave
// 11.08.2001 MGP - Major revision according to a design iteration
// 06.10.2001 MGP - Added strategy to test range for secondary generation
// 05.06.2002 F.Longo and G.Depaola - bug fixed in angular distribution
// 20.10.2002 G. Depaola - Change sampling method of theta
// 20.10.2002 G. Depaola - Change sampling method of theta
// 22.01.2003 V.Ivanchenko - Cut per region
// 24.04.2003 V.Ivanchenko - Cut per region mfpt
//
// --------------------------------------------------------------------
@@ -61,21 +63,21 @@
#include "G4VDataSetAlgorithm.hh"
#include "G4LogLogInterpolation.hh"
#include "G4CutsPerMaterialWarning.hh"
#include "G4MaterialCutsCouple.hh"
G4LowEnergyRayleigh::G4LowEnergyRayleigh(const G4String& processName)
: G4VDiscreteProcess(processName),
lowEnergyLimit(250*eV),
lowEnergyLimit(250*eV),
highEnergyLimit(100*GeV),
intrinsicLowEnergyLimit(10*eV),
intrinsicHighEnergyLimit(100*GeV)
{
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
highEnergyLimit > intrinsicHighEnergyLimit)
{
G4Exception("G4LowEnergyRayleigh::G4LowEnergyRayleigh - energy limit outside intrinsic process validity range");
}
crossSectionHandler = new G4CrossSectionHandler();
G4VDataSetAlgorithm* ffInterpolation = new G4LogLogInterpolation;
@@ -84,16 +86,16 @@ G4LowEnergyRayleigh::G4LowEnergyRayleigh(const G4String& processName)
meanFreePathTable = 0;
if (verboseLevel > 0)
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / GeV << " GeV"
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
G4LowEnergyRayleigh::~G4LowEnergyRayleigh()
{
delete meanFreePathTable;
@@ -103,9 +105,6 @@ G4LowEnergyRayleigh::~G4LowEnergyRayleigh()
void G4LowEnergyRayleigh::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&photon);
crossSectionHandler->Clear();
G4String crossSectionFile = "rayl/re-cs-";
@@ -115,7 +114,7 @@ void G4LowEnergyRayleigh::BuildPhysicsTable(const G4ParticleDefinition& photon)
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
}
G4VParticleChange* G4LowEnergyRayleigh::PostStepDoIt(const G4Track& aTrack,
G4VParticleChange* G4LowEnergyRayleigh::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
@@ -123,7 +122,7 @@ G4VParticleChange* G4LowEnergyRayleigh::PostStepDoIt(const G4Track& aTrack,
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double photonEnergy0 = incidentPhoton->GetKineticEnergy();
if (photonEnergy0 <= lowEnergyLimit)
{
aParticleChange.SetStatusChange(fStopAndKill);
@@ -136,10 +135,10 @@ G4VParticleChange* G4LowEnergyRayleigh::PostStepDoIt(const G4Track& aTrack,
G4ParticleMomentum photonDirection0 = incidentPhoton->GetMomentumDirection();
// Select randomly one element in the current material
G4Material* material = aTrack.GetMaterial();
G4int Z = crossSectionHandler->SelectRandomAtom(material,photonEnergy0);
// Sample the angle of the scattered photon
const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
G4int Z = crossSectionHandler->SelectRandomAtom(couple,photonEnergy0);
// Sample the angle of the scattered photon
G4double wlPhoton = h_Planck*c_light/photonEnergy0;
@@ -159,14 +158,14 @@ G4VParticleChange* G4LowEnergyRayleigh::PostStepDoIt(const G4Track& aTrack,
G4double sinThetaHalf = sqrt((1. - cosTheta) / 2.);
x = sinThetaHalf / (wlPhoton/cm);
if (x > 1.e+005)
if (x > 1.e+005)
dataFormFactor = formFactorData->FindValue(x,Z-1);
else
dataFormFactor = formFactorData->FindValue(0.,Z-1);
randomFormFactor = G4UniformRand() * Z * Z;
sinTheta = sqrt(1. - cosTheta*cosTheta);
gReject = dataFormFactor * dataFormFactor;
} while( gReject < randomFormFactor);
// Scattered photon angles. ( Z - axis along the parent photon)
@@ -174,14 +173,14 @@ G4VParticleChange* G4LowEnergyRayleigh::PostStepDoIt(const G4Track& aTrack,
G4double dirX = sinTheta*cos(phi);
G4double dirY = sinTheta*sin(phi);
G4double dirZ = cosTheta;
// Update G4VParticleChange for the scattered photon
// Update G4VParticleChange for the scattered photon
G4ThreeVector photonDirection1(dirX, dirY, dirZ);
photonDirection1.rotateUz(photonDirection0);
aParticleChange.SetEnergyChange(photonEnergy0);
aParticleChange.SetMomentumChange(photonDirection1);
aParticleChange.SetNumberOfSecondaries(0);
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
@@ -198,8 +197,8 @@ G4double G4LowEnergyRayleigh::GetMeanFreePath(const G4Track& track,
{
const G4DynamicParticle* photon = track.GetDynamicParticle();
G4double energy = photon->GetKineticEnergy();
G4Material* material = track.GetMaterial();
size_t materialIndex = material->GetIndex();
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
size_t materialIndex = couple->GetIndex();
G4double meanFreePath;
if (energy > highEnergyLimit) meanFreePath = meanFreePathTable->FindValue(highEnergyLimit,materialIndex);
@@ -0,0 +1,450 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4PenelopeBremsstrahlung.cc,v 1.5 2003/04/24 14:51:10 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// --------------------------------------------------------------
//
// File name: G4PenelopeBremsstrahlung
//
// Author: Luciano Pandola
//
// Creation date: February 2003
//
// Modifications:
// 24.04.2003 V.Ivanchenko - Cut per region mfpt
//
//----------------------------------------------------------------
#include "G4PenelopeBremsstrahlung.hh"
#include "G4PenelopeBremsstrahlungContinuous.hh"
#include "G4eBremsstrahlungSpectrum.hh"
#include "G4BremsstrahlungCrossSectionHandler.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4LogLogInterpolation.hh"
#include "G4VEMDataSet.hh"
#include "G4EnergyLossTables.hh"
#include "G4UnitsTable.hh"
#include "G4Electron.hh"
#include "G4Gamma.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4DataVector.hh"
#include "G4ProductionCutsTable.hh"
//
//
// Il load dei dati continui si puo' mettere nel BuildLossTable
//
//
// Anche la sezione d'urto totale dovrebbe essere convertita
// le tabelle di G4 mi paiono piu' complete pero' (le lascio!)
//
G4PenelopeBremsstrahlung::G4PenelopeBremsstrahlung(const G4String& nam)
: G4eLowEnergyLoss(nam),
crossSectionHandler(0),
theMeanFreePath(0),
energySpectrum(0)
{
materialAngularData.clear();
cutForPhotons = 0.;
verboseLevel = 0;
LoadAngularData();
}
G4PenelopeBremsstrahlung::~G4PenelopeBremsstrahlung()
{
if(crossSectionHandler) delete crossSectionHandler;
if(energySpectrum) delete energySpectrum;
if(theMeanFreePath) delete theMeanFreePath;
}
void G4PenelopeBremsstrahlung::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
{
if(verboseLevel > 0) {
G4cout << "G4PenelopeBremsstrahlung::BuildPhysicsTable start"
<< G4endl;
}
cutForSecondaryPhotons.clear();
// Create and fill BremsstrahlungParameters once
if( energySpectrum != 0 ) delete energySpectrum;
//grid of reduced energy bins for photons
G4DataVector ebins;
ebins.push_back(1.0e-12);
ebins.push_back(0.05);
ebins.push_back(0.075);
ebins.push_back(0.1);
ebins.push_back(0.125);
ebins.push_back(0.15);
ebins.push_back(0.2);
ebins.push_back(0.25);
ebins.push_back(0.3);
ebins.push_back(0.35);
ebins.push_back(0.40);
ebins.push_back(0.45);
ebins.push_back(0.50);
ebins.push_back(0.55);
ebins.push_back(0.60);
ebins.push_back(0.65);
ebins.push_back(0.70);
ebins.push_back(0.75);
ebins.push_back(0.80);
ebins.push_back(0.85);
ebins.push_back(0.90);
ebins.push_back(0.925);
ebins.push_back(0.95);
ebins.push_back(0.97);
ebins.push_back(0.99);
ebins.push_back(0.995);
ebins.push_back(0.999);
ebins.push_back(0.9995);
ebins.push_back(0.9999);
ebins.push_back(0.99995);
ebins.push_back(0.99999);
ebins.push_back(1.0);
const G4String dataName("/penelope/br-sp-pen.dat");
energySpectrum = new G4eBremsstrahlungSpectrum(ebins,dataName);
//the shape of the energy spectrum for positron is the same used for the electrons,
//as the differential cross section is scaled of a factor f(E,Z) which is independent
//on the energy of the gamma
if(verboseLevel > 0) {
G4cout << "G4PenelopeBremsstrahlungSpectrum is initialized"
<< G4endl;
}
// Create and fill G4CrossSectionHandler once
if( crossSectionHandler != 0 ) delete crossSectionHandler;
G4VDataSetAlgorithm* interpolation = new G4LogLogInterpolation();
G4double lowKineticEnergy = GetLowerBoundEloss();
G4double highKineticEnergy = GetUpperBoundEloss();
G4int totBin = GetNbinEloss();
crossSectionHandler = new G4BremsstrahlungCrossSectionHandler(energySpectrum, interpolation);
crossSectionHandler->Initialise(0,lowKineticEnergy, highKineticEnergy, totBin);
if (&aParticleType==G4Electron::Electron())
{
//G4cout << "Leggo le sezioni d'urto degli elettroni" << G4endl;
crossSectionHandler->LoadShellData("brem/br-cs-");
}
else
{
//G4cout << "Leggo le sezioni d'urto dei positroni" << G4endl;
crossSectionHandler->LoadShellData("penelope/br-cs-pos-"); //cross section for positrons
}
if (verboseLevel > 0) {
G4cout << GetProcessName()
<< " is created; Cross section data: "
<< G4endl;
crossSectionHandler->PrintData();
G4cout << "Parameters: "
<< G4endl;
energySpectrum->PrintData();
}
// Build loss table for Bremsstrahlung
BuildLossTable(aParticleType);
if(verboseLevel > 0) {
G4cout << "The loss table is built"
<< G4endl;
}
if (&aParticleType==G4Electron::Electron()) {
RecorderOfElectronProcess[CounterOfElectronProcess] = (*this).theLossTable;
CounterOfElectronProcess++;
PrintInfoDefinition();
} else {
RecorderOfPositronProcess[CounterOfPositronProcess] = (*this).theLossTable;
CounterOfPositronProcess++;
}
// Build mean free path data using cut values
if( theMeanFreePath != 0 ) delete theMeanFreePath;
theMeanFreePath = crossSectionHandler->
BuildMeanFreePathForMaterials(&cutForSecondaryPhotons);
if(verboseLevel > 0) {
G4cout << "The MeanFreePath table is built"
<< G4endl;
}
// Build common DEDX table for all ionisation processes
BuildDEDXTable(aParticleType);
if(verboseLevel > 0) {
G4cout << "G4PenelopeBremsstrahlung::BuildPhysicsTable end"
<< G4endl;
}
}
void G4PenelopeBremsstrahlung::BuildLossTable(const G4ParticleDefinition& aParticleType)
{
// Build table for energy loss due to soft brems
// the tables are built for *MATERIALS* binning is taken from LowEnergyLoss
G4double lowKineticEnergy = GetLowerBoundEloss();
G4double highKineticEnergy = GetUpperBoundEloss();
size_t totBin = GetNbinEloss();
// create table
if (theLossTable) {
theLossTable->clearAndDestroy();
delete theLossTable;
}
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
theLossTable = new G4PhysicsTable(numOfCouples);
// Clean up the vector of cuts
cutForSecondaryPhotons.clear();
// Loop for materials
for (size_t j=0; j<numOfCouples; j++) {
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(lowKineticEnergy,
highKineticEnergy,
totBin);
// get material parameters needed for the energy loss calculation
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(j);
const G4Material* material= couple->GetMaterial();
// the cut cannot be below lowest limit
G4double tCut = (*(theCoupleTable->GetEnergyCutsVector(0)))[j];
tCut = G4std::min(highKineticEnergy, tCut);
cutForSecondaryPhotons.push_back(tCut);
const G4ElementVector* theElementVector = material->GetElementVector();
size_t NumberOfElements = material->GetNumberOfElements() ;
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector();
if(verboseLevel > 1) {
G4cout << "Energy loss for material # " << j
<< " tCut(keV)= " << tCut/keV
<< G4endl;
}
G4DataVector* ionloss = new G4DataVector();
for (size_t i = 0; i<totBin; i++) {
ionloss->push_back(0.0); //il vettore ha come elementi totBin zeri
}
const G4String partName = aParticleType.GetParticleName();
// loop for elements in the material
for (size_t iel=0; iel<NumberOfElements; iel++ ) {
G4int Z = (G4int)((*theElementVector)[iel]->GetZ());
//costruttore del continuo per l'elemento Z
G4PenelopeBremsstrahlungContinuous* ContLoss = new G4PenelopeBremsstrahlungContinuous(Z,tCut,GetLowerBoundEloss(),
GetUpperBoundEloss(),
partName);
//l'inizializzazione va ripetuta per ogni Z!
// now comes the loop for the kinetic energy values
for (size_t k = 0; k<totBin; k++) {
G4double lowEdgeEnergy = aVector->GetLowEdgeEnergy(k);
//qui viene chiamato il metodo giusto della perdita continua
(*ionloss)[k] += ContLoss->CalculateStopping(lowEdgeEnergy) * theAtomicNumDensityVector[iel];
//if (Z == 29)
// G4cout << lowEdgeEnergy << " " << ContLoss->CalculateStopping(lowEdgeEnergy) * theAtomicNumDensityVector[iel] << G4endl;
//va chiamato una volta per ogni energia
//per ogni energia k, somma su tutti gli elementi del materiale
}
delete ContLoss;
}
for (size_t ibin = 0; ibin<totBin; ibin++) {
aVector->PutValue(ibin,(*ionloss)[ibin]); //un valore per ogni energia (somma sugli elementi del mate)
}
delete ionloss;
theLossTable->insert(aVector);
}
}
G4VParticleChange* G4PenelopeBremsstrahlung::PostStepDoIt(const G4Track& track,
const G4Step& step)
{
aParticleChange.Initialize(track);
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
const G4Material* material = couple->GetMaterial();
G4double kineticEnergy = track.GetKineticEnergy();
G4int index = couple->GetIndex();
G4double tCut = cutForSecondaryPhotons[index];
// Control limits
if(tCut >= kineticEnergy)
return G4VContinuousDiscreteProcess::PostStepDoIt(track, step);
G4int Z = crossSectionHandler->SelectRandomAtom(couple, kineticEnergy);
G4double tGamma = energySpectrum->SampleEnergy(Z, tCut, kineticEnergy, kineticEnergy);
//bisogna recuperare il puntatore
G4AngularData* elementData = materialAngularData[index]; //punta al vettore che contiene i puntatori del materiale
//look for the index of the selected atom
const G4ElementVector* theElementVector = material->GetElementVector();
size_t NumberOfElements = material->GetNumberOfElements();
// loop for elements in the material
size_t iel=0;
G4int Z_try=0,indexEl=0;
do {
if (iel >= NumberOfElements ) {
G4String excep = "Not found the angular data for material " + material->GetName();
G4Exception(excep);
}
Z_try = (G4int)((*theElementVector)[(size_t) iel]->GetZ());
indexEl = iel;
iel++;
}while(Z_try != Z);
G4PenelopeBremsstrahlungAngular* finalAngularData = (*elementData)[indexEl];
// Sample gamma angle (Z - axis along the parent particle).
G4double dirZ = finalAngularData->ExtractCosTheta(kineticEnergy,tGamma);
//G4std::ofstream fff("prova.dat",G4std::ios::app);
//fff << dirZ << G4endl;
//fff.close();
G4double totalEnergy = kineticEnergy + electron_mass_c2;
G4double phi = twopi * G4UniformRand();
G4double sinTheta = sqrt(1. - dirZ*dirZ);
G4double dirX = sinTheta*cos(phi);
G4double dirY = sinTheta*sin(phi);
G4ThreeVector gammaDirection (dirX, dirY, dirZ);
G4ThreeVector electronDirection = track.GetMomentumDirection();
gammaDirection.rotateUz(electronDirection);
//
// Update the incident particle
//
G4double finalEnergy = kineticEnergy - tGamma;
// Kinematic problem
if (finalEnergy < 0.) {
tGamma += finalEnergy;
finalEnergy = 0.0;
}
G4double momentum = sqrt((totalEnergy + electron_mass_c2)*kineticEnergy);
G4double finalX = momentum*electronDirection.x() - tGamma*gammaDirection.x();
G4double finalY = momentum*electronDirection.y() - tGamma*gammaDirection.y();
G4double finalZ = momentum*electronDirection.z() - tGamma*gammaDirection.z();
aParticleChange.SetNumberOfSecondaries(1);
G4double norm = 1./sqrt(finalX*finalX + finalY*finalY + finalZ*finalZ);
aParticleChange.SetMomentumChange(finalX*norm, finalY*norm, finalZ*norm);
aParticleChange.SetEnergyChange( finalEnergy );
// create G4DynamicParticle object for the gamma
G4DynamicParticle* aGamma= new G4DynamicParticle (G4Gamma::Gamma(),
gammaDirection, tGamma);
aParticleChange.AddSecondary(aGamma);
return G4VContinuousDiscreteProcess::PostStepDoIt(track, step);
}
void G4PenelopeBremsstrahlung::PrintInfoDefinition()
{
G4String comments = "Total cross sections from EEDL database for electrons.";
comments += "\n Total cross section for positrons calculated from the electrons";
comments += "\n through an empirical scaling function.";
comments += "\n Gamma energy sampled from a data-driven histogram.";
comments += "\n Implementation of the continuous dE/dx part.";
comments += "\n It can be used for electrons and positrons";
comments += "in the energy range [250eV,100GeV].";
comments += "\n The process must work with G4LowEnergyIonisation.";
G4cout << G4endl << GetProcessName() << ": " << comments << G4endl;
}
G4bool G4PenelopeBremsstrahlung::IsApplicable(const G4ParticleDefinition& particle)
{
return ( (&particle == G4Electron::Electron()) || (&particle == G4Positron::Positron()) );
}
G4double G4PenelopeBremsstrahlung::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition* cond)
{
//*cond = NotForced;
G4int index = (track.GetMaterialCutsCouple())->GetIndex();
const G4VEMDataSet* data = theMeanFreePath->GetComponent(index);
G4double meanFreePath = data->FindValue(track.GetKineticEnergy());
return meanFreePath;
}
void G4PenelopeBremsstrahlung::SetCutForLowEnSecPhotons(G4double cut)
{
cutForPhotons = cut;
}
void G4PenelopeBremsstrahlung::LoadAngularData()
{
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
const size_t numOfMaterials = G4Material::GetNumberOfMaterials();
materialAngularData.clear();
for (size_t j=0; j<numOfMaterials; j++) {
// get material parameters needed for the energy loss calculation
const G4Material* material= (*theMaterialTable)[j];
const G4ElementVector* theElementVector = material->GetElementVector();
size_t NumberOfElements = material->GetNumberOfElements();
// loop for elements in the material
G4AngularData* elementAngularData = new G4AngularData;
for (size_t iel=0; iel<NumberOfElements; iel++ ) {
G4int Z = (G4int)((*theElementVector)[iel]->GetZ());
G4PenelopeBremsstrahlungAngular* AngPointer = new G4PenelopeBremsstrahlungAngular(Z);
elementAngularData->push_back(AngPointer);
}
materialAngularData.push_back(elementAngularData);
}
}
@@ -0,0 +1,233 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4PenelopeBremsstrahlungAngular.cc,v 1.3 2003/03/28 11:16:29 gcosmo Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// --------------------------------------------------------------
//
// File name: G4PenelopeBremsstrahlungAngular
//
// Author: Luciano Pandola
//
// Creation date: February 2003
//
// History:
// -----------
// 04 Feb 2003 L. Pandola 1st implementation
// 19 Mar 2003 L. Pandola Bugs fixed
//----------------------------------------------------------------
#include "G4PenelopeBremsstrahlungAngular.hh"
#include "G4PenelopeInterpolator.hh"
#include "Randomize.hh"
#include "globals.hh"
G4PenelopeBremsstrahlungAngular::G4PenelopeBremsstrahlungAngular (G4int Zed)
: Zmat(Zed)
{
InterpolationTableForZ();
InterpolationForK();
}
G4PenelopeBremsstrahlungAngular::~G4PenelopeBremsstrahlungAngular()
{
}
void G4PenelopeBremsstrahlungAngular::InterpolationTableForZ()
{
G4double pZ[NumberofZPoints] = {2.0,8.0,13.0,47.0,79.0,92.0};
G4double pX[NumberofZPoints],pY[NumberofZPoints];
G4double QQ1[NumberofZPoints][NumberofEPoints][NumberofKPoints];
G4double QQ2[NumberofZPoints][NumberofEPoints][NumberofKPoints];
//Read information from DataBase file
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4PenelopeBremsstrahlungAngular - G4LEDATA environment variable not set!";
G4Exception(excep);
}
G4String pathString(path);
G4String pathFile = pathString + "/penelope/br-ang-pen.dat";
G4std::ifstream file(pathFile);
G4std::filebuf* lsdp = file.rdbuf();
if (!(lsdp->is_open()))
{
G4String excep = "G4PenelopeBremsstrahlungAngular - data file " + pathFile + " not found!";
G4Exception(excep);
}
G4int i=0,j=0,k=0; // i=index for Z, j=index for E, k=index for K
G4double a1,a2;
while(i != -1) {
file >> i >> j >> k >> a1 >> a2;
if (i > -1){
QQ1[i][j][k]=a1;
QQ2[i][j][k]=a2;
}
}
file.close();
//Interpolation in Z
for (i=0;i<NumberofEPoints;i++){
for (j=0;j<NumberofKPoints;j++){
for (k=0;k<NumberofZPoints;k++){
pX[k]=log(QQ1[k][i][j]);
pY[k]=QQ2[k][i][j];
}
G4PenelopeInterpolator* interpolator1 = new G4PenelopeInterpolator(pZ,pX,NumberofZPoints);
Q1[i][j]=exp(interpolator1->CubicSplineInterpolation((G4double) Zmat));
delete interpolator1;
G4PenelopeInterpolator* interpolator2 = new G4PenelopeInterpolator(pZ,pY,NumberofZPoints);
Q2[i][j]=interpolator2->CubicSplineInterpolation((G4double) Zmat);
delete interpolator2;
}
}
//G4std::ofstream fil("matrice.dat",G4std::ios::app);
//fil << "Numero atomico: " << Zmat << G4endl;
//for (i=0;i<NumberofEPoints;i++)
//{
// fil << Q1[i][0] << " " << Q1[i][1] << " " << Q1[i][2] << " " << Q1[i][3] << G4endl;
//}
//fil.close();
}
void G4PenelopeBremsstrahlungAngular::InterpolationForK()
{
G4double pE[NumberofEPoints] = {1.0e-03,5.0e-03,1.0e-02,5.0e-02,1.0e-01,5.0e-01};
G4double pK[NumberofKPoints] = {0.0,0.6,0.8,0.95};
G4double ppK[reducedEnergyGrid];
G4double pX[NumberofKPoints];
G4int i,j;
for(i=0;i<reducedEnergyGrid;i++){
ppK[i]=((G4double) i) * 0.05;
}
for(i=0;i<NumberofEPoints;i++){
betas[i]=sqrt(pE[i]*(pE[i]+2*electron_mass_c2))/(pE[i]+electron_mass_c2);
}
for (i=0;i<NumberofEPoints;i++){
for (j=0;j<NumberofKPoints;j++){
Q1[i][j]=Q1[i][j]/((G4double) Zmat);
}
}
//Expanded table of distribution parameters
for (i=0;i<NumberofEPoints;i++){
for (j=0;j<NumberofKPoints;j++){
pX[j]=log(Q1[i][j]); //logarithmic
}
G4PenelopeInterpolator* interpolator = new G4PenelopeInterpolator(pK,pX,NumberofKPoints);
for (j=0;j<reducedEnergyGrid;j++){
Q1E[i][j]=interpolator->CubicSplineInterpolation(ppK[j]);
}
delete interpolator;
for (j=0;j<NumberofKPoints;j++){
pX[j]=Q2[i][j];
}
G4PenelopeInterpolator* interpolator2 = new G4PenelopeInterpolator(pK,pX,NumberofKPoints);
for (j=0;j<reducedEnergyGrid;j++){
Q2E[i][j]=interpolator2->CubicSplineInterpolation(ppK[j]);
}
delete interpolator2;
}
}
G4double G4PenelopeBremsstrahlungAngular::ExtractCosTheta(G4double e1,G4double e2)
{
//e1 = kinetic energy of the electron
//e2 = energy of the bremsstrahlung photon
G4double beta = sqrt(e1*(e1+2*electron_mass_c2))/(e1+electron_mass_c2);
G4double RK=20.0*e2/e1;
G4int ik=G4std::min((G4int) RK,19);
G4double P10=0,P11=0,P1=0;
G4double P20=0,P21=0,P2=0;
G4double pX[NumberofEPoints];
//First coefficient
G4int i;
G4int j = ik;
for (i=0;i<NumberofEPoints;i++){
pX[i]=Q1E[i][j];
}
G4PenelopeInterpolator* interpolator = new G4PenelopeInterpolator(betas,pX,NumberofEPoints);
P10=interpolator->CubicSplineInterpolation(beta);
delete interpolator;
j++; //(j=ik+1)
for (i=0;i<NumberofEPoints;i++){
pX[i]=Q1E[i][j];
}
G4PenelopeInterpolator* interpolator2 = new G4PenelopeInterpolator(betas,pX,NumberofEPoints);
P11=interpolator2->CubicSplineInterpolation(beta);
delete interpolator2;
P1=P10+(RK-(G4double) ik)*(P11-P10);
//Second coefficient
j = ik;
for (i=0;i<NumberofEPoints;i++){
pX[i]=Q2E[i][j];
}
G4PenelopeInterpolator* interpolator3 = new G4PenelopeInterpolator(betas,pX,NumberofEPoints);
P20=interpolator3->CubicSplineInterpolation(beta);
delete interpolator3;
j++; //(j=ik+1)
for (i=0;i<NumberofEPoints;i++){
pX[i]=Q2E[i][j];
}
G4PenelopeInterpolator* interpolator4 = new G4PenelopeInterpolator(betas,pX,NumberofEPoints);
P21=interpolator4->CubicSplineInterpolation(beta);
delete interpolator4;
P2=P20+(RK-(G4double) ik)*(P21-P20);
//Sampling from the Lorenz-trasformed dipole distributions
P1=G4std::min(exp(P1)/beta,1.0);
G4double betap = G4std::min(G4std::max(beta*(1.0+P2/beta),0.0),0.9999);
G4double cdt=0,testf=0;
if (G4UniformRand() < P1){
do{
cdt = 2.0*G4UniformRand()-1.0;
testf=2.0*G4UniformRand()-(1.0+cdt*cdt);
}while(testf>0);
}
else{
do{
cdt = 2.0*G4UniformRand()-1.0;
testf=G4UniformRand()-(1.0-cdt*cdt);
}while(testf>0);
}
cdt = (cdt+betap)/(1.0+betap*cdt);
return cdt;
}
@@ -0,0 +1,279 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4PenelopeBremsstrahlungContinuous.cc,v 1.4 2003/03/28 11:16:29 gcosmo Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// --------------------------------------------------------------
//
// File name: G4PenelopeBremsstrahlungContinuous
//
// Author: Luciano Pandola
//
// Creation date: February 2003
// History:
// -----------
// 20 Feb 2003 L. Pandola 1st implementation
// 17 Mar 2003 L. Pandola Added the correction for positrons
// 19 Mar 2003 L. Pandola Bugs fixed
//----------------------------------------------------------------
#include "G4PenelopeBremsstrahlungContinuous.hh"
#include "G4PenelopeInterpolator.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
#include "Randomize.hh"
#include "G4ParticleDefinition.hh"
#include "globals.hh"
#include "g4std/strstream"
G4PenelopeBremsstrahlungContinuous::G4PenelopeBremsstrahlungContinuous (G4int Zed,G4double taglio,G4double e1,
G4double e2,
const G4String name) :
Zmat(Zed),tCut(taglio),MinE(e1),MaxE(e2),partName(name)
{
//Construct extended energy table
//200 bins between MinE and MaxE (logarithmic)
G4double EL=0.99999*MinE;
G4double EU=1.00001*MaxE;
DLFC=log(EU/EL)/((G4double) (NumberofExtendedEGrid-1));
ExtendedLogEnergy[0]=log(EL);
for (size_t i=1;i<NumberofExtendedEGrid;i++){
ExtendedLogEnergy[i]=ExtendedLogEnergy[i-1]+DLFC;
}
DLFC=1.0/DLFC;
LoadFromFile();
PrepareInterpolationTable();
}
G4PenelopeBremsstrahlungContinuous::~G4PenelopeBremsstrahlungContinuous()
{
}
void G4PenelopeBremsstrahlungContinuous::LoadFromFile()
{
//Read information from DataBase File
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4PenelopeBremsstrahlungContinuous - G4LEDATA environment variable not set!";
G4Exception(excep);
}
G4String pathString(path);
G4String filename = "br-pen-cont-";
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
ost << filename << Zmat << ".dat";
G4String name(nameChar);
G4String dirFile = pathString + "/penelope/" + name;
G4std::ifstream file(dirFile);
G4std::filebuf* lsdp = file.rdbuf();
if (!(lsdp->is_open()))
{
G4String excep = "G4PenelopeBremsstrahlungContinuous - data file " + name + " not found!";
G4Exception(excep);
}
G4double a1;
for (size_t i=0;i<NumberofEPoints;i++){
file >> a1;
Energies[i]=a1;
for (size_t j=0;j<NumberofKPoints;j++){
file >> a1;
ReducedCS[i][j]=a1/millibarn; //coversion present in Penelope source
}
file >> a1;
TotalCS[i]=a1/millibarn; //conversion present in Penelope source
file >> a1;
if (a1 != ((G4double) -1)){
G4String excep = "G4PenelopeBremsstrahlungContinuous - Check the bremms data file "+ name;
G4Exception(excep);
}
}
file.close();
}
void G4PenelopeBremsstrahlungContinuous::PrepareInterpolationTable()
{
//The energy-loss spectrum is re-normalized to reproduce the
//total scaled cross-section of Berger and Seltzer
G4double pK[NumberofKPoints] = {1.0e-12,0.05,0.075,0.1,0.125,0.15,0.2,0.25,
0.3,0.35,0.4,0.45,0.5,0.55,0.6,0.65,0.7,
0.75,0.8,0.85,0.9,0.925,0.95,0.97,0.99,
0.995,0.999,0.9995,0.9999,0.99995,0.99999,1.0};
G4double pY[NumberofKPoints];
size_t i=0,j=0;
for (i=0;i<NumberofEPoints;i++){
for (j=0;j<NumberofKPoints;j++){
pY[j]= ReducedCS[i][j];
}
G4PenelopeInterpolator* interpolator = new G4PenelopeInterpolator(pK,pY,NumberofKPoints);
G4double Rsum = interpolator->CalculateMomentum(1.0,0);
delete interpolator;
G4double Fact = (millibarn/cm2)*(Energies[i]+electron_mass_c2)*(1.0/fine_structure_const)/
(pow(classic_electr_radius,2)*(Energies[i]+2.0*electron_mass_c2));
G4double Normalization = TotalCS[i]/(Rsum*Fact);
G4double TST = abs(Normalization-100.0);
if (TST > 1.0) {
G4String excep = "G4PenelopeBremsstrahlungContinuous - Check the bremms data file";
G4Exception(excep);
}
for (j=0;j<NumberofKPoints;j++){
ReducedCS[i][j] = ReducedCS[i][j]*Normalization;
}
}
//Compute the scaled energy loss distribution and sampling parameters
// for the energies in the simulation grid
// Interpolation in E
G4double pX[NumberofEPoints];
G4double pYY[NumberofEPoints];
for (i=0;i<NumberofEPoints;i++){
pX[i] = log(Energies[i]);
}
for (j=0;j<NumberofKPoints;j++){
for (i=0;i<NumberofEPoints;i++){
pYY[i] = log(ReducedCS[i][j]);
}
G4PenelopeInterpolator* interpolator2 = new G4PenelopeInterpolator(pX,pYY,NumberofEPoints);
for (i=0;i<NumberofExtendedEGrid;i++){
G4double ELL = ExtendedLogEnergy[i];
if (ELL >= pX[0]) {
p0[i][j] = exp(interpolator2->CubicSplineInterpolation(ELL));
}
else
{
G4double F1=interpolator2->CubicSplineInterpolation(pX[0]);
G4double FP1 = interpolator2->FirstDerivative(pX[0]);
p0[i][j] = exp(F1+FP1*(ELL-pX[0]));
}
}
delete interpolator2;
}
//Forse questa roba (e Pbcut come membro privato) non serve
// G4double PDF[NumberofKPoints];
// for (i=0;i<NumberofExtendedEGrid;i++){
// for (j=0;j<NumberofKPoints;j++){
// PDF[j]=p0[i][j];
// }
// G4double Xc=0;
// if (i<(NumberofExtendedEGrid-1)){
// Xc=tCut/exp(ExtendedLogEnergy[i+1]);
// }
// else
// {
// Xc=tCut/exp(ExtendedLogEnergy[NumberofExtendedEGrid-1]);
// }
// G4PenelopeInterpolator* interpolator3 = new G4PenelopeInterpolator(pK,PDF,NumberofKPoints);
// Pbcut[i]=interpolator3->CalculateMomentum(Xc,-1);
// delete interpolator3;
// }
}
G4double G4PenelopeBremsstrahlungContinuous::CalculateStopping(G4double e1)
//Stopping power expressed in MeV/mm*2
{
G4double Xel=G4std::max(log(e1),ExtendedLogEnergy[0]);
G4double Xe=1.0+(Xel-ExtendedLogEnergy[0])*DLFC;
G4int Ke = (G4int) Xe;
G4double Xek = Xe-Ke;
//Global x-section factor
G4double Fact=pow((G4double) Zmat,2)*(pow(e1+electron_mass_c2,2)/(e1*(e1+2.0*electron_mass_c2)))
*(millibarn/cm2);
//G4cout << "Particella: " << partName << ";Z: " << Zmat << ";Energia: " << e1 << "; fattore di correzione: "
// << PositronCorrection(e1) << G4endl;
Fact=Fact*PositronCorrection(e1);
//Moments of the scaled bremss x-section
G4double wcre = tCut/e1;
G4double pY[NumberofKPoints];
G4double pK[NumberofKPoints] = {1.0e-12,0.05,0.075,0.1,0.125,0.15,0.2,0.25,
0.3,0.35,0.4,0.45,0.5,0.55,0.6,0.65,0.7,
0.75,0.8,0.85,0.9,0.925,0.95,0.97,0.99,
0.995,0.999,0.9995,0.9999,0.99995,0.99999,1.0};
for (size_t i=0;i<NumberofKPoints;i++){
pY[i] = p0[Ke][i];
}
G4PenelopeInterpolator* interpolator1 = new G4PenelopeInterpolator(pK,pY,NumberofKPoints);
G4double XS1A = interpolator1->CalculateMomentum(wcre,0);
G4double XS2A = interpolator1->CalculateMomentum(wcre,1);
delete interpolator1;
for (size_t k=0;k<NumberofKPoints;k++){
pY[k] = p0[G4std::min(Ke+1,(G4int) NumberofExtendedEGrid-1)][k];
}
G4PenelopeInterpolator* interpolator2 = new G4PenelopeInterpolator (pK,pY,NumberofKPoints);
G4double XS1B = interpolator2->CalculateMomentum(wcre,0);
G4double XS2B = interpolator2->CalculateMomentum(wcre,1);
delete interpolator2;
G4double XS1 = ((1.0-Xek)*XS1A+Xek*XS1B)*Fact*e1; //weighted mean between the energy bin of the grid
G4double XS2 = ((1.0-Xek)*XS2A+Xek*XS2B)*Fact*e1*e1; //straggling cross section (2nd momentum);
//Il secondo momento XS2 potrebbe tornare utile in seguito
//XS1 is given in MeV*cm2, as in Penelope, but it must be converted in MeV*mm2
XS1=XS1*cm2/mm2;
//XS2 is given in MeV2*cm2, as in Penelope, but it must be converted in MeV2*mm2
XS2=XS2*cm2/mm2;
//Deve includere anche le famose correzioni per tenere conto
//che la sezione d'urto varia sullo step!
//Il valore che tira fuori va nella tabella e non viene piu' modificato
return XS1;
}
G4double G4PenelopeBremsstrahlungContinuous::PositronCorrection(G4double en)
{
const G4double Coeff[7]={-1.2359e-01,6.1274e-2,-3.1516e-2,7.7446e-3,-1.0595e-3,
7.0568e-5,-1.8080e-6};
G4double T=0;
G4double correct=0;
if (partName == "e-") {
return 1.0; //no correction for electrons
}
else if (partName == "e+"){
T=log(1+((1e6*en)/(pow( (G4double) Zmat,2)*electron_mass_c2)));
for (G4int i=0;i<7;i++){
correct += Coeff[i]*pow(T,i+1);
}
correct = 1.0-exp(correct);
return correct;
}
else //ne' elettroni ne' positroni...exception
{
G4String excep = "G4PenelopeBremmstrahlungContinuous: the particle is not e- nor e+!";
G4Exception(excep);
return 0;
}
}
@@ -0,0 +1,660 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4PenelopeCompton.cc,v 1.10 2003/03/13 16:56:40 pandola Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Luciano Pandola
//
// History:
// --------
// 12 Feb 2003 MG Pia const argument in SelectRandomAtomForCompton
// Migration to "cuts per region"
// 14 Feb 2003 MG Pia Corrected compilation errors and warnings
// from SUN
// Modified some variables to lowercase initial
// 10 Mar 2003 V.Ivanchenko Remove CutPerMaterial warning
// 13 Mar 2003 L.Pandola Code "cleaned"
//
// -------------------------------------------------------------------
#include "G4PenelopeCompton.hh"
#include "Randomize.hh"
#include "G4ParticleDefinition.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4ForceCondition.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4DynamicParticle.hh"
#include "G4VParticleChange.hh"
#include "G4ThreeVector.hh"
#include "G4EnergyLossTables.hh"
#include "G4VCrossSectionHandler.hh"
#include "G4CrossSectionHandler.hh"
#include "G4VEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4CompositeEMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4LogLogInterpolation.hh"
#include "G4VRangeTest.hh"
#include "G4RangeTest.hh"
#include "G4PenelopeIntegrator.hh"
#include "G4MaterialCutsCouple.hh"
G4PenelopeCompton::G4PenelopeCompton(const G4String& processName)
: G4VDiscreteProcess(processName),
lowEnergyLimit(250*eV),
highEnergyLimit(100*GeV),
intrinsicLowEnergyLimit(10*eV),
intrinsicHighEnergyLimit(100*GeV),
energyForIntegration(0.0),
ZForIntegration(1),
nBins(200)
{
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
highEnergyLimit > intrinsicHighEnergyLimit)
{
G4Exception("G4PenelopeCompton::G4PenelopeCompton - energy outside intrinsic process validity range");
}
meanFreePathTable = 0;
ionizationEnergy = new G4std::vector<G4DataVector*>;
hartreeFunction = new G4std::vector<G4DataVector*>;
occupationNumber = new G4std::vector<G4DataVector*>;
rangeTest = new G4RangeTest;
ReadData(); //Legge i dati da file!
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
G4PenelopeCompton::~G4PenelopeCompton()
{
delete meanFreePathTable;
delete rangeTest;
delete matCrossSections;
delete ionizationEnergy;
delete hartreeFunction;
delete occupationNumber;
}
void G4PenelopeCompton::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
G4DataVector energyVector;
G4double dBin = log10(highEnergyLimit/lowEnergyLimit)/nBins;
G4int i;
for (i=0;i<nBins;i++)
{
energyVector.push_back(pow(10.,log10(lowEnergyLimit)+i*dBin));
}
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
G4int nMaterials = G4Material::GetNumberOfMaterials();
G4VDataSetAlgorithm* algo = new G4LogLogInterpolation();
size_t nOfBins = energyVector.size();
size_t bin=0;
G4DataVector* energies;
G4DataVector* data;
matCrossSections = new G4std::vector<G4VEMDataSet*>;
G4int m;
for (m=0; m<nMaterials; m++)
{
const G4Material* material= (*materialTable)[m];
G4int nElements = material->GetNumberOfElements();
const G4ElementVector* elementVector = material->GetElementVector();
const G4double* nAtomsPerVolume = material->GetAtomicNumDensityVector();
G4VEMDataSet* setForMat = new G4CompositeEMDataSet(algo,1.,1.);
for (i=0; i<nElements; i++) {
G4int Z = (G4int) (*elementVector)[i]->GetZ();
G4double density = nAtomsPerVolume[i];
G4double cross=0.0;
energies = new G4DataVector;
data = new G4DataVector;
for (bin=0; bin<nOfBins; bin++)
{
G4double e = energyVector[bin];
energies->push_back(e);
cross = density * CrossSection(e,Z);
data->push_back(cross);
}
G4VEMDataSet* elSet = new G4EMDataSet(i,energies,data,algo,1.,1.);
setForMat->AddComponent(elSet);
}
matCrossSections->push_back(setForMat);
}
G4double matCS = 0.0;
G4VEMDataSet* matCrossSet = new G4CompositeEMDataSet(algo,1.,1.);
G4VEMDataSet* materialSet = new G4CompositeEMDataSet(algo,1.,1.);
for (m=0; m<nMaterials; m++)
{
energies = new G4DataVector;
data = new G4DataVector;
const G4Material* material= (*materialTable)[m];
material= (*materialTable)[m];
for (bin=0; bin<nOfBins; bin++)
{
G4double energy = energyVector[bin];
energies->push_back(energy);
matCrossSet = (*matCrossSections)[m];
matCS = 0.0;
G4int nElm = matCrossSet->NumberOfComponents();
for(G4int j=0; j<nElm; j++) {
matCS += matCrossSet->GetComponent(j)->FindValue(energy);
}
if (matCS > 0.)
{
data->push_back(1./matCS);
}
else
{
data->push_back(DBL_MAX);
}
}
G4VEMDataSet* dataSet = new G4EMDataSet(m,energies,data,algo,1.,1.);
materialSet->AddComponent(dataSet);
}
meanFreePathTable = materialSet;
}
G4VParticleChange* G4PenelopeCompton::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
//Penelope model
aParticleChange.Initialize(aTrack);
// Dynamic particle quantities
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double photonEnergy0 = incidentPhoton->GetKineticEnergy();
if (photonEnergy0 <= lowEnergyLimit)
{
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit(photonEnergy0);
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
G4ParticleMomentum photonDirection0 = incidentPhoton->GetMomentumDirection();
const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
const G4Material* material = couple->GetMaterial();
G4int Z = SelectRandomAtomForCompton(material,photonEnergy0);
const G4int nmax = 64;
G4double rn[nmax],pac[nmax];
G4double ki,ki1,ki2,ki3,taumin,a1,a2;
G4double tau,TST;
G4double S=0.0;
G4double epsilon,cosTheta;
G4double harFunc = 0.0;
G4int occupNb= 0;
G4double ionEnergy=0.0;
G4int nosc = ((*occupationNumber)[Z-1])->size();
G4int iosc = nosc;
ki = photonEnergy0/electron_mass_c2;
ki2 = 2*ki+1.0;
ki3 = ki*ki;
ki1 = ki3-ki2-1.0;
taumin = 1.0/ki2;
a1 = log(ki2);
a2 = a1+2.0*ki*(1.0+ki)/(ki2*ki2);
if (photonEnergy0 > 5*MeV)
{
do{
do{
if ((a2*G4UniformRand()) < a1)
{
tau = pow(taumin,G4UniformRand());
}
else
{
tau = sqrt(1.0+G4UniformRand()*(taumin*taumin-1.0));
}
//rejection function
TST = (1+tau*(ki1+tau*(ki2+tau*ki3)))/(ki3*tau*(1.0+tau*tau));
}while (G4UniformRand()> TST);
epsilon=tau;
cosTheta = 1.0 - (1.0-tau)/(ki*tau);
//Target shell electrons
TST = Z*G4UniformRand();
iosc = nosc;
S=0.0;
for (G4int j=0;j<nosc;j++)
{
occupNb = (G4int) (*((*occupationNumber)[Z-1]))[j];
S = S + occupNb;
if (S > TST) iosc = j;
if (S > TST) break;
}
ionEnergy = (*((*ionizationEnergy)[Z-1]))[iosc];
}while((epsilon*photonEnergy0-photonEnergy0+ionEnergy) >0);
}
else //photonEnergy0<5 MeV
{
//Incoherent scattering function for theta=PI
G4double s0=0.0;
G4double pzomc=0.0,rni=0.0;
G4double aux=0.0;
for (G4int i=0;i<nosc;i++){
ionEnergy = (*((*ionizationEnergy)[Z-1]))[i];
if (photonEnergy0 > ionEnergy)
{
G4double aux = photonEnergy0*(photonEnergy0-ionEnergy)*2.0;
harFunc = (*((*hartreeFunction)[Z-1]))[i]/fine_structure_const;
occupNb = (G4int) (*((*occupationNumber)[Z-1]))[i];
pzomc = harFunc*(aux-electron_mass_c2*ionEnergy)/
(electron_mass_c2*sqrt(2.0*aux+pow(ionEnergy,2)));
if (pzomc > 0)
{
rni = 1.0-0.5*exp(0.5-pow(sqrt(0.5)+sqrt(2.0)*pzomc,2));
}
else
{
rni = 0.5*exp(0.5-pow(sqrt(0.5)-sqrt(2.0)*pzomc,2));
}
s0 = s0 + occupNb*rni;
}
}
//Sampling tau
G4double cdt1;
do
{
if ((G4UniformRand()*a2) < a1)
{
tau = pow(taumin,G4UniformRand());
}
else
{
tau = sqrt(1.0+G4UniformRand()*(taumin*taumin-1.0));
}
cdt1 = (1.0-tau)/(ki*tau);
S=0.0;
//Incoherent scattering function
for (G4int i=0;i<nosc;i++){
ionEnergy = (*((*ionizationEnergy)[Z-1]))[i];
if (photonEnergy0 > ionEnergy) //sum only on excitable levels
{
aux = photonEnergy0*(photonEnergy0-ionEnergy)*cdt1;
harFunc = (*((*hartreeFunction)[Z-1]))[i]/fine_structure_const;
occupNb = (G4int) (*((*occupationNumber)[Z-1]))[i];
pzomc = harFunc*(aux-electron_mass_c2*ionEnergy)/
(electron_mass_c2*sqrt(2.0*aux+pow(ionEnergy,2)));
if (pzomc > 0)
{
rn[i] = 1.0-0.5*exp(0.5-pow(sqrt(0.5)+sqrt(2.0)*pzomc,2));
}
else
{
rn[i] = 0.5*exp(0.5-pow(sqrt(0.5)-sqrt(2.0)*pzomc,2));
}
S = S + occupNb*rn[i];
pac[i] = S;
}
else
{
pac[i] = S-(1e-06);
}
}
//Rejection function
TST = S*(1.0+tau*(ki1+tau*(ki2+tau*ki3)))/(ki3*tau*(1.0+tau*tau));
}while ((G4UniformRand()*s0) > TST);
//Target electron shell
cosTheta = 1.0 - cdt1;
G4double fpzmax=0.0,fpz=0.0;
G4double A=0.0;
do
{
do
{
TST =S*G4UniformRand();
iosc=nosc;
for (G4int i=0;i<nosc;i++){
if (pac[i]>TST) iosc = i;
if (pac[i]>TST) break;
}
A = G4UniformRand()*rn[iosc];
harFunc = (*((*hartreeFunction)[Z-1]))[iosc]/fine_structure_const;
occupNb = (G4int) (*((*occupationNumber)[Z-1]))[iosc];
if (A < 0.5) {
pzomc = (sqrt(0.5)-sqrt(0.5-log(2.0*A)))/
(sqrt(2.0)*harFunc);
}
else
{
pzomc = (sqrt(0.5-log(2.0-2.0*A))-sqrt(0.5))/
(sqrt(2.0)*harFunc);
}
} while (pzomc < -1);
// F(EP) rejection
G4double XQC = 1.0+tau*(tau-2.0*cosTheta);
G4double AF = sqrt(XQC)*(1.0+tau*(tau-cosTheta)/XQC);
if (AF > 0) {
fpzmax = 1.0+AF*0.2;
}
else
{
fpzmax = 1.0-AF*0.2;
}
fpz = 1.0+AF*G4std::max(G4std::min(pzomc,0.2),-0.2);
}while ((fpzmax*G4UniformRand())>fpz);
//Energy of the scattered photon
G4double T = pow(pzomc,2);
G4double b1 = 1.0-T*tau*tau;
G4double b2 = 1.0-T*tau*cosTheta;
if (pzomc > 0.0)
{
epsilon = (tau/b1)*(b2+sqrt(abs(b2*b2-b1*(1.0-T))));
}
else
{
epsilon = (tau/b1)*(b2-sqrt(abs(b2*b2-b1*(1.0-T))));
}
}
G4double sinTheta = sqrt(1-pow(cosTheta,2));
G4double phi = twopi * G4UniformRand() ;
G4double dirx = sinTheta * cos(phi);
G4double diry = sinTheta * sin(phi);
G4double dirz = cosTheta ;
// Update G4VParticleChange for the scattered photon
G4ThreeVector photonDirection1(dirx,diry,dirz);
photonDirection1.rotateUz(photonDirection0);
aParticleChange.SetMomentumChange(photonDirection1) ;
G4double photonEnergy1 = epsilon * photonEnergy0;
if (photonEnergy1 > 0.)
{
aParticleChange.SetEnergyChange(photonEnergy1) ;
}
else
{
aParticleChange.SetEnergyChange(0.) ;
aParticleChange.SetStatusChange(fStopAndKill);
}
// Kinematics of the scattered electron
G4double diffEnergy = photonEnergy0*(1-epsilon);
ionEnergy = (*((*ionizationEnergy)[Z-1]))[iosc];
G4double eKineticEnergy = diffEnergy - ionEnergy;
G4double Q2 = pow(photonEnergy0,2)+photonEnergy1*(photonEnergy1-2.0*photonEnergy0*cosTheta);
G4double cosThetaE; //scattering angle for the electron
if (Q2 > 1.0e-12)
{
cosThetaE = (photonEnergy0-photonEnergy1*cosTheta)/sqrt(Q2);
}
else
{
cosThetaE = 1.0;
}
G4double sinThetaE = sqrt(1-pow(cosThetaE,2));
// Generate the electron only if with large enough range w.r.t. cuts and safety
G4double safety = aStep.GetPostStepPoint()->GetSafety();
if (rangeTest->Escape(G4Electron::Electron(),couple,eKineticEnergy,safety))
{
G4double xEl = sinThetaE * cos(phi+pi);
G4double yEl = sinThetaE * sin(phi+pi);
G4double zEl = cosThetaE;
G4ThreeVector eDirection(xEl,yEl,zEl); //electron direction
G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),
eDirection,eKineticEnergy) ;
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(electron);
aParticleChange.SetLocalEnergyDeposit(0.);
}
else
{
aParticleChange.SetNumberOfSecondaries(0);
aParticleChange.SetLocalEnergyDeposit(eKineticEnergy);
}
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep);
}
G4bool G4PenelopeCompton::IsApplicable(const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
}
G4double G4PenelopeCompton::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition*)
{
const G4DynamicParticle* photon = track.GetDynamicParticle();
G4double energy = photon->GetKineticEnergy();
G4Material* material = track.GetMaterial();
size_t materialIndex = material->GetIndex();
G4double meanFreePath;
if (energy > highEnergyLimit) meanFreePath = meanFreePathTable->FindValue(highEnergyLimit,materialIndex);
else if (energy < lowEnergyLimit) meanFreePath = DBL_MAX;
else meanFreePath = meanFreePathTable->FindValue(energy,materialIndex);
return meanFreePath;
}
void G4PenelopeCompton::ReadData()
{
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4PenelopeCompton - G4LEDATA environment variable not set!";
G4Exception(excep);
}
G4String pathString(path);
G4String pathFile = pathString + "/penelope/comptondata.dat";
G4std::ifstream file(pathFile);
G4std::filebuf* lsdp = file.rdbuf();
if (!(lsdp->is_open()))
{
G4String excep = "G4PenelopeCompton - data file " + pathFile + " not found!";
G4Exception(excep);
}
file.close();
//This algorithm is slow and unelegant!
//It must be improved.
G4int k1,k2;
G4double a1,a2;
G4int Z=0;
G4DataVector* f;
G4DataVector* u;
G4DataVector* j;
for(Z=1;Z<93;Z++) {
f = new G4DataVector;
u = new G4DataVector;
j = new G4DataVector;
G4std::ifstream file(pathFile);
k1=1;
while (k1>0)
{
file >> k1 >> k2 >> a1 >> a2;
if(k1 == Z)
{
f->push_back((G4double) k2);
u->push_back(a1);
j->push_back(a2);
}
}
file.close();
ionizationEnergy->push_back(u);
hartreeFunction->push_back(j);
occupationNumber->push_back(f);
}
//(*((*ionizationEnergy)[Z-1]))[i] contains the ionization energy of the i-th level of
//the element Z
};
G4double G4PenelopeCompton::CrossSection(G4double energy,G4int Z)
{
G4double cs=0.0;
energyForIntegration=energy;
ZForIntegration = Z;
if (energy< 5*MeV)
{
G4PenelopeIntegrator<G4PenelopeCompton,G4double (G4PenelopeCompton::*)(G4double)> theIntegrator;
cs = theIntegrator.Calculate(this,&G4PenelopeCompton::DifferentialCrossSection,-1.0,1.0,1e-05);
}
else
{
G4double ki=energy/electron_mass_c2;
G4double ki3=ki*ki;
G4double ki2=1.0+2*ki;
G4double ki1=ki3-ki2-1.0;
G4double t0=1.0/(ki2);
G4double csl = 0.5*ki3*t0*t0+ki2*t0+ki1*log(t0)-(1.0/t0);
G4int nosc = ((*occupationNumber)[Z-1])->size();
for (G4int i=0;i<nosc;i++)
{
G4double ionEnergy = (*((*ionizationEnergy)[Z-1]))[i];
G4double tau=(energy-ionEnergy)/energy;
if (tau > t0)
{
G4double csu = 0.5*ki3*tau*tau+ki2*tau+ki1*log(tau)-(1.0/tau);
G4int f = (G4int) (*((*occupationNumber)[Z-1]))[i];
cs = cs + f*(csu-csl);
}
}
cs=pi*classic_electr_radius*classic_electr_radius*cs/(ki*ki3);
}
return cs;
}
G4double G4PenelopeCompton::DifferentialCrossSection(G4double cosTheta)
{
const G4double k2 = sqrt(2.0);
const G4double k1 = sqrt(0.5);
const G4double k12 = 0.5;
G4double cdt1 = 1.0-cosTheta;
G4double energy = energyForIntegration;
G4int Z = ZForIntegration;
G4double ionEnergy=0.0,Pzimax=0.0,XKN=0.0;
G4double diffCS=0.0;
G4double x=0.0,siap=0.0;
G4double harFunc=0.0;
G4int occupNb;
//energy of Compton line;
G4double EOEC = 1.0+(energy/electron_mass_c2)*cdt1;
G4double ECOE = 1.0/EOEC;
//Incoherent scattering function (analytical profile)
G4double sia = 0.0;
G4int nosc = ((*occupationNumber)[Z-1])->size();
for (G4int i=0;i<nosc;i++){
ionEnergy = (*((*ionizationEnergy)[Z-1]))[i];
//Sum only of those shells for which E>Eion
if (energy > ionEnergy)
{
G4double aux = energy * (energy-ionEnergy)*cdt1;
Pzimax = (aux - electron_mass_c2*ionEnergy)/(electron_mass_c2*sqrt(2*aux+pow(ionEnergy,2)));
harFunc = (*((*hartreeFunction)[Z-1]))[i]/fine_structure_const;
occupNb = (G4int) (*((*occupationNumber)[Z-1]))[i];
x = harFunc*Pzimax;
if (x > 0)
{
siap = 1.0-0.5*exp(k12-pow((k1+k2*x),2));
}
else
{
siap = 0.5*exp(k12-pow((k1-k2*x),2));
}
sia = sia + occupNb*siap; //sum of all contributions;
}
}
XKN = EOEC+ECOE-1+cosTheta*cosTheta;
diffCS = pi*pow(classic_electr_radius,2)*pow(ECOE,2)*XKN*sia;
return diffCS;
}
G4int G4PenelopeCompton::SelectRandomAtomForCompton(const G4Material* material,G4double energy) const
{
G4int nElements = material->GetNumberOfElements();
//Special case: the material consists of one element
if (nElements == 1)
{
G4int Z = (G4int) material->GetZ();
return Z;
}
//Composite material
const G4ElementVector* elementVector = material->GetElementVector();
size_t materialIndex = material->GetIndex();
G4VEMDataSet* materialSet = (*matCrossSections)[materialIndex];
G4double materialCrossSection0 = 0.0;
G4DataVector cross;
cross.clear();
G4int i;
for (i=0;i<nElements;i++)
{
G4double cr = (materialSet->GetComponent(i))->FindValue(energy);
materialCrossSection0 += cr;
cross.push_back(materialCrossSection0); //cumulative cross section
}
G4double random = G4UniformRand()*materialCrossSection0;
for (i=0;i<nElements;i++)
{
if (random <= cross[i]) return (G4int) (*elementVector)[i]->GetZ();
}
//It should never get here
return 0;
}
@@ -0,0 +1,379 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
// --------------------------------------------------------------------
//
//
//
// --------------------------------------------------------------
//
// Author: L.Pandola
// History:
// --------
// 02 Dec 2002 L.Pandola 1st implementation
// 12 Feb 2003 MG Pia Migration to "cuts per region"
// 10 Mar 2003 V.Ivanchenko Remove CutPerMaterial warning
// 13 Mar 2003 L.Pandola Code "cleaned"
// 25 Mar 2003 L.Pandola Changed the name of the database file to read
// 24 Apr 2003 V.Ivanchenko Cut per region mfpt
// --------------------------------------------------------------
#include "G4PenelopeGammaConversion.hh"
#include "Randomize.hh"
#include "G4ParticleDefinition.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4ForceCondition.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4DynamicParticle.hh"
#include "G4VParticleChange.hh"
#include "G4ThreeVector.hh"
#include "G4Positron.hh"
#include "G4IonisParamElm.hh"
#include "G4Material.hh"
#include "G4VCrossSectionHandler.hh"
#include "G4CrossSectionHandler.hh"
#include "G4VEMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4LogLogInterpolation.hh"
#include "G4VRangeTest.hh"
#include "G4RangeTest.hh"
#include "G4MaterialCutsCouple.hh"
G4PenelopeGammaConversion::G4PenelopeGammaConversion(const G4String& processName)
: G4VDiscreteProcess(processName),
lowEnergyLimit(1.022000*MeV),
highEnergyLimit(100*GeV),
intrinsicLowEnergyLimit(1.022000*MeV),
intrinsicHighEnergyLimit(100*GeV),
smallEnergy(1.1*MeV)
{
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
highEnergyLimit > intrinsicHighEnergyLimit)
{
G4Exception("G4PenelopeGammaConversion::G4PenelopeGammaConversion - energy limit outside intrinsic process validity range");
}
// The following pointer is owned by G4DataHandler
crossSectionHandler = new G4CrossSectionHandler();
// Log log interpolation (default)
crossSectionHandler->Initialise(0,1.0220*MeV,100.*GeV,400);
meanFreePathTable = 0;
rangeTest = new G4RangeTest;
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< lowEnergyLimit / MeV << " MeV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
G4PenelopeGammaConversion::~G4PenelopeGammaConversion()
{
delete meanFreePathTable;
delete crossSectionHandler;
delete rangeTest;
}
void G4PenelopeGammaConversion::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
crossSectionHandler->Clear();
G4String crossSectionFile = "penelope/pp-cs-pen-";
crossSectionHandler->LoadData(crossSectionFile);
delete meanFreePathTable;
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
}
G4VParticleChange* G4PenelopeGammaConversion::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
aParticleChange.Initialize(aTrack);
const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double photonEnergy = incidentPhoton->GetKineticEnergy();
G4ParticleMomentum photonDirection = incidentPhoton->GetMomentumDirection();
G4double eps ;
G4double eki = electron_mass_c2 / photonEnergy ;
// Do it fast if photon energy < 1.1 MeV
if (photonEnergy < smallEnergy )
{
eps = eki + (1-2*eki) * G4UniformRand();
}
else
{
// Select randomly one element in the current material
const G4Element* element = crossSectionHandler->SelectRandomElement(couple,photonEnergy);
if (element == 0)
{
G4cout << "G4PenelopeGammaConversion::PostStepDoIt - element = 0" << G4endl;
}
G4IonisParamElm* ionisation = element->GetIonisation();
if (ionisation == 0)
{
G4cout << "G4PenelopeGammaConversion::PostStepDoIt - ionisation = 0" << G4endl;
}
//Low energy and Coulomb corrections
G4double Z=ionisation->GetZ();
G4double ZAlpha = Z*fine_structure_const;
G4double ScreenRadius = GetScreeningRadius(Z);
G4double funct1=0,g0=0;
G4double g1min=0,g2min=0;
funct1 = 4.0*log(ScreenRadius);
g0 = funct1-4*CoulombCorrection(ZAlpha)+LowEnergyCorrection(ZAlpha,eki);
G4double bmin = 2*eki*ScreenRadius;
g1min=g0+ScreenFunction(bmin,1);
g2min=g0+ScreenFunction(bmin,2);
G4double xr,a1,p1;
xr=0.5-eki;
a1=(2.0/3.0)*g1min*xr*xr;
p1=a1/(a1+g2min);
//Random sampling of eps
G4double rand1,rand2,rand3,b;
G4double g1;
do{
rand1 = G4UniformRand();
if (rand1 < p1) {
rand2 = 2.0*G4UniformRand()-1.0;
if (rand2 < 0) {
eps = 0.5 - xr*pow(abs(rand2),(1./3.));
}
else
{
eps = 0.5 + xr*pow(rand2,(1./3.));
}
b = (eki*ScreenRadius)/(2*eps*(1.0-eps));
g1 = g0+ScreenFunction(b,1);
if (g1 < 0) g1=0;
rand3 = G4UniformRand()*g1min;
}
else
{
eps = eki+2.0*xr*G4UniformRand();
b = (eki*ScreenRadius)/(2*eps*(1.0-eps));
g1 = g0+ScreenFunction(b,2);
if (g1 < 0) g1=0;
rand3 = G4UniformRand()*g2min;
}
} while (rand3>g1);
} //End of eps sampling
G4double electronTotEnergy;
G4double positronTotEnergy;
electronTotEnergy = eps*photonEnergy;
positronTotEnergy = (1.0-eps)*photonEnergy;
// Scattered electron (positron) angles. ( Z - axis along the parent photon)
//electron kinematics
G4double costheta_el,costheta_po;
G4double phi_el,phi_po;
G4double electronKineEnergy = G4std::max(0.,electronTotEnergy - electron_mass_c2) ;
costheta_el = G4UniformRand()*2.0-1.0;
G4double kk = sqrt(electronKineEnergy*(electronKineEnergy+2.*electron_mass_c2));
costheta_el = (costheta_el*electronTotEnergy+kk)/(electronTotEnergy+costheta_el*kk);
phi_el = twopi * G4UniformRand() ;
G4double dirX_el = sqrt(1.-costheta_el*costheta_el) * cos(phi_el);
G4double dirY_el = sqrt(1.-costheta_el*costheta_el) * sin(phi_el);
G4double dirZ_el = costheta_el;
//positron kinematics
G4double positronKineEnergy = G4std::max(0.,positronTotEnergy - electron_mass_c2) ;
costheta_po = G4UniformRand()*2.0-1.0;
kk = sqrt(positronKineEnergy*(positronKineEnergy+2.*electron_mass_c2));
costheta_po = (costheta_po*positronTotEnergy+kk)/(positronTotEnergy+costheta_po*kk);
phi_po = twopi * G4UniformRand() ;
G4double dirX_po = sqrt(1.-costheta_po*costheta_po) * cos(phi_po);
G4double dirY_po = sqrt(1.-costheta_po*costheta_po) * sin(phi_po);
G4double dirZ_po = costheta_po;
// Kinematics of the created pair:
// the electron and positron are assumed to have a symetric angular
// distribution with respect to the Z axis along the parent photon
G4double localEnergyDeposit = 0. ;
aParticleChange.SetNumberOfSecondaries(2) ;
// Generate the electron only if with large enough range w.r.t. cuts and safety
G4double safety = aStep.GetPostStepPoint()->GetSafety();
if (rangeTest->Escape(G4Electron::Electron(),couple,electronKineEnergy,safety))
{
G4ThreeVector electronDirection ( dirX_el, dirY_el, dirZ_el);
electronDirection.rotateUz(photonDirection);
G4DynamicParticle* particle1 = new G4DynamicParticle (G4Electron::Electron(),
electronDirection,
electronKineEnergy);
aParticleChange.AddSecondary(particle1) ;
}
else
{
localEnergyDeposit += electronKineEnergy ;
}
if (! (rangeTest->Escape(G4Positron::Positron(),couple,positronKineEnergy,safety)))
{
localEnergyDeposit += positronKineEnergy ;
positronKineEnergy = 0. ;
}
G4ThreeVector positronDirection(dirX_po,dirY_po,dirZ_po);
positronDirection.rotateUz(photonDirection);
// Create G4DynamicParticle object for the particle2
G4DynamicParticle* particle2 = new G4DynamicParticle(G4Positron::Positron(),
positronDirection, positronKineEnergy);
aParticleChange.AddSecondary(particle2) ;
aParticleChange.SetLocalEnergyDeposit(localEnergyDeposit) ;
// Kill the incident photon
aParticleChange.SetMomentumChange(0.,0.,0.) ;
aParticleChange.SetEnergyChange(0.) ;
aParticleChange.SetStatusChange(fStopAndKill) ;
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
G4bool G4PenelopeGammaConversion::IsApplicable(const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
}
G4double G4PenelopeGammaConversion::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition*)
{
const G4DynamicParticle* photon = track.GetDynamicParticle();
G4double energy = photon->GetKineticEnergy();
const G4MaterialCutsCouple* couple = track.GetMaterialCutsCouple();
size_t materialIndex = couple->GetIndex();
G4double meanFreePath;
if (energy > highEnergyLimit) meanFreePath = meanFreePathTable->FindValue(highEnergyLimit,materialIndex);
else if (energy < lowEnergyLimit) meanFreePath = DBL_MAX;
else meanFreePath = meanFreePathTable->FindValue(energy,materialIndex);
return meanFreePath;
}
G4double G4PenelopeGammaConversion::ScreenFunction(G4double b,G4int icase)
{
G4double bsquare=b*b;
G4double a0,f1,f2,g1,g2;
f1=2.0-2*log(1+bsquare);
f2=f1-(2.0/3.0);
if (b < 1.0e-10)
{
f1=f1-twopi*b;
}
else
{
a0 = 4*b*atan(1.0/b);
f1 = f1 - a0;
f2 = f2+2*bsquare*(4.0-a0-3*log((1+bsquare)/bsquare));
}
g1=0.5*(3*f1-f2);
g2=0.25*(3*f1+f2);
if (icase==1) {
return g1;
}
else
{
return g2;
}
}
G4double G4PenelopeGammaConversion::CoulombCorrection(G4double a)
{
G4double fc=0;
G4double b[7] = {0.202059,-0.03693,0.00835,-0.00201,0.00049,-0.00012,0.00003};
fc = ((1.0/(1.0+a*a))+b[0]+b[1]*pow(a,2)+b[2]*pow(a,4)+b[3]*pow(a,6)+b[4]*pow(a,8)+b[5]*pow(a,10)+b[6]*pow(a,12));
fc=pow(a,2)*fc;
return fc;
}
G4double G4PenelopeGammaConversion::LowEnergyCorrection(G4double a,G4double eki)
{
G4double f0=0,t=0;
G4double b[12] = {-1.744,-12.10,11.18,8.523,73.26,-41.41,-13.52,-121.1,94.41,8.946,62.05,-63.41};
t=sqrt(2.0*eki);
f0=(b[0]+b[1]*a+b[2]*a*a)*t+(b[3]+b[4]*a+b[5]*a*a)*pow(t,2)+(b[6]+b[7]*a+b[8]*a*a)*pow(t,3)+
(b[9]+b[10]*a+b[11]*a*a)*pow(t,4);
return f0;
}
G4double G4PenelopeGammaConversion::GetScreeningRadius(G4double Z)
{
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4PenelopeGammaConversion - G4LEDATA environment variable not set!";
G4Exception(excep);
}
G4String pathString(path);
G4String pathFile = pathString + "/penelope/pp-pen.dat";
G4std::ifstream file(pathFile);
G4std::filebuf* lsdp = file.rdbuf();
if (!(lsdp->is_open()))
{
G4String excep = "G4PenelopeGammaConversion - data file " + pathFile + "not found!";
G4Exception(excep);
}
G4int k;
G4double a1,a2;
while(!file.eof()) {
file >> k >> a1 >> a2;
if ((G4double) k == Z)
{
return a1;
}
}
G4String excep = "G4PenelopeGammaConversion - Screening Radius for not found in the data file";
G4Exception(excep);
return 0;
};
@@ -0,0 +1,241 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
//
// Author: Luciano Pandola (Luciano.Pandola@cern.ch)
//
// History:
// -----------
// 17 Feb 2003 LP Created
//
// -------------------------------------------------------------------
#include "G4PenelopeInterpolator.hh"
#include "G4DataVector.hh"
G4PenelopeInterpolator::G4PenelopeInterpolator(G4double* pX,G4double* pY,G4int nOfData,G4double S1,G4double SN) :
a(0),b(0),c(0),d(0),x(0),y(0)
{
// pX = X grid points (ascending order)
// pY = corresponding function values
// nOfData = number of points in the grid > 4
// S1 and S2 = second derivatives at X[0] and X[nOfData-1]
a = new G4DataVector;
b = new G4DataVector;
c = new G4DataVector;
d = new G4DataVector;
if (nOfData < 4 )
{
G4String excep = "Spline interpolation cannot be performed with less than 4 points";
G4Exception(excep);
}
G4int N1=nOfData-1;
G4int N2=nOfData-2;
G4int i;
G4int k=0;
G4DataVector A(N1),B(N2),D(nOfData);//auxiliary arrays
A.clear();
B.clear();
D.clear();
for (i=0;i<N1;i++){
if ((pX[i+1]-pX[i]) < 1.0e-13)
{
G4String excep = "Spline x values not in increasing order";
G4Exception(excep);
}
A.push_back(pX[i+1]-pX[i]);
D.push_back((pY[i+1]-pY[i])/A[i]);
}
//Symmetric coefficient matrix
for (i=0;i<N2;i++){
B.push_back(2.0*(A[i]+A[i+1]));
k=N1-i-1;
D[k]=6.0*(D[k]-D[k-1]);
}
D[1]=D[1]-A[0]*S1;
D[N1-1]=D[N1-1]-A[N1-1]*SN;
//Gauss solution of the tridiagonal system
for (i=1;i<N2;i++){
G4double R=A[i]/B[i-1];
B[i]=B[i]-R*A[i];
D[i+1]=D[i+1]-R*D[i];
}
//The sigma coefficients are stored in array D
D[N1-1]=D[N1-1]/B[N2-1];
for (i=1;i<N2;i++){
k=N1-i-1;
D[k]=(D[k]-A[k]*D[k+1])/B[k-1];
}
D.push_back(SN);
//Spline coefficients
G4double SI1=S1;
G4double SI=0,H=0,HI=0;
G4double store=0;
for (i=0;i<N1;i++){
SI=SI1;
SI1=D[i+1];
H=A[i];
HI=1.0/H;
store=HI*(SI*pow(pX[i+1],3)-SI1*pow(pX[i],3))/6.0+HI*(pY[i]*pX[i+1]-pY[i+1]*pX[i])+
H*(SI1*pX[i]-SI*pX[i+1])/6.0;
a->push_back(store);
store=(HI/2.0)*(SI1*pow(pX[i],2)-SI*pow(pX[i+1],2))+HI*(pY[i+1]-pY[i])+(H/6.0)*(SI-SI1);
b->push_back(store);
store=(HI/2.0)*(SI*pX[i+1]-SI1*pX[i]);
c->push_back(store);
store=(HI/6.0)*(SI1-SI);
d->push_back(store);
}
//Natural cubic spline for x > x[nOfData-1]
G4double FN=pY[nOfData-1];
store=(*b)[N1-1]+pX[nOfData-1]*(2.0*(*c)[N1-1]+pX[nOfData-1]*3.0*(*d)[N1-1]);
a->push_back(FN-pX[nOfData-1]*store);
b->push_back(store);
c->push_back(0.0);
d->push_back(0.0);
x = new G4DataVector;
y = new G4DataVector;
for (i=0;i<nOfData;i++){
x->push_back(pX[i]);
y->push_back(pY[i]);
}
return;
}
G4double G4PenelopeInterpolator::CubicSplineInterpolation(G4double xx)
{
G4double interp=0;
G4int index = FindBin(xx);
interp=(*a)[index]+xx*((*b)[index]+xx*((*c)[index]+xx*(*d)[index]));
return interp;
}
G4double G4PenelopeInterpolator::FirstDerivative(G4double xx)
{
G4double interp=0;
G4int index = FindBin(xx);
interp=(*b)[index]+xx*((*c)[index]*2.0+xx*(*d)[index]*3.0);
return interp;
}
G4double G4PenelopeInterpolator::CalculateMomentum(G4double UpperLimit,
G4int MomentumOrder)
{
G4int i;
G4int nOfData = (G4int) x->size();
const G4double eps=1.0e-35;
if (MomentumOrder < -1) G4Exception("Calculate Momentum: error 0");
if (nOfData < 2) G4Exception("Calculate Momentum: error 1");
if ((*x)[0]<0) G4Exception("Calculate Momentum: error 2");
for (i=1;i<nOfData;i++)
{
if ((*x)[i]<0) G4Exception("Calculate Momentum: error 3");
if ((*x)[i] < (*x)[i-1]) G4Exception ("Calculate Momentum: error 4");
}
G4double RMom=0.0;
if (UpperLimit < (*x)[0]) return RMom;
G4int iend=0;
G4double xt=G4std::min(UpperLimit,(*x)[nOfData-1]);
G4double x1,x2,y1,y2;
G4double xtc,dx,dy,a1,b1,ds;
for (i=0;i<(nOfData-1);i++){
x1=G4std::max((*x)[i],eps);
y1=(*y)[i];
x2=G4std::max((*x)[i+1],eps);
y2=(*y)[i+1];
if (xt < x2)
{
xtc=xt;
iend=1;
}
else
{
xtc=x2;
}
dx=x2-x1;
dy=y2-y1;
if (abs(dx) > (1e-14*abs(dy)))
{
b1=dy/dx;
a1=y1-b1*x1;
if (MomentumOrder == -1)
{
ds=a1*log(xtc/x1)+b1*(xtc-x1);
}
else
{
ds=a1*(pow(xtc,MomentumOrder+1)-pow(x1,MomentumOrder+1))/ ((G4double) (MomentumOrder+1))+
b1*(pow(xtc,MomentumOrder+2)-pow(x1,MomentumOrder+2))/((G4double) (MomentumOrder+2));
}
}
else
{
ds=0.5*(y1+y2)*pow((xtc-x1),MomentumOrder);
}
RMom += ds;
if (iend != 0) return RMom;
}
return RMom;
}
G4int G4PenelopeInterpolator::FindBin(G4double xx)
{
//Finds the interval x[i],x[i+1] which contains the value xx
G4int nbOfPoints=x->size();
if (xx > (*x)[nbOfPoints-1])
{
return (nbOfPoints-1);
}
if (xx < (*x)[0])
{
return 0;
}
G4int i=0,i1=nbOfPoints-1;
do{
G4int it=(i+i1)/2;
if (xx > (*x)[it])
{
i=it;
}
else
{
i1=it;
}
} while((i1-i) > 1);
return i;
}
@@ -0,0 +1,317 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// $Id: G4PenelopePhotoElectric.cc,v 1.5 2003/03/13 17:04:10 pandola Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: L. Pandola
//
// History:
// --------
// January 2003 - Created
// 12 Feb 2003 MG Pia Migration to "cuts per region"
// 10 Mar 2003 V.Ivanchenko Remome CutPerMaterial warning
// --------------------------------------------------------------
#include "G4PenelopePhotoElectric.hh"
#include "G4ParticleDefinition.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4ForceCondition.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4DynamicParticle.hh"
#include "G4VParticleChange.hh"
#include "G4ThreeVector.hh"
#include "G4VCrossSectionHandler.hh"
#include "G4CrossSectionHandler.hh"
#include "G4VEMDataSet.hh"
#include "G4CompositeEMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4LogLogInterpolation.hh"
#include "G4VRangeTest.hh"
#include "G4RangeNoTest.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4AtomicShell.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4ProductionCutsTable.hh"
G4PenelopePhotoElectric::G4PenelopePhotoElectric(const G4String& processName)
: G4VDiscreteProcess(processName), lowEnergyLimit(250*eV), highEnergyLimit(100*GeV),
intrinsicLowEnergyLimit(10*eV),
intrinsicHighEnergyLimit(100*GeV),
cutForLowEnergySecondaryPhotons(250.*eV),
cutForLowEnergySecondaryElectrons(250.*eV)
{
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
highEnergyLimit > intrinsicHighEnergyLimit)
{
G4Exception("G4PenelopePhotoElectric::G4PenelopePhotoElectric - energy limit outside intrinsic process validity range");
}
crossSectionHandler = new G4CrossSectionHandler();
shellCrossSectionHandler = new G4CrossSectionHandler();
meanFreePathTable = 0;
rangeTest = new G4RangeNoTest;
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
G4PenelopePhotoElectric::~G4PenelopePhotoElectric()
{
delete crossSectionHandler;
delete shellCrossSectionHandler;
delete meanFreePathTable;
delete rangeTest;
}
void G4PenelopePhotoElectric::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
crossSectionHandler->Clear();
G4String crossSectionFile = "penelope/ph-cs-pen-";
crossSectionHandler->LoadData(crossSectionFile);
shellCrossSectionHandler->Clear();
G4String shellCrossSectionFile = "penelope/ph-ss-cs-pen-";
shellCrossSectionHandler->LoadShellData(shellCrossSectionFile);
delete meanFreePathTable;
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
}
G4VParticleChange* G4PenelopePhotoElectric::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
// Fluorescence generated according to:
// J. Stepanek ,"A program to determine the radiation spectra due to a single atomic
// subshell ionisation by a particle or due to deexcitation or decay of radionuclides",
// Comp. Phys. Comm. 1206 pp 1-1-9 (1997)
aParticleChange.Initialize(aTrack);
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double photonEnergy = incidentPhoton->GetKineticEnergy();
if (photonEnergy <= lowEnergyLimit)
{
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit(photonEnergy);
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
G4ParticleMomentum photonDirection = incidentPhoton->GetMomentumDirection();
// Select randomly one element in the current material
const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
G4int Z = crossSectionHandler->SelectRandomAtom(couple,photonEnergy);
// Select the ionised shell in the current atom according to shell cross sections
size_t shellIndex = shellCrossSectionHandler->SelectRandomShell(Z,photonEnergy);
// Retrieve the corresponding identifier and binding energy of the selected shell
const G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
const G4AtomicShell* shell = transitionManager->Shell(Z,shellIndex);
G4double bindingEnergy = shell->BindingEnergy();
G4int shellId = shell->ShellId();
// Create lists of pointers to DynamicParticles (photons and electrons)
// (Is the electron vector necessary? To be checked)
G4std::vector<G4DynamicParticle*>* photonVector = 0;
G4std::vector<G4DynamicParticle*> electronVector;
G4double energyDeposit = 0.0;
// Primary outcoming electron
G4double eKineticEnergy = photonEnergy - bindingEnergy;
// There may be cases where the binding energy of the selected shell is > photon energy
// In such cases do not generate secondaries
if (eKineticEnergy > 0.)
{
// Generate the electron only if with large enough range w.r.t. cuts and safety
G4double safety = aStep.GetPostStepPoint()->GetSafety();
if (rangeTest->Escape(G4Electron::Electron(),couple,eKineticEnergy,safety))
{
// The electron is created in the direction of the incident photon ...
G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),
photonDirection,
eKineticEnergy);
electronVector.push_back(electron);
}
else
{
energyDeposit += eKineticEnergy;
}
}
else
{
bindingEnergy = photonEnergy;
}
G4int nElectrons = electronVector.size();
size_t nTotPhotons = 0;
G4int nPhotons=0;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t index = couple->GetIndex();
G4double cutg = (*(theCoupleTable->GetEnergyCutsVector(0)))[index];
cutg = G4std::min(cutForLowEnergySecondaryPhotons,cutg);
G4double cute = (*(theCoupleTable->GetEnergyCutsVector(1)))[index];
cute = G4std::min(cutForLowEnergySecondaryPhotons,cute);
G4DynamicParticle* aPhoton;
// Generation of fluorescence
// Data in EADL are available only for Z > 5
// Protection to avoid generating photons in the unphysical case of
// shell binding energy > photon energy
if (Z > 5 && (bindingEnergy > cutg || bindingEnergy > cute))
{
photonVector = deexcitationManager.GenerateParticles(Z,shellId);
nTotPhotons = photonVector->size();
for (size_t k=0; k<nTotPhotons; k++)
{
aPhoton = (*photonVector)[k];
if (aPhoton)
{
G4double itsCut = cutg;
if(aPhoton->GetDefinition() == G4Electron::Electron()) itsCut = cute;
G4double itsEnergy = aPhoton->GetKineticEnergy();
if (itsEnergy > itsCut && itsEnergy <= bindingEnergy)
{
nPhotons++;
// Local energy deposit is given as the sum of the
// energies of incident photons minus the energies
// of the outcoming fluorescence photons
bindingEnergy -= itsEnergy;
}
else
{
delete aPhoton;
(*photonVector)[k] = 0;
}
}
}
}
energyDeposit += bindingEnergy;
G4int nSecondaries = nElectrons + nPhotons;
aParticleChange.SetNumberOfSecondaries(nSecondaries);
for (G4int l = 0; l<nElectrons; l++ )
{
aPhoton = electronVector[l];
if(aPhoton) {
aParticleChange.AddSecondary(aPhoton);
}
}
for ( size_t ll = 0; ll < nTotPhotons; ll++)
{
aPhoton = (*photonVector)[ll];
if(aPhoton) {
aParticleChange.AddSecondary(aPhoton);
}
}
delete photonVector;
if (energyDeposit < 0)
{
G4cout << "WARNING - "
<< "G4PenelopePhotoElectric::PostStepDoIt - Negative energy deposit"
<< G4endl;
energyDeposit = 0;
}
// Kill the incident photon
aParticleChange.SetMomentumChange( 0., 0., 0. );
aParticleChange.SetEnergyChange( 0. );
aParticleChange.SetLocalEnergyDeposit(energyDeposit);
aParticleChange.SetStatusChange( fStopAndKill );
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep );
}
G4bool G4PenelopePhotoElectric::IsApplicable(const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
}
G4double G4PenelopePhotoElectric::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition*)
{
const G4DynamicParticle* photon = track.GetDynamicParticle();
G4double energy = photon->GetKineticEnergy();
G4Material* material = track.GetMaterial();
G4double meanFreePath = DBL_MAX;
G4double cross = shellCrossSectionHandler->ValueForMaterial(material,energy);
if(cross > 0.0) meanFreePath = 1.0/cross;
return meanFreePath;
}
void G4PenelopePhotoElectric::SetCutForLowEnSecPhotons(G4double cut)
{
cutForLowEnergySecondaryPhotons = cut;
deexcitationManager.SetCutForSecondaryPhotons(cut);
}
void G4PenelopePhotoElectric::SetCutForLowEnSecElectrons(G4double cut)
{
cutForLowEnergySecondaryElectrons = cut;
deexcitationManager.SetCutForAugerElectrons(cut);
}
void G4PenelopePhotoElectric::ActivateAuger(G4bool val)
{
deexcitationManager.ActivateAugerElectronProduction(val);
}
@@ -0,0 +1,499 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
// --------------------------------------------------------------------
//
// $Id: G4PenelopeRayleigh.cc,v 1.7 2003/03/13 16:55:35 pandola Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: L. Pandola (luciano.pandola@cern.ch)
//
// History:
// --------
// 14 Feb 2003 MG Pia Corrected compilation errors and warnings
// from SUN
// 10 Mar 2003 V.Ivanchenko Remove CutPerMaterial warning
// 12 Mar 2003 L.Pandola Code "cleaned" - Cuts per region
// --------------------------------------------------------------------
#include "G4PenelopeRayleigh.hh"
#include "Randomize.hh"
#include "G4ParticleDefinition.hh"
#include "G4Track.hh"
#include "G4Step.hh"
#include "G4ForceCondition.hh"
#include "G4Gamma.hh"
#include "G4Electron.hh"
#include "G4DynamicParticle.hh"
#include "G4VParticleChange.hh"
#include "G4ThreeVector.hh"
#include "G4VCrossSectionHandler.hh"
#include "G4CrossSectionHandler.hh"
#include "G4VEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4CompositeEMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4LogLogInterpolation.hh"
#include "G4PenelopeIntegrator.hh"
#include "G4MaterialCutsCouple.hh"
G4PenelopeRayleigh::G4PenelopeRayleigh(const G4String& processName)
: G4VDiscreteProcess(processName),
lowEnergyLimit(250*eV),
highEnergyLimit(100*GeV),
samplingConstant(0.0),
nBins(200),
intrinsicLowEnergyLimit(10*eV),
intrinsicHighEnergyLimit(100*GeV)
{
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
highEnergyLimit > intrinsicHighEnergyLimit)
{
G4Exception("G4PenelopeRayleigh::G4PenelopeRayleigh - energy limit outside intrinsic process validity range");
}
samplingFunction_x = new G4DataVector();
samplingFunction_y = new G4DataVector();
meanFreePathTable = 0;
material = 0;
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
G4PenelopeRayleigh::~G4PenelopeRayleigh()
{
delete meanFreePathTable;
delete samplingFunction_x;
delete samplingFunction_y;
}
void G4PenelopeRayleigh::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
G4DataVector energyVector;
G4double dBin = log10(highEnergyLimit/lowEnergyLimit)/nBins;
for (G4int i=0;i<nBins;i++)
{
energyVector.push_back(pow(10.,log10(lowEnergyLimit)+i*dBin));
}
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
G4int nMaterials = G4Material::GetNumberOfMaterials();
size_t nOfBins = energyVector.size();
size_t bin=0;
G4VDataSetAlgorithm* algo = new G4LogLogInterpolation();
G4VEMDataSet* materialSet = new G4CompositeEMDataSet(algo,1.,1.);
G4std::vector<G4VEMDataSet*> matCrossSections;
G4int m;
for (m=0; m<nMaterials; m++)
{
G4DataVector* energies = new G4DataVector;
G4DataVector* data = new G4DataVector;
material = (*materialTable)[m];
G4int nElements = material->GetNumberOfElements();
const G4ElementVector* elementVector = material->GetElementVector();
const G4double k1=849.3315;
G4int IZZ=0;
G4int iright=0;
for (G4int i=0; i<nElements; i++) {
G4int Z = (G4int) (*elementVector)[i]->GetZ();
if (Z>IZZ){
IZZ = Z;
iright=i;
}
}
for (bin=0; bin<nOfBins; bin++)
{
energies->push_back(energyVector[bin]);
G4double ec=G4std::min(energyVector[bin],0.5*IZZ);
facte=k1*pow(ec/electron_mass_c2,2);
G4double cs=0;
G4PenelopeIntegrator<G4PenelopeRayleigh,G4double(G4PenelopeRayleigh::*)(G4double)> theIntegrator;
cs =
theIntegrator.Calculate(this,&G4PenelopeRayleigh::DifferentialCrossSection,-1.0,0.90,1e-06);
cs += theIntegrator.Calculate(this,&G4PenelopeRayleigh::DifferentialCrossSection,0.90,0.9999999,1e-06);
cs = cs*pow((ec/energyVector[bin]),2)*pi*pow(classic_electr_radius,2);
const G4double* vector_of_atoms = material->GetVecNbOfAtomsPerVolume();
const G4int* stechiometric = material->GetAtomsVector();
G4double density;
if (stechiometric)
{
density = vector_of_atoms[iright]/stechiometric[iright]; //number of molecules per volume
}
else
{
density = vector_of_atoms[iright]; //non-bound molecules
}
G4double cross = density*cs;
data->push_back(cross);
}
G4VEMDataSet* elSet = new G4EMDataSet(0,energies,data,algo);
G4VEMDataSet* setForMat = new G4CompositeEMDataSet(algo);
setForMat->AddComponent(elSet);
matCrossSections.push_back(setForMat);
}
G4double matCS = 0.0;
for (m=0; m<nMaterials; m++)
{
G4DataVector* energies = new G4DataVector;
G4DataVector* data = new G4DataVector;
for (bin=0;bin<nOfBins;bin++){
energies->push_back(energyVector[bin]);
matCS = (matCrossSections[m]->GetComponent(0))->FindValue(energyVector[bin]);
if (matCS > 0.){
data->push_back(1./matCS);
}
else
{
data->push_back(DBL_MAX);
}
}
G4VEMDataSet* dataSet = new G4EMDataSet(m,energies,data,algo,1.,1.);
materialSet->AddComponent(dataSet);
}
meanFreePathTable = materialSet;
}
G4VParticleChange* G4PenelopeRayleigh::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
aParticleChange.Initialize(aTrack);
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double photonEnergy0 = incidentPhoton->GetKineticEnergy();
if (photonEnergy0 <= lowEnergyLimit)
{
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit(photonEnergy0);
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
G4ParticleMomentum photonDirection0 = incidentPhoton->GetMomentumDirection();
const G4MaterialCutsCouple* couple = aTrack.GetMaterialCutsCouple();
material = couple->GetMaterial();
// Sampling inizialitation (build internal table)
InizialiseSampling();
// Sample the angle of the scattered photon
const G4double xpar=41.2148;
G4double x2max = 2.0*log(xpar*photonEnergy0/electron_mass_c2);
G4int jm;
G4int asize = samplingFunction_x->size();
if (x2max<(*samplingFunction_x)[1])
{
jm=0;
}
else if(x2max>(*samplingFunction_x)[asize-2])
{
jm=asize-2;
}
else
{
jm=(G4int) ((x2max-(*samplingFunction_x)[0])/samplingConstant);
}
G4double rumax = (*samplingFunction_y)[jm]+((*samplingFunction_y)[jm+1]-(*samplingFunction_y)[jm])*
(x2max-(*samplingFunction_x)[jm])/((*samplingFunction_x)[jm+1]-(*samplingFunction_x)[jm]);
G4int j,ju,jt;
G4double ru,denomin,x2rat;
G4double CDT,G,rand;
do{
ru = rumax + log(G4UniformRand());
j=0;
ju=jm+1;
do{
jt=(j+ju)/2; //bipartition
if (ru > (*samplingFunction_y)[jt])
{
j=jt;
}
else
{
ju=jt;
}
}while ((ju-j)>1);
denomin = (*samplingFunction_y)[j+1]-(*samplingFunction_y)[j];
if (denomin > 1e-12)
{
x2rat = (*samplingFunction_x)[j]+(((*samplingFunction_x)[j+1]-(*samplingFunction_x)[j])*
(ru-(*samplingFunction_y)[j])/denomin)-x2max;
}
else
{
x2rat = (*samplingFunction_x)[j]-x2max;
}
CDT = 1.0-2.0*exp(x2rat);
G = 0.5*(1.0+CDT*CDT);
rand = G4UniformRand();
}while (rand>G);
G4double cosTheta = CDT;
G4double sinTheta = sqrt(1-cosTheta*cosTheta);
// Scattered photon angles. ( Z - axis along the parent photon)
G4double phi = twopi * G4UniformRand() ;
G4double dirX = sinTheta*cos(phi);
G4double dirY = sinTheta*sin(phi);
G4double dirZ = cosTheta;
// Update G4VParticleChange for the scattered photon
G4ThreeVector photonDirection1(dirX, dirY, dirZ);
photonDirection1.rotateUz(photonDirection0);
aParticleChange.SetEnergyChange(photonEnergy0);
aParticleChange.SetMomentumChange(photonDirection1);
aParticleChange.SetNumberOfSecondaries(0);
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
G4bool G4PenelopeRayleigh::IsApplicable(const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
}
G4double G4PenelopeRayleigh::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition*)
{
const G4DynamicParticle* photon = track.GetDynamicParticle();
G4double energy = photon->GetKineticEnergy();
material = track.GetMaterial();
size_t materialIndex = material->GetIndex();
G4double meanFreePath;
if (energy > highEnergyLimit) meanFreePath = meanFreePathTable->FindValue(highEnergyLimit,materialIndex);
else if (energy < lowEnergyLimit) meanFreePath = DBL_MAX;
else
{
meanFreePath = meanFreePathTable->FindValue(energy,materialIndex);
}
return meanFreePath;
}
void G4PenelopeRayleigh::InizialiseSampling()
{
const G4int points=241;
samplingFunction_x->clear();
samplingFunction_y->clear();
G4double sum = 0.0;
G4double Xlow=0;
G4double Xhigh=1e-04;
G4double fact = pow((1e06/Xhigh),(1/240.0));
G4PenelopeIntegrator<G4PenelopeRayleigh,G4double(G4PenelopeRayleigh::*)(G4double)> theIntegrator;
sum = theIntegrator.Calculate(this,&G4PenelopeRayleigh::MolecularFormFactor,
Xlow,Xhigh,1e-10);
samplingFunction_x->push_back(Xhigh);
samplingFunction_y->push_back(sum);
G4int i;
for (i=1;i<points;i++){
Xlow=Xhigh;
Xhigh=Xhigh*fact;
sum = theIntegrator.Calculate(this,
&G4PenelopeRayleigh::MolecularFormFactor,
Xlow,Xhigh,1e-10);
samplingFunction_x->push_back(Xhigh);
samplingFunction_y->push_back(sum+(*samplingFunction_y)[i-1]);
}
for (i=0;i<points;i++){
(*samplingFunction_x)[i]=log((*samplingFunction_x)[i]);
(*samplingFunction_y)[i]=log((*samplingFunction_y)[i]);
}
samplingConstant=log(fact);
}
G4double G4PenelopeRayleigh::MolecularFormFactor(G4double y)
{
const G4int ntot=95;
G4double RA1[ntot] = {0.0e0, 3.9265e+0, 4.3100e+1, 5.2757e+1, 2.5021e+1,
1.2211e+1, 9.3229e+0, 3.2455e+0, 2.4197e+0, 1.5985e+0,
3.0926e+1, 1.5315e+1, 7.7061e+0, 3.9493e+0, 2.2042e+0,
1.9453e+1, 1.9354e+1, 8.0374e+0, 8.3779e+1, 5.7370e+1,
5.2310e+1, 4.7514e+1, 4.3785e+1, 4.2048e+1, 3.6972e+1,
3.3849e+1, 3.1609e+1, 2.8763e+1, 2.7217e+1, 2.4263e+1,
2.2403e+1, 1.8606e+1, 1.5143e+1, 1.4226e+1, 1.1792e+1,
9.7574e+0, 1.2796e+1, 1.2854e+1, 1.2368e+1, 1.0208e+1,
8.2823e+0, 7.4677e+0, 7.6028e+0, 6.1090e+0, 5.5346e+0,
4.2340e+0, 4.0444e+0, 4.2905e+0, 4.7950e+0, 5.1112e+0,
5.2407e+0, 5.2153e+0, 5.1639e+0, 4.8814e+0, 5.8054e+0,
6.6724e+0, 6.5104e+0, 6.3364e+0, 6.2889e+0, 6.3028e+0,
6.3853e+0, 6.3475e+0, 6.5779e+0, 6.8486e+0, 7.0993e+0,
7.6122e+0, 7.9681e+0, 8.3481e+0, 6.3875e+0, 8.0042e+0,
8.0820e+0, 7.6940e+0, 7.1927e+0, 6.6751e+0, 6.1623e+0,
5.8335e+0, 5.5599e+0, 4.6551e+0, 4.4327e+0, 4.7601e+0,
5.2872e+0, 5.6084e+0, 5.7680e+0, 5.8041e+0, 5.7566e+0,
5.6541e+0, 6.3932e+0, 6.9313e+0, 7.0027e+0, 6.8796e+0,
6.4739e+0, 6.2405e+0, 6.0081e+0, 5.5708e+0, 5.3680e+0};
G4double RA2[ntot] = {0.0e0, 1.3426e-1, 9.4875e+1,-1.0896e+2,-4.5494e+1,
-1.9572e+1,-1.2382e+1,-3.6827e+0,-2.4542e+0,-1.4453e+0,
1.3401e+2, 7.9717e+1, 6.2164e+1, 4.0300e+1, 3.1682e+1,
-1.3639e+1,-1.5950e+1,-5.1523e+0, 1.8351e+2, 1.2205e+2,
1.0007e+2, 8.5632e+1, 7.9145e+1, 6.3675e+1, 6.2954e+1,
5.6601e+1, 5.4171e+1, 4.8752e+1, 3.8062e+1, 3.9933e+1,
4.8343e+1, 4.2137e+1, 3.4617e+1, 2.9430e+1, 2.4010e+1,
1.9744e+1, 4.0009e+1, 5.1614e+1, 5.0456e+1, 3.9088e+1,
2.6824e+1, 2.2953e+1, 2.4773e+1, 1.6893e+1, 1.4548e+1,
9.7226e+0, 1.0192e+1, 1.1153e+1, 1.3188e+1, 1.4733e+1,
1.5644e+1, 1.5939e+1, 1.5923e+1, 1.5254e+1, 2.0748e+1,
2.6901e+1, 2.7032e+1, 2.4938e+1, 2.1528e+1, 2.0362e+1,
1.9474e+1, 1.8238e+1, 1.7898e+1, 1.9174e+1, 1.9023e+1,
1.8194e+1, 1.8504e+1, 1.8955e+1, 1.4276e+1, 1.7558e+1,
1.8651e+1, 1.7984e+1, 1.6793e+1, 1.5469e+1, 1.4143e+1,
1.3149e+1, 1.2255e+1, 9.2352e+0, 8.6067e+0, 9.7460e+0,
1.1749e+1, 1.3281e+1, 1.4326e+1, 1.4920e+1, 1.5157e+1,
1.5131e+1, 1.9489e+1, 2.3649e+1, 2.4686e+1, 2.4760e+1,
2.1519e+1, 2.0099e+1, 1.8746e+1, 1.5943e+1, 1.4880e+1};
G4double RA3[ntot] = {0.0e0, 2.2648e+0, 1.0579e+3, 8.6177e+2, 2.4422e+2,
7.8788e+1, 3.8293e+1, 1.2564e+1, 6.9091e+0, 3.7926e+0,
0.0000e+0, 0.0000e+0, 1.6759e-9, 1.3026e+1, 3.0569e+0,
1.5521e+2, 1.2815e+2, 4.7378e+1, 9.2802e+2, 4.7508e+2,
3.6612e+2, 2.7582e+2, 2.1008e+2, 1.5903e+2, 1.2322e+2,
9.2898e+1, 7.1345e+1, 5.1651e+1, 3.8474e+1, 2.7410e+1,
1.9126e+1, 1.0889e+1, 5.3479e+0, 8.2223e+0, 5.0837e+0,
2.8905e+0, 2.7457e+0, 6.7082e-1, 0.0000e+0, 0.0000e+0,
0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
0.0000e+0, 0.0000e+0, 0.0000e+0, 1.7264e-1, 2.7322e-1,
3.9444e-1, 4.5648e-1, 6.2286e-1, 7.2468e-1, 8.4296e-1,
1.1698e+0, 1.2994e+0, 1.4295e+0, 0.0000e+0, 8.1570e-1,
6.9349e-1, 4.9536e-1, 3.1211e-1, 1.5931e-1, 2.9512e-2,
0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0,
0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0, 0.0000e+0};
G4double RA4[ntot] = {1.1055e1,6.3519e0,4.7367e+1, 3.9402e+1, 2.2896e+1,
1.3979e+1, 1.0766e+1, 6.5252e+0, 5.1631e+0, 4.0524e+0,
2.7145e+1, 1.8724e+1, 1.4782e+1, 1.1608e+1, 9.7750e+0,
1.6170e+1, 1.5249e+1, 9.1916e+0, 5.4499e+1, 4.1381e+1,
3.7395e+1, 3.3815e+1, 3.1135e+1, 2.8273e+1, 2.6140e+1,
2.3948e+1, 2.2406e+1, 2.0484e+1, 1.8453e+1, 1.7386e+1,
1.7301e+1, 1.5388e+1, 1.3411e+1, 1.2668e+1, 1.1133e+1,
9.8081e+0, 1.3031e+1, 1.4143e+1, 1.3815e+1, 1.2077e+1,
1.0033e+1, 9.2549e+0, 9.5338e+0, 7.9076e+0, 7.3263e+0,
5.9996e+0, 6.0087e+0, 6.2660e+0, 6.7914e+0, 7.1501e+0,
7.3367e+0, 7.3729e+0, 7.3508e+0, 7.1465e+0, 8.2731e+0,
9.3745e+0, 9.3508e+0, 8.9897e+0, 8.4566e+0, 8.2690e+0,
8.1398e+0, 7.9183e+0, 7.9123e+0, 8.1677e+0, 8.1871e+0,
8.1766e+0, 8.2881e+0, 8.4227e+0, 7.0273e+0, 8.0002e+0,
8.1440e+0, 7.9104e+0, 7.5685e+0, 7.1970e+0, 6.8184e+0,
6.5469e+0, 6.3056e+0, 5.4844e+0, 5.2832e+0, 5.5889e+0,
6.0919e+0, 6.4340e+0, 6.6426e+0, 6.7428e+0, 6.7636e+0,
6.7281e+0, 7.5729e+0, 8.2808e+0, 8.4400e+0, 8.4220e+0,
7.8662e+0, 7.5993e+0, 7.3353e+0, 6.7829e+0, 6.5520e+0};
G4double RA5[ntot] = {0.0e0, 4.9828e+0, 5.5674e+1, 3.0902e+1, 1.1496e+1,
4.8936e+0, 2.5506e+0, 1.2236e+0, 7.4698e-1, 4.7042e-1,
4.7809e+0, 4.6315e+0, 4.3677e+0, 4.9269e+0, 2.6033e+0,
9.6229e+0, 7.2592e+0, 4.1634e+0, 1.3999e+1, 8.6975e+0,
6.9630e+0, 5.4681e+0, 4.2653e+0, 3.2848e+0, 2.7354e+0,
2.1617e+0, 1.7030e+0, 1.2826e+0, 9.7080e-1, 7.2227e-1,
5.0874e-1, 3.1402e-1, 1.6360e-1, 3.2918e-1, 2.3570e-1,
1.5868e-1, 1.5146e-1, 9.7662e-2, 7.3151e-2, 6.4206e-2,
4.8945e-2, 4.3189e-2, 4.4368e-2, 3.3976e-2, 3.0466e-2,
2.4477e-2, 3.7202e-2, 3.7093e-2, 3.8161e-2, 3.8576e-2,
3.8403e-2, 3.7806e-2, 3.4958e-2, 3.6029e-2, 4.3087e-2,
4.7069e-2, 4.6452e-2, 4.2486e-2, 4.1517e-2, 4.1691e-2,
4.2813e-2, 4.2294e-2, 4.5287e-2, 4.8462e-2, 4.9726e-2,
5.5097e-2, 5.6568e-2, 5.8069e-2, 1.2270e-2, 3.8006e-2,
3.5048e-2, 3.0050e-2, 2.5069e-2, 2.0485e-2, 1.6151e-2,
1.4631e-2, 1.4034e-2, 1.1978e-2, 1.1522e-2, 1.2375e-2,
1.3805e-2, 1.4954e-2, 1.5832e-2, 1.6467e-2, 1.6896e-2,
1.7166e-2, 1.9954e-2, 2.2497e-2, 2.1942e-2, 2.1965e-2,
2.0005e-2, 1.8927e-2, 1.8167e-2, 1.6314e-2, 1.5522e-2};
G4double x=sqrt(y);
G4double gradx1=0.0;
G4double fa=0.0;
G4int nElements = material->GetNumberOfElements();
const G4ElementVector* elementVector = material->GetElementVector();
const G4int* stechiometric = material->GetAtomsVector();
const G4double* vector_of_atoms = material->GetVecNbOfAtomsPerVolume();
const G4double tot_atoms = material->GetTotNbOfAtomsPerVolume();
for (G4int i=0;i<nElements;i++){
G4int Z = (G4int) (*elementVector)[i]->GetZ();
if (Z>ntot) Z=95;
fa=Z*(1+y*(RA1[Z-1]+x*(RA2[Z-1]+x*RA3[Z-1])))/pow((1+y*(RA4[Z-1]+y*RA5[Z-1])),2);
G4bool a = ((Z>10) && (fa>2.0));
if (a)
{
G4double Pa,Pg,Pq,fb;
G4double k1=0.3125;
G4double k2=2.426311e-02;
Pa=(Z-k1)*fine_structure_const;
Pg=sqrt(1-pow(Pa,2));
Pq=k2*x/Pa;
fb=sin(2*Pg*atan(Pq))/(Pg*Pq*pow((1+Pq*Pq),Pg));
fa=G4std::max(fa,fb);
}
if (stechiometric)
{
gradx1=gradx1+stechiometric[i]*(fa*fa); //sum on the molecule
}
else
{
gradx1=gradx1+(vector_of_atoms[i]/tot_atoms)*(fa*fa); //weighted mean
}
}
return gradx1;
}
G4double G4PenelopeRayleigh::DifferentialCrossSection(G4double x)
{
G4double x2=facte*(1-x);
G4double gradx = (1+x*x)*MolecularFormFactor(x2);
return gradx;
}
@@ -54,8 +54,6 @@
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4QAOLowEnergyLoss.hh"
#include "PhysicalConstants.h"
#include "SystemOfUnits.h"
#include "G4DynamicParticle.hh"
#include "G4Material.hh"
#include "G4ParticleDefinition.hh"
@@ -21,34 +21,42 @@
// ********************************************************************
//
//
// $Id: G4RangeTest.cc,v 1.5 2002/05/28 09:20:21 pia Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4RangeTest.cc,v 1.6 2003/01/22 18:47:29 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// -----------
// 05 Oct 2001 MGP Created
// 21 Jan 2003 VI Cut per region
//
// -------------------------------------------------------------------
#include "G4RangeTest.hh"
#include "G4ParticleDefinition.hh"
#include "G4Material.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4EnergyLossTables.hh"
#include "G4Electron.hh"
#include "G4Positron.hh"
G4RangeTest::~G4RangeTest()
{ }
G4bool G4RangeTest::Escape(const G4ParticleDefinition* particle,
const G4Material* material,
G4double energy,
G4bool G4RangeTest::Escape(const G4ParticleDefinition* particle,
const G4MaterialCutsCouple* couple,
G4double energy,
G4double safety) const
{
G4double range = G4EnergyLossTables::GetRange(particle,energy,material);
G4double cut = particle->GetRangeThreshold(material);
G4double rMin = G4std::min(cut,safety);
G4bool value = (range > rMin);
G4bool value = true;
size_t idx = 0;
if(particle == G4Electron::Electron()) idx = 1;
else if(particle == G4Positron::Positron()) idx = 2;
if(idx>0) {
G4double range = G4EnergyLossTables::GetRange(particle,energy,couple);
G4double cut = couple->GetProductionCuts()->GetProductionCut(idx);
G4double rMin = G4std::min(cut,safety);
value = (range > rMin);
}
return value;
}
@@ -22,7 +22,7 @@
//
//
// $Id: G4SemiLogInterpolation.cc,v 1.4 2002/05/28 09:20:21 pia Exp $
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -22,7 +22,7 @@
//
//
// $Id: G4ShellData.cc,v 1.5 2002/05/28 09:20:21 pia Exp $
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -22,7 +22,7 @@
//
//
// $Id: G4ShellEMDataSet.cc,v 1.8 2002/05/28 09:20:21 pia Exp $
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -22,18 +22,19 @@
//
//
// $Id: G4ShellVacancy.cc
// GEANT4 tag $Name:
// GEANT4 tag $Name:
//
// Author: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
//
// History:
// -----------
// 21 Sept 2001 Elena Guardincerri Created
// 25 Mar 2002 V.Ivanchenko Change AverageNOfIonisations int->double
// 25 Mar 2002 V.Ivanchenko Change AverageNOfIonisations int->double
//
// -------------------------------------------------------------------
#include "G4ShellVacancy.hh"
#include "G4MaterialCutsCouple.hh"
#include "G4Material.hh"
#include "G4Poisson.hh"
#include "G4VEMDataSet.hh"
@@ -44,13 +45,13 @@ G4ShellVacancy::G4ShellVacancy()
G4ShellVacancy::~G4ShellVacancy()
{
{
G4int size = xsis.size();
for (G4int k =0; k<size; k++)
{
delete xsis[k];
xsis[k] = 0;
}
}
}
void G4ShellVacancy::AddXsiTable(G4VEMDataSet* set)
@@ -59,20 +60,20 @@ void G4ShellVacancy::AddXsiTable(G4VEMDataSet* set)
xsis.push_back(set);
}
G4std::vector<G4int> G4ShellVacancy::GenerateNumberOfIonisations(const G4Material*
material,
G4double
incidentEnergy,
G4std::vector<G4int> G4ShellVacancy::GenerateNumberOfIonisations(const G4MaterialCutsCouple*
couple,
G4double
incidentEnergy,
G4double eLoss) const
{
G4std::vector<G4int> numberOfIonisations;
{
G4std::vector<G4int> numberOfIonisations;
const G4Material* material = couple->GetMaterial();
G4int numberOfElements = material->GetNumberOfElements();
for (G4int i = 0; i<numberOfElements; i++)
{
G4double averageNumberOfIonisations = AverageNOfIonisations(material,
G4double averageNumberOfIonisations = AverageNOfIonisations(couple,
i,
incidentEnergy,
eLoss);
@@ -82,27 +83,27 @@ G4std::vector<G4int> G4ShellVacancy::GenerateNumberOfIonisations(const G4Materia
}
numberOfIonisations.push_back(ionisations);
}
return numberOfIonisations;
return numberOfIonisations;
}
G4double G4ShellVacancy::AverageNOfIonisations(const G4Material* material,
G4int index,
G4double G4ShellVacancy::AverageNOfIonisations(const G4MaterialCutsCouple* couple,
G4int index,
G4double energy,
G4double eLoss) const
{
// G4int indexOfElementInMaterial= -1;
G4double averageEnergy = energy - eLoss/2.;
size_t indexInMaterialTable = material->GetIndex();
size_t indexInMaterialTable = couple->GetIndex();
G4VEMDataSet* aSetOfXsi = xsis[indexInMaterialTable];
G4double aXsi = aSetOfXsi->FindValue(averageEnergy,index);
return aXsi * eLoss;
G4double aXsi = aSetOfXsi->FindValue(averageEnergy,index);
return aXsi * eLoss;
}
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4VCrossSectionHandler.cc,v 1.11 2002/07/30 10:06:21 gcosmo Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4VCrossSectionHandler.cc,v 1.12 2003/01/22 18:47:29 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -32,6 +32,7 @@
// 09 Oct 2001 VI Add FindValue with 3 parameters
// + NumberOfComponents
// 19 Jul 2002 VI Create composite data set for material
// 21 Jan 2003 VI Cut per region
//
// -------------------------------------------------------------------
@@ -42,10 +43,10 @@
#include "G4EMDataSet.hh"
#include "G4CompositeEMDataSet.hh"
#include "G4ShellEMDataSet.hh"
#include "G4MaterialTable.hh"
#include "G4ProductionCutsTable.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "Randomize.hh"
#include "Randomize.hh"
#include "g4std/map"
#include "g4std/vector"
#include "g4std/fstream"
@@ -62,10 +63,10 @@ G4VCrossSectionHandler::G4VCrossSectionHandler()
G4VCrossSectionHandler::G4VCrossSectionHandler(G4VDataSetAlgorithm* algorithm,
G4double minE,
G4double maxE,
G4double minE,
G4double maxE,
G4int bins,
G4double unitE,
G4double unitE,
G4double unitData,
G4int minZ,
G4int maxZ)
@@ -234,7 +235,7 @@ void G4VCrossSectionHandler::LoadShellData(const G4String& fileName)
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
ost << fileName << Z << ".dat";
G4String name(nameChar);
@@ -306,7 +307,7 @@ void G4VCrossSectionHandler::Clear()
for (pos = dataMap.begin(); pos != dataMap.end(); ++pos)
{
// The following is a workaround for STL ObjectSpace implementation,
// which does not support the standard and does not accept
// which does not support the standard and does not accept
// the syntax pos->first or pos->second
// G4VEMDataSet* dataSet = pos->second;
G4VEMDataSet* dataSet = (*pos).second;
@@ -349,7 +350,7 @@ G4double G4VCrossSectionHandler::FindValue(G4int Z, G4double energy,
G4int shellIndex) const
{
G4double value = 0.;
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
pos = dataMap.find(Z);
if (pos!= dataMap.end())
@@ -385,17 +386,17 @@ G4double G4VCrossSectionHandler::FindValue(G4int Z, G4double energy,
}
G4double G4VCrossSectionHandler::ValueForMaterial(const G4Material* material,
G4double G4VCrossSectionHandler::ValueForMaterial(const G4Material* material,
G4double energy) const
{
G4double value = 0.;
const G4ElementVector* elementVector = material->GetElementVector();
const G4double* nAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
const G4double* nAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4int nElements = material->GetNumberOfElements();
for (G4int i=0 ; i<nElements ; i++)
{
{
G4int Z = (G4int) (*elementVector)[i]->GetZ();
G4double elementValue = FindValue(Z,energy);
G4double nAtomsVol = nAtomsPerVolume[i];
@@ -406,7 +407,7 @@ G4double G4VCrossSectionHandler::ValueForMaterial(const G4Material* material,
}
G4VEMDataSet* G4VCrossSectionHandler::BuildMeanFreePathForMaterials(const G4DataVector* energyCuts)
G4VEMDataSet* G4VCrossSectionHandler::BuildMeanFreePathForMaterials(const G4DataVector* energyCuts)
{
// Builds a CompositeDataSet containing the mean free path for each material
// in the material table
@@ -414,13 +415,13 @@ G4VEMDataSet* G4VCrossSectionHandler::BuildMeanFreePathForMaterials(const G4Data
G4DataVector energyVector;
G4double dBin = log10(eMax/eMin) / nBins;
for (G4int i=0; i<nBins+1; i++)
for (G4int i=0; i<nBins+1; i++)
{
energyVector.push_back(pow(10., log10(eMin)+i*dBin));
}
// Factory method to build cross sections in derived classes,
// related to the type of physics process
// Factory method to build cross sections in derived classes,
// related to the type of physics process
if (crossSections != 0)
{ // Reset the list of cross sections
@@ -441,7 +442,7 @@ G4VEMDataSet* G4VCrossSectionHandler::BuildMeanFreePathForMaterials(const G4Data
crossSections = BuildCrossSectionsForMaterials(energyVector,energyCuts);
if (crossSections == 0)
if (crossSections == 0)
G4Exception("G4VCrossSectionHandler::BuildMeanFreePathForMaterials, crossSections = 0");
G4VDataSetAlgorithm* algo = CreateInterpolation();
@@ -449,10 +450,13 @@ G4VEMDataSet* G4VCrossSectionHandler::BuildMeanFreePathForMaterials(const G4Data
G4DataVector* energies;
G4DataVector* data;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
size_t nMaterials = G4Material::GetNumberOfMaterials();
for (size_t m=0; m<nMaterials; m++)
for (size_t m=0; m<numOfCouples; m++)
{
energies = new G4DataVector;
data = new G4DataVector;
@@ -484,15 +488,17 @@ G4VEMDataSet* G4VCrossSectionHandler::BuildMeanFreePathForMaterials(const G4Data
return materialSet;
}
G4int G4VCrossSectionHandler::SelectRandomAtom(const G4Material* material, G4double e) const
G4int G4VCrossSectionHandler::SelectRandomAtom(const G4MaterialCutsCouple* couple,
G4double e) const
{
// Select randomly an element within the material, according to the weight
// Select randomly an element within the material, according to the weight
// determined by the cross sections in the data set
const G4Material* material = couple->GetMaterial();
G4int nElements = material->GetNumberOfElements();
// Special case: the material consists of one element
if (nElements == 1)
if (nElements == 1)
{
G4int Z = (G4int) material->GetZ();
return Z;
@@ -501,66 +507,67 @@ G4int G4VCrossSectionHandler::SelectRandomAtom(const G4Material* material, G4dou
// Composite material
const G4ElementVector* elementVector = material->GetElementVector();
size_t materialIndex = material->GetIndex();
size_t materialIndex = couple->GetIndex();
G4VEMDataSet* materialSet = (*crossSections)[materialIndex];
G4double materialCrossSection0 = 0.0;
G4DataVector cross;
cross.clear();
for ( G4int i=0; i < nElements; i++ )
for ( G4int i=0; i < nElements; i++ )
{
G4double cr = materialSet->GetComponent(i)->FindValue(e);
materialCrossSection0 += cr;
cross.push_back(materialCrossSection0);
}
}
G4double random = G4UniformRand() * materialCrossSection0;
for (G4int k=0 ; k < nElements ; k++ )
{
{
if (random <= cross[k]) return (G4int) (*elementVector)[k]->GetZ();
}
// It should never get here
return 0;
}
const G4Element* G4VCrossSectionHandler::SelectRandomElement(const G4Material* material,
const G4Element* G4VCrossSectionHandler::SelectRandomElement(const G4MaterialCutsCouple* couple,
G4double e) const
{
// Select randomly an element within the material, according to the weight determined
// by the cross sections in the data set
const G4Material* material = couple->GetMaterial();
G4Element* nullElement = 0;
G4int nElements = material->GetNumberOfElements();
const G4ElementVector* elementVector = material->GetElementVector();
// Special case: the material consists of one element
if (nElements == 1)
if (nElements == 1)
{
G4Element* element = (*elementVector)[0];
return element;
}
else
{
// Composite material
// Composite material
size_t materialIndex = material->GetIndex();
size_t materialIndex = couple->GetIndex();
G4VEMDataSet* materialSet = (*crossSections)[materialIndex];
G4double materialCrossSection0 = 0.0;
G4DataVector cross;
cross.clear();
for (G4int i=0; i<nElements; i++)
for (G4int i=0; i<nElements; i++)
{
G4double cr = materialSet->GetComponent(i)->FindValue(e);
materialCrossSection0 += cr;
cross.push_back(materialCrossSection0);
}
}
G4double random = G4UniformRand() * materialCrossSection0;
for (G4int k=0 ; k < nElements ; k++ )
{
{
if (random <= cross[k]) return (*elementVector)[k];
}
// It should never end up here
@@ -586,8 +593,8 @@ G4int G4VCrossSectionHandler::SelectRandomShell(G4int Z, G4double e) const
G4VEMDataSet* dataSet = 0;
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
pos = dataMap.find(Z);
// The following is a workaround for STL ObjectSpace implementation,
// which does not support the standard and does not accept
// The following is a workaround for STL ObjectSpace implementation,
// which does not support the standard and does not accept
// the syntax pos->first or pos->second
// if (pos != dataMap.end()) dataSet = pos->second;
if (pos != dataMap.end()) dataSet = (*pos).second;
@@ -612,20 +619,20 @@ void G4VCrossSectionHandler::ActiveElements()
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
if (materialTable == 0)
G4Exception("G4VCrossSectionHandler::ActiveElements - no MaterialTable found)");
G4int nMaterials = G4Material::GetNumberOfMaterials();
for (G4int m=0; m<nMaterials; m++)
{
const G4Material* material= (*materialTable)[m];
const G4Material* material= (*materialTable)[m];
const G4ElementVector* elementVector = material->GetElementVector();
const G4int nElements = material->GetNumberOfElements();
for (G4int iEl=0; iEl<nElements; iEl++)
{
G4Element* element = (*elementVector)[iEl];
G4double Z = element->GetZ();
if (!(activeZ.contains(Z)) && Z >= zMin && Z <= zMax)
if (!(activeZ.contains(Z)) && Z >= zMin && Z <= zMax)
{
activeZ.push_back(Z);
}
@@ -642,7 +649,7 @@ G4VDataSetAlgorithm* G4VCrossSectionHandler::CreateInterpolation()
G4int G4VCrossSectionHandler::NumberOfComponents(G4int Z) const
{
G4int n = 0;
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
pos = dataMap.find(Z);
if (pos!= dataMap.end())
@@ -21,12 +21,12 @@
// ********************************************************************
//
//
// $Id: G4VeLowEnergyLoss.cc,v 1.18 2002/09/09 08:54:08 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4VeLowEnergyLoss.cc,v 1.21 2003/04/24 11:24:16 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
//
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
// GEANT 4 class implementation file
//
// History: first implementation, based on object model of
// 2nd December 1995, G.Cosmo
@@ -38,16 +38,20 @@
// 10/05/01 V.Ivanchenko Clean up againist Linux compilation with -Wall
// 22/05/01 V.Ivanchenko Update range calculation
// 23/11/01 V.Ivanchenko Move static member-functions from header to source
// 22/01/03 V.Ivanchenko Cut per region
// 11/02/03 V.Ivanchenko Add limits to fluctuations
// 24/04/03 V.Ivanchenko Fix the problem of table size
//
// --------------------------------------------------------------
#include "G4VeLowEnergyLoss.hh"
#include "G4ProductionCutsTable.hh"
G4double G4VeLowEnergyLoss::ParticleMass ;
G4double G4VeLowEnergyLoss::taulow ;
G4double G4VeLowEnergyLoss::tauhigh ;
G4double G4VeLowEnergyLoss::ltaulow ;
G4double G4VeLowEnergyLoss::ltauhigh ;
G4double G4VeLowEnergyLoss::ParticleMass ;
G4double G4VeLowEnergyLoss::taulow ;
G4double G4VeLowEnergyLoss::tauhigh ;
G4double G4VeLowEnergyLoss::ltaulow ;
G4double G4VeLowEnergyLoss::ltauhigh ;
G4bool G4VeLowEnergyLoss::rndmStepFlag = false;
@@ -59,7 +63,7 @@ G4double G4VeLowEnergyLoss::c2lim = 2.*(1.-dRoverRange)*finalRange ;
G4double G4VeLowEnergyLoss::c3lim = -(1.-dRoverRange)*finalRange*finalRange;
//
//
G4VeLowEnergyLoss::G4VeLowEnergyLoss()
:G4VContinuousDiscreteProcess("No Name Loss Process"),
@@ -70,7 +74,7 @@ G4VeLowEnergyLoss::G4VeLowEnergyLoss()
G4Exception("G4VeLowEnergyLoss:: default constructor is called");
}
//
//
G4VeLowEnergyLoss::G4VeLowEnergyLoss(const G4String& aName , G4ProcessType aType)
: G4VContinuousDiscreteProcess(aName, aType),
@@ -80,13 +84,13 @@ G4VeLowEnergyLoss::G4VeLowEnergyLoss(const G4String& aName , G4ProcessType aType
{
}
//
//
G4VeLowEnergyLoss::~G4VeLowEnergyLoss()
{
}
//
//
G4VeLowEnergyLoss::G4VeLowEnergyLoss(G4VeLowEnergyLoss& right)
: G4VContinuousDiscreteProcess(right),
@@ -96,19 +100,19 @@ G4VeLowEnergyLoss::G4VeLowEnergyLoss(G4VeLowEnergyLoss& right)
{
}
void G4VeLowEnergyLoss::SetRndmStep(G4bool value)
void G4VeLowEnergyLoss::SetRndmStep(G4bool value)
{
rndmStepFlag = value;
}
void G4VeLowEnergyLoss::SetEnlossFluc(G4bool value)
void G4VeLowEnergyLoss::SetEnlossFluc(G4bool value)
{
EnlossFlucFlag = value;
}
void G4VeLowEnergyLoss::SetStepFunction (G4double c1, G4double c2)
{
dRoverRange = c1;
dRoverRange = c1;
finalRange = c2;
c1lim=dRoverRange;
c2lim=2.*(1-dRoverRange)*finalRange;
@@ -116,22 +120,22 @@ void G4VeLowEnergyLoss::SetStepFunction (G4double c1, G4double c2)
}
G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeTable(
G4PhysicsTable* theDEDXTable,G4PhysicsTable* theRangeTable,
G4PhysicsTable* theDEDXTable,G4PhysicsTable* theRangeTable,
G4double lowestKineticEnergy,G4double highestKineticEnergy,
G4int TotBin)
// Build range table from the energy loss table
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfCouples = theDEDXTable->length();
if(theRangeTable)
{ theRangeTable->clearAndDestroy();
delete theRangeTable; }
theRangeTable = new G4PhysicsTable(numOfMaterials);
theRangeTable = new G4PhysicsTable(numOfCouples);
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (G4int J=0; J<numOfCouples; J++)
{
G4PhysicsLogVector* aVector;
aVector = new G4PhysicsLogVector(lowestKineticEnergy,
@@ -141,9 +145,9 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeTable(
theRangeTable->insert(aVector);
}
return theRangeTable ;
}
}
//
//
void G4VeLowEnergyLoss::BuildRangeVector(G4PhysicsTable* theDEDXTable,
G4double lowestKineticEnergy,
@@ -179,9 +183,9 @@ void G4VeLowEnergyLoss::BuildRangeVector(G4PhysicsTable* theDEDXTable,
dedx = dedx1 ;
energy1 = energy2 ;
}
}
}
//
//
G4double G4VeLowEnergyLoss::RangeIntLin(G4PhysicsVector* physicsVector,
G4int nbin)
@@ -212,7 +216,7 @@ G4double G4VeLowEnergyLoss::RangeIntLin(G4PhysicsVector* physicsVector,
return Value;
}
//
//
G4double G4VeLowEnergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
G4int nbin)
@@ -246,24 +250,24 @@ G4double G4VeLowEnergyLoss::RangeIntLog(G4PhysicsVector* physicsVector,
}
//
//
G4PhysicsTable* G4VeLowEnergyLoss::BuildLabTimeTable(G4PhysicsTable* theDEDXTable,
G4PhysicsTable* theLabTimeTable,
G4double lowestKineticEnergy,
G4double highestKineticEnergy,G4int TotBin)
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfCouples = G4ProductionCutsTable::GetProductionCutsTable()->GetTableSize();
if(theLabTimeTable)
{ theLabTimeTable->clearAndDestroy();
delete theLabTimeTable; }
theLabTimeTable = new G4PhysicsTable(numOfMaterials);
theLabTimeTable = new G4PhysicsTable(numOfCouples);
for (G4int J=0; J<numOfMaterials; J++)
for (G4int J=0; J<numOfCouples; J++)
{
G4PhysicsLogVector* aVector;
@@ -288,15 +292,15 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildProperTimeTable(G4PhysicsTable* theDEDXT
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfCouples = G4ProductionCutsTable::GetProductionCutsTable()->GetTableSize();
if(theProperTimeTable)
{ theProperTimeTable->clearAndDestroy();
delete theProperTimeTable; }
theProperTimeTable = new G4PhysicsTable(numOfMaterials);
theProperTimeTable = new G4PhysicsTable(numOfCouples);
for (G4int J=0; J<numOfMaterials; J++)
for (G4int J=0; J<numOfCouples; J++)
{
G4PhysicsLogVector* aVector;
@@ -513,15 +517,15 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildInverseRangeTable(G4PhysicsTable* theRan
{
G4bool b;
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfCouples = G4ProductionCutsTable::GetProductionCutsTable()->GetTableSize();
if(theInverseRangeTable)
{ theInverseRangeTable->clearAndDestroy();
delete theInverseRangeTable; }
theInverseRangeTable = new G4PhysicsTable(numOfMaterials);
theInverseRangeTable = new G4PhysicsTable(numOfCouples);
// loop for materials
for (G4int i=0; i<numOfMaterials; i++)
for (G4int i=0; i<numOfCouples; i++)
{
G4PhysicsVector* pv = (*theRangeTable)[i];
@@ -549,7 +553,7 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildInverseRangeTable(G4PhysicsTable* theRan
for (ihigh=ilow+1; ihigh<nbins; ihigh++) {
energy2 = pv->GetLowEdgeEnergy(ihigh);
range2 = pv->GetValue(energy2, b);
range2 = pv->GetValue(energy2, b);
if(range2 >= range || ihigh == nbins-1) {
ilow = ihigh - 1;
energy1 = pv->GetLowEdgeEnergy(ilow);
@@ -634,12 +638,12 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeCoeffATable(G4PhysicsTable* theRang
// create table for coefficients "A"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfCouples = G4ProductionCutsTable::GetProductionCutsTable()->GetTableSize();
if(theRangeCoeffATable)
{ theRangeCoeffATable->clearAndDestroy();
delete theRangeCoeffATable; }
theRangeCoeffATable = new G4PhysicsTable(numOfMaterials);
theRangeCoeffATable = new G4PhysicsTable(numOfCouples);
G4double RTable = exp(log(highestKineticEnergy/lowestKineticEnergy)/TotBin) ;
G4double R2 = RTable*RTable ;
@@ -650,7 +654,7 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeCoeffATable(G4PhysicsTable* theRang
G4bool isOut;
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (G4int J=0; J<numOfCouples; J++)
{
G4int binmax=TotBin ;
G4PhysicsLinearVector* aVector =
@@ -696,12 +700,12 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeCoeffBTable(G4PhysicsTable* theRang
// create table for coefficients "B"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfCouples = G4ProductionCutsTable::GetProductionCutsTable()->GetTableSize();
if(theRangeCoeffBTable)
{ theRangeCoeffBTable->clearAndDestroy();
delete theRangeCoeffBTable; }
theRangeCoeffBTable = new G4PhysicsTable(numOfMaterials);
theRangeCoeffBTable = new G4PhysicsTable(numOfCouples);
G4double RTable = exp(log(highestKineticEnergy/lowestKineticEnergy)/TotBin) ;
G4double R2 = RTable*RTable ;
@@ -712,7 +716,7 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeCoeffBTable(G4PhysicsTable* theRang
G4bool isOut;
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (G4int J=0; J<numOfCouples; J++)
{
G4int binmax=TotBin ;
G4PhysicsLinearVector* aVector =
@@ -757,12 +761,12 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeCoeffCTable(G4PhysicsTable* theRang
// create table for coefficients "C"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfCouples = G4ProductionCutsTable::GetProductionCutsTable()->GetTableSize();
if(theRangeCoeffCTable)
{ theRangeCoeffCTable->clearAndDestroy();
delete theRangeCoeffCTable; }
theRangeCoeffCTable = new G4PhysicsTable(numOfMaterials);
theRangeCoeffCTable = new G4PhysicsTable(numOfCouples);
G4double RTable = exp(log(highestKineticEnergy/lowestKineticEnergy)/TotBin) ;
G4double R2 = RTable*RTable ;
@@ -773,7 +777,7 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeCoeffCTable(G4PhysicsTable* theRang
G4bool isOut;
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (G4int J=0; J<numOfCouples; J++)
{
G4int binmax=TotBin ;
G4PhysicsLinearVector* aVector =
@@ -811,7 +815,7 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeCoeffCTable(G4PhysicsTable* theRang
//
G4double G4VeLowEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4Material* aMaterial,
const G4MaterialCutsCouple* couple,
G4double MeanLoss,
G4double step)
// calculate actual loss from the mean loss
@@ -823,14 +827,14 @@ G4double G4VeLowEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
static const G4double alim=10.;
static const G4double kappa = 10. ;
static const G4double factor = twopi_mc2_rcl2 ;
const G4Material* aMaterial = couple->GetMaterial();
// check if the material has changed ( cache mechanism)
if (aMaterial != lastMaterial)
{
lastMaterial = aMaterial;
imat = aMaterial->GetIndex();
imat = couple->GetIndex();
f1Fluct = aMaterial->GetIonisation()->GetF1fluct();
f2Fluct = aMaterial->GetIonisation()->GetF2fluct();
e1Fluct = aMaterial->GetIonisation()->GetEnergy1fluct();
@@ -851,7 +855,7 @@ G4double G4VeLowEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
G4double dp3;
G4double siga ;
// shortcut for very very small loss
// shortcut for very very small loss
if(MeanLoss < minLoss) return MeanLoss ;
// get particle data
@@ -859,67 +863,60 @@ G4double G4VeLowEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
// G4cout << "MGP -- Fluc Tkin " << Tkin/keV << " keV " << " MeanLoss = " << MeanLoss/keV << G4endl;
threshold = G4Electron::Electron()->GetEnergyThreshold(aMaterial);
threshold = (*((G4ProductionCutsTable::GetProductionCutsTable())
->GetEnergyCutsVector(1)))[imat];
G4double rmass = electron_mass_c2/ParticleMass;
G4double tau = Tkin/ParticleMass, tau1 = tau+1., tau2 = tau*(tau+2.);
G4double Tm = 2.*electron_mass_c2*tau2/(1.+2.*tau1*rmass+rmass*rmass);
// G4cout << "MGP Particle mass " << ParticleMass/MeV << " Tm " << Tm << G4endl;
if (Tm <= ipotFluct) Tm = ipotFluct ;
if(Tm > threshold) Tm = threshold;
beta2 = tau2/(tau1*tau1);
// Gaussian fluctuation ?
if(MeanLoss >= kappa*Tm)
if(MeanLoss >= kappa*Tm || MeanLoss <= kappa*ipotFluct)
{
G4double electronDensity = aMaterial->GetElectronDensity() ;
siga = sqrt(Tm*(1.0-0.5*beta2)*step*
factor*electronDensity/beta2) ;
loss = G4RandGauss::shoot(MeanLoss,siga) ;
if(loss < 0.) loss = 0. ;
do {
loss = G4RandGauss::shoot(MeanLoss,siga) ;
} while (loss < 0. || loss > 2.0*MeanLoss);
return loss ;
}
w1 = Tm/ipotFluct;
w2 = log(2.*electron_mass_c2*tau2);
C = MeanLoss*(1.-rateFluct)/(w2-ipotLogFluct-beta2);
a1 = C*f1Fluct*(w2-e1LogFluct-beta2)/e1Fluct;
a2 = C*f2Fluct*(w2-e2LogFluct-beta2)/e2Fluct;
if(Tm > ipotFluct)
a3 = rateFluct*MeanLoss*(Tm-ipotFluct)/(ipotFluct*Tm*log(w1));
else
{
a1 /= 1.-rateFluct ;
a2 /= 1.-rateFluct ;
a3 = 0. ;
}
a3 = rateFluct*MeanLoss*(Tm-ipotFluct)/(ipotFluct*Tm*log(w1));
suma = a1+a2+a3;
loss = 0. ;
if(suma < sumaLim) // very small Step
{
e0 = aMaterial->GetIonisation()->GetEnergy0fluct();
// G4cout << "MGP e0 = " << e0/keV << G4endl;
if(Tm == ipotFluct)
{
a3 = MeanLoss/e0;
if(a3>alim)
{
siga=sqrt(a3) ;
p3 = G4std::max(0,G4int(G4RandGauss::shoot(a3,siga)+0.5));
}
else p3 = G4Poisson(a3);
loss = p3*e0 ;
if(p3 > 0) loss += (1.-2.*G4UniformRand())*e0 ;
// G4cout << "MGP very small step " << loss/keV << G4endl;
}
@@ -929,8 +926,8 @@ G4double G4VeLowEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
Tm = Tm-ipotFluct+e0 ;
// MGP ---- workaround to avoid log argument<0, TO BE CHECKED
if (Tm <= 0.)
{
if (Tm <= 0.)
{
loss = MeanLoss;
p3 = 0;
// G4cout << "MGP correction loss = MeanLoss " << loss/keV << G4endl;
@@ -971,7 +968,7 @@ G4double G4VeLowEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
}
}
}
else // not so small Step
{
// excitation type 1
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4eBremsstrahlungSpectrum.cc,v 1.7 2002/05/30 17:53:09 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4eBremsstrahlungSpectrum.cc,v 1.9 2003/02/28 08:42:18 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// -------------------------------------------------------------------
//
@@ -31,14 +31,16 @@
// File name: G4eBremsstrahlungSpectrum
//
// Author: V.Ivanchenko (Vladimir.Ivanchenko@cern.ch)
//
//
// Creation date: 29 September 2001
//
// Modifications:
// Modifications:
// 10.10.01 MGP Revision to improve code quality and consistency with design
// 15.11.01 VI Update spectrum model Bethe-Haitler spectrum at high energy
// 30.05.02 VI Update interpolation between 2 last energy points in the
// parametrisation
// 21.02.03 V.Ivanchenko Energy bins are defined in the constructor
// 28.02.03 V.Ivanchenko Filename is defined in the constructor
//
// -------------------------------------------------------------------
@@ -47,36 +49,27 @@
#include "Randomize.hh"
G4eBremsstrahlungSpectrum::G4eBremsstrahlungSpectrum():
G4VEnergySpectrum(),
G4eBremsstrahlungSpectrum::G4eBremsstrahlungSpectrum(const G4DataVector& bins,
const G4String& name):G4VEnergySpectrum(),
lowestE(0.1*eV),
length(15)
xp(bins)
{
theBRparam = new G4BremsstrahlungParameters();
xp.clear();
for(size_t i=0; i<length; i++) {
G4double x = 0.1*((G4double)i);
if(i == 0) x = 0.01;
if(i == 10) x = 0.95;
if(i == 11) x = 0.97;
if(i == 12) x = 0.99;
if(i == 13) x = 0.995;
if(i == 14) x = 1.0;
xp.push_back(x);
}
length = xp.size();
theBRparam = new G4BremsstrahlungParameters(name,length+1);
verbose = 0;
}
G4eBremsstrahlungSpectrum::~G4eBremsstrahlungSpectrum()
G4eBremsstrahlungSpectrum::~G4eBremsstrahlungSpectrum()
{
delete theBRparam;
}
G4double G4eBremsstrahlungSpectrum::Probability(G4int Z,
G4double tmin,
G4double tmax,
G4double G4eBremsstrahlungSpectrum::Probability(G4int Z,
G4double tmin,
G4double tmax,
G4double e,
G4int,
const G4ParticleDefinition*) const
@@ -95,20 +88,20 @@ G4double G4eBremsstrahlungSpectrum::Probability(G4int Z,
for (size_t i=0; i<=length; i++) {
p.push_back(theBRparam->Parameter(i, Z, e));
}
G4double x = IntSpectrum(t0, tm, p);
G4double y = IntSpectrum(z, 1.0, p);
G4double y = IntSpectrum(z, 1.0, p);
if(1 < verbose) {
G4cout << "tcut(MeV)= " << tmin/MeV
<< "; tMax(MeV)= " << tmax/MeV
<< "; t0= " << t0
<< "; tm= " << tm
G4cout << "tcut(MeV)= " << tmin/MeV
<< "; tMax(MeV)= " << tmax/MeV
<< "; t0= " << t0
<< "; tm= " << tm
<< "; xp[0]= " << xp[0]
<< "; z= " << z
<< "; val= " << x
<< "; nor= " << y
<< "; z= " << z
<< "; val= " << x
<< "; nor= " << y
<< G4endl;
}
p.clear();
@@ -117,13 +110,13 @@ G4double G4eBremsstrahlungSpectrum::Probability(G4int Z,
else x = 0.0;
// if(x < 0.0) x = 0.0;
return x;
return x;
}
G4double G4eBremsstrahlungSpectrum::AverageEnergy(G4int Z,
G4double tmin,
G4double tmax,
G4double tmin,
G4double tmax,
G4double e,
G4int,
const G4ParticleDefinition*) const
@@ -153,16 +146,16 @@ G4double G4eBremsstrahlungSpectrum::AverageEnergy(G4int Z,
G4double f = Function(z0, p);
x += 0.5*f*z0*(z0 - c*atan(z0/c));
x *= e;
x *= e;
if(1 < verbose) {
G4cout << "tcut(MeV)= " << tmin/MeV
<< "; tMax(MeV)= " << tmax/MeV
<< "; e(MeV)= " << e/MeV
<< "; t0= " << t0
<< "; tm= " << tm
G4cout << "tcut(MeV)= " << tmin/MeV
<< "; tMax(MeV)= " << tmax/MeV
<< "; e(MeV)= " << e/MeV
<< "; t0= " << t0
<< "; tm= " << tm
<< "; y= " << y
<< "; x= " << x
<< "; x= " << x
<< G4endl;
}
p.clear();
@@ -171,13 +164,13 @@ G4double G4eBremsstrahlungSpectrum::AverageEnergy(G4int Z,
else x = 0.0;
// if(x < 0.0) x = 0.0;
return x;
return x;
}
G4double G4eBremsstrahlungSpectrum::SampleEnergy(G4int Z,
G4double tmin,
G4double tmax,
G4double tmin,
G4double tmax,
G4double e,
G4int,
const G4ParticleDefinition*) const
@@ -194,7 +187,7 @@ G4double G4eBremsstrahlungSpectrum::SampleEnergy(G4int Z,
for (size_t i=0; i<=length; i++) {
p.push_back(theBRparam->Parameter(i, Z, e));
}
G4double amaj = G4std::max(p[15], 1. - (p[1] - p[0])/9.);
G4double amaj = G4std::max(p[length], 1. - (p[1] - p[0])*xp[0]/(xp[1] - xp[0]) );
G4double amax = log(tm);
G4double amin = log(t0);
@@ -206,8 +199,8 @@ G4double G4eBremsstrahlungSpectrum::SampleEnergy(G4int Z,
fun = Function(tgam, p);
if(fun > amaj) {
G4cout << "WARNING in G4eBremsstrahlungSpectrum::SampleEnergy:"
<< " Majoranta " << amaj
G4cout << "WARNING in G4eBremsstrahlungSpectrum::SampleEnergy:"
<< " Majoranta " << amaj
<< " < " << fun
<< G4endl;
}
@@ -219,19 +212,19 @@ G4double G4eBremsstrahlungSpectrum::SampleEnergy(G4int Z,
p.clear();
return tgam;
return tgam;
}
G4double G4eBremsstrahlungSpectrum::IntSpectrum(G4double xMin,
G4double G4eBremsstrahlungSpectrum::IntSpectrum(G4double xMin,
G4double xMax,
const G4DataVector& p) const
{
G4double x1 = G4std::min(xMin, xp[0]);
G4double x2 = G4std::min(xMax, xp[0]);
G4double sum = 0.0;
if(x1 < x2) {
G4double k = (p[1] - p[0])/0.09;
G4double k = (p[1] - p[0])/(xp[1] - xp[0]);
sum += (1. - k*xp[0])*log(x2/x1) + k*(x2 - x1);
}
@@ -248,7 +241,7 @@ G4double G4eBremsstrahlungSpectrum::IntSpectrum(G4double xMin,
return sum;
}
G4double G4eBremsstrahlungSpectrum::AverageValue(G4double xMin,
G4double G4eBremsstrahlungSpectrum::AverageValue(G4double xMin,
G4double xMax,
const G4DataVector& p) const
{
@@ -257,9 +250,9 @@ G4double G4eBremsstrahlungSpectrum::AverageValue(G4double xMin,
G4double z1 = x1;
G4double z2 = x2;
G4double sum = 0.0;
if(x1 < x2) {
G4double k = (p[1] - p[0])/0.09;
G4double k = (p[1] - p[0])/(xp[1] - xp[0]);
sum += (z2 - z1)*(1. - k*xp[0]);
z1 *= x1;
z2 *= x2;
@@ -277,15 +270,15 @@ G4double G4eBremsstrahlungSpectrum::AverageValue(G4double xMin,
}
if(sum < 0.0) sum = 0.0;
return sum;
}
G4double G4eBremsstrahlungSpectrum::Function(G4double x,
}
G4double G4eBremsstrahlungSpectrum::Function(G4double x,
const G4DataVector& p) const
{
G4double f = 0.0;
if(x <= xp[0]) {
f = 1. + (p[1] - p[0])*(x - xp[0])/0.09;
f = 1. + (p[1] - p[0])*(x - xp[0])/(xp[1] - xp[0]);
} else {
@@ -298,7 +291,7 @@ G4double G4eBremsstrahlungSpectrum::Function(G4double x,
}
}
return f;
}
}
void G4eBremsstrahlungSpectrum::PrintData() const
{ theBRparam->PrintData(); }
@@ -311,6 +304,6 @@ G4double G4eBremsstrahlungSpectrum::Excitation(G4int Z, G4double kineticEnergy)
G4double G4eBremsstrahlungSpectrum::MaxEnergyOfSecondaries(G4double kineticEnergy,
G4int Z,
const G4ParticleDefinition*) const
{
return kineticEnergy;
{
return kineticEnergy;
}
@@ -20,8 +20,8 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4eIonisationCrossSectionHandler.cc,v 1.8 2002/07/19 17:32:50 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4eIonisationCrossSectionHandler.cc,v 1.9 2003/01/22 18:47:29 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// -------------------------------------------------------------------
//
@@ -35,8 +35,9 @@
// Creation date: 25 Sept 2001
//
// Modifications:
// 10 Oct 2001 M.G. Pia Revision to improve code quality and consistency with design
// 19 Jul 2002 VI Create composite data set for material
// 10 Oct 2001 M.G. Pia Revision to improve code quality and consistency with design
// 19 Jul 2002 VI Create composite data set for material
// 21 Jan 2003 V.Ivanchenko Cut per region
//
// -------------------------------------------------------------------
@@ -50,11 +51,11 @@
#include "G4VEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4Material.hh"
#include "G4MaterialTable.hh"
#include "G4ProductionCutsTable.hh"
G4eIonisationCrossSectionHandler::G4eIonisationCrossSectionHandler(
const G4VEnergySpectrum* spec, G4VDataSetAlgorithm* alg,
const G4VEnergySpectrum* spec, G4VDataSetAlgorithm* alg,
G4double emin, G4double emax, G4int nbin)
: G4VCrossSectionHandler(),
theParam(spec)
@@ -64,15 +65,15 @@ G4eIonisationCrossSectionHandler::G4eIonisationCrossSectionHandler(
}
G4eIonisationCrossSectionHandler::~G4eIonisationCrossSectionHandler()
G4eIonisationCrossSectionHandler::~G4eIonisationCrossSectionHandler()
{
delete interp;
}
G4std::vector<G4VEMDataSet*>* G4eIonisationCrossSectionHandler::BuildCrossSectionsForMaterials(
const G4DataVector& energyVector,
const G4DataVector* energyCuts)
const G4DataVector& energyVector,
const G4DataVector* energyCuts)
{
G4int verbose = 0;
G4std::vector<G4VEMDataSet*>* set = new G4std::vector<G4VEMDataSet*>;
@@ -81,33 +82,31 @@ G4std::vector<G4VEMDataSet*>* G4eIonisationCrossSectionHandler::BuildCrossSectio
G4DataVector* cs;
G4int nOfBins = energyVector.size();
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
if (materialTable == 0)
G4Exception("G4VCrossSectionHandler::G4VCrossSectionHandler - no MaterialTable found)");
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
G4int nMaterials = G4Material::GetNumberOfMaterials();
for (size_t m=0; m<numOfCouples; m++) {
for (G4int m=0; m<nMaterials; m++) {
const G4Material* material = (*materialTable)[m];
const G4MaterialCutsCouple* couple = theCoupleTable->GetMaterialCutsCouple(m);
const G4Material* material= couple->GetMaterial();
const G4ElementVector* elementVector = material->GetElementVector();
//const G4double* nAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
const G4double* nAtomsPerVolume = material->GetAtomicNumDensityVector();
G4int nElements = material->GetNumberOfElements();
if(verbose > 0) {
G4cout << "eIonisation CS for " << m << "th material "
<< material->GetName()
<< " eEl= " << nElements << G4endl;
G4cout << "eIonisation CS for " << m << "th material "
<< material->GetName()
<< " eEl= " << nElements << G4endl;
}
G4double tcut = (*energyCuts)[m];
G4VDataSetAlgorithm* algo = interp->Clone();
G4VEMDataSet* setForMat = new G4CompositeEMDataSet(algo,1.,1.);
for (G4int i=0; i<nElements; i++) {
G4int Z = (G4int) (*elementVector)[i]->GetZ();
G4int nShells = NumberOfComponents(Z);
energies = new G4DataVector;
@@ -123,10 +122,10 @@ G4std::vector<G4VEMDataSet*>* G4eIonisationCrossSectionHandler::BuildCrossSectio
if(e > tcut) {
for (G4int n=0; n<nShells; n++) {
G4double cross = FindValue(Z, e, n);
G4double p = theParam->Probability(Z, tcut, e, e, n);
G4double p = theParam->Probability(Z, tcut, e, e, n);
value += cross * p * density;
if(verbose>0 && m == 0 && e>=1. && e<=0.) {
if(verbose>0 && m == 0 && e>=1. && e<=0.) {
G4cout << "G4eIonCrossSH: e(MeV)= " << e/MeV
<< " n= " << n
<< " cross= " << cross
@@ -137,18 +136,18 @@ G4std::vector<G4VEMDataSet*>* G4eIonisationCrossSectionHandler::BuildCrossSectio
<< " Z= " << Z
<< G4endl;
}
}
}
cs->push_back(value);
}
}
G4VDataSetAlgorithm* algo = interp->Clone();
G4VEMDataSet* elSet = new G4EMDataSet(i,energies,cs,algo,1.,1.);
setForMat->AddComponent(elSet);
}
set->push_back(setForMat);
}
return set;
}
@@ -22,7 +22,7 @@
//
//
// $Id: G4eIonisationParameters.cc,v 1.19 2002/05/30 17:53:09 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
@@ -21,7 +21,7 @@
// ********************************************************************
//
// $Id: G4eIonisationSpectrum.cc,v 1.20 2002/07/19 17:32:50 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// GEANT4 tag $Name: geant4-05-01 $
//
// -------------------------------------------------------------------
//
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4eLowEnergyLoss.cc,v 1.29 2002/10/28 09:43:51 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4eLowEnergyLoss.cc,v 1.30 2003/01/22 18:47:29 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// -----------------------------------------------------------
// GEANT 4 class implementation file
@@ -42,7 +42,7 @@
// 08-09-98: cleanup
// 24-09-98: rndmStepFlag false by default (no randomization of the step)
// 14-10-98: messenger file added.
// 16-10-98: public method SetStepFunction()
// 16-10-98: public method SetStepFunction()
// 20-01-99: important correction in AlongStepDoIt , L.Urban
// 10/02/00 modifications , new e.m. structure, L.Urban
// 11/04/00: Bug fix in dE/dx fluctuation simulation, Veronique Lefebure
@@ -52,19 +52,21 @@
// 18/10/01 Revision to improve code quality and consistency with design, MGP
// 19/10/01 update according to new design, V.Ivanchenko
// 24/10/01 MGP - Protection against negative energy loss in AlongStepDoIt
// 26/10/01 VI Clean up access to deexcitation
// 26/10/01 VI Clean up access to deexcitation
// 23/11/01 VI Move static member-functions from header to source
// 28/05/02 VI Remove flag fStopAndKill
// 03/06/02 MGP - Restore fStopAndKill
// 28/10/02 VI Optimal binning for dE/dx
// 21/01/03 VI cut per region
//
// --------------------------------------------------------------
#include "G4eLowEnergyLoss.hh"
#include "G4EnergyLossMessenger.hh"
#include "G4Poisson.hh"
#include "G4ProductionCutsTable.hh"
//
//
// Initialisation of static data members
// -------------------------------------
@@ -84,7 +86,7 @@ G4PhysicsTable** G4eLowEnergyLoss::RecorderOfElectronProcess =
new G4PhysicsTable*[10];
G4PhysicsTable** G4eLowEnergyLoss::RecorderOfPositronProcess =
new G4PhysicsTable*[10];
G4PhysicsTable* G4eLowEnergyLoss::theDEDXElectronTable = 0;
G4PhysicsTable* G4eLowEnergyLoss::theDEDXPositronTable = 0;
@@ -136,7 +138,7 @@ G4eLowEnergyLoss::G4eLowEnergyLoss(const G4String& processName)
if(!eLossMessenger) eLossMessenger = new G4EnergyLossMessenger();
}
//
//
G4eLowEnergyLoss::~G4eLowEnergyLoss()
{
@@ -170,19 +172,19 @@ G4int G4eLowEnergyLoss::GetNbOfProcesses()
void G4eLowEnergyLoss::SetLowerBoundEloss(G4double val)
{
LowerBoundEloss=val;
}
}
void G4eLowEnergyLoss::SetUpperBoundEloss(G4double val)
{
UpperBoundEloss=val;
}
void G4eLowEnergyLoss::SetNbinEloss(G4int nb)
{
NbinEloss=nb;
}
G4double G4eLowEnergyLoss::GetLowerBoundEloss()
G4double G4eLowEnergyLoss::GetLowerBoundEloss()
{
return LowerBoundEloss;
}
@@ -191,7 +193,7 @@ G4double G4eLowEnergyLoss::GetUpperBoundEloss()
{
return UpperBoundEloss;
}
G4int G4eLowEnergyLoss::GetNbinEloss()
{
return NbinEloss;
@@ -210,11 +212,13 @@ void G4eLowEnergyLoss::BuildDEDXTable(
LOGRTable=lrate/NbinEloss;
RTable =exp(LOGRTable);
// Build energy loss table as a sum of the energy loss due to the
// different processes.
// different processes.
//
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
// create table for the total energy loss
if (&aParticleType==G4Electron::Electron())
@@ -224,11 +228,11 @@ void G4eLowEnergyLoss::BuildDEDXTable(
if (CounterOfProcess == NbOfProcesses)
{
if (theDEDXElectronTable)
{
{
theDEDXElectronTable->clearAndDestroy();
delete theDEDXElectronTable;
delete theDEDXElectronTable;
}
theDEDXElectronTable = new G4PhysicsTable(numOfMaterials);
theDEDXElectronTable = new G4PhysicsTable(numOfCouples);
theDEDXTable = theDEDXElectronTable;
}
}
@@ -239,11 +243,11 @@ void G4eLowEnergyLoss::BuildDEDXTable(
if (CounterOfProcess == NbOfProcesses)
{
if (theDEDXPositronTable)
{
{
theDEDXPositronTable->clearAndDestroy();
delete theDEDXPositronTable;
delete theDEDXPositronTable;
}
theDEDXPositronTable = new G4PhysicsTable(numOfMaterials);
theDEDXPositronTable = new G4PhysicsTable(numOfCouples);
theDEDXTable = theDEDXPositronTable;
}
}
@@ -256,39 +260,39 @@ void G4eLowEnergyLoss::BuildDEDXTable(
G4bool isOutRange;
G4PhysicsTable* pointer;
for (G4int J=0; J<numOfMaterials; J++)
for (size_t J=0; J<numOfCouples; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowerBoundEloss, UpperBoundEloss, NbinEloss);
LowerBoundEloss, UpperBoundEloss, NbinEloss);
// loop for the kinetic energy
for (G4int i=0; i<NbinEloss; i++)
for (G4int i=0; i<NbinEloss; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
//here comes the sum of the different tables created by the
//processes (ionisation,bremsstrahlung,etc...)
Value = 0.;
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
//here comes the sum of the different tables created by the
//processes (ionisation,bremsstrahlung,etc...)
Value = 0.;
for (G4int process=0; process < NbOfProcesses; process++)
{
pointer= RecorderOfProcess[process];
Value += (*pointer)[J]->GetValue(LowEdgeEnergy,isOutRange);
}
aVector->PutValue(i,Value) ;
aVector->PutValue(i,Value) ;
}
theDEDXTable->insert(aVector) ;
}
//reset counter to zero
if (&aParticleType==G4Electron::Electron()) CounterOfElectronProcess=0;
if (&aParticleType==G4Positron::Positron()) CounterOfPositronProcess=0;
ParticleMass = aParticleType.GetPDGMass();
ParticleMass = aParticleType.GetPDGMass();
if (&aParticleType==G4Electron::Electron())
{
@@ -370,7 +374,7 @@ void G4eLowEnergyLoss::BuildDEDXTable(
// make the energy loss and the range table available
G4EnergyLossTables::Register(&aParticleType,
G4EnergyLossTables::Register(&aParticleType,
(&aParticleType==G4Electron::Electron())?
theDEDXElectronTable: theDEDXPositronTable,
(&aParticleType==G4Electron::Electron())?
@@ -385,83 +389,83 @@ void G4eLowEnergyLoss::BuildDEDXTable(
}
}
//
//
G4VParticleChange* G4eLowEnergyLoss::AlongStepDoIt( const G4Track& trackData,
const G4Step& stepData)
{
{
// compute the energy loss after a Step
static const G4double faclow = 1.5 ;
// get particle and material pointers from trackData
// get particle and material pointers from trackData
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double E = aParticle->GetKineticEnergy() ;
G4Material* aMaterial = trackData.GetMaterial();
G4double E = aParticle->GetKineticEnergy();
const G4MaterialCutsCouple* couple = trackData.GetMaterialCutsCouple();
G4double Step = stepData.GetStepLength();
aParticleChange.Initialize(trackData);
//fParticleChange.Initialize(trackData);
G4double MeanLoss, finalT;
aParticleChange.Initialize(trackData);
//fParticleChange.Initialize(trackData);
if (E < MinKineticEnergy) finalT = 0.;
else if ( E< faclow*LowerBoundEloss)
G4double MeanLoss, finalT;
if (E < MinKineticEnergy) finalT = 0.;
else if ( E< faclow*LowerBoundEloss)
{
if (Step >= fRangeNow) finalT = 0.;
if (Step >= fRangeNow) finalT = 0.;
// else finalT = E*(1.-Step/fRangeNow) ;
else finalT = E*(1.-sqrt(Step/fRangeNow)) ;
}
else if (E>=UpperBoundEloss) finalT = E - Step*fdEdx;
else if (Step >= fRangeNow) finalT = 0.;
else if (Step >= fRangeNow) finalT = 0.;
else
{
if(Step/fRangeNow < linLossLimit) finalT = E-Step*fdEdx ;
else
{
if (Charge<0.) finalT = G4EnergyLossTables::GetPreciseEnergyFromRange
(G4Electron::Electron(),fRangeNow-Step,aMaterial);
(G4Electron::Electron(),fRangeNow-Step,couple);
else finalT = G4EnergyLossTables::GetPreciseEnergyFromRange
(G4Positron::Positron(),fRangeNow-Step,aMaterial);
(G4Positron::Positron(),fRangeNow-Step,couple);
}
}
if(finalT < MinKineticEnergy) finalT = 0. ;
MeanLoss = E-finalT ;
MeanLoss = E-finalT ;
//now the loss with fluctuation
if ((EnlossFlucFlag) && (finalT > 0.) && (finalT < E)&&(E > LowerBoundEloss))
{
finalT = E-GetLossWithFluct(aParticle,aMaterial,MeanLoss,Step);
finalT = E-GetLossWithFluct(aParticle,couple,MeanLoss,Step);
if (finalT < 0.) finalT = 0.;
}
// kill the particle if the kinetic energy <= 0
// kill the particle if the kinetic energy <= 0
if (finalT <= 0. )
{
finalT = 0.;
aParticleChange.SetStatusChange(fStopAndKill);
}
aParticleChange.SetStatusChange(fStopAndKill);
}
G4double edep = E - finalT;
aParticleChange.SetEnergyChange(finalT);
aParticleChange.SetEnergyChange(finalT);
// Deexcitation of ionised atoms
G4std::vector<G4DynamicParticle*>* deexcitationProducts = 0;
if (theFluo) deexcitationProducts = DeexciteAtom(aMaterial,E,edep);
if (theFluo) deexcitationProducts = DeexciteAtom(couple,E,edep);
size_t nSecondaries = 0;
size_t nSecondaries = 0;
if (deexcitationProducts != 0) nSecondaries = deexcitationProducts->size();
aParticleChange.SetNumberOfSecondaries(nSecondaries);
if (nSecondaries > 0) {
const G4StepPoint* preStep = stepData.GetPreStepPoint();
@@ -474,14 +478,14 @@ G4VParticleChange* G4eLowEnergyLoss::AlongStepDoIt( const G4Track& trackData,
deltaT -= t;
G4double time, q;
G4ThreeVector position;
for (size_t i=0; i<nSecondaries; i++) {
G4DynamicParticle* part = (*deexcitationProducts)[i];
G4DynamicParticle* part = (*deexcitationProducts)[i];
if (part != 0) {
G4double eSecondary = part->GetKineticEnergy();
edep -= eSecondary;
if (edep > 0.)
if (edep > 0.)
{
q = G4UniformRand();
time = deltaT*q + t;
@@ -498,14 +502,13 @@ G4VParticleChange* G4eLowEnergyLoss::AlongStepDoIt( const G4Track& trackData,
}
}
}
}
delete deexcitationProducts;
}
delete deexcitationProducts;
aParticleChange.SetLocalEnergyDeposit(edep);
return &aParticleChange;
}
//
//
File diff suppressed because it is too large Load Diff
@@ -21,23 +21,23 @@
// ********************************************************************
//
//
// $Id: G4hLowEnergyLoss.cc,v 1.17 2002/10/28 09:43:52 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-00 $
// $Id: G4hLowEnergyLoss.cc,v 1.19 2003/01/23 11:39:07 vnivanch Exp $
// GEANT4 tag $Name: geant4-05-01 $
//
// -----------------------------------------------------------
// GEANT 4 class implementation file
// GEANT 4 class implementation file
//
// History: based on object model of
// 2nd December 1995, G.Cosmo
// ---------- G4hEnergyLoss physics process -----------
// by Laszlo Urban, 30 May 1997
// by Laszlo Urban, 30 May 1997
//
// **************************************************************
// It is the first implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
// It calculates the energy loss of charged hadrons.
// **************************************************************
//
// 7/10/98 bug fixes + some cleanup , L.Urban
// 7/10/98 bug fixes + some cleanup , L.Urban
// 22/10/98 cleanup , L.Urban
// 07/12/98 works for ions as well+ bug corrected, L.Urban
// 02/02/99 several bugs fixed, L.Urban
@@ -46,19 +46,22 @@
// 10/05/01 V.Ivanchenko Clean up againist Linux compilation with -Wall
// 23/11/01 V.Ivanchenko Move static member-functions from header to source
// 28/10/02 V.Ivanchenko Optimal binning for dE/dx
// 21/01/03 V.Ivanchenko Cut per region
// 23/01/03 V.Ivanchenko Fix in table build
// --------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4hLowEnergyLoss.hh"
#include "G4EnergyLossTables.hh"
#include "G4Poisson.hh"
#include "G4ProductionCutsTable.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
// Initialisation of static members ******************************************
// contributing processes : ion.loss ->NumberOfProcesses is initialized
// to 1 . YOU DO NOT HAVE TO CHANGE this variable for a 'normal' run.
// You have to change NumberOfProcesses
// You have to change NumberOfProcesses
// if you invent a new process contributing to the cont. energy loss,
// NumberOfProcesses should be 2 in this case,
// or for debugging purposes.
@@ -133,7 +136,7 @@ G4bool G4hLowEnergyLoss::rndmStepFlag = false ;
G4bool G4hLowEnergyLoss::EnlossFlucFlag = true ;
G4double G4hLowEnergyLoss::LowestKineticEnergy = 10.*eV;
G4double G4hLowEnergyLoss::HighestKineticEnergy= 100.*GeV;
G4double G4hLowEnergyLoss::HighestKineticEnergy= 100.*GeV;
G4int G4hLowEnergyLoss::TotBin = 360;
G4double G4hLowEnergyLoss::RTable,G4hLowEnergyLoss::LOGRTable;
@@ -143,7 +146,6 @@ G4double G4hLowEnergyLoss::RTable,G4hLowEnergyLoss::LOGRTable;
G4hLowEnergyLoss::G4hLowEnergyLoss(const G4String& processName)
: G4VContinuousDiscreteProcess (processName),
lastMaterial (0),
MaxExcitationNumber (1.e6),
probLimFluct (0.01),
nmaxDirectFluct (100),
@@ -230,49 +232,26 @@ void G4hLowEnergyLoss::BuildDEDXTable(
const G4ParticleDefinition& aParticleType)
{
// calculate data members TotBin,LOGRTable,RTable first
/*
G4double binning = dRoverRange;
G4double lrate = log(HighestKineticEnergy/LowestKineticEnergy);
G4int nbin = G4int(lrate/log(1.+binning) + 0.5 );
nbin = (nbin+25)/50;
LOGRTable=lrate/TotBin;
RTable =exp(LOGRTable);
*/
// create table if there is no table or there is a new cut value
G4bool MakeTable = false ;
// ---- MGP ---- workaround for the deprecated "cuts per material"
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
const G4Material* material = (*theMaterialTable)[0];
G4double ElectronCutInRange = G4Electron::Electron()->GetEnergyThreshold(material);
// was = G4Electron::Electron()->GetCuts();
// ---- MGP ----
// create/fill proton or antiproton tables depending on the charge
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
// create/fill proton or antiproton tables depending on the charge
Charge = aParticleType.GetPDGCharge()/eplus;
ParticleMass = aParticleType.GetPDGMass() ;
if (Charge>0.) {theDEDXTable= theDEDXpTable;}
else {theDEDXTable= theDEDXpbarTable;}
if(
((Charge>0.) && ((theDEDXTable==0) ||
(ElectronCutInRange != ptableElectronCutInRange)))
||
((Charge<0.) && ((theDEDXTable==0) ||
(ElectronCutInRange != pbartableElectronCutInRange)))
if( ((Charge>0.) && (theDEDXTable==0)) ||
((Charge<0.) && (theDEDXTable==0))
)
MakeTable = true ;
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if( MakeTable )
{
// Build energy loss table as a sum of the energy loss due to the
// different processes.
if( Charge >0.)
// different processes.
if( Charge >0.)
{
RecorderOfProcess=RecorderOfpProcess;
CounterOfProcess=CounterOfpProcess;
@@ -282,9 +261,8 @@ void G4hLowEnergyLoss::BuildDEDXTable(
if(theDEDXpTable)
{ theDEDXpTable->clearAndDestroy();
delete theDEDXpTable; }
theDEDXpTable = new G4PhysicsTable(numOfMaterials);
theDEDXpTable = new G4PhysicsTable(numOfCouples);
theDEDXTable = theDEDXpTable;
ptableElectronCutInRange = ElectronCutInRange ;
}
}
else
@@ -297,9 +275,8 @@ void G4hLowEnergyLoss::BuildDEDXTable(
if(theDEDXpbarTable)
{ theDEDXpbarTable->clearAndDestroy();
delete theDEDXpbarTable; }
theDEDXpbarTable = new G4PhysicsTable(numOfMaterials);
theDEDXpbarTable = new G4PhysicsTable(numOfCouples);
theDEDXTable = theDEDXpbarTable;
pbartableElectronCutInRange = ElectronCutInRange ;
}
}
@@ -310,18 +287,18 @@ void G4hLowEnergyLoss::BuildDEDXTable(
G4bool isOutRange ;
G4PhysicsTable* pointer ;
for (G4int J=0; J<numOfMaterials; J++)
{
for (size_t J=0; J<numOfCouples; J++)
{
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(
LowestKineticEnergy, HighestKineticEnergy, TotBin);
LowestKineticEnergy, HighestKineticEnergy, TotBin);
// loop for the kinetic energy
for (G4int i=0; i<TotBin; i++)
{
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
Value = 0. ;
// loop for the contributing processes
for (G4int process=0; process < NumberOfProcesses; process++)
{
@@ -330,24 +307,24 @@ void G4hLowEnergyLoss::BuildDEDXTable(
GetValue(LowEdgeEnergy,isOutRange) ;
}
aVector->PutValue(i,Value) ;
aVector->PutValue(i,Value) ;
}
theDEDXTable->insert(aVector) ;
}
// reset counter to zero ..................
if( Charge >0.)
if( Charge >0.)
CounterOfpProcess=0 ;
else
CounterOfpbarProcess=0 ;
// Build range table
BuildRangeTable( aParticleType);
BuildRangeTable( aParticleType);
// Build lab/proper time tables
BuildTimeTables( aParticleType) ;
// Build coeff tables for the energy loss calculation
BuildRangeCoeffATable( aParticleType);
BuildRangeCoeffBTable( aParticleType);
@@ -360,7 +337,7 @@ void G4hLowEnergyLoss::BuildDEDXTable(
}
// make the energy loss and the range table available
G4EnergyLossTables::Register(&aParticleType,
G4EnergyLossTables::Register(&aParticleType,
(Charge>0)?
theDEDXpTable: theDEDXpbarTable,
(Charge>0)?
@@ -378,35 +355,37 @@ void G4hLowEnergyLoss::BuildDEDXTable(
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyLoss::BuildRangeTable(
const G4ParticleDefinition& aParticleType)
// Build range table from the energy loss table
{
Mass = aParticleType.GetPDGMass();
Mass = aParticleType.GetPDGMass();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if( Charge >0.)
{
{
if(theRangepTable)
{ theRangepTable->clearAndDestroy();
delete theRangepTable; }
theRangepTable = new G4PhysicsTable(numOfMaterials);
theRangepTable = new G4PhysicsTable(numOfCouples);
theRangeTable = theRangepTable ;
}
else
{
{
if(theRangepbarTable)
{ theRangepbarTable->clearAndDestroy();
delete theRangepbarTable; }
theRangepbarTable = new G4PhysicsTable(numOfMaterials);
theRangepbarTable = new G4PhysicsTable(numOfCouples);
theRangeTable = theRangepbarTable ;
}
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (size_t J=0; J<numOfCouples; J++)
{
G4PhysicsLogVector* aVector;
aVector = new G4PhysicsLogVector(LowestKineticEnergy,
@@ -415,7 +394,7 @@ void G4hLowEnergyLoss::BuildRangeTable(
BuildRangeVector(J, aVector);
theRangeTable->insert(aVector);
}
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -423,20 +402,22 @@ void G4hLowEnergyLoss::BuildTimeTables(
const G4ParticleDefinition& aParticleType)
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if(&aParticleType == G4Proton::Proton())
{
if(theLabTimepTable)
{ theLabTimepTable->clearAndDestroy();
delete theLabTimepTable; }
theLabTimepTable = new G4PhysicsTable(numOfMaterials);
theLabTimepTable = new G4PhysicsTable(numOfCouples);
theLabTimeTable = theLabTimepTable ;
if(theProperTimepTable)
{ theProperTimepTable->clearAndDestroy();
delete theProperTimepTable; }
theProperTimepTable = new G4PhysicsTable(numOfMaterials);
theProperTimepTable = new G4PhysicsTable(numOfCouples);
theProperTimeTable = theProperTimepTable ;
}
@@ -445,17 +426,17 @@ void G4hLowEnergyLoss::BuildTimeTables(
if(theLabTimepbarTable)
{ theLabTimepbarTable->clearAndDestroy();
delete theLabTimepbarTable; }
theLabTimepbarTable = new G4PhysicsTable(numOfMaterials);
theLabTimepbarTable = new G4PhysicsTable(numOfCouples);
theLabTimeTable = theLabTimepbarTable ;
if(theProperTimepbarTable)
{ theProperTimepbarTable->clearAndDestroy();
delete theProperTimepbarTable; }
theProperTimepbarTable = new G4PhysicsTable(numOfMaterials);
theProperTimepbarTable = new G4PhysicsTable(numOfCouples);
theProperTimeTable = theProperTimepbarTable ;
}
for (G4int J=0; J<numOfMaterials; J++)
for (size_t J=0; J<numOfCouples; J++)
{
G4PhysicsLogVector* aVector;
G4PhysicsLogVector* bVector;
@@ -591,7 +572,7 @@ void G4hLowEnergyLoss::BuildProperTimeVector(G4int materialIndex,
G4int i=-1;
G4double oldValue = 0. ;
G4double tauold ;
do
do
{
i += 1 ;
LowEdgeEnergy = timeVector->GetLowEdgeEnergy(i);
@@ -764,23 +745,23 @@ void G4hLowEnergyLoss::BuildRangeCoeffATable(
// create table for coefficients "A"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfCouples = G4ProductionCutsTable::GetProductionCutsTable()->GetTableSize();
if(Charge>0.)
{
if(thepRangeCoeffATable)
{ thepRangeCoeffATable->clearAndDestroy();
delete thepRangeCoeffATable; }
thepRangeCoeffATable = new G4PhysicsTable(numOfMaterials);
thepRangeCoeffATable = new G4PhysicsTable(numOfCouples);
theRangeCoeffATable = thepRangeCoeffATable ;
theRangeTable = theRangepTable ;
}
else
else
{
if(thepbarRangeCoeffATable)
{ thepbarRangeCoeffATable->clearAndDestroy();
delete thepbarRangeCoeffATable; }
thepbarRangeCoeffATable = new G4PhysicsTable(numOfMaterials);
thepbarRangeCoeffATable = new G4PhysicsTable(numOfCouples);
theRangeCoeffATable = thepbarRangeCoeffATable ;
theRangeTable = theRangepbarTable ;
}
@@ -793,7 +774,7 @@ void G4hLowEnergyLoss::BuildRangeCoeffATable(
G4bool isOut;
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (G4int J=0; J<numOfCouples; J++)
{
G4int binmax=TotBin ;
G4PhysicsLinearVector* aVector =
@@ -836,14 +817,14 @@ void G4hLowEnergyLoss::BuildRangeCoeffBTable(
// create table for coefficients "B"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfCouples = G4ProductionCutsTable::GetProductionCutsTable()->GetTableSize();
if(Charge>0.)
{
if(thepRangeCoeffBTable)
{ thepRangeCoeffBTable->clearAndDestroy();
delete thepRangeCoeffBTable; }
thepRangeCoeffBTable = new G4PhysicsTable(numOfMaterials);
thepRangeCoeffBTable = new G4PhysicsTable(numOfCouples);
theRangeCoeffBTable = thepRangeCoeffBTable ;
theRangeTable = theRangepTable ;
}
@@ -852,7 +833,7 @@ void G4hLowEnergyLoss::BuildRangeCoeffBTable(
if(thepbarRangeCoeffBTable)
{ thepbarRangeCoeffBTable->clearAndDestroy();
delete thepbarRangeCoeffBTable; }
thepbarRangeCoeffBTable = new G4PhysicsTable(numOfMaterials);
thepbarRangeCoeffBTable = new G4PhysicsTable(numOfCouples);
theRangeCoeffBTable = thepbarRangeCoeffBTable ;
theRangeTable = theRangepbarTable ;
}
@@ -865,7 +846,7 @@ void G4hLowEnergyLoss::BuildRangeCoeffBTable(
G4bool isOut;
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (G4int J=0; J<numOfCouples; J++)
{
G4int binmax=TotBin ;
G4PhysicsLinearVector* aVector =
@@ -907,14 +888,14 @@ void G4hLowEnergyLoss::BuildRangeCoeffCTable(
// create table for coefficients "C"
{
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
G4int numOfCouples = G4ProductionCutsTable::GetProductionCutsTable()->GetTableSize();
if(Charge>0.)
{
if(thepRangeCoeffCTable)
{ thepRangeCoeffCTable->clearAndDestroy();
delete thepRangeCoeffCTable; }
thepRangeCoeffCTable = new G4PhysicsTable(numOfMaterials);
thepRangeCoeffCTable = new G4PhysicsTable(numOfCouples);
theRangeCoeffCTable = thepRangeCoeffCTable ;
theRangeTable = theRangepTable ;
}
@@ -923,7 +904,7 @@ void G4hLowEnergyLoss::BuildRangeCoeffCTable(
if(thepbarRangeCoeffCTable)
{ thepbarRangeCoeffCTable->clearAndDestroy();
delete thepbarRangeCoeffCTable; }
thepbarRangeCoeffCTable = new G4PhysicsTable(numOfMaterials);
thepbarRangeCoeffCTable = new G4PhysicsTable(numOfCouples);
theRangeCoeffCTable = thepbarRangeCoeffCTable ;
theRangeTable = theRangepbarTable ;
}
@@ -936,7 +917,7 @@ void G4hLowEnergyLoss::BuildRangeCoeffCTable(
G4bool isOut;
// loop for materials
for (G4int J=0; J<numOfMaterials; J++)
for (G4int J=0; J<numOfCouples; J++)
{
G4int binmax=TotBin ;
G4PhysicsLinearVector* aVector =
@@ -978,13 +959,16 @@ void G4hLowEnergyLoss::BuildInverseRangeTable(
{
G4bool b;
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
if(&aParticleType == G4Proton::Proton())
{
if(theInverseRangepTable)
{ theInverseRangepTable->clearAndDestroy();
delete theInverseRangepTable; }
theInverseRangepTable = new G4PhysicsTable(numOfMaterials);
theInverseRangepTable = new G4PhysicsTable(numOfCouples);
theInverseRangeTable = theInverseRangepTable ;
theRangeTable = theRangepTable ;
theDEDXTable = theDEDXpTable ;
@@ -998,7 +982,7 @@ void G4hLowEnergyLoss::BuildInverseRangeTable(
if(theInverseRangepbarTable)
{ theInverseRangepbarTable->clearAndDestroy();
delete theInverseRangepbarTable; }
theInverseRangepbarTable = new G4PhysicsTable(numOfMaterials);
theInverseRangepbarTable = new G4PhysicsTable(numOfCouples);
theInverseRangeTable = theInverseRangepbarTable ;
theRangeTable = theRangepbarTable ;
theDEDXTable = theDEDXpbarTable ;
@@ -1008,7 +992,7 @@ void G4hLowEnergyLoss::BuildInverseRangeTable(
}
// loop for materials
for (G4int i=0; i<numOfMaterials; i++)
for (size_t i=0; i<numOfCouples; i++)
{
G4PhysicsVector* pv = (*theRangeTable)[i];
@@ -1036,11 +1020,11 @@ void G4hLowEnergyLoss::BuildInverseRangeTable(
for (ihigh=ilow+1; ihigh<nbins; ihigh++) {
energy2 = pv->GetLowEdgeEnergy(ihigh);
range2 = pv->GetValue(energy2, b);
range2 = pv->GetValue(energy2, b);
if(range2 >= range || ihigh == nbins-1) {
ilow = ihigh - 1;
energy1 = pv->GetLowEdgeEnergy(ilow);
range1 = pv->GetValue(energy1, b);
range1 = pv->GetValue(energy1, b);
break;
}
}
@@ -1106,5 +1090,24 @@ void G4hLowEnergyLoss::InvertRangeVector(G4int materialIndex,
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4bool G4hLowEnergyLoss::CutsWhereModified()
{
G4bool wasModified = false;
const G4ProductionCutsTable* theCoupleTable=
G4ProductionCutsTable::GetProductionCutsTable();
size_t numOfCouples = theCoupleTable->GetTableSize();
for (size_t j=0; j<numOfCouples; j++){
if (theCoupleTable->GetMaterialCutsCouple(j)->IsRecalcNeeded()) {
wasModified = true;
break;
}
}
return wasModified;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
@@ -37,6 +37,7 @@
// 18/08/2000 V.Ivanchenko TRIM85 model is added
// 03/10/2000 V.Ivanchenko CodeWizard clean up
// 10/05/2001 V.Ivanchenko Clean up againist Linux compilation with -Wall
// 30/12/2003 V.Ivanchenko SRIM2003 model is added
//
// Class Description:
//
@@ -55,6 +56,8 @@
#include "G4hZiegler1977p.hh"
#include "G4hZiegler1977He.hh"
#include "G4hZiegler1985p.hh"
#include "G4hSRIM2000p.hh"
//#include "G4hSRIM2003p.hh"
#include "G4hICRU49p.hh"
#include "G4hICRU49He.hh"
#include "G4DynamicParticle.hh"
@@ -83,11 +86,12 @@ void G4hParametrisedLossModel::InitializeMe()
G4String ir49p = G4String("ICRU_R49p") ;
G4String ir49He = G4String("ICRU_R49He") ;
G4String zi85p = G4String("Ziegler1985p") ;
if(zi77p == modelName) {
G4String zi00p = G4String("SRIM2000p") ;
if(zi77p == modelName) {
eStopingPowerTable = new G4hZiegler1977p();
highEnergyLimit = 100.0*MeV;
lowEnergyLimit = 1.0*keV;
} else if(zi77He == modelName) {
eStopingPowerTable = new G4hZiegler1977He();
highEnergyLimit = 10.0*MeV/4.0;
@@ -96,7 +100,12 @@ void G4hParametrisedLossModel::InitializeMe()
} else if(zi85p == modelName) {
eStopingPowerTable = new G4hZiegler1985p();
highEnergyLimit = 100.0*MeV;
lowEnergyLimit = 1.0*eV;
lowEnergyLimit = 1.0*keV;
} else if(zi00p == modelName) {
eStopingPowerTable = new G4hSRIM2000p();
highEnergyLimit = 100.0*MeV;
lowEnergyLimit = 1.0*keV;
} else if(ir49p == modelName || blank == modelName) {
eStopingPowerTable = new G4hICRU49p();
@@ -107,7 +116,7 @@ void G4hParametrisedLossModel::InitializeMe()
eStopingPowerTable = new G4hICRU49He();
highEnergyLimit = 10.0*MeV/4.0;
lowEnergyLimit = 1.0*keV/4.0;
} else {
G4cout <<
"G4hLowEnergyIonisation warning: There is no table with the modelName <"
@@ -0,0 +1,224 @@
//
// ********************************************************************
// * DISCLAIMER *
// * *
// * The following disclaimer summarizes all the specific disclaimers *
// * of contributors to this software. The specific disclaimers,which *
// * govern, are listed with their locations in: *
// * http://cern.ch/geant4/license *
// * *
// * Neither the authors of this software system, nor their employing *
// * institutes,nor the agencies providing financial support for this *
// * work make any representation or warranty, express or implied, *
// * regarding this software system or assume any liability for its *
// * use. *
// * *
// * This code implementation is the intellectual property of the *
// * GEANT4 collaboration. *
// * By copying, distributing or modifying the Program (or any work *
// * based on the Program) you indicate your acceptance of this *
// * statement, and all its terms. *
// ********************************************************************
//
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4hSRIM2000p
//
// Author: V.Ivanchenko (Vladimir.Ivanchenko@cern.ch)
//
// Creation date: 07 Jan 2003
//
// Modifications:
//
// Class Description:
//
// Electronic stopping power parametrised according to
// J. F. Ziegler, SRIM-2000 software package from www.SRIM.org
//
// Class Description: End
//
// -------------------------------------------------------------------
//
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#include "G4hSRIM2000p.hh"
#include "G4UnitsTable.hh"
#include "globals.hh"
#include "G4Material.hh"
G4double G4hSRIM2000p::a[92][8] = {
{ 1.28116E-02, 5.33047E-03, 6.51042E-01, 5.31902E-01, 1.95901E03, 1.18870E00, 5.98263E02, 9.54514E-03}
,{ 3.11787E-01, 4.99529E-03, 1.18546E-01, 9.20917E-01, 9.84843E02, 1.08223E00, 5.54388E02, 5.05072E-02}
,{ 6.44503E-01, 5.00368E-03, 8.66544E-01, 5.67488E-01, 9.62900E02, 1.01566E00, 1.62034E03, 2.37767E-02}
,{ 9.53561E-01, 5.07406E-03, 1.30450E00, 5.90300E-01, 1.94512E03, 1.05703E00, 3.26951E02, 1.30441E-02}
,{ 1.53151E00, 4.88520E-03, 2.56760E00, 4.23246E-01, 1.73888E03, 1.03208E00, 1.82942E03, 2.00331E-02}
,{ 2.40289E00, 4.91497E-03, 2.49101E00, 4.14939E-01, 1.85836E03, 1.01581E00, 2.50417E03, 1.81984E-02}
,{ 3.31007E00, 4.95744E-03, 5.40621E-01, 7.79940E-01, 1.10415E03, 9.67848E-01, 2.23535E03, 5.31612E-02}
,{ 9.72706E-01, 5.00390E-03, 1.35102E00, 5.49800E-01, 1.25428E03, 9.68356E-01, 5.09320E03, 5.36453E-02}
,{ 6.90408E-01, 4.62723E-03, 3.26749E-01, 1.10520E00, 1.30190E03, 9.43525E-01, 4.70373E01, 2.80245E-02}
,{ 2.81235E-01, 4.59698E-03, 5.25630E-01, 8.78183E-01, 1.15830E03, 9.38564E-01, 1.01606E01, 4.14147E-02}
,{ 2.15352E00, 4.40847E-03, 2.30923E00, 6.06001E-01, 1.33224E03, 9.43478E-01, 7.35116E02, 5.77231E-02}
,{ 3.42983E00, 4.36897E-03, 2.39377E00, 5.54737E-01, 1.14029E03, 9.29844E-01, 2.10748E03, 7.89342E-02}
,{ 3.89096E-02, 4.54168E-03, 4.27975E00, 4.78838E-01, 1.31642E03, 9.34106E-01, 5.65574E02, 5.27220E-02}
,{ 1.33101E00, 4.43533E-03, 1.52262E00, 7.75843E-01, 1.22702E03, 9.14146E-01, 1.09117E03, 4.44972E-02}
,{ 5.78119E00, 3.98281E-03, 3.24072E-01, 1.22769E00, 6.73459E02, 8.65731E-01, 1.23619E02, 1.82036E-01}
,{ 6.11741E-01, 4.46376E-03, 3.38101E00, 5.42907E-01, 1.16067E03, 9.12049E-01, 1.40312E04, 8.77050E-02}
,{ 1.15307E00, 4.47333E-03, 4.20464E00, 5.38231E-01, 1.30113E03, 9.02702E-01, 4.92301E03, 5.25717E-02}
,{ 1.70408E00, 4.47609E-03, 2.75072E00, 5.83835E-01, 2.71393E03, 9.53183E-01, 2.03579E03, 1.46897E-02}
,{ 2.60265E00, 4.32185E-03, 1.56811E00, 8.64656E-01, 5.56393E02, 8.44750E-01, 1.20010E02, 9.62648E-01}
,{ 5.36555E-01, 4.40846E-03, 3.22706E00, 6.02927E-01, 5.00851E02, 8.33450E-01, 1.76639E03, 2.02699E00}
,{ 1.71870E00, 4.36934E-03, 4.60285E00, 5.16212E-01, 1.60160E03, 9.14664E-01, 6.34168E03, 6.29243E-02}
,{ 1.46403E-01, 4.84558E-03, 5.54014E00, 4.55903E-01, 1.76346E03, 9.19014E-01, 3.95193E03, 5.50341E-02}
,{ 4.21238E00, 4.00130E-03, 3.79858E00, 4.82892E-01, 2.41697E03, 9.36204E-01, 7.73596E03, 2.89635E-02}
,{ 6.97881E-01, 4.30794E-03, 2.28630E00, 7.84069E-01, 9.67872E02, 8.57874E-01, 1.78526E01, 1.11149E-01}
,{ 5.92743E-01, 4.31334E-03, 1.40625E00, 9.68261E-01, 1.42642E03, 8.81488E-01, 1.44002E01, 4.24183E-02}
,{ 2.83155E-02, 3.54506E-03, 5.64961E-01, 1.24111E00, 1.52781E03, 8.81848E-01, 2.59497E01, 3.54067E-02}
,{ 2.69545E-01, 4.32088E-03, 2.24249E00, 7.64706E-01, 1.24391E03, 8.67051E-01, 2.34911E01, 6.04457E-02}
,{ 3.68234E00, 4.37139E-03, 1.52146E00, 7.36656E-01, 1.47086E03, 8.74909E-01, 2.51685E02, 4.28115E-02}
,{ 2.15403E00, 4.32278E-03, 2.69390E00, 5.23003E-01, 1.71727E03, 8.93617E-01, 2.09938E03, 5.25222E-02}
,{ 5.31847E-01, 3.82833E-03, 6.75606E-01, 1.06647E00, 1.00848E03, 8.26099E-01, 3.58939E01, 4.19818E-02}
,{ 6.91973E00, 4.01198E-03, 5.22284E-01, 9.74708E-01, 8.99033E02, 8.21636E-01, 3.71581E02, 7.38361E-02}
,{ 1.80976E00, 4.48896E-03, 5.66120E00, 4.18493E-01, 1.55821E03, 8.70542E-01, 1.75605E03, 6.05859E-02}
,{ 1.64641E00, 4.30255E-03, 5.12108E00, 5.16356E-01, 1.02024E03, 8.32723E-01, 2.20277E03, 8.46531E-02}
,{ 4.07150E00, 4.29051E-03, 3.33803E00, 5.43517E-01, 2.60626E03, 9.03072E-01, 1.08974E03, 1.81133E-02}
,{ 1.99798E00, 4.29503E-03, 3.23907E00, 5.93111E-01, 4.64572E03, 9.47444E-01, 6.40841E02, 9.69460E-03}
,{ 5.08884E00, 4.25630E-03, 1.43000E00, 7.22156E-01, 7.08778E03, 9.79865E-01, 7.62818E02, 6.04351E-03}
,{ 6.26370E-01, 4.13189E-03, 6.66229E-02, 2.65318E00, 1.07460E03, 8.14706E-01, 8.69523E00, 5.04427E-02}
,{ 5.04987E00, 3.93427E-03, 4.95613E00, 5.27062E-01, 1.88617E03, 8.68672E-01, 4.81765E03, 3.49423E-02}
,{ 1.17376E00, 4.21587E-03, 5.93823E00, 4.90520E-01, 1.55691E03, 8.49851E-01, 7.82193E03, 4.34207E-02}
,{ 7.26083E00, 4.19413E-03, 5.93121E00, 4.47579E-01, 4.68769E03, 9.39722E-01, 2.44636E03, 1.01526E-02}
,{ 3.51621E-01, 4.12551E-03, 1.33637E00, 1.28649E00, 1.49535E03, 8.50544E-01, 1.27864E01, 4.71084E-02}
,{ 1.79112E-02, 4.17066E-03, 1.16601E00, 1.18837E00, 1.26027E03, 8.25733E-01, 1.29721E01, 4.82827E-02}
,{ 3.72287E00, 4.17681E-03, 4.62860E00, 5.67689E-01, 1.67802E03, 8.62020E-01, 3.09395E03, 6.24402E-02}
,{ 1.79112E-02, 4.17066E-03, 1.16601E00, 1.18837E00, 1.26027E03, 8.25733E-01, 1.29721E01, 4.82827E-02}
,{ 3.07959E-01, 4.14183E-03, 5.45099E-01, 1.36766E00, 1.49906E03, 8.36456E-01, 2.65156E01, 3.82323E-02}
,{ 8.13324E-01, 4.21976E-03, 5.48878E00, 6.21228E-01, 1.49147E03, 8.43298E-01, 1.70197E01, 6.33415E-02}
,{ 2.89508E00, 4.20494E-03, 5.30021E00, 4.58632E-01, 1.38077E03, 8.35929E-01, 1.31565E04, 7.68200E-02}
,{ 3.47169E00, 4.13440E-03, 3.23372E00, 6.37885E-01, 1.11636E03, 8.19589E-01, 4.76603E03, 1.17895E-01}
,{ 2.28576E00, 4.22582E-03, 3.48478E00, 6.25713E-01, 8.04033E02, 7.95990E-01, 8.95357E03, 3.02479E-01}
,{ 4.70915E00, 4.09414E-03, 3.88322E00, 5.82491E-01, 1.03140E03, 8.15544E-01, 1.33004E04, 1.67355E-01}
,{ 7.35883E00, 4.38746E-03, 3.22730E00, 6.93616E-01, 1.36465E03, 8.32171E-01, 1.51236E03, 7.87703E-02}
,{ 1.20379E00, 4.21476E-03, 4.65732E00, 6.15557E-01, 8.57568E02, 7.94208E-01, 5.81437E03, 2.55765E-01}
,{ 4.21323E00, 4.20978E-03, 4.67533E00, 5.79451E-01, 3.50393E03, 8.92614E-01, 1.46887E03, 1.43590E-02}
,{ 1.00615E01, 3.91035E-03, 3.64002E-01, 1.20347E00, 1.53997E03, 8.21892E-01, 1.42428E03, 4.02424E-02}
,{ 3.73157E-01, 3.64035E-03, 2.26519E00, 1.15100E00, 1.67529E03, 8.37764E-01, 1.30656E01, 5.16993E-02}
,{ 4.82483E00, 4.14578E-03, 6.09343E00, 5.70256E-01, 2.30011E03, 8.63588E-01, 2.98072E03, 3.86788E-02}
,{ 5.74872E-01, 4.10857E-03, 2.76314E00, 8.78406E-01, 6.54727E02, 7.77081E-01, 4.60584E02, 9.63426E-01}
,{ 3.27544E00, 4.21774E-03, 5.76803E00, 5.40540E-01, 6.63129E03, 9.42817E-01, 7.44066E02, 8.30259E-03}
,{ 2.99783E00, 4.09014E-03, 4.52986E00, 6.20247E-01, 2.16115E03, 8.56688E-01, 1.26859E03, 4.30305E-02}
,{ 3.02248E00, 4.10313E-03, 3.16182E00, 7.50444E-01, 6.87321E02, 7.65038E-01, 3.63380E02, 3.89438E-01}
,{ 3.56550E00, 4.11367E-03, 6.01196E00, 5.21709E-01, 1.83002E03, 8.38996E-01, 3.66199E03, 5.75667E-02}
,{ 3.64072E00, 4.17820E-03, 4.87424E00, 5.78614E-01, 1.26770E03, 8.22111E-01, 3.50817E03, 2.41737E-01}
,{ 5.42525E-01, 4.12806E-03, 4.33656E00, 6.39323E-01, 1.10785E03, 7.88122E-01, 3.52321E02, 9.46601E-02}
,{ 7.54702E00, 4.08134E-03, 4.92913E00, 5.07107E-01, 2.56583E03, 8.61877E-01, 3.29996E03, 3.12730E-02}
,{ 4.43006E00, 4.19028E-03, 5.39210E00, 5.08608E-01, 3.60527E03, 8.85038E-01, 1.68786E03, 1.64866E-02}
,{ 4.31706E00, 4.06269E-03, 3.55237E00, 5.72971E-01, 2.13874E03, 8.39174E-01, 3.20435E03, 2.94710E-02}
,{ 2.73097E00, 4.02842E-03, 3.10590E00, 6.45438E-01, 1.80236E03, 8.20889E-01, 6.91941E02, 3.06839E-02}
,{ 1.27982E00, 4.05535E-03, 4.63018E00, 5.73846E-01, 1.59512E03, 8.16419E-01, 1.06728E03, 5.52321E-02}
,{ 5.75613E00, 4.04905E-03, 4.35700E00, 5.24956E-01, 2.20732E03, 8.37956E-01, 1.57951E03, 2.71650E-02}
,{ 9.20610E00, 4.03636E-03, 3.37689E00, 5.72174E-01, 3.66035E03, 8.68034E-01, 1.19114E03, 9.53995E-03}
,{ 8.23962E00, 4.04348E-03, 3.83028E00, 5.34511E-01, 4.35771E03, 8.82431E-01, 1.52426E03, 7.86437E-03}
,{ 3.06189E00, 4.05111E-03, 3.58030E00, 5.90820E-01, 2.34610E03, 8.37132E-01, 1.22199E03, 2.00717E-02}
,{ 7.99485E00, 3.29576E-03, 1.26335E00, 7.77934E-01, 1.80413E03, 8.12400E-01, 1.26630E03, 2.63526E-02}
,{ 6.48326E00, 4.14609E-03, 7.76185E-01, 1.08393E00, 2.50557E02, 6.43106E-01, 1.77277E02, 8.98821E-01}
,{ 6.20494E-01, 4.03017E-03, 2.53792E00, 6.77642E-01, 7.27918E02, 7.48340E-01, 1.17069E02, 2.01369E-01}
,{ 5.51045E-01, 4.02571E-03, 2.70928E00, 6.83870E-01, 1.08946E03, 7.77755E-01, 1.08830E03, 8.10305E-02}
,{ 1.26011E00, 4.04797E-03, 3.57127E00, 5.25416E-01, 2.61309E03, 8.53001E-01, 2.15571E03, 2.82139E-02}
,{ 3.20857E00, 4.05101E-03, 3.66577E00, 5.36178E-01, 3.09116E03, 8.56024E-01, 1.50812E03, 1.54014E-02}
,{ 1.04066E00, 4.05071E-03, 5.61035E00, 4.39133E-01, 3.64613E03, 8.69259E-01, 2.87840E03, 1.39437E-02}
,{ 1.04586E00, 4.05038E-03, 5.38433E00, 4.45067E-01, 3.71715E03, 8.70310E-01, 2.90728E03, 1.32933E-02}
,{ 3.15124E00, 4.05235E-03, 4.09956E00, 5.42499E-01, 3.24631E03, 8.57723E-01, 1.69177E03, 1.50581E-02}
,{ 3.06995E00, 4.05334E-03, 6.62045E00, 4.52822E-01, 3.38058E03, 8.60267E-01, 2.63856E03, 1.53938E-02}
,{ 3.84541E00, 4.06028E-03, 8.77920E00, 4.42301E-01, 2.72199E03, 8.43866E-01, 2.51315E03, 2.28962E-02}
,{ 4.36117E00, 4.05648E-03, 8.18512E00, 4.36260E-01, 3.11358E03, 8.52235E-01, 3.00179E03, 1.72051E-02}
,{ 4.36117E00, 4.05648E-03, 8.18512E00, 4.36260E-01, 3.11358E03, 8.52235E-01, 3.00179E03, 1.72051E-02}
,{ 3.22200E00, 4.00409E-03, 5.90236E00, 5.26779E-01, 4.04015E03, 8.68037E-01, 1.65835E03, 1.17469E-02}
,{ 9.34124E00, 3.96606E-03, 7.92099E00, 4.29769E-01, 5.18090E03, 8.87726E-01, 2.17316E03, 9.20070E-03}
,{ 6.28686E00, 3.96735E-03, 5.81778E00, 5.35859E-01, 4.86643E03, 8.84427E-01, 2.25734E03, 1.05815E-02}
,{ 5.92839E00, 3.96948E-03, 6.40824E00, 5.21225E-01, 4.61951E03, 8.80827E-01, 2.32352E03, 1.16274E-02}
,{ 5.24536E00, 3.97440E-03, 6.79689E00, 4.85424E-01, 4.58631E03, 8.77944E-01, 2.48150E03, 1.12824E-02}
,{ 2.77047E00, 3.98192E-03, 3.55107E00, 6.38231E-01, 2.51688E03, 8.29309E-01, 2.15559E03, 2.31207E-02}
,{ 2.78483E00, 3.98116E-03, 3.32988E00, 6.47983E-01, 2.66277E03, 8.36780E-01, 2.33743E03, 2.40740E-02}
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4hSRIM2000p::G4hSRIM2000p():G4VhElectronicStoppingPower(),
protonMassAMU(1.007276)
{;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4hSRIM2000p::~G4hSRIM2000p()
{;}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4hSRIM2000p::HasMaterial(const G4Material* material)
{
if(1 == (material->GetNumberOfElements())) return true;
return false ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4hSRIM2000p::StoppingPower(const G4Material* material,
G4double kineticEnergy)
{
G4double ionloss = 0.0 ;
// pure material (normally not the case for this function)
if(1 == (material->GetNumberOfElements())) {
G4double z = material->GetZ() ;
ionloss = ElectronicStoppingPower( z, kineticEnergy ) ;
}
return ionloss;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4hSRIM2000p::ElectronicStoppingPower(G4double z,
G4double kineticEnergy) const
{
G4double ionloss ;
G4int i = G4int(z) - 1 ; // index of atom
if(i < 0) i = 0 ;
if(i > 91) i = 91 ;
// Proton kinetic energy for parametrisation in Ziegler's units (keV/amu)
G4double T = kineticEnergy/(keV*protonMassAMU) ;
G4double e = T ;
if ( T < 25.0 ) e = 25.0 ;
// universal approximation
G4double slow = a[i][0] * pow(e, a[i][1]) + a[i][2] * pow(e, a[i][3]) ;
G4double shigh = log( a[i][6]/e + a[i][7]*e ) * a[i][4] / pow(e, a[i][5]) ;
ionloss = slow*shigh / (slow + shigh) ;
// low energy region
if ( T < 25.0 ) {
G4double s = 0.45 ;
// light elements
if(6.5 > z) s = 0.25 ;
// semiconductors
if(5 == i || 13 == i || 31 == i) s = 0.375 ;
ionloss *= pow(T/25.0, s) ;
}
if ( ionloss < 0.0) ionloss = 0.0 ;
return ionloss;
}