Import Geant4 4.0.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-08 16:18:25 +02:00
parent 36c080dca6
commit 921d3b1cda
3990 changed files with 185376 additions and 82884 deletions
@@ -0,0 +1,237 @@
//
// ********************************************************************
// * 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: G4AtomicTransitionManager.hh,v 1.2 ????
// GEANT4 tag $Name: geant4-04-00 $
//
// Authors: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
// Alfonso Mantero (Alfonso.Mantero@ge.infn.it)
//
// History:
// -----------
//
// 16 Sept 2001 First committed to cvs
//
// -------------------------------------------------------------------
#include "G4AtomicDeexcitation.hh"
#include "Randomize.hh"
#include "G4Gamma.hh"
G4AtomicDeexcitation::G4AtomicDeexcitation()
{ }
G4AtomicDeexcitation::~G4AtomicDeexcitation()
{ }
G4std::vector<G4DynamicParticle*>* G4AtomicDeexcitation::GenerateParticles(G4int Z,G4int shellId)
{
G4std::vector<G4DynamicParticle*>* vectorOfParticles = new G4std::vector<G4DynamicParticle*>;
G4DynamicParticle* aParticle;
G4int provShellId = 0;
G4int counter = 0;
// The aim of this loop is to generate more than one fluorecence photon
// from the same ionizing event
while (provShellId >= 0)
{
if (counter == 0)
// First call to GenerateParticles(...):
// shellId is given by the process
{
provShellId = SelectTypeOfTransition(Z, shellId);
if ( provShellId >0)
{
aParticle = GenerateFluorescence(Z,shellId,provShellId);
}
else if ( provShellId ==-1)
{
aParticle = GenerateAuger(Z, shellId);
}
else
{
G4Exception("G4AtomicDeexcitation: starting shell uncorrect: check it");
}
}
else
// Following calls to GenerateParticles(...):
// newShellId is given by GenerateFluorescence(...)
{
provShellId = SelectTypeOfTransition(Z,newShellId);
if ( provShellId >0)
{
aParticle = GenerateFluorescence(Z,newShellId,provShellId);
}
else if ( provShellId ==-1)
{
aParticle = GenerateAuger(Z, newShellId);
}
else
{
G4Exception("G4AtomicDeexcitation: starting shell uncorrect: check it");
}
}
counter++;
vectorOfParticles->push_back(aParticle);
}
return vectorOfParticles;
}
const G4int G4AtomicDeexcitation::SelectTypeOfTransition(G4int Z, G4int shellId)
{
if (shellId <=0 )
{G4Exception("G4AtomicDeexcitation: zero or negative shellId");}
G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
G4int provShellId = -1;
G4int shellNum = 0;
G4int maxNumOfShells = transitionManager->NumberOfReachableShells(Z);
const G4AtomicTransition* refShell = transitionManager->ReachableShell(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 radiative transition
if ( shellId <= refShell->FinalShellId())
{
while (shellId != transitionManager->ReachableShell(Z,shellNum)->FinalShellId())
{
if(shellNum ==maxNumOfShells-1)
{
break;
}
shellNum++;
}
G4int transProb = 1;
G4double partialProb = G4UniformRand();
G4double partSum = 0;
const G4AtomicTransition* aShell = transitionManager->ReachableShell(Z,shellNum);
G4int trSize = (aShell->TransitionProbabilities()).size();
// Loop over the shells wich can provide an electron for a
// radiative transition towards shellId:
// in every loop the partial sum of the first transProb shells
// is calculated and compared with a random number [0,1].
// If the partial sum is greater the shell whose index transProb
// is chosen as the starting shell for a radiative transition
// and its identity is returned
// Else, terminateded the loop, -1 is returned
while(transProb < trSize){
partSum += aShell->TransitionProbability(transProb);
if(partialProb <= partSum)
{
provShellId = aShell->OriginatingShellId(transProb);
break;
}
transProb++;
}
}
else
{
provShellId = -1;
}
return provShellId;
}
G4DynamicParticle* G4AtomicDeexcitation::GenerateFluorescence(G4int Z,
G4int shellId,
G4int provShellId )
{
G4AtomicTransitionManager* transitionManager = G4AtomicTransitionManager::Instance();
// G4int provenienceShell = provShellId;
//isotropic angular distribution for the outcoming photon
G4double newcosTh = 1.-2.*G4UniformRand();
G4double newsinTh = sqrt(1.-newcosTh*newcosTh);
G4double newPhi = twopi*G4UniformRand();
G4double xDir = newsinTh*sin(newPhi);
G4double yDir = newsinTh*cos(newPhi);
G4double zDir = newcosTh;
G4ThreeVector newGammaDirection(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 gamma leaving provShellId for shellId
G4double transitionEnergy = transitionManager->
ReachableShell(Z,shellNum)->TransitionEnergy(index);
// This is the shell where the new vacancy is: it is the same
// shell where the electron came from
newShellId = transitionManager->
ReachableShell(Z,shellNum)->OriginatingShellId(index);
G4DynamicParticle* newPart = new G4DynamicParticle(G4Gamma::Gamma(),
newGammaDirection,
transitionEnergy);
return newPart;
}
G4DynamicParticle* G4AtomicDeexcitation::GenerateAuger(G4int Z, G4int shellId)
{
return 0;
}
@@ -21,42 +21,37 @@
// ********************************************************************
//
//
// -------------------------------------------------------------------
// GEANT 4 class file
// $Id: G4AtomicShell.cc,v 1.2 ????
// GEANT4 tag $Name: geant4-04-00 $
//
// CERN, Geneva, Switzerland
// Authors: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
// Alfonso Mantero (Alfonso.Mantero@ge.infn.it)
//
// File name: G4FirstLevel.hh
// History:
// -----------
// 16 Sept 2001 EG Modified according to a design iteration in the
// LowEnergy category
//
// Author: Alessandra Forti (Alessandra.Forti@cern.ch)
//
// Creation date: 1 Giugno 1999
//
// Modifications: 24.04.01 V.Ivanchenko remove RogueWave
//
// -------------------------------------------------------------------
#include "G4FirstLevel.hh"
#include "G4AtomicShell.hh"
G4AtomicShell::G4AtomicShell(G4int id, G4double energy)
{
identifier = id;
bindingEnergy = energy;
}
G4FirstLevel::~G4FirstLevel(){
G4AtomicShell::~G4AtomicShell()
{ }
//this->clearAndDestroy();
this->clear();
}
G4bool G4FirstLevel::operator == (const G4FirstLevel& input) const{
// return( this->entries() == input.entries());
return( this->size() == input.size());
}
G4bool G4FirstLevel::operator < (const G4FirstLevel& input) const{
// return(this->entries() < input.entries());
return(this->size() < input.size());
G4double G4AtomicShell::BindingEnergy() const {
return bindingEnergy;
}
G4int G4AtomicShell::ShellId() const{
return identifier;
}
@@ -0,0 +1,84 @@
//
// ********************************************************************
// * 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: G4AtomicTransition.cc,v 1.2 ????
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
//
// History:
// -----------
// 16 Sept 2001 EG Modified according to a design iteration in the
// LowEnergy category
//
// -------------------------------------------------------------------
#include "G4AtomicTransition.hh"
G4AtomicTransition::G4AtomicTransition(G4int finalShell,
const G4std::vector<G4int>& ids,
const G4DataVector& energies,
const G4DataVector& prob)
{
finalShellId = finalShell;
originatingShellIds = ids;
transitionEnergies = energies;
transitionProbabilities = prob;
}
G4AtomicTransition::~G4AtomicTransition()
{ }
const G4std::vector<G4int>& G4AtomicTransition::OriginatingShellIds() const
{
return originatingShellIds;
}
const G4DataVector& G4AtomicTransition::TransitionEnergies() const
{
return transitionEnergies;
}
const G4DataVector& G4AtomicTransition::TransitionProbabilities() const
{
return transitionProbabilities;
}
const G4int G4AtomicTransition::FinalShellId() const
{
return finalShellId;
}
G4int G4AtomicTransition::OriginatingShellId(G4int index) const
{
return originatingShellIds[index];
}
G4double G4AtomicTransition::TransitionEnergy(G4int index) const
{
return transitionEnergies[index];
}
G4double G4AtomicTransition::TransitionProbability(G4int index) const
{
return transitionProbabilities[index];
}
@@ -0,0 +1,324 @@
//
// ********************************************************************
// * 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: G4AtomicTransitionManager.cc,v 1.2 ????
// GEANT4 tag $Name: geant4-04-00 $
//
// Authors: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
// Alfonso Mantero (Alfonso.Mantero@ge.infn.it)
//
// History:
// -----------
// 16 Sep 2001 E. Guardincerri First Committed to cvs
//
// -------------------------------------------------------------------
#include "G4AtomicTransitionManager.hh"
G4AtomicTransitionManager::G4AtomicTransitionManager(G4int minZ, G4int maxZ, G4int limitInfTable,G4int limitSupTable)
:zMin(minZ), zMax(maxZ),infTableLimit(limitInfTable),supTableLimit(limitSupTable)
{
// infTableLimit is initialized to 6 because EADL lacks data for Z<=5
G4ShellData* shellManager = new G4ShellData;
shellManager->LoadData("/fluor/binding");
// Fills shellTable with the data from EADL, identities and binding
// energies of shells
for (G4int Z = zMin; Z<= zMax; Z++)
{
G4std::vector<G4AtomicShell*> vectorOfShells;
size_t numberOfShells=shellManager->NumberOfShells(Z);
for (size_t shellIndex = 0; shellIndex<numberOfShells; shellIndex++)
{
G4int shellId = shellManager->ShellId(Z,shellIndex);
G4double bindingEnergy = shellManager->BindingEnergy(Z,shellIndex);
G4AtomicShell * shell = new G4AtomicShell(shellId,bindingEnergy);
vectorOfShells.push_back(shell);
}
// shellTable.insert(G4std::make_pair(Z, vectorOfShells));
shellTable[Z] = vectorOfShells;
}
// Fills transitionTable with the data from EADL, identities, transition
// energies and transition probabilities
for (G4int Znum= infTableLimit; Znum<=supTableLimit; Znum++)
{ G4FluoData* fluoManager = new G4FluoData;
G4std::vector<G4AtomicTransition*> vectorOfTransitions;
fluoManager->LoadData(Znum);
size_t numberOfVacancies = fluoManager-> NumberOfVacancies();
for (size_t vacancyIndex = 0; vacancyIndex<numberOfVacancies; vacancyIndex++)
{
G4std::vector<G4int> vectorOfIds;
G4DataVector vectorOfEnergies;
G4DataVector vectorOfProbabilities;
G4int finalShell = fluoManager->VacancyId(vacancyIndex);
size_t numberOfTransitions = fluoManager->NumberOfTransitions(vacancyIndex);
for (size_t origShellIndex = 0; origShellIndex <= numberOfTransitions;origShellIndex++)
{
G4int originatingShellId = fluoManager->StartShellId(origShellIndex,vacancyIndex);
vectorOfIds.push_back(originatingShellId);
G4double transitionEnergy = fluoManager->StartShellEnergy(origShellIndex,vacancyIndex);
vectorOfEnergies.push_back(transitionEnergy);
G4double transitionProbability = fluoManager->StartShellProb(origShellIndex,vacancyIndex);
vectorOfProbabilities.push_back(transitionProbability);
}
G4AtomicTransition * transition = new G4AtomicTransition (finalShell,vectorOfIds,
vectorOfEnergies,vectorOfProbabilities);
vectorOfTransitions.push_back(transition);
}
// transitionTable.insert(G4std::make_pair(Znum, vectorOfTransitions));
transitionTable[Znum] = vectorOfTransitions;
delete fluoManager;
}
delete shellManager;
}
G4AtomicTransitionManager::~G4AtomicTransitionManager()
{ G4std::map<G4int,G4std::vector<G4AtomicShell*>,G4std::less<G4int> >::iterator pos;
for (pos = shellTable.begin(); pos != shellTable.end(); pos++){
G4std::vector< G4AtomicShell*>vec = (*pos).second;
G4int vecSize=vec.size();
for (G4int i=0; i< vecSize; i++){
delete vec[i];
}
}
G4std::map<G4int,G4std::vector<G4AtomicTransition*>,G4std::less<G4int> >::iterator ppos;
for (ppos = transitionTable.begin(); ppos != transitionTable.end(); ppos++){
G4std::vector< G4AtomicTransition*>vec = (*ppos).second;
G4int vecSize=vec.size();
for (G4int i=0; i< vecSize; i++){
delete vec[i];
}
}
}
G4AtomicTransitionManager* G4AtomicTransitionManager::instance = 0;
G4AtomicTransitionManager* G4AtomicTransitionManager::Instance()
{
if (instance==0)
{
instance = new G4AtomicTransitionManager;
}
return instance;
}
const G4AtomicShell* G4AtomicTransitionManager::Shell(G4int Z, size_t shellIndex)
{
G4std::map<G4int,G4std::vector<G4AtomicShell*>,G4std::less<G4int> >::iterator pos;
pos = shellTable.find(Z);
if (pos!= shellTable.end()){
G4std::vector<G4AtomicShell*> v = (*pos).second;
if (shellIndex<v.size()){
return(v[shellIndex]);
}
else {
G4Exception("G4AtomicTransitionManager:shell not found");
return 0;
}
}
else{
G4Exception("G4AtomicTransitionManager:Z not found");
return 0;
}
}
const G4AtomicTransition* G4AtomicTransitionManager:: ReachableShell(G4int Z,size_t shellIndex)
{
G4std::map<G4int,G4std::vector<G4AtomicTransition*>,G4std::less<G4int> >::iterator pos;
pos = transitionTable.find(Z);
if (pos!= transitionTable.end())
{
G4std::vector<G4AtomicTransition*> v = (*pos).second;
if (shellIndex < v.size()) return(v[shellIndex]);
else {
G4Exception("G4AtomicTransitionManager:reachable shell not found");
return 0;
}
}
else{
G4Exception("G4AtomicTransitionManager:Z not found");
return 0;
}
}
G4int G4AtomicTransitionManager::NumberOfShells (G4int Z)
{
G4std::map<G4int,G4std::vector<G4AtomicShell*>,G4std::less<G4int> >::iterator pos;
pos = shellTable.find(Z);
if (pos!= shellTable.end()){
G4std::vector<G4AtomicShell*> v = (*pos).second;
return v.size();
}
else{
G4Exception( "G4AtomicTransitionManager: Z not found" );
return 0;
}
}
G4int G4AtomicTransitionManager::NumberOfReachableShells(G4int Z)
{
G4std::map<G4int,G4std::vector<G4AtomicTransition*>,G4std::less<G4int> >::iterator pos;
pos = transitionTable.find(Z);
if (pos!= transitionTable.end())
{
G4std::vector<G4AtomicTransition*> v = (*pos).second;
return v.size();
}
else
{
G4Exception( "G4AtomicTransitionManager: Z not found" );
return 0;
}
}
G4double G4AtomicTransitionManager::TotalRadiativeTransitionProbability(G4int Z,
size_t shellIndex)
{
G4std::map<G4int,G4std::vector<G4AtomicTransition*>,G4std::less<G4int> >::iterator pos;
pos = transitionTable.find(Z);
if (pos!= transitionTable.end())
{
G4std::vector<G4AtomicTransition*> v = (*pos).second;
if (shellIndex < v.size())
{
G4AtomicTransition* transition = v[shellIndex];
G4DataVector transProb = transition->TransitionProbabilities();
G4double totalRadTransProb = 0;
for (size_t j = 1; j<transProb.size(); j++)
{
totalRadTransProb = totalRadTransProb + transProb[j];
}
return totalRadTransProb;
}
else {
G4Exception( "G4AtomicTransitionManager: shell not found" );
return 0;
}
}
else{
G4Exception( "G4AtomicTransitionManager: Z not found");
return 0;
}
}
G4double G4AtomicTransitionManager::TotalNonRadiativeTransitionProbability(G4int Z, size_t shellIndex)
{
G4std::map<G4int,G4std::vector<G4AtomicTransition*>,G4std::less<G4int> >::iterator pos;
pos = transitionTable.find(Z);
if (pos!= transitionTable.end()){
G4std::vector<G4AtomicTransition*> v = (*pos).second;
if (shellIndex<v.size()){
G4AtomicTransition* transition=v[shellIndex];
G4DataVector transProb = transition->TransitionProbabilities();
G4double totalRadTransProb = 0;
for(size_t j = 1; j<transProb.size(); j++)
{
totalRadTransProb = totalRadTransProb + transProb[j];
}
G4double totalNonRadTransProb= (1 - totalRadTransProb);
return totalNonRadTransProb; }
else {
G4Exception( "shell not found");
return 0;
}
}
else{
G4Exception("Z not found");
return 0;
}
}
@@ -0,0 +1,125 @@
//
// ********************************************************************
// * 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: G4BremsstrahlungCrossSectionHandler.cc,v 1.5 2001/10/25 14:31:20 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4BremsstrahlungCrossSectionHandler
//
// Author: V.Ivanchenko (Vladimir.Ivanchenko@cern.ch)
//
// Creation date: 25 September 2001
//
// Modifications:
// 10.10.2001 MGP Revision to improve code quality and consistency with design
//
// -------------------------------------------------------------------
#include "G4BremsstrahlungCrossSectionHandler.hh"
#include "G4eBremsstrahlungSpectrum.hh"
#include "G4DataVector.hh"
#include "G4CompositeEMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4SemiLogInterpolation.hh"
#include "G4VEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4Material.hh"
#include "G4MaterialTable.hh"
G4BremsstrahlungCrossSectionHandler::G4BremsstrahlungCrossSectionHandler(const G4VEnergySpectrum* spec,
G4VDataSetAlgorithm* alg)
: theBR(spec)
{
interp = new G4SemiLogInterpolation();
}
G4BremsstrahlungCrossSectionHandler::~G4BremsstrahlungCrossSectionHandler()
{
delete interp;
}
G4std::vector<G4VEMDataSet*>*
G4BremsstrahlungCrossSectionHandler::BuildCrossSectionsForMaterials(const G4DataVector& energyVector,
const G4DataVector* energyCuts)
{
G4std::vector<G4VEMDataSet*>* set = new G4std::vector<G4VEMDataSet*>;
G4DataVector* energies;
G4DataVector* cs;
G4int nOfBins = energyVector.size();
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
if (materialTable == 0)
G4Exception("G4VCrossSectionHandler::G4VCrossSectionHandler - no MaterialTable found)");
G4int nMaterials = G4Material::GetNumberOfMaterials();
for (G4int m=0; m<nMaterials; m++) {
const G4Material* material = (*materialTable)[m];
const G4ElementVector* elementVector = material->GetElementVector();
const G4double* nAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4int nElements = material->GetNumberOfElements();
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());
energies = new G4DataVector;
cs = new G4DataVector;
G4double density = nAtomsPerVolume[i];
for (G4int bin=0; bin<nOfBins; bin++) {
G4double e = energyVector[bin];
energies->push_back(e);
G4double value = 0.0;
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;
}
@@ -0,0 +1,295 @@
//
// ********************************************************************
// * 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: G4BremsstrahlungParameters.cc,v 1.11 2001/11/29 22:59:56 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
// V.Ivanchenko (Vladimir.Ivantchenko@cern.ch)
//
// History:
// -----------
// 31 Jul 2001 MGP Created
// 12.09.01 V.Ivanchenko Add activeZ and paramA
// 25.09.01 V.Ivanchenko Add parameter C and change interface to B
// 29.11.01 V.Ivanchenko Update parametrisation
//
// -------------------------------------------------------------------
#include "G4BremsstrahlungParameters.hh"
#include "G4VEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4LogLogInterpolation.hh"
#include "G4Material.hh"
#include "g4std/fstream"
#include "g4std/strstream"
G4BremsstrahlungParameters:: G4BremsstrahlungParameters(G4int minZ, G4int maxZ)
: zMin(minZ),
zMax(maxZ),
length(16)
{
LoadData();
}
G4BremsstrahlungParameters::~G4BremsstrahlungParameters()
{
// 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++)
{
G4VEMDataSet* dataSet = (*pos).second;
delete dataSet;
}
activeZ.clear();
paramC.clear();
}
G4double G4BremsstrahlungParameters::Parameter(G4int parameterIndex,
G4int Z,
G4double energy) const
{
G4double value = 0.;
G4int id = Z*20 + parameterIndex;
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
pos = param.find(id);
if (pos!= param.end()) {
G4VEMDataSet* dataSet = (*pos).second;
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 = "
<< id << G4endl;
}
return value;
}
void G4BremsstrahlungParameters::LoadData()
{
// Build the complete string identifying the file with the data set
// define active elements
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
if (materialTable == 0)
G4Exception("G4CrossSectionHandler: no MaterialTable found)");
G4int nMaterials = G4Material::GetNumberOfMaterials();
G4double x = 1.e-9;
for (G4int mm=0; mm<100; mm++) {
paramC.push_back(x);
}
for (G4int m=0; m<nMaterials; 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();
G4int iz = (G4int)Z;
if(iz < 100)
paramC[iz] = 0.217635e-33*(material->GetTotNbOfElectPerVolume());
if (!(activeZ.contains(Z))) {
activeZ.push_back(Z);
}
}
}
// Read parameters
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = G4String("G4BremsstrahlungParameters - G4LEDATA")
+ G4String("environment variable not set");
G4Exception(excep);
}
G4String pathString_a(path);
G4String name_a = pathString_a + "/brem/br-sp.dat";
G4std::ifstream file_a(name_a);
G4std::filebuf* lsdp_a = file_a.rdbuf();
if (! (lsdp_a->is_open()) ) {
G4String excep = G4String("G4BremsstrahlungParameters: cannot open file ")
+ name_a;
G4Exception(excep);
}
// The file is organized into two columns:
// 1st column is the energy
// 2nd column is the corresponding value
// The file terminates with the pattern: -1 -1
// -2 -2
G4DataVector* energies;
G4DataVector* data;
G4double ener = 0.0;
G4double sum = 0.0;
energies = new G4DataVector();
data = new G4DataVector();
G4int z = 0;
G4bool used = false;
G4std::vector<G4DataVector*> a;
for (size_t j=0; j<length; j++) {
G4DataVector* aa = new G4DataVector();
a.push_back(aa);
}
G4DataVector e;
e.clear();
do {
file_a >> ener >> sum;
// End of file
if (ener == -2) {
break;
// End of next element
} else if (ener == -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;
G4VDataSetAlgorithm* inter = new G4LogLogInterpolation();
G4DataVector* eVector = new G4DataVector;
size_t eSize = e.size();
for (size_t s=0; s<eSize; s++) {
eVector->push_back(e[s]);
}
G4VEMDataSet* set = new G4EMDataSet(id,eVector,a[k],inter,1.,1.);
param[id] = set;
}
used = true;
a.clear();
for (size_t j=0; j<length; j++) {
G4DataVector* aa = new G4DataVector();
a.push_back(aa);
}
}
if(!used) {
for (size_t j=0; j<length; j++) {
a[j]->clear();
used = false;
}
}
e.clear();
} else {
if(ener > 1000.) ener = 1000.;
e.push_back(ener);
a[length-1]->push_back(sum);
for (size_t j=0; j<length-1; j++) {
G4double qRead;
file_a >> qRead;
/*
if(ener == 1000.) {
G4double x = 0.1*((G4double)j);
if(j == 0) x = 0.01;
if(j == 10) x = 0.95;
if(j == 11) x = 0.97;
if(j == 12) x = 0.99;
if(j == 13) x = 0.995;
if(j == 14) x = 1.0;
qRead = 1. - x + 0.75*x*x;
}
*/
a[j]->push_back(qRead);
}
}
} while (ener != -2);
file_a.close();
}
G4double G4BremsstrahlungParameters::ParameterC(G4int id) const
{
G4int n = paramC.size();
if (id < 0 || id >= n) {
G4String ex = "G4BremsstrahlungParameters::ParameterC - wrong id=" + id;
G4Exception(ex);
}
return paramC[id];
}
void G4BremsstrahlungParameters::PrintData() const
{
G4cout << G4endl;
G4cout << "===== G4BremsstrahlungParameters =====" << G4endl;
G4cout << G4endl;
G4cout << "===== Parameters =====" << G4endl;
G4cout << G4endl;
size_t nZ = activeZ.size();
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
for (size_t j=0; j<nZ; j++) {
G4int Z = (G4int)activeZ[j];
for (size_t i=0; i<length; i++) {
pos = param.find(Z*20 + i);
if (pos!= param.end()) {
G4cout << "===== Z= " << Z
<< " parameter[" << i << "] ====="
<< G4endl;
G4VEMDataSet* dataSet = (*pos).second;
dataSet->PrintData();
}
}
}
G4cout << "==========================================" << G4endl;
}
@@ -0,0 +1,188 @@
//
// ********************************************************************
// * 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: G4CompositeEMDataSet.cc,v 1.5 2001/10/25 02:32:16 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// -----------
// 1 Aug 2001 MGP Created
//
// -------------------------------------------------------------------
#include "G4CompositeEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "g4std/fstream"
#include "g4std/strstream"
G4CompositeEMDataSet::G4CompositeEMDataSet(G4VDataSetAlgorithm* interpolation,
G4double unitE, G4double unitData,
G4int minZ, G4int maxZ)
:algorithm(interpolation), unit1(unitE), unit2(unitData), zMin(minZ), zMax(maxZ)
{
nComponents = 0;
}
G4CompositeEMDataSet::G4CompositeEMDataSet(const G4String& dataFile,
G4VDataSetAlgorithm* interpolation,
G4double unitE, G4double unitData,
G4int minZ, G4int maxZ)
: algorithm(interpolation), unit1(unitE), unit2(unitData), zMin(minZ), zMax(maxZ)
{
nComponents = 0;
LoadData(dataFile);
}
G4CompositeEMDataSet::~G4CompositeEMDataSet()
{
for (size_t i=0; i<nComponents; i++)
{
delete components[i];
}
delete algorithm;
}
G4double G4CompositeEMDataSet::FindValue(G4double e, G4int id) const
{
// Returns the value in component id corresponding to e
G4double value = 0.;
G4VEMDataSet* component = components[id];
if (component != 0)
{
value = component->FindValue(e);
}
else
{
G4cout << "WARNING - G4CompositeEMDataSet::FindValue - component "
<< id << " not found" << G4endl;
}
return value;
}
void G4CompositeEMDataSet::PrintData() const
{
G4cout << "The data set has " << nComponents << " components" << G4endl;
for (size_t i=0; i<nComponents; i++)
{
G4cout << "--- Component " << i << " ---" << G4endl;
G4VEMDataSet* component = components[i];
component->PrintData();
}
}
void G4CompositeEMDataSet::LoadData(const G4String& fileName)
{
for (G4int Z=zMin; Z<zMax; Z++)
{
// Build the complete string identifying the file with the data set
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
ost << fileName << Z << ".dat";
G4String name(nameChar);
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4CompositeEMDataSet - G4LEDATA environment variable not set";
G4Exception(excep);
}
G4String pathString(path);
G4String dirFile = pathString + "/" + name;
G4std::ifstream file(dirFile);
G4std::filebuf* lsdp = file.rdbuf();
if (! (lsdp->is_open()) )
{
G4String excep = "G4CompositeEMDataSet - data file: " + dirFile + " not found";
G4Exception(excep);
}
G4double a = 0;
G4int k = 1;
G4DataVector* energies = new G4DataVector;
G4DataVector* data = new G4DataVector;
do
{
file >> a;
G4int nColumns = 2;
// The file is organized into two columns:
// 1st column is the energy
// 2nd column is the corresponding value
// The file terminates with the pattern: -1 -1
// -2 -2
if (a == -1 || a == -2)
{
}
else
{
if (k%nColumns != 0)
{
G4double e = a * unit1;
energies->push_back(e);
k++;
}
else if (k%nColumns == 0)
{
G4double value = a * unit2;
data->push_back(value);
k = 1;
}
}
} while (a != -2); // end of file
file.close();
G4VDataSetAlgorithm* algo = algorithm->Clone();
G4VEMDataSet* dataSet = new G4EMDataSet(Z,energies,data,algo);
AddComponent(dataSet);
}
}
void G4CompositeEMDataSet::AddComponent(G4VEMDataSet* component)
{
components.push_back(component);
nComponents++;
}
const G4DataVector& G4CompositeEMDataSet::GetEnergies(G4int i) const
{
const G4VEMDataSet* component = GetComponent(i);
return (component->GetEnergies(i));
}
const G4DataVector& G4CompositeEMDataSet::GetData(G4int i) const
{
const G4VEMDataSet* component = GetComponent(i);
return (component->GetData(i));
}
@@ -0,0 +1,90 @@
//
// ********************************************************************
// * 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: G4CrossSectionHandler.cc,v 1.12 2001/10/08 07:48:57 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// -----------
// 1 Aug 2001 MGP Created
//
// -------------------------------------------------------------------
#include "G4CrossSectionHandler.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4VEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4CompositeEMDataSet.hh"
#include "G4ShellEMDataSet.hh"
#include "G4MaterialTable.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "Randomize.hh"
#include "g4std/map"
#include "g4std/vector"
#include "g4std/fstream"
#include "g4std/strstream"
#include "G4LogLogInterpolation.hh"
G4CrossSectionHandler::G4CrossSectionHandler()
{ }
G4CrossSectionHandler::~G4CrossSectionHandler()
{ }
G4std::vector<G4VEMDataSet*>*
G4CrossSectionHandler::BuildCrossSectionsForMaterials(const G4DataVector& energyVector,
const G4DataVector* energyCuts)
{
G4DataVector* energies;
G4DataVector* data;
G4std::vector<G4VEMDataSet*>* matCrossSections = new G4std::vector<G4VEMDataSet*>;
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
G4int nMaterials = G4Material::GetNumberOfMaterials();
size_t nOfBins = energyVector.size();
for (G4int m=0; m<nMaterials; m++)
{
const G4Material* material= (*materialTable)[m];
energies = new G4DataVector;
data = new G4DataVector;
G4VDataSetAlgorithm* interpolationAlgo = CreateInterpolation();
for (size_t bin=0; bin<nOfBins; bin++)
{
G4double e = energyVector[bin];
energies->push_back(e);
G4double materialCrossSection = ValueForMaterial(material,e);
data->push_back(materialCrossSection);
}
G4VEMDataSet* dataSet = new G4EMDataSet(m,energies,data,interpolationAlgo,1.,1.);
matCrossSections->push_back(dataSet);
}
return matCrossSections;
}
@@ -0,0 +1,73 @@
//
// ********************************************************************
// * 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-04-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;
}
}
}
@@ -0,0 +1,218 @@
//
// ********************************************************************
// * 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: G4EMDataSet.cc,v 1.5 2001/10/08 07:48:57 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// -----------
// 31 Jul 2001 MGP Created
//
// -------------------------------------------------------------------
#include "G4EMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "g4std/fstream"
#include "g4std/strstream"
// Constructor
G4EMDataSet::G4EMDataSet(G4int Z,
G4DataVector* points,
G4DataVector* values,
G4VDataSetAlgorithm* interpolation,
G4double unitE, G4double unitData)
:z(Z), energies(points), data(values), algorithm(interpolation)
{
numberOfBins = energies->size();
unit1 = unitE;
unit2 = unitData;
if (interpolation == 0)
G4Exception("G4EMDataSet::G4EMDataSet - interpolation algorithm = 0");
}
G4EMDataSet:: G4EMDataSet(G4int Z,
const G4String& dataFile,
G4VDataSetAlgorithm* interpolation,
G4double unitE, G4double unitData)
:z(Z), algorithm(interpolation)
{
energies = new G4DataVector;
data = new G4DataVector;
unit1 = unitE;
unit2 = unitData;
LoadData(dataFile);
numberOfBins = energies->size();
if (interpolation == 0)
G4Exception("G4EMDataSet::G4EMDataSet - interpolation algorithm = 0");
}
// Destructor
G4EMDataSet::~G4EMDataSet()
{
delete algorithm;
delete energies;
delete data;
}
G4double G4EMDataSet::FindValue(G4double e, G4int id) const
{
G4double value;
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);
}
return value;
}
G4int G4EMDataSet::FindBinLocation(G4double energy) const
{
// Protection against call outside allowed range
G4double e0 = (*energies)[0];
if (energy < e0)
{
// G4cout << z
// << " - WARNING - G4EMDataSet::FindBinLocation called with argument "
// << energy
// << " outside lower limit "
// << e0
// << "; replaced with lower limit"
// << G4endl;
energy = e0;
}
size_t lowerBound = 0;
size_t upperBound = numberOfBins - 1;
// Binary search
while (lowerBound <= upperBound)
{
size_t midBin = (lowerBound + upperBound)/2;
if ( energy < (*energies)[midBin] ) upperBound = midBin-1;
else lowerBound = midBin+1;
}
return upperBound;
}
void G4EMDataSet::LoadData(const G4String& fileName)
{
// Build the complete string identifying the file with the data set
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
ost << fileName << z << ".dat";
G4String name(nameChar);
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4EMDataSet - G4LEDATA environment variable not set";
G4Exception(excep);
}
G4String pathString(path);
G4String dirFile = pathString + "/" + name;
G4std::ifstream file(dirFile);
G4std::filebuf* lsdp = file.rdbuf();
if (! (lsdp->is_open()) )
{
G4String excep = "G4EMDataSet - data file: " + dirFile + " not found";
G4Exception(excep);
}
G4double a = 0;
G4int k = 1;
do
{
file >> a;
G4int nColumns = 2;
// The file is organized into two columns:
// 1st column is the energy
// 2nd column is the corresponding value
// The file terminates with the pattern: -1 -1
// -2 -2
if (a == -1 || a == -2)
{
}
else
{
if (k%nColumns != 0)
{
G4double e = a * unit1;
energies->push_back(e);
k++;
}
else if (k%nColumns == 0)
{
G4double value = a * unit2;
data->push_back(value);
k = 1;
}
}
} while (a != -2); // end of file
file.close();
}
void G4EMDataSet::PrintData() const
{
size_t size = numberOfBins;
for (size_t i=0; i<size; i++)
{
G4double e = (*energies)[i] / unit1;
G4double sigma = (*data)[i] / unit2 ;
G4cout << "Point: "
<< e
<< " - Data value : "
<< sigma
<< G4endl;
}
}
@@ -0,0 +1,319 @@
//
// ********************************************************************
// * 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: G4FluoDataData.cc,v 1.2
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
//
// History:
// -----------
// 16 Sept 2001 First committed to cvs
//
// -------------------------------------------------------------------
#include "G4FluoData.hh"
#include "G4DataVector.hh"
#include "g4std/fstream"
#include "g4std/strstream"
G4FluoData::G4FluoData()
{
numberOfVacancies=0;
}
G4FluoData::~G4FluoData()
{
G4std::map<G4int,G4DataVector*,G4std::less<G4int> >::iterator pos;
for (pos = idMap.begin(); pos != idMap.end(); pos++)
{
G4DataVector* dataSet = (*pos).second;
delete dataSet;
}
for (pos = energyMap.begin(); pos != energyMap.end(); pos++)
{
G4DataVector* dataSet = (*pos).second;
delete dataSet;
}
for (pos = probabilityMap.begin(); pos != probabilityMap.end(); pos++)
{
G4DataVector* dataSet = (*pos).second;
delete dataSet;
}
}
size_t G4FluoData::NumberOfVacancies() const
{
return numberOfVacancies;
}
G4int G4FluoData::VacancyId(G4int vacancyIndex) const
{
G4int n = -1;
if (vacancyIndex<0 || vacancyIndex>=numberOfVacancies)
{G4Exception("G4FluoData::vacancyIndex outside boundaries");}
else
{
G4std::map<G4int,G4DataVector*,G4std::less<G4int> >::const_iterator pos;
pos = idMap.find(vacancyIndex);
if (pos!= idMap.end())
{ G4DataVector dataSet = (*(*pos).second);
n = (G4int) dataSet[0];
}
}
return n;
}
size_t G4FluoData::NumberOfTransitions(G4int vacancyIndex) const
{
G4int n = 0;
if (vacancyIndex<0 || vacancyIndex>=numberOfVacancies)
{G4Exception("G4FluoData::vacancyIndex outside boundaries");}
else
{
n = nInitShells[vacancyIndex]-1;
//-1 is necessary because the elements of the vector nInitShells
//include also the vacancy shell:
// -1 subtracts this last one
}
return n;
}
G4int G4FluoData::StartShellId(G4int initIndex,G4int vacancyIndex)
{
G4int n = -1;
if (vacancyIndex<0 || vacancyIndex>=numberOfVacancies)
{G4Exception("G4FluoData::vacancyIndex outside boundaries");}
else
{
G4std::map<G4int,G4DataVector*,G4std::less<G4int> >::const_iterator pos;
pos = idMap.find(vacancyIndex);
G4DataVector dataSet = *((*pos).second);
G4int nData = dataSet.size();
if (initIndex >= 0 && initIndex < nData)
{
n = (G4int) dataSet[initIndex];
}
}
return n;
}
G4double G4FluoData::StartShellEnergy(G4int initIndex,G4int vacancyIndex)
{
G4double n = -1;
if (vacancyIndex<0 || vacancyIndex>=numberOfVacancies)
{G4Exception("G4FluoData::vacancyIndex outside boundaries");}
else
{
G4std::map<G4int,G4DataVector*,G4std::less<G4int> >::const_iterator pos;
pos = energyMap.find(vacancyIndex);
G4DataVector dataSet = *((*pos).second);
G4int nData = dataSet.size();
if (initIndex >= 0 && initIndex < nData)
{
n = dataSet[initIndex];
}
}
return n;
}
G4double G4FluoData::StartShellProb(G4int initIndex,G4int vacancyIndex)
{
G4double n = -1;
if (vacancyIndex<0 || vacancyIndex>=numberOfVacancies)
{G4Exception("G4FluoData::vacancyIndex outside boundaries");}
else
{
G4std::map<G4int,G4DataVector*,G4std::less<G4int> >::const_iterator pos;
pos = probabilityMap.find(vacancyIndex);
G4DataVector dataSet = *((*pos).second);
G4int nData = dataSet.size();
if (initIndex >= 0 && initIndex < nData)
{
n = dataSet[initIndex];
}
}
return n;
}
void G4FluoData::LoadData(G4int Z)
{
// Build the complete string identifying the file with the data set
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
if(Z != 0){
ost << "fl-tr-pr-"<< Z << ".dat";
}
else{
ost << "fl-tr-pr-"<<".dat";
}
G4String name(nameChar);
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4EMDataSet - G4LEDATA environment variable not set";
G4Exception(excep);
}
G4String pathString(path);
G4String dirFile = pathString + "/fluor/" + name;
G4std::ifstream file(dirFile);
G4std::filebuf* lsdp = file.rdbuf();
if (! (lsdp->is_open()) )
{
G4String excep = "G4FluoData - data file: " + dirFile + " not found";
G4Exception(excep);
}
G4double a = 0;
G4int k = 1;
G4int s = 0;
G4int vacId = 0;
G4DataVector* initIds = new G4DataVector;
G4DataVector* transEnergies = new G4DataVector;
G4DataVector* transProbabilities = new G4DataVector;
do {
file >> a;
G4int nColumns = 3;
if (a == -1)
{
if (s == 0)
{
// End of a shell data set
idMap[vacId] = initIds;
energyMap[vacId] = transEnergies;
probabilityMap[vacId] = transProbabilities;
// G4double size=transProbabilities->size();
G4int n = initIds->size();
nInitShells.push_back(n);
numberOfVacancies++;
// Start of new shell data set
initIds = new G4DataVector;
transEnergies = new G4DataVector;
transProbabilities = new G4DataVector;
vacId++;
}
s++;
if (s == nColumns)
{
s = 0;
}
}
else if (a == -2)
{
// End of file; delete the empty vectors created
//when encountering the last -1 -1 row
delete initIds;
delete transEnergies;
delete transProbabilities;
}
else
{
if(k%nColumns == 2)
{
// 2nd column is transition probabilities
transProbabilities->push_back(a);
k++;
}
else if (k%nColumns == 1)
{
// 1st column is shell id
initIds->push_back(a);
k++;
}
else if (k%nColumns == 0)
{//third column is transition energies
G4double e = a * MeV;
transEnergies->push_back(e);
k=1;
}
}
}
while (a != -2); // end of file
file.close();
}
void G4FluoData::PrintData()
{
for (G4int i = 0; i <numberOfVacancies; i++)
{
G4cout << "---- TransitionData for the vacancy nb "
<<i
<<" ----- "
<<G4endl;
for (size_t k = 0; k<=NumberOfTransitions(i); k++)
{
G4int id = StartShellId(k,i);
G4double e = StartShellEnergy(k,i) /MeV;
G4double p = StartShellProb(k,i);
G4cout << k <<") Shell id: " << id <<G4endl;
G4cout << " - Transition energy = " << e << " MeV "<<G4endl;
G4cout << " - Transition probability = " << p <<G4endl;
}
G4cout << "-------------------------------------------------"
<< G4endl;
}
}
@@ -21,42 +21,52 @@
// ********************************************************************
//
//
// -------------------------------------------------------------------
// GEANT 4 class file
// $Id: G4LinInterpolation.cc,v 1.1 2001/11/29 19:01:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// CERN, Geneva, Switzerland
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// File name: G4SecondLevel.hh
// History:
// -----------
// 31 Jul 2001 MGP Created
//
// Author: Alessandra Forti (Alessandra.Forti@cern.ch)
//
// Creation date: 1 Giugno 1999
//
// Modifications: 24.04.01 V.Ivanchenko remove RogueWave
//
// -------------------------------------------------------------------
#include "G4SecondLevel.hh"
#include "G4LinInterpolation.hh"
// Constructor
G4LinInterpolation::G4LinInterpolation()
{ }
G4SecondLevel::~G4SecondLevel(){
// Destructor
// this->clearAndDestroy();
this->clear();
G4LinInterpolation::~G4LinInterpolation()
{ }
G4double G4LinInterpolation::Calculate(G4double x, G4int bin,
const G4DataVector& points,
const G4DataVector& data) const
{
G4int nBins = data.size() - 1;
G4double value = 0.;
if (x < points[0])
{
value = 0.;
}
else if (bin < nBins)
{
G4double e1 = points[bin];
G4double e2 = points[bin+1];
G4double d1 = data[bin];
G4double d2 = data[bin+1];
value = d1 + (d2 - d1)*(x - e1)/(e2 - e1);
}
else
{
value = data[nBins];
}
return value;
}
G4bool G4SecondLevel::operator == (const G4SecondLevel& input) const{
// return( this->entries() == input.entries());
return( this->size() == input.size());
}
G4bool G4SecondLevel::operator < (const G4SecondLevel& input) const{
// return(this->entries() < input.entries());
return(this->size() < input.size());
}
@@ -0,0 +1,74 @@
//
// ********************************************************************
// * 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: G4LogLogInterpolation.cc,v 1.3 2001/09/10 18:07:35 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// -----------
// 31 Jul 2001 MGP Created
//
// -------------------------------------------------------------------
#include "G4LogLogInterpolation.hh"
// Constructor
G4LogLogInterpolation::G4LogLogInterpolation()
{ }
// Destructor
G4LogLogInterpolation::~G4LogLogInterpolation()
{ }
G4double G4LogLogInterpolation::Calculate(G4double x, G4int bin,
const G4DataVector& points,
const G4DataVector& data) const
{
G4int nBins = data.size() - 1;
G4double value = 0.;
if (x < points[0])
{
value = 0.;
}
else if (bin < nBins)
{
G4double e1 = points[bin];
G4double e2 = points[bin+1];
G4double d1 = data[bin];
G4double d2 = data[bin+1];
value = (log10(d1)*log10(e2/x) + log10(d2)*log10(x/e1)) / log10(e2/e1);
value = pow(10,value);
}
else
{
value = data[nBins];
}
return value;
}
@@ -20,22 +20,20 @@
// * statement, and all its terms. *
// ********************************************************************
//
//
// $Id: G4LowEnergyBremsstrahlung.cc,v 1.34.2.2 2001/06/28 20:19:28 gunter Exp $
// GEANT4 tag $Name: $
//
// $Id: G4LowEnergyBremsstrahlung.cc,v 1.54 2001/11/29 19:01:36 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
// CERN Geneva Switzerland
//
// ------------ G4LowEnergyBremsstrahlung: low energy modifications --------
// by Alessandra Forti, March 1999
// File name: G4LowEnergyBremsstrahlung
//
// **************************************************************
// Author: Alessandra Forti, Vladimir Ivanchenko
//
// 18.04.2000 V.L.
// - First implementation of continuous energy loss.
// Creation date: March 1999
//
// Modifications:
// 18.04.2000 V.L.
// - First implementation of continuous energy loss.
// 17.02.2000 Veronique Lefebure
// - correct bug : the gamma energy was not deposited when the gamma was
// not produced when its energy was < cutForLowEnergySecondaryPhotons
@@ -47,198 +45,141 @@
// Added map of the elements A. Forti
// 20.09.00 update printout V.Ivanchenko
// 24.04.01 V.Ivanchenko remove RogueWave
// 29.09.2001 V.Ivanchenko: major revision based on design iteration
// 10.10.2001 MGP Revision to improve code quality and consistency with design
// 18.10.2001 MGP Revision to improve code quality
// 28.10.2001 VI Update printout
// 29.11.2001 VI New parametrisation
//
// --------------------------------------------------------------
#include "G4LowEnergyBremsstrahlung.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"
//
// constructor
G4LowEnergyBremsstrahlung::G4LowEnergyBremsstrahlung(const G4String& processName)
: G4eLowEnergyLoss(processName), // initialization
theCrossSectionTable(0),
theMeanFreePathTable(0),
ATable(0),
BTable(0),
ZNumVec(0),
lowEnergyCut(0.1*eV),
cutForLowEnergySecondaryPhotons(0.)
{
lowestKineticEnergy = GetLowerBoundEloss();
highestKineticEnergy = GetUpperBoundEloss();
totBin = GetNbinEloss();
#include "G4CutsPerMaterialWarning.hh"
G4LowEnergyBremsstrahlung::G4LowEnergyBremsstrahlung(const G4String& nam)
: G4eLowEnergyLoss(nam),
crossSectionHandler(0),
theMeanFreePath(0),
energySpectrum(0)
{
cutForPhotons = 0.;
verboseLevel = 0;
}
//
// destructor
G4LowEnergyBremsstrahlung::~G4LowEnergyBremsstrahlung()
{
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
if (ATable) {
delete ATable;
}
if (BTable) {
delete BTable;
}
if (&partialSumSigma) {
partialSumSigma.clearAndDestroy();
}
if(crossSectionHandler) delete crossSectionHandler;
if(energySpectrum) delete energySpectrum;
if(theMeanFreePath) delete theMeanFreePath;
}
//
// SET CUT FOR LOW ENERGY SECONDARY PHOTONS A. FORTI
void G4LowEnergyBremsstrahlung::SetCutForLowEnSecPhotons(G4double cut){
cutForLowEnergySecondaryPhotons = cut;
}
// METHOD BELOW FROM STANDARD E_M PROCESSES CODE
void G4LowEnergyBremsstrahlung::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
{
BuildZVec();
// energy sampling formula coefficient
BuildATable();
BuildBTable();
BuildCrossSectionTable() ;
if(verboseLevel > 0) {
G4cout << "G4LowEnergyBremsstrahlung::BuildPhysicsTable start"
<< G4endl;
}
BuildLossTable(aParticleType) ;
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&aParticleType);
cutForSecondaryPhotons.clear();
if (&aParticleType==G4Electron::Electron()){
// Create and fill BremsstrahlungParameters once
if( energySpectrum != 0 ) delete energySpectrum;
energySpectrum = new G4eBremsstrahlungSpectrum();
RecorderOfElectronProcess[CounterOfElectronProcess] = (*this).theLossTable ;
if(verboseLevel > 0) {
G4cout << "G4LowEnergyBremsstrahlungSpectrum 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);
crossSectionHandler->LoadShellData("brem/br-cs-");
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 ;
} else {
RecorderOfPositronProcess[CounterOfPositronProcess] = (*this).theLossTable;
CounterOfPositronProcess++;
}
BuildMeanFreePathTable() ;
BuildDEDXTable(aParticleType) ;
}
//
// CONSTRUCT THE CROSS SECTION TABLE FOR THE ELEMENTS MAPPED IN ZNUMVEC.
void G4LowEnergyBremsstrahlung::BuildCrossSectionTable(){
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
theCrossSectionTable = new G4SecondLevel();
G4int dataNum = 2;
for(size_t TableInd = 0; TableInd < ZNumVec->size(); TableInd++){
G4int AtomInd = (G4int) (*ZNumVec)[TableInd];
G4FirstLevel* oneAtomCS = util.BuildFirstLevelTables(AtomInd, dataNum, "brem/br-cs-");
// theCrossSectionTable->insert(oneAtomCS);
theCrossSectionTable->push_back(oneAtomCS);
}//end for on atoms
}
// Build mean free path data using cut values
// CONSTRUCT THE TABLE OF THE FIRST PARAMETER OF THE SAMPLING FORMULA
void G4LowEnergyBremsstrahlung::BuildATable(){
if( theMeanFreePath != 0 ) delete theMeanFreePath;
theMeanFreePath = crossSectionHandler->
BuildMeanFreePathForMaterials(&cutForSecondaryPhotons);
if (ATable) {
delete ATable;
}
G4int dataNum = 2;
ATable = util.BuildSecondLevelTables(0,dataNum,"brem/br-co-a");
}
// CONSTRUCT THE TABLE OF THE PARAMETERS OF THE FORMULA OF THE
// SECOND PARAMETER OF THE SAMPLING FORMULA
void G4LowEnergyBremsstrahlung::BuildBTable(){
if (BTable) {
delete BTable;
}
G4int dataNum = 2;
BTable = util.BuildFirstLevelTables(0, dataNum, "brem/br-co-b");
}
// Vector mapping the existing elements in the material table
// needed at initialization time to load only the necessary data
void G4LowEnergyBremsstrahlung::BuildZVec(){
const G4MaterialTable* theMaterialTable=G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
ZNumVec = new G4DataVector();
for (G4int J=0 ; J < numOfMaterials; J++){
const G4Material* material= (*theMaterialTable)[J];
const G4ElementVector* theElementVector = material->GetElementVector();
const G4int NumberOfElements = material->GetNumberOfElements() ;
for (G4int iel=0; iel<NumberOfElements; iel++ ){
G4double Zel = (*theElementVector)(iel)->GetZ();
if( !(ZNumVec->contains(Zel)) ) {
ZNumVec->push_back(Zel);
} else{
continue;
if(verboseLevel > 0) {
G4cout << "The MeanFreePath table is built"
<< G4endl;
}
}
}
// Build common DEDX table for all ionisation processes
BuildDEDXTable(aParticleType);
if(verboseLevel > 0) {
G4cout << "G4LowEnergyBremsstrahlung::BuildPhysicsTable end"
<< G4endl;
}
}
void G4LowEnergyBremsstrahlung::BuildLossTable(const G4ParticleDefinition& aParticleType)
{
// Build table for energy loss due to soft brems
// the tables are built for *MATERIALS*
// 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) {
@@ -246,466 +187,176 @@ void G4LowEnergyBremsstrahlung::BuildLossTable(const G4ParticleDefinition& aPart
delete theLossTable;
}
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
const G4int numOfMaterials = theMaterialTable->length();
const size_t numOfMaterials = G4Material::GetNumberOfMaterials();
theLossTable = new G4PhysicsTable(numOfMaterials);
// loop for materials
// Clean up the vector of cuts
cutForSecondaryPhotons.clear();
// Loop for materials
for (G4int J=0; J<numOfMaterials; J++){
for (size_t j=0; j<numOfMaterials; j++) {
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(lowestKineticEnergy,
highestKineticEnergy,
totBin);
// get material parameters needed for the energy loss calculation
const G4Material* material= (*theMaterialTable)[J];
// create physics vector and fill it
G4PhysicsLogVector* aVector = new G4PhysicsLogVector(lowKineticEnergy,
highKineticEnergy,
totBin);
const G4double Tcut = G4Gamma::Gamma()->GetCutsInEnergy()[material->GetIndex()] ;
G4cout<<"*** LE Bremsstrahlung using Gamma Tcut = "<<Tcut
<<" for material "<< material->GetName()
<<G4endl;
const G4ElementVector* theElementVector = material->GetElementVector();
const G4int NumberOfElements = material->GetNumberOfElements() ;
const G4double* theAtomicNumDensityVector = material->GetAtomicNumDensityVector();
// now comes the loop for the kinetic energy values
for (G4int i = 0 ; i < totBin ; i++){
// get material parameters needed for the energy loss calculation
const G4Material* material= (*theMaterialTable)[j];
const G4double LowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
G4double ionloss = 0.;
// loop for elements in the material
for (G4int iel=0; iel<NumberOfElements; iel++ ){
const G4double Z = (*theElementVector)(iel)->GetZ();
ionloss += GetEnergyLossWithCut(Z,LowEdgeEnergy,Tcut)*
theAtomicNumDensityVector[iel] ;
}
aVector->PutValue(i,ionloss) ;
// the cut cannot be below lowest limit
G4double tCut = G4std::min(highKineticEnergy,
((G4Gamma::Gamma())->GetEnergyThreshold(material)));
// ((G4Gamma::Gamma())->GetCutsInEnergy())[j]);
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;
}
theLossTable->insert(aVector);
}
}
//
// now comes the loop for the kinetic energy values
for (size_t i = 0; i<totBin; i++) {
//
// METHOD BELOW FROM STANDARD E_M PROCESSES CODE MODIFIED TO USE
// LIVERMORE DATA (using log-log interpolation as reported in stepanek paper)
//
void G4LowEnergyBremsstrahlung::BuildMeanFreePathTable()
// Build mean free path tables for the gamma emission by e- or e+.
// tables are Build for MATERIALS. see GENERAL part of processes in GEANT4
// manual
{
G4double FixedEnergy = (lowestKineticEnergy + highestKineticEnergy)/2.;
//create table
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
G4double NumbOfMaterials = G4Material::GetNumberOfMaterials();
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4Material* material;
G4double* CutInKineticEnergy = G4Gamma::Gamma()->GetCutsInEnergy() ;
partialSumSigma.clearAndDestroy();
partialSumSigma.resize(NumbOfMaterials);
G4double LowEdgeEnergy , Value;
theMeanFreePathTable = new G4PhysicsTable(NumbOfMaterials);
G4PhysicsLogVector* ptrVector;
for ( G4int J=0 ; J < NumbOfMaterials; J++ ){
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(lowestKineticEnergy, highestKineticEnergy,
totBin ) ;
material= (*theMaterialTable)(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* theAtomNumDensityVector = material->GetAtomicNumDensityVector();
const G4double Threshold = CutInKineticEnergy[J] ;
for ( G4int i = 0 ; i < totBin ; i++ ){
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy( i ) ;
const G4double BigPath= DBL_MAX;
G4double SIGMA = 0 ;
for ( size_t k=0 ; k < material->GetNumberOfElements() ; k++ ){
G4int AtomIndex = (G4int) (*theElementVector)(k)->GetZ();
G4double interCrsSec = GetCrossSectionWithCut(AtomIndex, LowEdgeEnergy,Threshold);
SIGMA += theAtomNumDensityVector[k]*interCrsSec;
}
Value = SIGMA<=0.0 ? BigPath : 1./SIGMA ;
ptrVector->PutValue( i , Value ) ;
}
theMeanFreePathTable->insert( ptrVector );
// Compute the partialSumSigma table at a given fixed energy
ComputepartialSumSigma(FixedEnergy, material,Threshold) ;
}
G4double lowEdgeEnergy = aVector->GetLowEdgeEnergy(i);
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 pro = energySpectrum->Probability(Z, 0.0, tCut, lowEdgeEnergy);
G4double cs= crossSectionHandler->FindValue(Z, lowEdgeEnergy);
ionloss += e * cs * pro * theAtomicNumDensityVector[iel];
if(verboseLevel > 1) {
G4cout << "Z= " << Z
<< "; tCut(keV)= " << tCut/keV
<< "; E(keV)= " << lowEdgeEnergy/keV
<< "; Eav(keV)= " << e/keV
<< "; pro= " << pro
<< "; cs= " << cs
<< "; loss= " << ionloss
<< G4endl;
}
}
aVector->PutValue(i,ionloss);
}
theLossTable->insert(aVector);
}
}
//
//
// METHOD BELOW FROM STANDARD E_M PROCESSES CODE MODIFIED TO USE
// LIVERMORE DATA (using log-log interpolation as reported in stepanek paper)
//
void G4LowEnergyBremsstrahlung::ComputepartialSumSigma(const G4double KineticEnergy,
const G4Material* aMaterial,
const G4double Threshold)
// Build the table of cross section per element. The table is built for MATERIALS.
// This table is used by DoIt to select randomly an element in the material.
G4VParticleChange* G4LowEnergyBremsstrahlung::PostStepDoIt(const G4Track& track,
const G4Step& step)
{
G4int Imate = aMaterial->GetIndex();
G4int NbOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
aParticleChange.Initialize(track);
partialSumSigma[Imate] = new G4DataVector();
const G4Material* material = track.GetMaterial();
G4double kineticEnergy = track.GetKineticEnergy();
G4int index = material->GetIndex();
G4double tCut = cutForSecondaryPhotons[index];
G4double SIGMA = 0. ;
// Control limits
if(tCut >= kineticEnergy)
return G4VContinuousDiscreteProcess::PostStepDoIt(track, step);
for ( G4int Ielem=0 ; Ielem < NbOfElements ; Ielem++ ){
G4int Z = crossSectionHandler->SelectRandomAtom(material, kineticEnergy);
G4int AtomIndex = (G4int) (*theElementVector)(Ielem)->GetZ();
G4double interCrsSec = GetCrossSectionWithCut(AtomIndex,KineticEnergy,Threshold);
SIGMA += theAtomNumDensityVector[Ielem]*interCrsSec;
partialSumSigma[Imate]->push_back(SIGMA);
}
}
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)
// Phys211) derived from Tsai distribution (Rev Mod Phys 49,421(1977))
G4VParticleChange* G4LowEnergyBremsstrahlung::PostStepDoIt(const G4Track& trackData,
const G4Step& stepData){
G4double totalEnergy = kineticEnergy + electron_mass_c2;
// This parametrization is derived from :
// Migdal corrections (dielectric suppression).
// Migdal: Phys Rev 103:1811 (1956); Messel & Crawford: Pergamon Press (1970)
//
aParticleChange.Initialize(trackData);
G4Material* aMaterial=trackData.GetMaterial() ;
const G4DynamicParticle* aDynamicParticle=trackData.GetDynamicParticle();
G4double charge = aDynamicParticle->GetDefinition()->GetPDGCharge();
G4double ElectKinEn = aDynamicParticle->GetKineticEnergy();
const G4double a1 = 0.625, a2 = 3.*a1, d = 27.;
G4double u = - log(G4UniformRand()*G4UniformRand());
// MGP debug
// G4cout << "G4LowEnergyBremsstrahlung::PostStepDoIt - ElectKinEn "
// << ElectKinEn/keV << " keV " << G4endl;
// MGP end
if(ElectKinEn <= lowestKineticEnergy){
if (9./(9.+d) > G4UniformRand()) u /= a1;
else u /= a2;
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit(ElectKinEn);
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);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
G4ParticleMomentum ElectDirection = aDynamicParticle->GetMomentumDirection();
// Gamma production cut in this material
G4double GammaEnergyCut = (G4Gamma::GetCutsInEnergy())[aMaterial->GetIndex()];
// check against insufficient energy
if (ElectKinEn < GammaEnergyCut){
aParticleChange.SetEnergyChange(ElectKinEn);
aParticleChange.SetLocalEnergyDeposit(0.);
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
// select randomly one element constituing the material
G4Element* anElement = SelectRandomAtom(aMaterial);
// limits of the energy sampling
G4double TotalEnergy = ElectKinEn + electron_mass_c2;
// G4double TotalEnergysquare = TotalEnergy*TotalEnergy ;
G4ThreeVector gammaDirection (dirX, dirY, dirZ);
G4ThreeVector electronDirection = track.GetMomentumDirection();
gammaDirection.rotateUz(electronDirection);
//
// The emitted gamma energy is from EEDL data fitted with A/E+B function.
// Original formula A/E+B+C*E and sampling methods are reported by J. Stepanek
// formula has been modified by A. Forti and S. Giani.
//
// sample the energy of the emitted gamma
//
G4double p1 = 0, p2 = 0;
G4double coeffA = 0, coeffB = 0;
G4int AtomicNum = (G4int) anElement->GetZ();
coeffA = ComputeA(AtomicNum, ElectKinEn);
coeffB = ComputeB(AtomicNum, ElectKinEn);
//const G4double minEn = lowEnergyCut;
const G4double minEn = GammaEnergyCut;
p1 = coeffA*log(ElectKinEn/minEn);
p2 = coeffB*(ElectKinEn - minEn);
G4double IntegrProb = p1+p2;
G4double R1 = G4UniformRand()*IntegrProb;
G4double GammaEnergy = 0.;
if(R1 <= p1){
// Update the incident particle
//
G4double R2 = G4UniformRand();
GammaEnergy = ElectKinEn*pow((minEn/ElectKinEn),R2);
/// stepanek does: GammaEnergy = exp(R2*log(ElectKinEn/minEn)+log(ElectKinEn));
}
else if ((p1 < R1) && (R1 <= p1+p2)){
G4double finalEnergy = kineticEnergy - tGamma;
G4double R2 = G4UniformRand();
GammaEnergy = ElectKinEn - R2*(ElectKinEn - minEn);
// Kinematic problem
if (finalEnergy < 0.) {
tGamma += finalEnergy;
finalEnergy = 0.0;
}
// MGP debug
// if (GammaEnergy > 10*keV)
// G4cout << "MGP BremPostStepDoIt eGamma = " << GammaEnergy/keV << " keV" << G4endl;
G4double momentum = sqrt((totalEnergy + electron_mass_c2)*kineticEnergy);
/*
G4double R1 = minEn + G4UniformRand()*(ElectKinEn- minEn);
G4double Max = coeffA/minEn + coeffB;
G4double R2 = G4UniformRand()*Max;
while (coeffA/R1 + coeffB < R2){
R1 = minEn + G4UniformRand()*(ElectKinEn- minEn);
R2 = G4UniformRand()*Max;
}
G4double GammaEnergy = R1;
*/
//**********************//
// Angular distribution //
//**********************//
// angles of the emitted gamma. ( Z - axis along the parent particle)
// universal distribution suggested by L. Urban (Geant3 manual (1993) Phys211),
// derived from Tsai distribution (Rev Mod Phys 49,421(1977))
if(GammaEnergy < minEn){
G4cerr<<"Problem with bremsstrahlung gamma energy sampling: Energy<cut:"
<<GammaEnergy<<" < "<<minEn
<<G4endl;
}
G4double u;
const G4double a1 = 0.625 , a2 = 3.*a1 , d = 27. ;
if (9./(9.+d) > G4UniformRand()) u = - log(G4UniformRand()*G4UniformRand())/a1 ;
else u = - log(G4UniformRand()*G4UniformRand())/a2 ;
G4double Teta = u*electron_mass_c2/TotalEnergy ;
G4double Phi = twopi * G4UniformRand() ;
G4double dirx = sin(Teta)*cos(Phi) , diry = sin(Teta)*sin(Phi) , dirz = cos(Teta) ;
G4ThreeVector GammaDirection ( dirx, diry, dirz);
GammaDirection.rotateUz(ElectDirection);
//
// Update the incident particle
//
G4double NewKinEnergy = ElectKinEn - GammaEnergy;
//
///final state electron:
//
if (NewKinEnergy > 0.){
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.SetMomentumChange( ElectDirection );
aParticleChange.SetEnergyChange( NewKinEnergy );
aParticleChange.SetNumberOfSecondaries(1);
G4double norm = 1./sqrt(finalX*finalX + finalY*finalY + finalZ*finalZ);
aParticleChange.SetMomentumChange(finalX*norm, finalY*norm, finalZ*norm);
aParticleChange.SetEnergyChange( finalEnergy );
}
else{
aParticleChange.SetEnergyChange( 0. );
if (charge<0.){
aParticleChange.SetStatusChange(fStopAndKill);
}
else{
aParticleChange.SetStatusChange(fStopButAlive);
}
}
//
///emitted photon:
//
if(GammaEnergy < GammaEnergyCut){
// create G4DynamicParticle object for the gamma
G4DynamicParticle* aGamma= new G4DynamicParticle (G4Gamma::Gamma(),
gammaDirection, tGamma);
aParticleChange.AddSecondary(aGamma);
aParticleChange.SetLocalEnergyDeposit(GammaEnergy);
}
else{
// create G4DynamicParticle object for the Gamma
G4DynamicParticle* aGamma= new G4DynamicParticle (G4Gamma::Gamma(),
GammaDirection, GammaEnergy);
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(aGamma);
aParticleChange.SetLocalEnergyDeposit(0.);
}
#ifdef G4VERBOSE
if(verboseLevel > 15){
G4cout<<"LE Bremsstrahlung PostStepDoIt"<<G4endl;
}
#endif
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
return G4VContinuousDiscreteProcess::PostStepDoIt(track, step);
}
G4double G4LowEnergyBremsstrahlung::GetEnergyLossWithCut(const G4double AtomicNumber,
const G4double KineticEnergy,
const G4double Tcut){
const G4double minEn = lowEnergyCut ;
if(minEn == 0.) G4cerr<<"Minimum Gamma energy should be finite"<<G4endl;
// shortcut ..........................
if(Tcut <= minEn) return 0. ;
G4double CrossSection = GetCrossSection(AtomicNumber,KineticEnergy) ;
// shortcut ..........................
if(CrossSection <= 0.) return 0. ;
G4double loss = 0.;
//
// energy spectrum of the emitted gamma
//
G4double MeanTinc;
MeanTinc = KineticEnergy;
const G4double MeanCS = GetCrossSection(AtomicNumber,MeanTinc);
const G4double coeffA = ComputeA(AtomicNumber, MeanTinc);
const G4double coeffB = ComputeB(AtomicNumber, MeanTinc);
//
//integration of T*dSigma/dT between Tmin = minEn and Tcut
//
G4double Tmax;
//
//integration of T*dSigma/dT between Tmin = minEn and Tcut
//
Tmax = Tcut;
if(Tmax>MeanTinc) Tmax = MeanTinc;
G4double SmallLoss = 0.;
SmallLoss = 0.5*coeffB*(Tmax*Tmax - minEn*minEn) + coeffA*(Tmax-minEn);
if(SmallLoss < 0.) G4cerr<<"Problem with integration of gamma spectrum: SmallLoss = "<<SmallLoss<<G4endl;
//
//integration of dSigma/dT between Tmin = minEn and KineticEnergy
//
Tmax = MeanTinc;
G4double norm = coeffB*(Tmax-minEn) + coeffA*log(Tmax/minEn);
if(norm <= 0.) G4cerr<<"Problem with integration of gamma spectrum: norm = "<<norm<<G4endl;
SmallLoss *= MeanCS/norm ;
loss+=SmallLoss;
return loss ;
}
//
G4double G4LowEnergyBremsstrahlung::GetCrossSection(const G4double AtomicNumber,
const G4double KineticEnergy){
const G4FirstLevel* oneAtomCS
= (*theCrossSectionTable)[ZNumVec->index(AtomicNumber)];
return util.DataLogInterpolation(KineticEnergy,
(*(*oneAtomCS)[0]),
(*(*oneAtomCS)[1]) )*barn;
}
G4double G4LowEnergyBremsstrahlung::GetCrossSectionWithCut(const G4double AtomicNumber,
const G4double KineticEnergy,
const G4double Tcut){
if(KineticEnergy<=Tcut) return 0.;
G4double Tmin = Tcut;
if(Tcut<lowEnergyCut) Tmin = lowEnergyCut;
G4double Tmax = KineticEnergy;
G4double CrossSection = GetCrossSection(AtomicNumber,KineticEnergy) ;
if(CrossSection <= 0.) return 0.;
const G4double coeffA = ComputeA(AtomicNumber, KineticEnergy);
const G4double coeffB = ComputeB(AtomicNumber, KineticEnergy);
G4double fraction = coeffB*(Tmax-Tmin) + coeffA*log(Tmax/Tmin);
if(fraction <= 0.) G4cerr<<"Problem with integration of gamma spectrum: fraction = "<<fraction<<G4endl;
G4double norm = coeffB*(Tmax-lowEnergyCut) + coeffA*log(Tmax/lowEnergyCut);
if(norm <= 0.) G4cerr<<"Problem with integration of gamma spectrum: norm = "<<norm<<G4endl;
fraction /= norm;
return CrossSection*fraction;
}
//
// METHOD BELOW FROM STANDARD E_M PROCESSES CODE MODIFIED TO USE
// LIVERMORE DATA (using log-log interpolation as reported in stepanek paper)
G4Element* G4LowEnergyBremsstrahlung::SelectRandomAtom(G4Material* aMaterial) const
{
const G4int Index = aMaterial->GetIndex();
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
G4double rval = G4UniformRand()*((*partialSumSigma[Index])[NumberOfElements-1]);
for ( G4int i=0; i < NumberOfElements; i++ )
if (rval <= (*partialSumSigma[Index])[i]) return ((*theElementVector)(i));
return (*theElementVector)(0);
}
//
void G4LowEnergyBremsstrahlung::PrintInfoDefinition()
{
G4String comments = "Total cross sections from EEDL database,";
comments += "Gamma energy sampled from a parametrised formula.";
comments += "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 G4LowEnergyIonisation";
G4cout << G4endl << GetProcessName() << ": " << comments<<G4endl;
G4String comments = "Total cross sections from EEDL database.";
comments += "\n Gamma energy sampled from a parameterised formula.";
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 G4LowEnergyIonisation.";
G4cout << G4endl << GetProcessName() << ": " << comments << G4endl;
}
//
G4bool G4LowEnergyBremsstrahlung::IsApplicable(const G4ParticleDefinition& particle)
{
return ( (&particle == G4Electron::Electron()) );
}
G4double G4LowEnergyBremsstrahlung::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition* cond)
{
*cond = NotForced;
G4int index = (track.GetMaterial())->GetIndex();
const G4VEMDataSet* data = theMeanFreePath->GetComponent(index);
G4double meanFreePath = data->FindValue(track.GetKineticEnergy());
return meanFreePath;
}
void G4LowEnergyBremsstrahlung::SetCutForLowEnSecPhotons(G4double cut)
{
cutForPhotons = cut;
}
@@ -20,416 +20,242 @@
// * statement, and all its terms. *
// ********************************************************************
//
// $Id: G4LowEnergyCompton.cc,v 1.33 2001/11/07 20:47:29 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// $Id: G4LowEnergyCompton.cc,v 1.25.2.2 2001/06/28 20:19:29 gunter Exp $
// GEANT4 tag $Name: $
// Author: A. Forti
// Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
// CERN Geneva Switzerland
//
// ------------ G4LowEnergyCompton low energy modifications --------
// by Alessandra Forti, October 1998
// **************************************************************
// History:
// --------
// Added Livermore data table construction methods A. Forti
// Modified BuildMeanFreePath to read new data tables A. Forti
// Modified PostStepDoIt to insert sampling with EPDL97 data A. Forti
// Added SelectRandomAtom A. Forti
// Added map of the elements A. Forti
// 24.04.01 V.Ivanchenko remove RogueWave
// --------------------------------------------------------------
// 24.04.2001 V.Ivanchenko - Remove RogueWave
// 06.08.2001 MGP - Revised according to a design iteration
//
// -------------------------------------------------------------------
// This Class Header
#include "G4LowEnergyCompton.hh"
// Collaborating Class Headers
#include "G4EnergyLossTables.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 "G4CompositeEMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4LogLogInterpolation.hh"
#include "G4VRangeTest.hh"
#include "G4RangeTest.hh"
#include "G4CutsPerMaterialWarning.hh"
// constructor
G4LowEnergyCompton::G4LowEnergyCompton(const G4String& processName)
: G4VDiscreteProcess(processName),
theCrossSectionTable(0),
theScatteringFunctionTable(0),
theMeanFreePathTable(0),
ZNumVec(0),
lowestEnergyLimit (250*eV), // initialization
highestEnergyLimit(100*GeV),
numbBinTable(200)
lowEnergyLimit(250*eV),
highEnergyLimit(100*GeV),
intrinsicLowEnergyLimit(10*eV),
intrinsicHighEnergyLimit(100*GeV)
{
if (verboseLevel>0) {
G4cout << GetProcessName() << " is created "<< G4endl;
G4cout << "lowestEnergy: " << lowestEnergyLimit/keV << "keV ";
G4cout << "highestEnergy: " << highestEnergyLimit/TeV << "TeV " << G4endl;
}
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
highEnergyLimit > intrinsicHighEnergyLimit)
{
G4Exception("G4LowEnergyCompton::G4LowEnergyCompton - energy outside intrinsic process validity range");
}
crossSectionHandler = new G4CrossSectionHandler;
G4VDataSetAlgorithm* scatterInterpolation = new G4LogLogInterpolation;
G4String scatterFile = "comp/ce-sf-";
scatterFunctionData = new G4CompositeEMDataSet(scatterFile,scatterInterpolation,1.,1.);
meanFreePathTable = 0;
rangeTest = new G4RangeTest;
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
// destructor
G4LowEnergyCompton::~G4LowEnergyCompton()
{
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
if (theScatteringFunctionTable) {
delete theScatteringFunctionTable;
}
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
delete meanFreePathTable;
delete crossSectionHandler;
delete scatterFunctionData;
delete rangeTest;
}
// methods.............................................................................
void G4LowEnergyCompton::BuildPhysicsTable(const G4ParticleDefinition& GammaType){
BuildZVec();
// Build microscopic cross section table and mean free path table
BuildCrossSectionTable();
// Build mean free path table for the Compton Scattering process
BuildMeanFreePathTable();
// build the scattering function table
BuildScatteringFunctionTable();
}
// BUILD THE CS TABLE FOR THE ELEMENTS MAPPED IN ZNUMVEC
void G4LowEnergyCompton::BuildCrossSectionTable(){
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
void G4LowEnergyCompton::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
theCrossSectionTable = new G4SecondLevel();
G4int dataNum = 2;
for(size_t TableInd = 0; TableInd < ZNumVec->size(); TableInd++){
G4int AtomInd = (G4int) (*ZNumVec)[TableInd];
G4FirstLevel* oneAtomCS = util.BuildFirstLevelTables(AtomInd, dataNum, "comp/ce-cs-");
// theCrossSectionTable->insert(oneAtomCS);
theCrossSectionTable->push_back(oneAtomCS);
}//end for on atoms
}
// BUILD THE SF TABLE FOR THE ELEMENTS MAPPED IN ZNUMVEC
void G4LowEnergyCompton::BuildScatteringFunctionTable(){
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&photon);
if (theScatteringFunctionTable) {
delete theScatteringFunctionTable;
}
crossSectionHandler->Clear();
G4String crossSectionFile = "comp/ce-cs-";
crossSectionHandler->LoadData(crossSectionFile);
theScatteringFunctionTable = new G4SecondLevel();
G4int dataNum = 2;
for(size_t TableInd = 0; TableInd < ZNumVec->size(); TableInd++){
G4int AtomInd = (G4int) (*ZNumVec)[TableInd];
G4FirstLevel* oneAtomSF = util.BuildFirstLevelTables(AtomInd, dataNum, "comp/ce-sf-");
// theScatteringFunctionTable->insert(oneAtomSF);
theScatteringFunctionTable->push_back(oneAtomSF);
}//end for on atoms
}
// vector mapping the elements in the material table
void G4LowEnergyCompton::BuildZVec(){
const G4MaterialTable* theMaterialTable=G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
ZNumVec = new G4DataVector();
for (G4int J=0 ; J < numOfMaterials; J++){
const G4Material* material= (*theMaterialTable)[J];
const G4ElementVector* theElementVector = material->GetElementVector();
const G4int NumberOfElements = material->GetNumberOfElements() ;
for (G4int iel=0; iel<NumberOfElements; iel++ ){
G4double Zel = (*theElementVector)(iel)->GetZ();
if(ZNumVec->contains(Zel) == FALSE){
ZNumVec->push_back(Zel);
} else{
continue;
}
}
}
delete meanFreePathTable;
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
}
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
// 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
// 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
// (Nucl Phys 20(1960),15).
G4VParticleChange* G4LowEnergyCompton::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep){
//
// The scattered gamma energy is sampled according to Klein - Nishina formula.
// And then Accepted or rejected basing of 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
// 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
// (Nuc Phys 20(1960),15).
// GEANT4 internal units
//
aParticleChange.Initialize(aTrack);
// Dynamic particle quantities
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
G4double GammaEnergy0 = aDynamicGamma->GetKineticEnergy();
if(GammaEnergy0 <= lowestEnergyLimit){
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit(GammaEnergy0);
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double photonEnergy0 = incidentPhoton->GetKineticEnergy();
}
G4double E0_m = GammaEnergy0 / electron_mass_c2 ;
G4ParticleMomentum GammaDirection0 = aDynamicGamma->GetMomentumDirection();
// Select randomly one element
G4Material* aMaterial = aTrack.GetMaterial();
// const G4int numOfElem = aMaterial->GetNumberOfElements();
G4Element* theElement = SelectRandomAtom(aDynamicGamma, aMaterial);
G4int elementZ = (G4int) theElement->GetZ();
G4double epsilon, epsilonsq, onecost, sint2, greject ;
G4double epsilon0 = 1./(1. + 2*E0_m) , epsilon0sq = epsilon0*epsilon0;
G4double alpha1 = - log(epsilon0) , alpha2 = 0.5*(1.- epsilon0sq);
G4double ScatteringFunction, x;
G4double wlGamma = h_Planck*c_light/GammaEnergy0;
// sample the energy rate of the scattered gamma
do{
if ( alpha1/(alpha1+alpha2) > G4UniformRand()){
epsilon = exp(-alpha1*G4UniformRand()); // pow(epsilon0,G4UniformRand())
epsilonsq = epsilon*epsilon;
}
else{
epsilonsq = epsilon0sq + (1.- epsilon0sq)*G4UniformRand();
epsilon = sqrt(epsilonsq);
}
onecost = (1.- epsilon)/(epsilon*E0_m);
sint2 = onecost*(2.-onecost);
x = sqrt(onecost/2)/(wlGamma/cm);
const G4FirstLevel* oneAtomSF
= (*theScatteringFunctionTable)[ZNumVec->index(elementZ)];
ScatteringFunction = util.DataLogInterpolation(x, (*(*oneAtomSF)[0]),
(*(*oneAtomSF)[1]));
greject = (1. - epsilon*sint2/(1.+ epsilonsq))*ScatteringFunction;
} while(greject < G4UniformRand()*elementZ);
G4double cosTeta = 1. - onecost , sinTeta = sqrt (sint2);
G4double Phi = twopi * G4UniformRand() ;
G4double dirx = sinTeta*cos(Phi) , diry = sinTeta*sin(Phi) , dirz = cosTeta ;
//
// update G4VParticleChange for the scattered gamma
//
G4ThreeVector GammaDirection1 ( dirx,diry,dirz );
GammaDirection1.rotateUz(GammaDirection0);
aParticleChange.SetMomentumChange( GammaDirection1 ) ;
G4double GammaEnergy1 = epsilon*GammaEnergy0;
if (GammaEnergy1 > 0.)
if (photonEnergy0 <= lowEnergyLimit)
{
aParticleChange.SetEnergyChange( GammaEnergy1 ) ;
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit(photonEnergy0);
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
G4double e0m = photonEnergy0 / electron_mass_c2 ;
G4ParticleMomentum photonDirection0 = incidentPhoton->GetMomentumDirection();
// Select randomly one element in the current material
G4Material* material = aTrack.GetMaterial();
G4int Z = crossSectionHandler->SelectRandomAtom(material,photonEnergy0);
G4double epsilon0 = 1. / (1. + 2. * e0m);
G4double epsilon0Sq = epsilon0 * epsilon0;
G4double alpha1 = -log(epsilon0);
G4double alpha2 = 0.5 * (1. - epsilon0Sq);
G4double wlPhoton = h_Planck*c_light/photonEnergy0;
// Sample the energy of the scattered photon
G4double epsilon;
G4double epsilonSq;
G4double oneCosT;
G4double sinT2;
G4double gReject;
do
{
if ( alpha1/(alpha1+alpha2) > G4UniformRand())
{
epsilon = exp(-alpha1 * G4UniformRand()); // pow(epsilon0,G4UniformRand())
epsilonSq = epsilon * epsilon;
}
else
{
epsilonSq = epsilon0Sq + (1. - epsilon0Sq) * G4UniformRand();
epsilon = sqrt(epsilonSq);
}
oneCosT = (1. - epsilon) / ( epsilon * e0m);
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;
G4double sinTheta = sqrt (sinT2);
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);
}
//
// kinematic of the scattered electron
//
G4double ElecKineEnergy = GammaEnergy0 - GammaEnergy1 ;
if (G4EnergyLossTables::GetRange(G4Electron::Electron(), ElecKineEnergy, aMaterial)
>= G4std::min(G4Electron::GetCuts(), aStep.GetPostStepPoint()->GetSafety())){
// Kinematics of the scattered electron
G4double eKineticEnergy = photonEnergy0 - photonEnergy1;
G4double ElecMomentum = sqrt(ElecKineEnergy*(ElecKineEnergy+2.*electron_mass_c2));
G4ThreeVector ElecDirection((GammaEnergy0*GammaDirection0 -
GammaEnergy1*GammaDirection1)*(1./ElecMomentum));
// create G4DynamicParticle object for the electron.
G4DynamicParticle* aElectron= new G4DynamicParticle (G4Electron::Electron(),
ElecDirection, ElecKineEnergy) ;
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary( aElectron );
aParticleChange.SetLocalEnergyDeposit (0.);
}
else{
aParticleChange.SetNumberOfSecondaries(0);
aParticleChange.SetLocalEnergyDeposit (ElecKineEnergy);
}
#ifdef G4VERBOSE
if(verboseLevel > 0){
G4cout<<"LE Compton Effect PostStepDoIt"<<G4endl;
}
#endif
// 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))
{
G4double eMomentum = sqrt(eKineticEnergy*(eKineticEnergy+2.*electron_mass_c2));
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.);
}
else
{
aParticleChange.SetNumberOfSecondaries(0);
aParticleChange.SetLocalEnergyDeposit(eKineticEnergy);
}
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep);
}
// used log-log interpolation instead of linear interpolation to build the MFP
// as reported in the stepanek paper
void G4LowEnergyCompton::BuildMeanFreePathTable(){
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable; }
// material
G4double NumbOfMaterials = G4Material::GetNumberOfMaterials();
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
G4Material* material;
// MeanFreePath
G4double LowEdgeEnergy, Value;
theMeanFreePathTable = new G4PhysicsTable(NumbOfMaterials);
G4PhysicsLogVector* ptrVector;
for ( G4int J = 0 ; J < NumbOfMaterials; J++ ) { // For each material
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(lowestEnergyLimit, highestEnergyLimit, numbBinTable);
material = (*theMaterialTable)(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* theAtomNumDensityVector = material->GetAtomicNumDensityVector();
for ( G4int i = 0 ; i < numbBinTable ; i++ ){
//For each energy
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy(i);
const G4double BigPath= DBL_MAX;
G4double SIGMA = 0 ;
for ( size_t k=0 ; k < material->GetNumberOfElements() ; k++ ){
G4int AtomIndex = (G4int) (*theElementVector)(k)->GetZ();
const G4FirstLevel* oneAtomCS
= (*theCrossSectionTable)[ZNumVec->index(AtomIndex)];
G4double interCrsSec = util.DataLogInterpolation(LowEdgeEnergy,
(*(*oneAtomCS)[0]),
(*(*oneAtomCS)[1]))*barn;
SIGMA += theAtomNumDensityVector[k]*interCrsSec;
}
Value = SIGMA<=0.0 ? BigPath : 1./SIGMA ;
ptrVector->PutValue( i , Value ) ;
}
theMeanFreePathTable->insertAt( J , ptrVector );
}
G4bool G4LowEnergyCompton::IsApplicable(const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
}
// METHOD BELOW FROM STANDARD E_M PROCESSES CODE MODIFIED TO USE
// LIVERMORE DATA (using log-log interpolation as reported in stepanek paper)
G4Element* G4LowEnergyCompton::SelectRandomAtom(const G4DynamicParticle* aDynamicGamma,
G4Material* aMaterial){
// select randomly 1 element within the material
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
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();
if (NumberOfElements == 1) return (*theElementVector)(0);
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
G4double PartialSumSigma = 0.;
G4double rval = 0;
rval = G4UniformRand()/meanFreePath;
for ( G4int i=0 ; i < NumberOfElements ; i++ ){
G4double crossSection;
if (GammaEnergy < lowestEnergyLimit)
crossSection = 0. ;
else {
if (GammaEnergy > highestEnergyLimit) GammaEnergy = 0.99*highestEnergyLimit ;
G4int AtomIndex = (G4int) (*theElementVector)(i)->GetZ();
const G4FirstLevel* oneAtomCS
= (*theCrossSectionTable)[ZNumVec->index(AtomIndex)];
crossSection = util.DataLogInterpolation(GammaEnergy,
(*(*oneAtomCS)[0]),
(*(*oneAtomCS)[1]))*barn;
}
PartialSumSigma += theAtomNumDensityVector[i] * crossSection;
if(rval <= PartialSumSigma) return ((*theElementVector)(i));
}
return (*theElementVector)(0);
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;
}
@@ -20,149 +20,114 @@
// * statement, and all its terms. *
// ********************************************************************
//
//
// $Id: G4LowEnergyGammaConversion.cc,v 1.19.2.2 2001/06/28 20:19:29 gunter Exp $
// GEANT4 tag $Name: $
// --------------------------------------------------------------------
///
// $Id: G4LowEnergyGammaConversion.cc,v 1.26 2001/11/07 21:31:16 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
// CERN Geneva Switzerland
//
// ------------ G4LowEnergyGammaConversion physics process --------
// by A.Forti 1999/03/02
// Author: A. Forti
// Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// --------
// 02/03/1999 A. Forti 1st implementation
// 14.03.2000 Veronique Lefebure;
// 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
//
// --------------------------------------------------------------
// This Class Header
#include "G4LowEnergyGammaConversion.hh"
// Collaborating Class Headers
#include "globals.hh"
#include "Randomize.hh"
#include "G4EnergyLossTables.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 "G4CutsPerMaterialWarning.hh"
// constructor
G4LowEnergyGammaConversion::G4LowEnergyGammaConversion(const G4String& processName)
: G4VDiscreteProcess(processName),
theCrossSectionTable(0),
theMeanFreePathTable(0),
ZNumVec(0),
//Use lowest limit of EPDL97 which is larger than 2*electron_mass_c2 = 1.02199812 MeV
lowestEnergyLimit (1.022000*MeV),
highestEnergyLimit(100*GeV),
NumbBinTable(200)
lowEnergyLimit(1.022000*MeV),
highEnergyLimit(100*GeV),
intrinsicLowEnergyLimit(1.022000*MeV),
intrinsicHighEnergyLimit(100*GeV),
smallEnergy(2.*MeV)
{
if (verboseLevel>0) {
G4cout << GetProcessName() << " is created "<< G4endl;
G4cout << "lowestEnergy: " << lowestEnergyLimit/keV << "keV ";
G4cout << "highestEnergy: " << highestEnergyLimit/GeV << "GeV " << G4endl;
}
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
highEnergyLimit > intrinsicHighEnergyLimit)
{
G4Exception("G4LowEnergyGammaConversion::G4LowEnergyGammaConversion - energy limit outside intrinsic process validity range");
}
// The following pointer is owned by G4DataHandler
crossSectionHandler = new G4CrossSectionHandler();
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;
}
}
// destructor
G4LowEnergyGammaConversion::~G4LowEnergyGammaConversion()
{
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
}
// methods.............................................................................
void G4LowEnergyGammaConversion::BuildPhysicsTable(const G4ParticleDefinition& GammaType){
BuildZVec();
// Build microscopic cross section tables for the Compton Scattering process
BuildCrossSectionTable();
// Build mean free path table for the Compton Scattering process
BuildMeanFreePathTable();
delete meanFreePathTable;
delete crossSectionHandler;
delete rangeTest;
}
void G4LowEnergyGammaConversion::BuildCrossSectionTable(){
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
theCrossSectionTable = new G4SecondLevel();
G4int dataNum = 2;
for(size_t TableInd = 0; TableInd < ZNumVec->size(); TableInd++){
G4int AtomInd = (G4int) (*ZNumVec)[TableInd];
G4FirstLevel* oneAtomCS = util.BuildFirstLevelTables(AtomInd, dataNum, "pair/pp-cs-");
// theCrossSectionTable->insert(oneAtomCS);
theCrossSectionTable->push_back(oneAtomCS);
}//end for on atoms
}
void G4LowEnergyGammaConversion::BuildZVec(){
const G4MaterialTable* theMaterialTable=G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
void G4LowEnergyGammaConversion::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
ZNumVec = new G4DataVector();
for (G4int J=0 ; J < numOfMaterials; J++){
const G4Material* material= (*theMaterialTable)[J];
const G4ElementVector* theElementVector = material->GetElementVector();
const G4int NumberOfElements = material->GetNumberOfElements() ;
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&photon);
for (G4int iel=0; iel<NumberOfElements; iel++ ){
G4double Zel = (*theElementVector)(iel)->GetZ();
if(ZNumVec->contains(Zel) == FALSE){
ZNumVec->push_back(Zel);
} else{
continue;
}
}
}
crossSectionHandler->Clear();
G4String crossSectionFile = "pair/pp-cs-";
crossSectionHandler->LoadData(crossSectionFile);
delete meanFreePathTable;
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
}
G4VParticleChange* G4LowEnergyGammaConversion::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep){
//
// The secondaries e+e- energies are sampled using the Bethe - Heitler
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
// number techniques of Butcher & Messel is used (Nuc Phys 20(1960),15).
//
// GEANT4 internal units.
//
// 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
@@ -171,262 +136,216 @@ G4VParticleChange* G4LowEnergyGammaConversion::PostStepDoIt(const G4Track& aTrac
aParticleChange.Initialize(aTrack);
G4Material* aMaterial = aTrack.GetMaterial();
G4Material* material = aTrack.GetMaterial();
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
G4ParticleMomentum GammaDirection = aDynamicGamma->GetMomentumDirection();
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double photonEnergy = incidentPhoton->GetKineticEnergy();
G4ParticleMomentum photonDirection = incidentPhoton->GetMomentumDirection();
G4double epsil ;
G4double epsil0 = electron_mass_c2 / GammaEnergy ;
G4double epsilon ;
G4double epsilon0 = electron_mass_c2 / photonEnergy ;
// do it fast if GammaEnergy < 2. MeV
const G4double Egsmall=2.*MeV;
if (GammaEnergy<Egsmall) { epsil = epsil0 + (0.5-epsil0)*G4UniformRand(); }
else{ // now comes the case with GammaEnergy >= 2. MeV
// Do it fast if photon energy < 2. MeV
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);
if (element == 0)
{
G4cout << "G4LowEnergyGammaConversion::PostStepDoIt - element = 0" << G4endl;
}
G4IonisParamElm* ionisation = element->GetIonisation();
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());
// select randomly one element constituing the material
G4Element* anElement = SelectRandomAtom(aDynamicGamma, aMaterial);
// Extract Coulomb factor for this Element
G4double FZ = 8.*(anElement->GetIonisation()->GetlogZ3());
if (GammaEnergy > 50.*MeV) FZ += 8.*(anElement->GetfCoulomb());
// limits of the screening variable
G4double screenfac = 136.*epsil0/(anElement->GetIonisation()->GetZ3()) ;
G4double screenmax = exp ((42.24 - FZ)/8.368) - 0.952 ;
G4double screenmin = G4std::min(4.*screenfac,screenmax) ;
// limits of the energy sampling
G4double epsil1 = 0.5 - 0.5*sqrt(1. - screenmin/screenmax) ;
G4double epsilmin = G4std::max(epsil0,epsil1) , epsilrange = 0.5 - epsilmin ;
//
// sample the energy rate of the created electron (or positron)
//
//G4double epsil, screenvar, greject ;
G4double screenvar, greject ;
G4double F10 = ScreenFunction1(screenmin) - FZ , F20 = ScreenFunction2(screenmin) - FZ;
G4double NormF1 = G4std::max(F10*epsilrange*epsilrange,0.) , NormF2 = G4std::max(1.5*F20,0.);
do {
if ( NormF1/(NormF1+NormF2) > G4UniformRand() ){
epsil = 0.5 - epsilrange*pow(G4UniformRand(), 1/3) ;
screenvar = screenfac/(epsil*(1-epsil));
greject = (ScreenFunction1(screenvar) - FZ)/F10 ;
}
else {
epsil = epsilmin + epsilrange*G4UniformRand();
screenvar = screenfac/(epsil*(1-epsil));
greject = (ScreenFunction2(screenvar) - FZ)/F20 ;
}
// 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) ;
} while( greject < G4UniformRand() );
} // end of epsil sampling.........................
// 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)
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
{
epsilon = epsilonMin + epsilonRange * G4UniformRand();
screen = screenFactor / (epsilon * (1 - epsilon));
gReject = (ScreenFunction2(screen) - fZ) / f20 ;
}
} while ( gReject < G4UniformRand() );
} // End of epsilon sampling
//
// fixe charges randomly
//
// Fix charges randomly
G4double ElectTotEnergy, PositTotEnergy;
if (RandBit::shootBit()){
G4double electronTotEnergy;
G4double positronTotEnergy;
ElectTotEnergy = (1.-epsil)*GammaEnergy;
PositTotEnergy = epsil*GammaEnergy;
}
else{
PositTotEnergy = (1.-epsil)*GammaEnergy;
ElectTotEnergy = epsil*GammaEnergy;
}
if (RandBit::shootBit())
{
electronTotEnergy = (1. - epsilon) * photonEnergy;
positronTotEnergy = epsilon * photonEnergy;
}
else
{
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))
// 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)
G4double u;
const G4double a1 = 0.625 , a2 = 3.*a1 , d = 27. ;
const G4double a1 = 0.625;
G4double a2 = 3. * a1;
// G4double d = 27. ;
if (9./(9.+d) > G4UniformRand()){
u = - log(G4UniformRand()*G4UniformRand())/a1 ;
}
// if (9. / (9. + d) > G4UniformRand())
if (0.25 > G4UniformRand())
{
u = - log(G4UniformRand() * G4UniformRand()) / a1 ;
}
else
{
u = - log(G4UniformRand() * G4UniformRand()) / a2 ;
}
else{
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);
G4double Teta = u*electron_mass_c2/GammaEnergy ;
G4double Phi = twopi * G4UniformRand() ;
G4double dirx = sin(Teta)*cos(Phi) , diry = sin(Teta)*sin(Phi) , dirz = cos(Teta);
//
// kinematic of the created pair
// 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.
// distribution with respect to the Z axis along the parent photon
G4double LocalEnerDeposit = 0. ;
G4double localEnergyDeposit = 0. ;
aParticleChange.SetNumberOfSecondaries(2) ;
G4double ElectKineEnergy = G4std::max(0.,ElectTotEnergy - electron_mass_c2) ;
aParticleChange.SetNumberOfSecondaries(2.) ;
G4double electronKineEnergy = G4std::max(0.,electronTotEnergy - electron_mass_c2) ;
// if (G4EnergyLossTables::GetRange(G4Electron::Electron(), ElectKineEnergy, aMaterial)
// >= G4std::min(G4Electron::GetCuts(), aStep.GetPostStepPoint()->GetSafety()) ){
if((G4EnergyLossTables::GetRange(G4Electron::Electron(),
ElectKineEnergy,aMaterial)>aStep.GetPostStepPoint()->GetSafety())
||
(ElectKineEnergy >
(G4Electron::Electron()->GetCutsInEnergy())[aMaterial->GetIndex()]))
// Generate the electron only if with large enough range w.r.t. cuts and safety
{
G4double safety = aStep.GetPostStepPoint()->GetSafety();
G4ThreeVector ElectDirection ( dirx, diry, dirz );
ElectDirection.rotateUz(GammaDirection);
// create G4DynamicParticle object for the particle1
G4DynamicParticle* aParticle1= new G4DynamicParticle (G4Electron::Electron(),ElectDirection, ElectKineEnergy);
if (rangeTest->Escape(G4Electron::Electron(),material,electronKineEnergy,safety))
{
G4ThreeVector electronDirection ( dirX, dirY, dirZ );
electronDirection.rotateUz(photonDirection);
G4DynamicParticle* particle1 = new G4DynamicParticle (G4Electron::Electron(),
electronDirection,
electronKineEnergy);
aParticleChange.AddSecondary(particle1) ;
}
else
{
localEnergyDeposit += electronKineEnergy ;
}
aParticleChange.AddSecondary( aParticle1 ) ;
}
else{
LocalEnerDeposit += ElectKineEnergy ;
}
// The e+ is always created (even with kinetic energy = 0) for further annihilation
G4double positronKineEnergy = G4std::max(0.,positronTotEnergy - electron_mass_c2) ;
// the e+ is always created (even with Ekine=0) for further annihilation.
G4double PositKineEnergy = G4std::max(0.,PositTotEnergy - electron_mass_c2) ;
if (G4EnergyLossTables::GetRange(G4Positron::Positron(),PositKineEnergy,aMaterial)
< G4std::min(G4Positron::GetCuts(), aStep.GetPostStepPoint()->GetSafety()) ){
LocalEnerDeposit += PositKineEnergy ;
PositKineEnergy = 0. ;
}
G4ThreeVector PositDirection ( -dirx, -diry, dirz );
PositDirection.rotateUz(GammaDirection);
// Is the local energy deposit correct, if the positron is always created?
if (! (rangeTest->Escape(G4Positron::Positron(),material,positronKineEnergy,safety)))
{
localEnergyDeposit += positronKineEnergy ;
positronKineEnergy = 0. ;
}
G4ThreeVector positronDirection(-dirX,-dirY,dirZ);
positronDirection.rotateUz(photonDirection);
// create G4DynamicParticle object for the particle2
G4DynamicParticle* aParticle2= new G4DynamicParticle (G4Positron::Positron(),
PositDirection, PositKineEnergy);
// Create G4DynamicParticle object for the particle2
G4DynamicParticle* particle2 = new G4DynamicParticle(G4Positron::Positron(),
positronDirection, positronKineEnergy);
aParticleChange.AddSecondary(particle2) ;
aParticleChange.AddSecondary( aParticle2 ) ;
aParticleChange.SetLocalEnergyDeposit(localEnergyDeposit) ;
aParticleChange.SetLocalEnergyDeposit( LocalEnerDeposit ) ;
//
// Kill the incident photon
//
aParticleChange.SetMomentumChange( 0., 0., 0. ) ;
aParticleChange.SetEnergyChange( 0. ) ;
aParticleChange.SetStatusChange( fStopAndKill ) ;
#ifdef G4VERBOSE
if(verboseLevel > 15){
G4cout<<"LE Gamma Conversion PostStepDoIt"<<G4endl;
}
#endif
aParticleChange.SetMomentumChange(0.,0.,0.) ;
aParticleChange.SetEnergyChange(0.) ;
aParticleChange.SetStatusChange(fStopAndKill) ;
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep );
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
void G4LowEnergyGammaConversion::BuildMeanFreePathTable(){
G4bool G4LowEnergyGammaConversion::IsApplicable(const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
}
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable; }
G4double G4LowEnergyGammaConversion::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();
// material
G4double NumbOfMaterials = G4Material::GetNumberOfMaterials();
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
G4Material* material;
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;
}
// MeanFreePath
G4double LowEdgeEnergy, Value;
theMeanFreePathTable = new G4PhysicsTable(NumbOfMaterials);
G4PhysicsLogVector* ptrVector;
G4double G4LowEnergyGammaConversion::ScreenFunction1(G4double screenVariable)
{
// Compute the value of the screening function 3*phi1 - phi2
for ( G4int J = 0 ; J < NumbOfMaterials; J++ ) { // For each material
G4double value;
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(lowestEnergyLimit, highestEnergyLimit, NumbBinTable);
material = (*theMaterialTable)(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* theAtomNumDensityVector = material->GetAtomicNumDensityVector();
for ( G4int i = 0 ; i < NumbBinTable ; i++ ){
//For each energy
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy(i);
const G4double BigPath= DBL_MAX;
G4double SIGMA = 0 ;
for ( size_t k=0 ; k < material->GetNumberOfElements() ; k++ ){
// For each element
G4int AtomIndex = (G4int) (*theElementVector)(k)->GetZ();
const G4FirstLevel* oneAtomCS
= (*theCrossSectionTable)[ZNumVec->index(AtomIndex)];
G4double interCrsSec = util.DataLogInterpolation(LowEdgeEnergy,
(*(*oneAtomCS)[0]),
(*(*oneAtomCS)[1]))*barn;
SIGMA += theAtomNumDensityVector[k]*interCrsSec;
}
Value = SIGMA<=0.0 ? BigPath : 1./SIGMA ;
ptrVector->PutValue( i , Value ) ;
}
theMeanFreePathTable->insertAt( J , ptrVector ) ;
}
}
G4Element* G4LowEnergyGammaConversion::SelectRandomAtom(const G4DynamicParticle* aDynamicGamma, G4Material* aMaterial){
// select randomly 1 element within the material
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
if (NumberOfElements == 1) return (*theElementVector)(0);
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
G4double PartialSumSigma = 0.;
G4double rval = G4UniformRand()/MeanFreePath;
for ( G4int i=0 ; i < NumberOfElements ; i++ ){
G4double crossSection;
if (GammaEnergy < lowestEnergyLimit)
crossSection = 0. ;
else {
if (GammaEnergy > highestEnergyLimit) GammaEnergy = 0.99*highestEnergyLimit ;
G4int AtomIndex = (G4int) (*theElementVector)(i)->GetZ();
const G4FirstLevel* oneAtomCS
= (*theCrossSectionTable)[ZNumVec->index(AtomIndex)];
crossSection = util.DataLogInterpolation(GammaEnergy,
(*(*oneAtomCS)[0]),
(*(*oneAtomCS)[1]))*barn;
}
PartialSumSigma += theAtomNumDensityVector[i] * crossSection;
if(rval <= PartialSumSigma) return ((*theElementVector)(i));
}
// G4cout << " WARNING !!! - The Material '"<< aMaterial->GetName()
// << "' has no elements" << G4endl;
return (*theElementVector)(0);
}
if (screenVariable > 1.)
value = 42.24 - 8.368 * log(screenVariable + 0.952);
else
value = 42.392 - screenVariable * (7.796 - 1.961 * screenVariable);
return value;
}
G4double G4LowEnergyGammaConversion::ScreenFunction2(G4double screenVariable)
{
// Compute the value of the screening function 1.5*phi1 - 0.5*phi2
G4double value;
if (screenVariable > 1.)
value = 42.24 - 8.368 * log(screenVariable + 0.952);
else
value = 41.405 - screenVariable * (5.828 - 0.8945 * screenVariable);
return value;
}
File diff suppressed because it is too large Load Diff
@@ -21,17 +21,21 @@
// ********************************************************************
//
//
// $Id: G4LowEnergyPhotoElectric.cc,v 1.31.2.2 2001/06/28 20:19:30 gunter Exp $
// GEANT4 tag $Name: $
// $Id: G4LowEnergyPhotoElectric.cc,v 1.42 2001/11/07 21:31:16 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
// CERN Geneva Switzerland
// Author: A. Forti
// Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// ------------ G4LowEnergyPhotoelctric: low energy modifications --------
// by Alessandra Forti, October 1998
// **************************************************************
// History:
// --------
// October 1998 - low energy modifications by Alessandra Forti
// Added Livermore data table construction methods A. Forti
// Modified BuildMeanFreePath to read new data tables A. Forti
// Added EnergySampling method A. Forti
// Modified PostStepDoIt to insert sampling with EPDL97 data A. Forti
// Added SelectRandomAtom A. Forti
// Added map of the elements A. Forti
// 10.04.2000 VL
// - Correcting Fluorescence transition probabilities in order to take into account
// non-radiative transitions. No Auger electron simulated yet: energy is locally deposited.
@@ -41,707 +45,264 @@
// . no Fluorescence was simulated when the photo-electron energy
// was below production threshold.
//
// Added Livermore data table construction methods A. Forti
// Modified BuildMeanFreePath to read new data tables A. Forti
// Added EnergySampling method A. Forti
// Modified PostStepDoIt to insert sampling with EPDL97 data A. Forti
// Added SelectRandomAtom A. Forti
// Added map of the elements A. Forti
// 07-09-99, if no e- emitted: edep=photon energy, mma
// 24.04.01 V.Ivanchenko remove RogueWave
// 12.08.2001 MGP Revised according to a design iteration
// 16.09.2001 E. Guardincerri Added fluorescence generation
// 06.10.2001 MGP Added protection to avoid negative electron energies
// when binding energy of selected shell > photon energy
//
// --------------------------------------------------------------
// This Class Header
#include "G4LowEnergyPhotoElectric.hh"
// Collaborating Class Headers
#include "G4EnergyLossTables.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 "G4RangeTest.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4AtomicShell.hh"
typedef G4std::vector<G4DynamicParticle*> G4ParticleVector;
#include "G4CutsPerMaterialWarning.hh"
// ..
// constructor
G4LowEnergyPhotoElectric::G4LowEnergyPhotoElectric(const G4String& processName)
: G4VDiscreteProcess(processName), // initialization
lowestEnergyLimit (250*eV),
highestEnergyLimit(100*GeV),
NumbBinTable(200),
CutForLowEnergySecondaryPhotons(0.),
theCrossSectionTable(0),
theMeanFreePathTable(0),
allAtomShellCrossSec(0),
theFluorTransitionTable(0),
theBindingEnergyTable(0),
ZNumVec(0),
ZNumVecFluor(0),
MeanFreePath(0.)
: G4VDiscreteProcess(processName), lowEnergyLimit(250*eV), highEnergyLimit(100*GeV),
intrinsicLowEnergyLimit(10*eV),
intrinsicHighEnergyLimit(100*GeV),
cutForLowEnergySecondaryPhotons(0.)
{
if (verboseLevel>0) {
G4cout << GetProcessName() << " is created "<< G4endl;
G4cout << "lowestEnergy: " << lowestEnergyLimit/keV << "keV ";
G4cout << "highestEnergy: " << highestEnergyLimit/MeV << "MeV " << G4endl;
}
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
highEnergyLimit > intrinsicHighEnergyLimit)
{
G4Exception("G4LowEnergyPhotoElectric::G4LowEnergyPhotoElectric - energy limit outside intrinsic process validity range");
}
crossSectionHandler = new G4CrossSectionHandler();
shellCrossSectionHandler = new G4CrossSectionHandler();
meanFreePathTable = 0;
rangeTest = new G4RangeTest;
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
// ..
// destructor
G4LowEnergyPhotoElectric::~G4LowEnergyPhotoElectric()
{
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
if (theBindingEnergyTable) {
// theBindingEnergyTable->clearAndDestroy();
theBindingEnergyTable->clear();
delete theBindingEnergyTable;
}
if (theMeanFreePathTable) {
// theMeanFreePathTable->clearAndDestroy();
theMeanFreePathTable->clear();
delete theMeanFreePathTable;
}
// ClearAndDestroy of this tables is called in their destructors
if (theFluorTransitionTable) {
delete theFluorTransitionTable;
}
if (allAtomShellCrossSec) {
delete allAtomShellCrossSec;
}
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
if(ZNumVecFluor){
ZNumVecFluor->erase(ZNumVecFluor->begin(),ZNumVecFluor->end());
delete ZNumVecFluor;
}
}
// ..
void G4LowEnergyPhotoElectric::SetCutForLowEnSecPhotons(G4double cut){
CutForLowEnergySecondaryPhotons = cut;
delete crossSectionHandler;
delete shellCrossSectionHandler;
delete meanFreePathTable;
delete rangeTest;
}
// ..
void G4LowEnergyPhotoElectric::BuildPhysicsTable(const G4ParticleDefinition& PhotonType)
// Build microscopic cross section table and mean free path table
void G4LowEnergyPhotoElectric::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
BuildZVec();
BuildCrossSectionTable();
BuildShellCrossSectionTable();
BuildMeanFreePathTable();
BuildBindingEnergyTable();
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&photon);
BuildFluorTransitionTable();
crossSectionHandler->Clear();
G4String crossSectionFile = "phot/pe-cs-";
crossSectionHandler->LoadData(crossSectionFile);
shellCrossSectionHandler->Clear();
G4String shellCrossSectionFile = "phot/pe-ss-cs-";
shellCrossSectionHandler->LoadShellData(shellCrossSectionFile);
delete meanFreePathTable;
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
}
// ..
// CONSTRUCT THE CROSS SECTION TABLE FOR THE ELEMENTS MAPPED IN ZNUMVEC USING EPDL DATA
void G4LowEnergyPhotoElectric::BuildCrossSectionTable(){
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
theCrossSectionTable = new G4SecondLevel();
G4int dataNum = 2;
for(size_t TableInd = 0; TableInd < ZNumVec->size(); TableInd++){
G4int AtomInd = (G4int) (*ZNumVec)[TableInd];
G4FirstLevel* oneAtomCS = util.BuildFirstLevelTables(AtomInd, dataNum, "phot/pe-cs-");
// theCrossSectionTable->insert(oneAtomCS);
theCrossSectionTable->push_back(oneAtomCS);
}//end for on atoms
}
// ..
// CONSTRUCT THE SUBSHELL CS TABLE FOR THE ELEMENTS MAPPED IN ZNUMVEC USING EPDL DATA
void G4LowEnergyPhotoElectric::BuildShellCrossSectionTable(){
if (allAtomShellCrossSec) {
delete allAtomShellCrossSec;
}
allAtomShellCrossSec = new allAtomTable();
G4int dataNum = 2;
for(size_t TableInd = 0; TableInd < ZNumVec->size(); TableInd++){
G4int AtomInd = (G4int) (*ZNumVec)[TableInd];
oneAtomTable* oneAtomShellCS = util.BuildSecondLevelTables(AtomInd, dataNum, "phot/pe-ss-cs-");
// allAtomShellCrossSec->insert(oneAtomShellCS);
allAtomShellCrossSec->push_back(oneAtomShellCS);
}//end for on atoms
}
// ..
// CONSTRUCT THE BE TABLE FOR THE ELEMENTS MAPPED IN ZNUMVEC USING EADL DATA
void G4LowEnergyPhotoElectric::BuildBindingEnergyTable(){
if (theBindingEnergyTable) {
delete theBindingEnergyTable;
}
G4int dataNum = 2;
theBindingEnergyTable = util.BuildSecondLevelTables(0,dataNum,"fluor/binding");
}
// ..
// CONSTRUCT THE FTP TABLE FOR THE ELEMENTS MAPPED IN ZNUMVEC USING EADL DATA
void G4LowEnergyPhotoElectric::BuildFluorTransitionTable(){
if (theFluorTransitionTable) {
delete theFluorTransitionTable;
}
theFluorTransitionTable = new allAtomTable();
ZNumVecFluor = new G4DataVector(*ZNumVec);
G4int dataNum = 3;
for(size_t TableInd = 0; TableInd < ZNumVec->size(); TableInd++){
G4int AtomInd = (G4int) (*ZNumVec)[TableInd];
if(AtomInd > 5){
oneAtomTable* oneAtomShellFL = util.BuildSecondLevelTables(AtomInd, dataNum, "fluor/fl-tr-pr-");
// theFluorTransitionTable->insert(oneAtomShellFL);
theFluorTransitionTable->push_back(oneAtomShellFL);
}
else{
ZNumVecFluor->remove(AtomInd);
}
}//end for on atoms
}
// ..
//
// vector mapping the elements of the material table
//
void G4LowEnergyPhotoElectric::BuildZVec(){
const G4MaterialTable* theMaterialTable=G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
ZNumVec = new G4DataVector();
for (G4int J=0 ; J < numOfMaterials; J++){
const G4Material* material= (*theMaterialTable)[J];
const G4ElementVector* theElementVector = material->GetElementVector();
const G4int NumberOfElements = material->GetNumberOfElements() ;
for (G4int iel=0; iel<NumberOfElements; iel++ ){
G4double Zel = (*theElementVector)(iel)->GetZ();
if(ZNumVec->contains(Zel) == FALSE){
ZNumVec->push_back(Zel);
} else{
continue;
}
}
}
}
// ..
// Compute total cross section from subshell integrated cross section: needed for
// selection of the first subshell ionized.
G4double G4LowEnergyPhotoElectric::ComputeCrossSection(const G4double AtomIndex,
const G4double IncEnergy){
// calculates the microscopic cross section from subshell cross sections
//(it is called for elements , AtomicNumber = Z )
G4double TotalCrossSection(0.);
const oneAtomTable* oneAtomCS
= (*allAtomShellCrossSec)[ZNumVec->index(AtomIndex)];
for(size_t ind = 0; ind < oneAtomCS->size(); ind++){
G4double crossSec = 0;
G4DataVector* EnergyVector = (*(*oneAtomCS)[ind])[0];
G4DataVector* CrossSecVector = (*(*oneAtomCS)[ind])[1];
if(IncEnergy < (*EnergyVector)[1]){ // First element is the shell number
crossSec = 0;
}
else{
crossSec = util.DataLogInterpolation(IncEnergy, (*EnergyVector), (*CrossSecVector))*barn;
}
TotalCrossSection += crossSec;
}
return TotalCrossSection ;
}
// ..
void G4LowEnergyPhotoElectric::BuildMeanFreePathTable(){
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable; }
// material
G4double NumbOfMaterials = G4Material::GetNumberOfMaterials();
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
G4Material* material;
// MeanFreePath
G4double LowEdgeEnergy, Value;
theMeanFreePathTable = new G4PhysicsTable(NumbOfMaterials);
G4PhysicsLogVector* ptrVector;
for ( G4int J = 0 ; J < NumbOfMaterials; J++ ) { // For each material
//create physics vector then fill it ....
// WARNING: Lower limit of total cross sections in the data is the binding energy
// of the relative subshell. MeanFreePath table require a common lowest limit.
// This lowestEnergyLimit is at the moment fixed at 250 ev.
ptrVector = new G4PhysicsLogVector(lowestEnergyLimit, highestEnergyLimit, NumbBinTable);
material = (*theMaterialTable)(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* theAtomNumDensityVector = material->GetAtomicNumDensityVector();
for ( G4int i = 0 ; i < NumbBinTable ; i++ ){
//For each energy
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy(i);
G4double SIGMA = 0;
for ( size_t k=0 ; k < material->GetNumberOfElements() ; k++ ){
// For each element
G4int AtomIndex = (G4int) (*theElementVector)(k)->GetZ();
const G4FirstLevel* oneAtomCS
= (*theCrossSectionTable)[ZNumVec->index(AtomIndex)];
G4double interCrsSec = util.DataLogInterpolation(LowEdgeEnergy, (*(*oneAtomCS)[0]), (*(*oneAtomCS)[1]))*barn;
SIGMA += theAtomNumDensityVector[k]*interCrsSec;
}
Value = SIGMA > DBL_MIN ? 1./SIGMA : DBL_MAX ;
ptrVector->PutValue( i , Value ) ;
}
theMeanFreePathTable->insertAt( J , ptrVector ) ;
}
}
// ..
G4VParticleChange* G4LowEnergyPhotoElectric::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep){
// Fluorescence (as reported by stepanek):
// J. Stepanek " A program to determine the radiation spectra due to a single atomic
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
// subshell ionisation by a particle or due to deexcitation or decay of radionuclides",
// Comp. Phys. Comm. 1206 pp 1-1-9 (1997)
//
// incoming particle initialization
aParticleChange.Initialize(aTrack);
G4Material* aMaterial = aTrack.GetMaterial();
const G4DynamicParticle* aDynamicPhoton = aTrack.GetDynamicParticle();
const G4double PhotonEnergy = aDynamicPhoton->GetKineticEnergy();
if(PhotonEnergy <= lowestEnergyLimit){
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit(PhotonEnergy);
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
const G4ParticleMomentum PhotonDirection = aDynamicPhoton->GetMomentumDirection();
// select randomly one element constituing the material.
G4Element* anElement = SelectRandomAtom(aDynamicPhoton, aMaterial);
// PAY ATTENTION TO THE MEANING OF THIS NUMBER!!! SelectRandomAtom requires to use AtomNum
// the BindingEnergyTable requires AtomNum-1
G4int AtomNum = (G4int) anElement->GetZ();
// First Ionised subshell is chosen basing on subshell integrated cross section EPDL97
// using the partial sum method.
// Select the subshell WARNING!!!!: it returns the subshell index in the table.
G4int subShellIndex = SelectRandomShell(AtomNum, PhotonEnergy);
G4FirstLevel* theBindEnVec = (*theBindingEnergyTable)[AtomNum-1];
G4int thePrimaryShell = (G4int) (*(*theBindEnVec)[0])[subShellIndex];
G4double BindingEn = ((*(*theBindEnVec)[1])[subShellIndex])*MeV;
if(thePrimShVec.size() != 0){
thePrimShVec.clear();
}
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
G4Material* material = aTrack.GetMaterial();
G4int Z = crossSectionHandler->SelectRandomAtom(material,photonEnergy);
thePrimShVec.push_back(thePrimaryShell);
// 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
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)
G4ParticleVector photvec;
// G4int photInd = 0;
G4ParticleVector elecvec;
// G4int elecInd = 0;
// (Is the electron vector necessary? To be checked)
G4std::vector<G4DynamicParticle*>* photonVector = 0;
G4std::vector<G4DynamicParticle*> electronVector;
// primary outcoming electron
G4double ElecKineEnergy = (PhotonEnergy - BindingEn);
G4double energyDeposit = bindingEnergy;
G4double theEnergyDeposit = BindingEn;
// Primary outcoming electron
G4double eKineticEnergy = photonEnergy - bindingEnergy;
if (G4EnergyLossTables::GetRange(G4Electron::Electron(),ElecKineEnergy,aMaterial)
>= G4std::min(G4Electron::GetCuts(), aStep.GetPostStepPoint()->GetSafety())){
// 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();
// the electron is created in the direction of the incident photon ...
G4DynamicParticle* aElectron = new G4DynamicParticle (G4Electron::Electron(),
PhotonDirection, ElecKineEnergy) ;
elecvec.push_back(aElectron);
} // END OF CUTS
if (rangeTest->Escape(G4Electron::Electron(),material,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
{
energyDeposit = photonEnergy;
}
G4int nElectrons = electronVector.size();
size_t nTotPhotons = 0;
G4int nPhotons=0;
// 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 && eKineticEnergy > 0.)
{
photonVector = deexcitationManager.GenerateParticles(Z,shellId);
nTotPhotons = photonVector->size();
for (size_t k=0; k<nTotPhotons; k++)
{
G4DynamicParticle* aPhoton = (*photonVector)[k];
if (aPhoton == 0)
{
delete aPhoton;
}
else
{
G4double itsKineticEnergy = aPhoton->GetKineticEnergy();
G4double eDepositTmp = energyDeposit - itsKineticEnergy;
if (itsKineticEnergy >= cutForLowEnergySecondaryPhotons &&
eDepositTmp > 0.)
{
nPhotons++;
// Local energy deposit is given as the sum of the
// energies of incident photons minus the energies
// of the outcoming fluorescence photons
energyDeposit -= itsKineticEnergy;
}
else
{ delete aPhoton; }
}
}
}
G4int nSecondaries = nElectrons + nPhotons;
else{
theEnergyDeposit += ElecKineEnergy;
}
// load the transition probability table for the element
// theTable[i][j][k]
// i = subshell, j = type of information (second shell, transition energy ,
// transition probability), k = previous vectors.
if(AtomNum > 5){
G4bool ThereAreShells = TRUE;
G4int AtomInd = ZNumVecFluor->index(AtomNum);
oneAtomTable* oneAtomFluorTrans = (*theFluorTransitionTable)[AtomInd];
while(ThereAreShells == TRUE){
// Select the second transition from another subshell
// fluorPar[0] = SubShell
// fluorPar[1] = Sec SubShell (if there is),
// fluorPar[2] = Transition Probability
// the same for augerPar
G4double fluorPar[3] = {0};
ThereAreShells = SelectRandomTransition(thePrimaryShell,
fluorPar,
oneAtomFluorTrans);
// Daugther dynamic particle
G4DynamicParticle* newPart;
// Direction of the outcoming particle isotropic selection
G4double newcosTh = 1-2*G4UniformRand();
G4double newsinTh = sqrt(1-newcosTh*newcosTh);
G4double newPhi = twopi*G4UniformRand();
G4double dirx, diry, dirz;
dirz = newcosTh;
diry = newsinTh*cos(newPhi);
dirx = newsinTh*sin(newPhi);
G4ThreeVector newPartDirection(dirx, diry, dirz);
/////newPartDirection.rotateUz(PhotonDirection);
if(ThereAreShells != FALSE){
thePrimaryShell = (G4int) fluorPar[0];
if(fluorPar[2]*MeV >= CutForLowEnergySecondaryPhotons){
theEnergyDeposit -= fluorPar[2]*MeV;
newPart = new G4DynamicParticle (G4Gamma::Gamma(),
newPartDirection,
fluorPar[2]*MeV);
// photvec.append(newPart);
photvec.push_back(newPart);
}
}
else{
/////Energy deposition vl
////=================NEW================vl
/*
G4int k = 0;
while(thePrimaryShell != (*(*theBindEnVec)[0])[k]) k++;
G4double lastTransEnergy = ((*(*theBindEnVec)[1])[k])*MeV;
thePrimaryShell = (G4int) fluorPar[0];
if(lastTransEnergy >= CutForLowEnergySecondaryPhotons){
theEnergyDeposit -= lastTransEnergy;
newPart = new G4DynamicParticle (G4Gamma::Gamma(),
newPartDirection,
lastTransEnergy) ;
photvec.push_back(newPart);
}
thePrimShVec.insert(thePrimaryShell);
*/
}
}
} //END OF THE CHECK ON ATOMIC NUMBER
G4int numOfElec = elecvec.size();
G4int numOfPhot = photvec.size();
G4int numOfDau = numOfElec + numOfPhot;
aParticleChange.SetNumberOfSecondaries(numOfDau);
G4int l = 0;
for( l = 0; l<numOfElec; l++ ){
aParticleChange.AddSecondary(elecvec[l]);
aParticleChange.SetNumberOfSecondaries(nSecondaries);
G4int l = 0;
for ( l = 0; l<nElectrons; l++ )
{
aParticleChange.AddSecondary(electronVector[l]);
}
for(l = 0; l < numOfPhot; l++) {
aParticleChange.AddSecondary(photvec[l]);
for (l = 0; l < nPhotons; l++)
{
aParticleChange.AddSecondary((*photonVector)[l]);
}
photvec.clear();
elecvec.clear();
if(theEnergyDeposit < 0){
theEnergyDeposit = 0;
delete photonVector;
if (energyDeposit < 0)
{
G4cout << "WARNING - "
<< "G4LowEnergyPhotoElectric::PostStepDoIt - Negative energy deposit"
<< G4endl;
energyDeposit = 0;
}
// Kill the incident photon
aParticleChange.SetMomentumChange( 0., 0., 0. );
aParticleChange.SetEnergyChange( 0. );
if (theEnergyDeposit < 0) theEnergyDeposit = 0;
aParticleChange.SetLocalEnergyDeposit(theEnergyDeposit);
aParticleChange.SetLocalEnergyDeposit(energyDeposit);
aParticleChange.SetStatusChange( fStopAndKill );
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep );
}
// ..
G4int G4LowEnergyPhotoElectric::SelectRandomShell(const G4int AtomIndex,
const G4double IncEnergy)
{
G4double partialSum = 0;
G4double totalSum = ComputeCrossSection(AtomIndex,IncEnergy);
G4double rval = totalSum*G4UniformRand();
const oneAtomTable* oneAtomCS
= (*allAtomShellCrossSec)[ZNumVec->index(AtomIndex)];
for(size_t ind = 0; ind < oneAtomCS->size(); ind++){
G4double crossSec;
G4DataVector* EnergyVector = (*(*oneAtomCS)[ind])[0];
G4DataVector* CrossSecVector = (*(*oneAtomCS)[ind])[1];
if(IncEnergy < (*EnergyVector)[0]){ //First element is the shell number
crossSec = 0;
}
else{
crossSec = util.DataLogInterpolation(IncEnergy, (*EnergyVector), (*CrossSecVector))*barn;
}
partialSum += crossSec;
if(rval <= partialSum) return ind;
}
G4Exception("LEPhotoElectric: Cannot select a shell");
return 0;
}
// ..
G4Element*
G4LowEnergyPhotoElectric::SelectRandomAtom(const G4DynamicParticle* aDynamicPhoton,
G4Material* aMaterial)
G4bool G4LowEnergyPhotoElectric::IsApplicable(const G4ParticleDefinition& particle)
{
// select randomly 1 element within the material
G4double GammaEnergy = aDynamicPhoton->GetKineticEnergy();
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
if (NumberOfElements == 1) return (*theElementVector)(0);
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
G4double PartialSumSigma = 0. ;
G4double rval = G4UniformRand()/MeanFreePath;
for ( G4int i=0 ; i < NumberOfElements ; i++ ){
G4double crossSection;
if (GammaEnergy < lowestEnergyLimit)
crossSection = 0. ;
else {
if (GammaEnergy > highestEnergyLimit) GammaEnergy = 0.99*highestEnergyLimit ;
G4int AtomIndex = (G4int) (*theElementVector)(i)->GetZ();
const G4FirstLevel* oneAtomCS
= (*theCrossSectionTable)[ZNumVec->index(AtomIndex)];
crossSection = util.DataLogInterpolation(GammaEnergy, (*(*oneAtomCS)[0]), (*(*oneAtomCS)[1]))*barn;
}
PartialSumSigma += theAtomNumDensityVector[i] * crossSection;
if (rval <= PartialSumSigma) return ((*theElementVector)(i));
}
return (*theElementVector)(0);
}
// ..
//
// Select a random transition with the transition probabilities and the partial sum
// method using EADL data (A. Forti)
//
G4bool G4LowEnergyPhotoElectric::SelectRandomTransition(G4int thePrimShell,
G4double* TransParam,
const oneAtomTable* TransitionTable){
G4int SubShellCol = 0, ProbCol = 1, EnergyCol = 2;
// transitionTable contains all the transition probabilities of one atom:
// loop on subshell is inside the method.
// when the last subshell is reached CollIsFull becomes FALSE.
G4bool ColIsFull = FALSE;
G4int ShellNum = 0;
// G4double TotalSum = 0;
G4int maxNumOfShells = TransitionTable->size()-1;
if(thePrimShell <= 0) {
G4cerr<<"*** Unvalid Primary shell: "<<thePrimShell<<G4endl;
return FALSE;
}
if(thePrimShell <= (*(*(*TransitionTable)[maxNumOfShells])[0])[0]){
while(thePrimShell != (*(*(*TransitionTable)[ShellNum])[0])[0]){
if(ShellNum == maxNumOfShells){
break;
}
ShellNum++;
}
// TransProb is the index of the loop and of the table of transition. it starts from 1
// because the first element of the data table is the primary shell id number and not a
// transition probability: it must not be added to TotalSum.
G4int TransProb = 1;
// Include non-radiative transitions (vl):
//// for(TransProb = 1; TransProb < (*(*TransitionTable)[ShellNum])[ProbCol]->length(); TransProb++){
//// TotalSum += (*(*(*TransitionTable)[ShellNum])[ProbCol])[TransProb];
//// }
////G4double PartialProb = G4UniformRand()*TotalSum;
////
G4double PartialProb = G4UniformRand();
//vl.
G4double PartSum = 0;
TransProb = 1;
G4int trSize = (*(*TransitionTable)[ShellNum])[ProbCol]->size();
while(TransProb < trSize){
PartSum += (*(*(*TransitionTable)[ShellNum])[ProbCol])[TransProb];
if(PartialProb <= PartSum){
TransParam[0] = (*(*(*TransitionTable)[ShellNum])[SubShellCol])[TransProb];
TransParam[1] = (*(*(*TransitionTable)[ShellNum])[ProbCol])[TransProb];
TransParam[2] = (*(*(*TransitionTable)[ShellNum])[EnergyCol])[TransProb];
ColIsFull = TRUE;
break;
}
TransProb++;
}
}
else{
ColIsFull = FALSE;
}
return ColIsFull;
return ( &particle == G4Gamma::Gamma() );
}
// ..
G4double G4LowEnergyPhotoElectric::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 G4LowEnergyPhotoElectric::SetCutForLowEnSecPhotons(G4double cut)
{
cutForLowEnergySecondaryPhotons = cut;
}
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4LowEnergyPolarizedCompton.cc,v 1.5.2.2 2001/06/28 20:19:30 gunter Exp $
// GEANT4 tag $Name: $
// $Id: G4LowEnergyPolarizedCompton.cc,v 1.11 2001/11/07 21:31:16 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// ------------------------------------------------------------
// GEANT 4 class implementation file
@@ -38,6 +38,8 @@
// Temporary protection to avoid crash in the case
// of polarisation || incident photon direction
//
// 17 October 2001 - F.Longo - Revised according to a design iteration
//
// ************************************************************
//
// Corrections by Rui Curado da Silva (2000)
@@ -49,257 +51,88 @@
// --------------------------------------------------------------
#include "G4LowEnergyPolarizedCompton.hh"
#include "G4Electron.hh"
#include "G4EnergyLossTables.hh"
#include "G4Gamma.hh"
#include "G4SecondLevel.hh"
#include "G4PhysicsTable.hh"
#include "G4DataVector.hh"
#include "Randomize.hh"
#include "G4ParticleDefinition.hh"
#include "G4ThreeVector.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 "G4RangeTest.hh"
#include "G4CutsPerMaterialWarning.hh"
// constructor
G4LowEnergyPolarizedCompton::G4LowEnergyPolarizedCompton(const G4String& processName)
: G4VDiscreteProcess(processName),
theCrossSectionTable(0),
theScatteringFunctionTable(0),
theMeanFreePathTable(0),
ZNumVec(0),
lowestEnergyLimit (250*eV), // initialization
highestEnergyLimit(100*GeV),
numbBinTable(200),
meanFreePath(0)
lowEnergyLimit (250*eV), // initialization
highEnergyLimit(100*GeV),
intrinsicLowEnergyLimit(10*eV),
intrinsicHighEnergyLimit(100*GeV)
{
if (verboseLevel>0) {
G4cout << GetProcessName() << " is created "<< G4endl;
G4cout << "LowestEnergy: " << lowestEnergyLimit/keV << "keV ";
G4cout << "HighestEnergy: " << highestEnergyLimit/TeV << "TeV " << G4endl;
}
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
G4CompositeEMDataSet(scatterFile,scatterInterpolation,1.,1.);
meanFreePathTable = 0;
rangeTest = new G4RangeTest;
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
// destructor
G4LowEnergyPolarizedCompton::~G4LowEnergyPolarizedCompton()
{
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
if (theScatteringFunctionTable) {
delete theScatteringFunctionTable;
}
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
delete meanFreePathTable;
delete crossSectionHandler;
delete scatterFunctionData;
delete rangeTest;
}
void G4LowEnergyPolarizedCompton::BuildPhysicsTable(const G4ParticleDefinition& GammaType){
BuildZVec();
// Build microscopic cross section table and mean free path table
BuildCrossSectionTable();
// Build mean free path table for the Compton Scattering process
BuildMeanFreePathTable();
// build the scattering function table
BuildScatteringFunctionTable();
}
void G4LowEnergyPolarizedCompton::BuildCrossSectionTable(){
// BUILD THE CS TABLE FOR THE ELEMENTS MAPPED IN ZNUMVEC
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
void G4LowEnergyPolarizedCompton::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
theCrossSectionTable = new G4SecondLevel();
G4int dataNum = 2;
for(size_t tableInd = 0; tableInd < ZNumVec->size(); tableInd++){
G4int atomInd = (G4int) (*ZNumVec)[tableInd];
G4FirstLevel* oneAtomCS = util.BuildFirstLevelTables(atomInd, dataNum, "comp/ce-cs-");
// theCrossSectionTable->insert(oneAtomCS);
theCrossSectionTable->push_back(oneAtomCS);
}//end for on atoms
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&photon);
crossSectionHandler->Clear();
G4String crossSectionFile = "comp/ce-cs-";
crossSectionHandler->LoadData(crossSectionFile);
delete meanFreePathTable;
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
}
void G4LowEnergyPolarizedCompton::BuildScatteringFunctionTable(){
// BUILD THE SF TABLE FOR THE ELEMENTS MAPPED IN ZNUMVEC
if (theScatteringFunctionTable) {
delete theScatteringFunctionTable;
}
theScatteringFunctionTable = new G4SecondLevel();
G4int dataNum = 2;
for(size_t tableInd = 0; tableInd < ZNumVec->size(); tableInd++){
G4int atomInd = (G4int) (*ZNumVec)[tableInd];
G4FirstLevel* oneAtomSF = util.BuildFirstLevelTables(atomInd, dataNum, "comp/ce-sf-");
// theScatteringFunctionTable->insert(oneAtomSF);
theScatteringFunctionTable->push_back(oneAtomSF);
}//end for on atoms
}
void G4LowEnergyPolarizedCompton::BuildZVec(){
// vector mapping the elements in the material table
const G4MaterialTable* theMaterialTable=G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
ZNumVec = new G4DataVector();
for (G4int J=0 ; J < numOfMaterials; J++){
const G4Material* material= (*theMaterialTable)[J];
const G4ElementVector* theElementVector = material->GetElementVector();
const G4int numberOfElements = material->GetNumberOfElements() ;
for (G4int iel=0; iel<numberOfElements; iel++ ){
G4double Zel = (*theElementVector)(iel)->GetZ();
if(!(ZNumVec->contains(Zel))){
ZNumVec->push_back(Zel);
} else{
continue;
}
}
}
}
void G4LowEnergyPolarizedCompton::BuildMeanFreePathTable(){
// used log-log interpolation instead of linear interpolation to build the MFP
// as reported in the stepanek paper
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable; }
// material
G4double NumbOfMaterials = G4Material::GetNumberOfMaterials();
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
G4Material* material;
// MeanFreePath
G4double lowEdgeEnergy, value;
theMeanFreePathTable = new G4PhysicsTable(NumbOfMaterials);
G4PhysicsLogVector* ptrVector;
for ( G4int J = 0 ; J < NumbOfMaterials; J++ ) { // For each material
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(lowestEnergyLimit, highestEnergyLimit, numbBinTable);
material = (*theMaterialTable)(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* theAtomNumDensityVector = material->GetAtomicNumDensityVector();
for ( G4int i = 0 ; i < numbBinTable ; i++ ){
//For each energy
lowEdgeEnergy = ptrVector->GetLowEdgeEnergy(i);
const G4double bigPath = DBL_MAX;
G4double sigma = 0. ;
for ( size_t k=0 ; k < material->GetNumberOfElements() ; k++ ){
G4int atomIndex = (G4int) (*theElementVector)(k)->GetZ();
const G4FirstLevel* oneAtomCS
= (*theCrossSectionTable)[ZNumVec->index(atomIndex)];
G4double interCrsSec = util.DataLogInterpolation(lowEdgeEnergy,
(*(*oneAtomCS)[0]),
(*(*oneAtomCS)[1]))*barn;
sigma += theAtomNumDensityVector[k]*interCrsSec;
}
value = sigma<=0.0 ? bigPath : 1./sigma ;
ptrVector->PutValue( i , value ) ;
}
theMeanFreePathTable->insertAt( J , ptrVector );
}
}
G4Element* G4LowEnergyPolarizedCompton::SelectRandomAtom(const G4DynamicParticle* aDynamicGamma,
G4Material* aMaterial){
// METHOD BELOW FROM STANDARD E_M PROCESSES CODE MODIFIED TO USE
// LIVERMORE DATA (using log-log interpolation as reported in stepanek paper)
// select randomly 1 element within the material
G4double gammaEnergy = aDynamicGamma->GetKineticEnergy();
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
if (NumberOfElements == 1) return (*theElementVector)(0);
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
G4double partialSumSigma = 0.;
G4double rval = 0;
rval = G4UniformRand()/meanFreePath;
for ( G4int i=0 ; i < NumberOfElements ; i++ ){
G4double crossSection;
if (gammaEnergy < lowestEnergyLimit)
crossSection = 0. ;
else {
if (gammaEnergy > highestEnergyLimit) gammaEnergy = 0.99*highestEnergyLimit ;
G4int atomIndex = (G4int) (*theElementVector)(i)->GetZ();
const G4FirstLevel* oneAtomCS
= (*theCrossSectionTable)[ZNumVec->index(atomIndex)];
crossSection = util.DataLogInterpolation(gammaEnergy,
(*(*oneAtomCS)[0]),
(*(*oneAtomCS)[1]))*barn;
}
partialSumSigma += theAtomNumDensityVector[i] * crossSection;
if(rval <= partialSumSigma) return ((*theElementVector)(i));
}
return (*theElementVector)(0);
}
G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
@@ -312,261 +145,211 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
aParticleChange.Initialize(aTrack);
// Dynamic particle quantities
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
G4double gammaEnergy0 = aDynamicGamma->GetKineticEnergy();
G4ThreeVector gammaPolarization0 = aDynamicGamma->GetPolarization();
G4double polarisation = gammaPolarization0.mag();
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double gammaEnergy0 = incidentPhoton->GetKineticEnergy();
G4ThreeVector gammaPolarization0 = incidentPhoton->GetPolarization();
// Check magnitude of polarisation vector
G4bool isPolarised = false;
if (polarisation > 0. && polarisation <= 1.)
{
isPolarised = true;
}
// gammaPolarization0 = gammaPolarization0.unit(); //
// Temporary protection: a polarisation parallel to the
// direction causes problems; in that case apply the regular LowEnergyCompton algorithm
G4ThreeVector gammaDirection = aDynamicGamma->GetMomentumDirection();
// Protection: a polarisation parallel to the
// direction causes problems;
// in that case find a random polarization
G4ThreeVector gammaDirection = incidentPhoton->GetMomentumDirection();
G4double scalarproduct = gammaPolarization0.dot(gammaDirection);
G4double angle = gammaPolarization0.angle(gammaDirection);
if (angle == 0.)
if (scalarproduct != 0. || angle == 0)
{
isPolarised = false;
// isPolarised = false;
gammaPolarization0 = SetRandomPolarization(gammaDirection);
}
// End of temporary protection
// End of Protection
// G4double polarisation = gammaPolarization0.mag();
// Within energy limit?
if(gammaEnergy0 <= lowestEnergyLimit)
{
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit(gammaEnergy0);
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
if(gammaEnergy0 <= lowEnergyLimit)
{
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit(gammaEnergy0);
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
// Select randomly one element
G4Material* aMaterial = aTrack.GetMaterial();
G4Element* theElement = SelectRandomAtom(aDynamicGamma, aMaterial);
G4int elementZ = (G4int) theElement->GetZ();
G4double E0_m = gammaEnergy0 / electron_mass_c2 ;
G4ThreeVector gammaDirection0 = incidentPhoton->GetMomentumDirection();
G4ThreeVector gammaDirection0 = aDynamicGamma->GetMomentumDirection();
// 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
G4double epsilon, epsilonSq, onecost, sinThetaSqr, greject ;
G4double epsilon0 = 1./(1. + 2*E0_m);
G4double epsilon0Sq = epsilon0*epsilon0;
G4double alpha1 = - log(epsilon0);
G4double alpha2 = 0.5*(1.- epsilon0Sq);
G4double ScatteringFunction;
G4double x;
G4double wlGamma = h_Planck*c_light/gammaEnergy0;
G4double gammaEnergy1;
G4ThreeVector gammaDirection1;
// if (isPolarised) // apply Polarized Condition
// {
if (isPolarised)
do {
if ( alpha1/(alpha1+alpha2) > G4UniformRand() )
{
epsilon = exp(-alpha1*G4UniformRand());
epsilonSq = epsilon*epsilon;
}
else
{
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
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "sin(theta)**2 = "
<< sinThetaSqr
<< "; set to 1"
<< G4endl;
sinThetaSqr = 1.;
}
if (sinThetaSqr < 0.)
{
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "sin(theta)**2 = "
<< sinThetaSqr
<< "; set to 0"
<< G4endl;
sinThetaSqr = 0.;
}
// End protection
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);
} while(greject < G4UniformRand()*Z);
//(greject < G4UniformRand());
// ****************************************************
// Phi determination
// ****************************************************
G4double phi = SetPhi(epsilon,sinThetaSqr);
//
// scattered gamma angles. ( Z - axis along the parent gamma)
//
G4double cosTheta = 1. - onecost;
// Protection
if (cosTheta > 1.)
{
do {
if ( alpha1/(alpha1+alpha2) > G4UniformRand() )
{
epsilon = exp(-alpha1*G4UniformRand());
epsilonSq = epsilon*epsilon;
}
else
{
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
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "sin(theta)**2 = "
<< sinThetaSqr
<< "; set to 1"
<< G4endl;
sinThetaSqr = 1.;
}
if (sinThetaSqr < 0.)
{
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "sin(theta)**2 = "
<< sinThetaSqr
<< "; set to 0"
<< G4endl;
sinThetaSqr = 0.;
}
// End protection
greject = 1. - epsilon*sinThetaSqr/(1.+ epsilonSq);
} while (greject < G4UniformRand());
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "cosTheta = "
<< cosTheta
<< "; set to 1"
<< G4endl;
cosTheta = 1.;
}
if (cosTheta < -1.)
{
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "cosTheta = "
<< cosTheta
<< "; set to -1"
<< G4endl;
cosTheta = -1.;
}
// End protection
G4double sinTheta = sqrt (sinThetaSqr);
// Protection
if (sinTheta > 1.)
{
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "sinTheta = "
<< sinTheta
<< "; set to 1"
<< G4endl;
sinTheta = 1.;
}
if (sinTheta < -1.)
{
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "sinTheta = "
<< sinTheta
<< "; set to -1"
<< G4endl;
sinTheta = -1.;
}
// End protection
// ****************************************************
// Phi determination
// ****************************************************
G4double dirx = sinTheta*cos(phi);
G4double diry = sinTheta*sin(phi);
G4double dirz = cosTheta ;
//
// update G4VParticleChange for the scattered photon
//
gammaEnergy1 = epsilon*gammaEnergy0;
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
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "cosTheta = "
<< cosTheta
<< "; set to 1"
<< G4endl;
cosTheta = 1.;
}
if (cosTheta < -1.)
{
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "cosTheta = "
<< cosTheta
<< "; set to -1"
<< G4endl;
cosTheta = -1.;
}
// End protection
G4double sinTheta = sqrt (sinThetaSqr);
// Protection
if (sinTheta > 1.)
{
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "sinTheta = "
<< sinTheta
<< "; set to 1"
<< G4endl;
sinTheta = 1.;
}
if (sinTheta < -1.)
{
if (verboseLevel>0) G4cout
<< " -- Warning -- G4LowEnergyPolarizedCompton::PostStepDoIt "
<< "sinTheta = "
<< sinTheta
<< "; set to -1"
<< G4endl;
sinTheta = -1.;
}
// End protection
G4double dirx = sinTheta*cos(phi);
G4double diry = sinTheta*sin(phi);
G4double dirz = cosTheta ;
//
// update G4VParticleChange for the scattered gamma
//
gammaEnergy1 = epsilon*gammaEnergy0;
// New polarization
G4ThreeVector gammaPolarization1 = SetNewPolarization(epsilon,
sinThetaSqr,
phi,
cosTheta);
// Set new direction
//G4ThreeVector tmpDirection1( dirx,diry,dirz );
G4ParticleMomentum tmpDirection1( dirx,diry,dirz );
gammaDirection1 = tmpDirection1;
// Change reference frame.
SystemOfRefChange(gammaDirection0,gammaDirection1,
gammaPolarization0,gammaPolarization1);
if (gammaEnergy1 > 0.)
{
aParticleChange.SetEnergyChange( gammaEnergy1 ) ;
}
else
{
aParticleChange.SetEnergyChange(0.) ;
aParticleChange.SetStatusChange(fStopAndKill);
}
// New polarization
G4ThreeVector gammaPolarization1 = SetNewPolarization(epsilon,
sinThetaSqr,
phi,
cosTheta);
// Set new direction
//G4ThreeVector tmpDirection1( dirx,diry,dirz );
G4ParticleMomentum tmpDirection1( dirx,diry,dirz );
gammaDirection1 = tmpDirection1;
// Change reference frame.
SystemOfRefChange(gammaDirection0,gammaDirection1,
gammaPolarization0,gammaPolarization1);
if (gammaEnergy1 > 0.)
{
aParticleChange.SetEnergyChange( gammaEnergy1 ) ;
}
else
{
// Temporary, same algorithm as G4LowEnergyCompton
do{
if ( alpha1/(alpha1+alpha2) > G4UniformRand()){
epsilon = exp(-alpha1*G4UniformRand()); // pow(epsilon0,G4UniformRand())
epsilonSq = epsilon*epsilon;
}
else{
epsilonSq = epsilon0Sq + (1.- epsilon0Sq)*G4UniformRand();
epsilon = sqrt(epsilonSq);
}
onecost = (1.- epsilon)/(epsilon*E0_m);
sinThetaSqr = onecost*(2.-onecost);
x = sqrt(onecost/2)/(wlGamma/cm);
const G4FirstLevel* oneAtomSF
= (*theScatteringFunctionTable)[ZNumVec->index(elementZ)];
ScatteringFunction = util.DataLogInterpolation(x, (*(*oneAtomSF)[0]),
(*(*oneAtomSF)[1]));
greject = (1. - epsilon*sinThetaSqr/(1.+ epsilonSq))*ScatteringFunction;
} while(greject < G4UniformRand()*elementZ);
G4double cosTheta = 1. - onecost ;
G4double sinTheta = sqrt (sinThetaSqr);
G4double phi = twopi * G4UniformRand() ;
G4double dirx = sinTheta*cos(phi) , diry = sinTheta*sin(phi) , dirz = cosTheta ;
//
// update G4VParticleChange for the scattered gamma
//
G4ThreeVector tmpGammaDirection( dirx,diry,dirz );
gammaDirection1 = tmpGammaDirection;
gammaDirection1.rotateUz(gammaDirection0);
aParticleChange.SetMomentumChange( gammaDirection1 ) ;
gammaEnergy1 = epsilon*gammaEnergy0;
if (gammaEnergy1 > 0.)
{
aParticleChange.SetEnergyChange( gammaEnergy1 ) ;
}
else
{
aParticleChange.SetEnergyChange(0.) ;
aParticleChange.SetStatusChange(fStopAndKill);
}
{
aParticleChange.SetEnergyChange(0.) ;
aParticleChange.SetStatusChange(fStopAndKill);
}
//
@@ -575,37 +358,27 @@ G4VParticleChange* G4LowEnergyPolarizedCompton::PostStepDoIt(const G4Track& aTra
G4double ElecKineEnergy = gammaEnergy0 - gammaEnergy1 ;
if((G4EnergyLossTables::GetRange(G4Electron::Electron(),
ElecKineEnergy,aMaterial)>aStep.GetPostStepPoint()->GetSafety())
||
(ElecKineEnergy >
(G4Electron::Electron()->GetCutsInEnergy())[aMaterial->GetIndex()]))
// 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))
{
G4double ElecMomentum = sqrt(ElecKineEnergy*(ElecKineEnergy+2.*electron_mass_c2));
G4ThreeVector ElecDirection (
(gammaEnergy0*gammaDirection0 - gammaEnergy1*gammaDirection1)*(1./ElecMomentum) );
// create G4DynamicParticle object for the electron.
G4DynamicParticle* aElectron= new G4DynamicParticle (G4Electron::Electron(),
ElecDirection,
ElecKineEnergy) ;
aParticleChange.SetNumberOfSecondaries(1) ;
aParticleChange.AddSecondary( aElectron ) ;
aParticleChange.SetLocalEnergyDeposit (0.) ;
G4ThreeVector ElecDirection((gammaEnergy0 * gammaDirection0 -
gammaEnergy1 * gammaDirection1) * (1./ElecMomentum));
G4DynamicParticle* electron = new G4DynamicParticle (G4Electron::Electron(),ElecDirection,ElecKineEnergy) ;
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary(electron);
aParticleChange.SetLocalEnergyDeposit(0.);
}
else
{
aParticleChange.SetNumberOfSecondaries(0) ;
aParticleChange.SetLocalEnergyDeposit (ElecKineEnergy) ;
aParticleChange.SetNumberOfSecondaries(0);
aParticleChange.SetLocalEnergyDeposit(ElecKineEnergy);
}
// --- The end ---
// Reset NbOfInteractionLengthLeft and return aParticleChange
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep);
}
@@ -640,6 +413,44 @@ G4double G4LowEnergyPolarizedCompton::SetPhi(G4double energyRate,
}
G4ThreeVector G4LowEnergyPolarizedCompton::SetPerpendicularVector(G4ThreeVector& a)
{
G4double dx = a.x();
G4double dy = a.y();
G4double dz = a.z();
G4double x = dx < 0.0 ? -dx : dx;
G4double y = dy < 0.0 ? -dy : dy;
G4double z = dz < 0.0 ? -dz : dz;
if (x < y) {
return x < z ? G4ThreeVector(-dy,dx,0) : G4ThreeVector(0,-dz,dy);
}else{
return y < z ? G4ThreeVector(dz,0,-dx) : G4ThreeVector(-dy,dx,0);
}
}
G4ThreeVector G4LowEnergyPolarizedCompton::SetRandomPolarization(G4ThreeVector& direction0)
{
G4ThreeVector d0 = direction0.unit();
G4ThreeVector a1 = SetPerpendicularVector(d0); //different orthogonal
G4ThreeVector a0 = a1.unit(); // unit vector
G4double rand1 = G4UniformRand();
G4double angle = twopi*rand1; // random polar angle
G4ThreeVector b0 = d0.cross(a0); // cross product
G4ThreeVector c;
c.setX(cos(angle)*(a0.x())+sin(angle)*b0.x());
c.setY(cos(angle)*(a0.y())+sin(angle)*b0.y());
c.setZ(cos(angle)*(a0.z())+sin(angle)*b0.z());
G4ThreeVector c0 = c.unit();
return c0;
}
G4ThreeVector G4LowEnergyPolarizedCompton::SetNewPolarization(G4double epsilon,
G4double sinSqrTh,
G4double phi,
@@ -683,9 +494,9 @@ G4ThreeVector G4LowEnergyPolarizedCompton::SetNewPolarization(G4double epsilon,
G4double xParallel = normalisation*cosBeta;
G4double yParallel = -(sinSqrTh*cosPhi*sinPhi)*cosBeta/normalisation;
G4double zParallel = -(cosTheta*sinTheta*cosPhi)*cosBeta/normalisation;
G4double zParallel = -(costheta*sinTheta*cosPhi)*cosBeta/normalisation;
G4double xPerpendicular = 0.;
G4double yPerpendicular = (cosTheta)*sinBeta/normalisation;
G4double yPerpendicular = (costheta)*sinBeta/normalisation;
G4double zPerpendicular = -(sinTheta*sinPhi)*sinBeta/normalisation;
G4double xTotal = (xParallel + xPerpendicular);
@@ -737,7 +548,9 @@ void G4LowEnergyPolarizedCompton::SystemOfRefChange
}
// Added protection
G4double psi = 0;
if (sinPsi < 0.) psi = -pi/2.;
if (sinPsi > 0.) psi = pi/2.;
@@ -768,32 +581,19 @@ G4bool G4LowEnergyPolarizedCompton::IsApplicable(const G4ParticleDefinition& par
}
G4double G4LowEnergyPolarizedCompton::GetMeanFreePath(const G4Track& aTrack, G4double, G4ForceCondition*)
G4double G4LowEnergyPolarizedCompton::GetMeanFreePath(const G4Track& track,
G4double previousStepSize,
G4ForceCondition*)
{
// returns the gamma mean free path in GEANT4 internal units
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
G4double gammaEnergy = aDynamicGamma->GetKineticEnergy();
G4Material* aMaterial = aTrack.GetMaterial();
// G4bool isOutRange ;
if (gammaEnergy > highestEnergyLimit)
{
meanFreePath = DBL_MAX;
}
else if(gammaEnergy < lowestEnergyLimit)
{
meanFreePath = DBL_MIN;
}
else
{
meanFreePath = util.DataLogInterpolation(gammaEnergy,
aMaterial->GetIndex(),
theMeanFreePathTable);
}
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;
}
@@ -810,4 +610,3 @@ G4double G4LowEnergyPolarizedCompton::GetMeanFreePath(const G4Track& aTrack, G4d
@@ -20,363 +20,191 @@
// * statement, and all its terms. *
// ********************************************************************
//
// --------------------------------------------------------------------
//
// $Id: G4LowEnergyRayleigh.cc,v 1.22.2.2 2001/06/28 20:19:30 gunter Exp $
// GEANT4 tag $Name: $
// $Id: G4LowEnergyRayleigh.cc,v 1.28 2001/11/07 21:31:16 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
// CERN Geneva Switzerland
// Author: A. Forti
// Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// ------------ G4LowEnergyRayleigh physics process --------
// by Alessandra Forti, November 1998
// **************************************************************
// 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
// --------------------------------------------------------------
// 11.08.2001 MGP - Major revision according to a design iteration
// 06.10.2001 MGP - Added strategy to test range for secondary generation
//
// --------------------------------------------------------------------
// This Class Header
#include "G4LowEnergyRayleigh.hh"
// Collaborating Class Headers
#include "G4EnergyLossTables.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 "G4CompositeEMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4LogLogInterpolation.hh"
#include "G4CutsPerMaterialWarning.hh"
// constructor
G4LowEnergyRayleigh::G4LowEnergyRayleigh(const G4String& processName)
: G4VDiscreteProcess(processName),
theCrossSectionTable(0),
theFormFactorTable(0),
theMeanFreePathTable(0),
ZNumVec(0),
lowestEnergyLimit (250*eV), // initialization
highestEnergyLimit(100*GeV),
NumbBinTable(200),
MeanFreePath(0)
lowEnergyLimit(250*eV),
highEnergyLimit(100*GeV),
intrinsicLowEnergyLimit(10*eV),
intrinsicHighEnergyLimit(100*GeV)
{
if (verboseLevel>0) {
G4cout << GetProcessName() << " is created "<< G4endl;
G4cout << "lowestEnergy: " << lowestEnergyLimit/keV << "keV ";
G4cout << "highestEnergy: " << highestEnergyLimit/TeV << "TeV " << G4endl;
}
if (lowEnergyLimit < intrinsicLowEnergyLimit ||
highEnergyLimit > intrinsicHighEnergyLimit)
{
G4Exception("G4LowEnergyRayleigh::G4LowEnergyRayleigh - energy limit outside intrinsic process validity range");
}
crossSectionHandler = new G4CrossSectionHandler();
G4VDataSetAlgorithm* ffInterpolation = new G4LogLogInterpolation;
G4String formFactorFile = "rayl/re-ff-";
formFactorData = new G4CompositeEMDataSet(formFactorFile,ffInterpolation,1.,1.);
meanFreePathTable = 0;
if (verboseLevel > 0)
{
G4cout << GetProcessName() << " is created " << G4endl
<< "Energy range: "
<< lowEnergyLimit / keV << " keV - "
<< highEnergyLimit / GeV << " GeV"
<< G4endl;
}
}
// destructor
G4LowEnergyRayleigh::~G4LowEnergyRayleigh()
{
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
if(theFormFactorTable){
delete theFormFactorTable;
}
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
delete theMeanFreePathTable;
}
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
delete meanFreePathTable;
delete crossSectionHandler;
delete formFactorData;
}
// methods.............................................................................
void G4LowEnergyRayleigh::BuildPhysicsTable(const G4ParticleDefinition& GammaType){
BuildZVec();
// Build microscopic cross section tables for the Rayleigh process
BuildCrossSectionTable();
void G4LowEnergyRayleigh::BuildPhysicsTable(const G4ParticleDefinition& photon)
{
// Build mean free path table for the Rayleigh Scattering process
BuildMeanFreePathTable();
// build the scattering function table
BuildFormFactorTable();
}
// CONSTRUCT THE CS TABLE FOR THE ELEMENTS MAPPED IN ZNUMVEC USING EPDL97 DATA
void G4LowEnergyRayleigh::BuildCrossSectionTable(){
if (theCrossSectionTable) {
delete theCrossSectionTable;
}
G4CutsPerMaterialWarning warning;
warning.PrintWarning(&photon);
theCrossSectionTable = new G4SecondLevel();
G4int dataNum = 2;
for(size_t TableInd = 0; TableInd < ZNumVec->size(); TableInd++){
G4int AtomInd = (G4int) (*ZNumVec)[TableInd];
G4FirstLevel* oneAtomCS = util.BuildFirstLevelTables(AtomInd, dataNum, "rayl/re-cs-");
// theCrossSectionTable->insert(oneAtomCS);
theCrossSectionTable->push_back(oneAtomCS);
}//end for on atoms
}
// BUILD THE FF TABLE FOR THE ELEMENTS MAPPED IN ZNUMVEC USING EPDL97 DATA
void G4LowEnergyRayleigh::BuildFormFactorTable(){
if (theFormFactorTable) {
delete theFormFactorTable;
}
crossSectionHandler->Clear();
G4String crossSectionFile = "rayl/re-cs-";
crossSectionHandler->LoadData(crossSectionFile);
theFormFactorTable = new G4SecondLevel();
G4int dataNum = 2;
for(size_t TableInd = 0; TableInd < ZNumVec->size(); TableInd++){
G4int AtomInd = (G4int) (*ZNumVec)[TableInd];
G4FirstLevel* oneAtomFF = util.BuildFirstLevelTables(AtomInd, dataNum, "rayl/re-ff-");
// theFormFactorTable->insert(oneAtomFF);
theFormFactorTable->push_back(oneAtomFF);
}//end for on atoms
}
// vector mapping the elements in the material table
void G4LowEnergyRayleigh::BuildZVec(){
const G4MaterialTable* theMaterialTable=G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
if(ZNumVec){
ZNumVec->clear();
delete ZNumVec;
}
ZNumVec = new G4DataVector();
for (G4int J=0 ; J < numOfMaterials; J++){
const G4Material* material= (*theMaterialTable)[J];
const G4ElementVector* theElementVector = material->GetElementVector();
const G4int NumberOfElements = material->GetNumberOfElements() ;
for (G4int iel=0; iel<NumberOfElements; iel++ ){
G4double Zel = (*theElementVector)(iel)->GetZ();
if(ZNumVec->contains(Zel) == FALSE){
ZNumVec->push_back(Zel);
} else{
continue;
}
}
}
delete meanFreePathTable;
meanFreePathTable = crossSectionHandler->BuildMeanFreePathForMaterials();
}
G4VParticleChange* G4LowEnergyRayleigh::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep){
//
// The scattered gamma energy is sampled according to Form Factors
// multiplied by the Rayleigh distribution with a pure rejection technique.
// EGS4 W.R. Nelson et al. The EGS4 Code System. SLAC-Report-265 , December 1985
// Expression of the angular distribution as Rayleigh distribution and Form factors
// 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.
// 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).
G4VParticleChange* G4LowEnergyRayleigh::PostStepDoIt(const G4Track& aTrack,
const G4Step& aStep)
{
// The scattered gamma energy is sampled according to Form Factors
// multiplied by the Rayleigh distribution with a pure rejection technique.
// EGS4 W.R. Nelson et al. The EGS4 Code System. SLAC-Report-265 , December 1985
// Expression of the angular distribution as Rayleigh distribution and
// Form factors is taken from D. E. Cullen "A simple model of photon transport"
// NIM B Phys. 101 (1995). Method of sampling with form factors is different.
// 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).
aParticleChange.Initialize(aTrack);
// Dynamic particle quantities
const G4DynamicParticle* aDynamicGamma = aTrack.GetDynamicParticle();
G4double GammaEnergy0 = aDynamicGamma->GetKineticEnergy();
if(GammaEnergy0 <= lowestEnergyLimit){
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit(GammaEnergy0);
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
// G4double E0_m = GammaEnergy0 / electron_mass_c2 ;
G4ParticleMomentum GammaDirection0 = aDynamicGamma->GetMomentumDirection();
const G4DynamicParticle* incidentPhoton = aTrack.GetDynamicParticle();
G4double photonEnergy0 = incidentPhoton->GetKineticEnergy();
// Select randomly one element
G4Material* aMaterial = aTrack.GetMaterial();
// const G4int numOfElem = aMaterial->GetNumberOfElements();
G4Element* theElement = SelectRandomAtom(aDynamicGamma, aMaterial);
if (photonEnergy0 <= lowEnergyLimit)
{
aParticleChange.SetStatusChange(fStopAndKill);
aParticleChange.SetEnergyChange(0.);
aParticleChange.SetLocalEnergyDeposit(photonEnergy0);
return G4VDiscreteProcess::PostStepDoIt(aTrack,aStep);
}
// G4double e0m = photonEnergy0 / electron_mass_c2 ;
G4ParticleMomentum photonDirection0 = incidentPhoton->GetMomentumDirection();
// Select randomly one element in the current material
G4Material* material = aTrack.GetMaterial();
G4int Z = crossSectionHandler->SelectRandomAtom(material,photonEnergy0);
// sample the energy of the scattered gamma
// Sample the energy of the scattered photon
G4double wlGamma = h_Planck*c_light/GammaEnergy0;
G4int elementZ = (G4int) theElement->GetZ();
// G4double tableIndex = elementZ - 1;
G4double wlPhoton = h_Planck*c_light/photonEnergy0;
G4double Theta, DataFormFactor;
G4double cosTheta, greject;
G4double Theta_Half, x, SinThHalf, RandomFormFactor;
G4double gReject;
G4double randomFormFactor;
G4double cosTheta;
G4double sinTheta;
do{
Theta_Half = G4UniformRand()*pi/2;
SinThHalf = sin(Theta_Half);
x = SinThHalf/(wlGamma/cm);
const G4FirstLevel* oneAtomFF
= (*theFormFactorTable)[ZNumVec->index(elementZ)];
DataFormFactor = util.DataLogInterpolation(x, (*(*oneAtomFF)[0]),
(*(*oneAtomFF)[1]));
RandomFormFactor = G4UniformRand()*elementZ*elementZ;
Theta = Theta_Half*2;
cosTheta = cos(Theta);
sinTheta = sin(Theta);
G4double sqr_rayl = 1+cosTheta*cosTheta;
greject = sqr_rayl*DataFormFactor*DataFormFactor;
}while( greject < RandomFormFactor);
do
{
G4double thetaHalf = G4UniformRand() * pi / 2.;
G4double sinThetaHalf = sin(thetaHalf);
G4double x = sinThetaHalf / (wlPhoton/cm);
G4double dataFormFactor = formFactorData->FindValue(x,Z-1);
randomFormFactor = G4UniformRand() * Z * Z;
G4double theta = thetaHalf*2;
cosTheta = cos(theta);
sinTheta = sin(theta);
G4double sqrRayl = 1 + cosTheta * cosTheta;
gReject = sqrRayl * dataFormFactor * dataFormFactor;
} while( gReject < randomFormFactor);
// scattered gamma angles. ( Z - axis along the parent gamma)
G4double Phi = twopi * G4UniformRand() ;
G4double dirx = sinTheta*cos(Phi) , diry = sinTheta*sin(Phi) , dirz = 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 gamma
G4ThreeVector GammaDirection1(dirx, diry, dirz);
// Update G4VParticleChange for the scattered photon
G4ThreeVector photonDirection1(dirX, dirY, dirZ);
GammaDirection1.rotateUz(GammaDirection0);
aParticleChange.SetEnergyChange(GammaEnergy0);
aParticleChange.SetMomentumChange(GammaDirection1);
photonDirection1.rotateUz(photonDirection0);
aParticleChange.SetEnergyChange(photonEnergy0);
aParticleChange.SetMomentumChange(photonDirection1);
aParticleChange.SetNumberOfSecondaries(0);
#ifdef G4VERBOSE
if(verboseLevel > 15){
G4cout<<"LE Rayleigh PostStepDoIt"<<G4endl;
}
#endif
return G4VDiscreteProcess::PostStepDoIt( aTrack, aStep);
}
// used log-log interpolation instead of linear interpolation to build the MFP
void G4LowEnergyRayleigh::BuildMeanFreePathTable(){
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy(); delete theMeanFreePathTable; }
// material
G4double NumbOfMaterials = G4Material::GetNumberOfMaterials();
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
G4Material* material;
// MeanFreePath
G4double LowEdgeEnergy, Value;
theMeanFreePathTable = new G4PhysicsTable(NumbOfMaterials);
G4PhysicsLogVector* ptrVector;
for ( G4int J = 0 ; J < NumbOfMaterials; J++ ) { // For each material
//create physics vector then fill it ....
ptrVector = new G4PhysicsLogVector(lowestEnergyLimit, highestEnergyLimit, NumbBinTable);
material = (*theMaterialTable)(J);
const G4ElementVector* theElementVector = material->GetElementVector();
const G4double* theAtomNumDensityVector = material->GetAtomicNumDensityVector();
for ( G4int i = 0 ; i < NumbBinTable ; i++ ){
//For each energy
LowEdgeEnergy = ptrVector->GetLowEdgeEnergy(i);
const G4double BigPath= DBL_MAX;
G4double SIGMA = 0 ;
for ( size_t k=0 ; k < material->GetNumberOfElements() ; k++ ){
// For each element
G4double AtomIndex = (*theElementVector)(k)->GetZ();
const G4FirstLevel* oneAtomCS
= (*theCrossSectionTable)[ZNumVec->index(AtomIndex)];
G4double interCrsSec = util.DataLogInterpolation(LowEdgeEnergy,
(*(*oneAtomCS)[0]),
(*(*oneAtomCS)[1]))*barn;
SIGMA += theAtomNumDensityVector[k]*interCrsSec;
}
Value = SIGMA<=0.0 ? BigPath : 1./SIGMA ;
ptrVector->PutValue( i , Value ) ;
}
theMeanFreePathTable->insertAt( J , ptrVector ) ;
}
return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}
// METHOD BELOW FROM STANDARD E_M PROCESSES CODE MODIFIED TO USE
// LIVERMORE DATA (using log-log interpolation as reported in stepanek paper)
G4Element* G4LowEnergyRayleigh::SelectRandomAtom(const G4DynamicParticle* aDynamicGamma,
G4Material* aMaterial) {
// select randomly 1 element within the material
G4double GammaEnergy = aDynamicGamma->GetKineticEnergy();
const G4int NumberOfElements = aMaterial->GetNumberOfElements();
const G4ElementVector* theElementVector = aMaterial->GetElementVector();
if (NumberOfElements == 1) return (*theElementVector)(0);
const G4double* theAtomNumDensityVector = aMaterial->GetAtomicNumDensityVector();
G4double PartialSumSigma = 0.;
G4double rval = G4UniformRand()/MeanFreePath;
for ( G4int i=0 ; i < NumberOfElements ; i++ ){
G4double crossSection;
if (GammaEnergy < lowestEnergyLimit)
crossSection = 0. ;
else {
if (GammaEnergy > highestEnergyLimit) GammaEnergy = 0.99*highestEnergyLimit ;
G4double AtomIndex = (*theElementVector)(i)->GetZ();
const G4FirstLevel* oneAtomCS
= (*theCrossSectionTable)[ZNumVec->index(AtomIndex)];
crossSection = util.DataLogInterpolation(GammaEnergy,
(*(*oneAtomCS)[0]),
(*(*oneAtomCS)[1]))*barn;
}
PartialSumSigma += theAtomNumDensityVector[i] * crossSection;
if(rval <= PartialSumSigma) return ((*theElementVector)(i));
}
return (*theElementVector)(0);
G4bool G4LowEnergyRayleigh::IsApplicable(const G4ParticleDefinition& particle)
{
return ( &particle == G4Gamma::Gamma() );
}
G4double G4LowEnergyRayleigh::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;
}
@@ -1,244 +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: G4LowEnergyUtilities.cc,v 1.9.2.1 2001/06/28 19:11:51 gunter Exp $
// GEANT4 tag $Name: $
//
//
// --------------------------------------------------------------
// GEANT 4 class implementation file
//
// File name: G4LowEnergyUtilitie
//
// Author: A.Forti
//
// Creation date: 2 March 1999
//
// Modifications: 16.11.00 MG Pia Replaced HepString with G4String
// 24.04.01 V.Ivanchenko remove RogueWave
//
// --------------------------------------------------------------
// This Class Header
#include "G4LowEnergyUtilities.hh"
// Collaborating Class Headers
#include "G4Element.hh"
#include "G4DynamicParticle.hh"
#include "G4Material.hh"
#include "g4std/fstream"
#include "g4std/fstream"
#include "g4std/strstream"
G4LowEnergyUtilities::G4LowEnergyUtilities()
{}
G4LowEnergyUtilities::~G4LowEnergyUtilities()
{}
G4SecondLevel* G4LowEnergyUtilities::BuildSecondLevelTables(const G4int TableInd,
const G4int ParNum,
const char* prename){
G4String prenameStr(prename);
// HepString name, prenameStr(prename);
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
if(TableInd != 0){
ost << prenameStr << TableInd << ".dat";
// HepString Znum(TableInd);
// name = prenameStr + Znum + ".dat";
}
else{
ost << prenameStr << ".dat";
// name = prenameStr+ ".dat";
}
G4String name(nameChar);
char* path = getenv("G4LEDATA");
if(!path){
G4String excep = "Error!!! G4LEDATA (Low Energy Electromagnetic processes data directory) environment variable not set";
G4Exception(excep);
}
G4String path_string(path);
G4String dir_file = path_string + "/" + name;
G4std::ifstream file(dir_file);
G4std::filebuf* lsdp = file.rdbuf();
if(!lsdp->is_open()){
G4String excep = "Error!!!! data file: " + dir_file + " NOT found";
G4Exception(excep);
}
oneAtomTable* oneAtomPar = new oneAtomTable();
oneShellTable* oneShellPar = new oneShellTable();
for(G4int j = 0; j < ParNum; j++){
// oneShellPar->insertAt(j,new G4DataVector());
oneShellPar->push_back(new G4DataVector());
}
G4double a = 0;
G4int k = 1, s = 0;
do{
file>>a;
if(a == -1){
if(s == 0){
// oneAtomPar->insert(oneShellPar);
oneAtomPar->push_back(oneShellPar);
oneShellPar = new oneShellTable();
for(G4int j = 0; j < ParNum; j++){
// oneShellPar->insertAt(j,new G4DataVector());
oneShellPar->push_back(new G4DataVector());
}
}
s++;
if(s == ParNum){
s = 0;
}
}
else if(a == -2){
delete oneShellPar;
}
else{
if(k%ParNum != 0){
(*oneShellPar)[k-1]->push_back(a);
k++;
}
else if(k%ParNum == 0){
(*oneShellPar)[k-1]->push_back(a);
k = 1;
}
}
}while(a != -2); //end for on file
file.close();
return oneAtomPar;
}
G4FirstLevel* G4LowEnergyUtilities::BuildFirstLevelTables(const G4int TableInd,
const G4int ParNum,
const char* prename){
G4String prenameStr(prename);
// HepString name, prenameStr(prename);
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
if(TableInd != 0){
ost << prenameStr << TableInd << ".dat";
// HepString Znum(TableInd);
// name = prenameStr + Znum + ".dat";
}
else{
ost << prenameStr << ".dat";
// name = prenameStr+ ".dat";
}
G4String name(nameChar);
char* path = getenv("G4LEDATA");
if(!path){
G4String excep = "Error!!! G4LEDATA (Low Energy Electromagnetic processes data directory) environment variable not set";
G4Exception(excep);
}
G4String path_string(path);
G4String dir_file = path_string + "/" + name;
G4std::ifstream file(dir_file);
G4std::filebuf* lsdp = file.rdbuf();
if(!lsdp->is_open()){
G4String excep = "Error!!!! data file: " + dir_file + " NOT found";
G4Exception(excep);
}
G4FirstLevel* oneAtomPar = new G4FirstLevel();
for(G4int j = 0; j < ParNum; j++){
// oneAtomPar->insertAt(j,new G4DataVector());
oneAtomPar->push_back(new G4DataVector());
}
G4double a = 0;
G4int k = 1;
do{
file>>a;
if(a == -1 || a == -2){
}
else{
if(k%ParNum != 0){
(*oneAtomPar)[k-1]->push_back(a);
k++;
}
else if(k%ParNum == 0){
(*oneAtomPar)[k-1]->push_back(a);
k = 1;
}
}
}while(a != -2); //end for on file
file.close();
return oneAtomPar;
}
@@ -21,46 +21,31 @@
// ********************************************************************
//
//
// -------------------------------------------------------------------
// GEANT 4 class file
// $Id: G4RangeTest.cc,v 1.4 2001/11/07 20:47:30 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// CERN, Geneva, Switzerland
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// File name: G4ThirdLevel.hh
// History:
// -----------
// 05 Oct 2001 MGP Created
//
// Author: Alessandra Forti (Alessandra.Forti@cern.ch)
//
// Creation date: 1 Giugno 1999
//
// Modifications: 24.04.01 V.Ivanchenko remove RogueWave
//
// -------------------------------------------------------------------
#include "G4ThirdLevel.hh"
#include "G4RangeTest.hh"
#include "G4ParticleDefinition.hh"
#include "G4Material.hh"
#include "G4EnergyLossTables.hh"
G4bool G4RangeTest::Escape(const G4ParticleDefinition* particle,
const G4Material* material,
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);
G4ThirdLevel::~G4ThirdLevel(){
// this->clearAndDestroy();
this->clear();
return value;
}
G4bool G4ThirdLevel::operator == (const G4ThirdLevel& input) const{
// return( this->entries() == input.entries());
return( this->size() == input.size());
}
G4bool G4ThirdLevel::operator < (const G4ThirdLevel& input) const{
// return(this->entries() < input.entries());
return(this->size() < input.size());
}
@@ -0,0 +1,72 @@
//
// ********************************************************************
// * 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: G4SemiLogInterpolation.cc,v 1.3 2001/09/10 18:07:35 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// -----------
// 31 Jul 2001 MGP Created
//
// -------------------------------------------------------------------
#include "G4SemiLogInterpolation.hh"
// Constructor
G4SemiLogInterpolation::G4SemiLogInterpolation()
{ }
// Destructor
G4SemiLogInterpolation::~G4SemiLogInterpolation()
{ }
G4double G4SemiLogInterpolation::Calculate(G4double x, G4int bin,
const G4DataVector& points,
const G4DataVector& data) const
{
G4int nBins = data.size() - 1;
G4double value = 0.;
if (x < points[0])
{
value = 0.;
}
else if (bin < nBins)
{
G4double e1 = points[bin];
G4double e2 = points[bin+1];
G4double d1 = data[bin];
G4double d2 = data[bin+1];
value = (d1*log10(e2/x) + d2*log10(x/e1)) / log10(e2/e1);
}
else
{
value = data[nBins];
}
return value;
}
@@ -0,0 +1,245 @@
//
// ********************************************************************
// * 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: G4ShellData.cc,v 1.4 2001/09/26 21:19:23 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// -----------
// 31 Jul 2001 MGP Created
//
// -------------------------------------------------------------------
#include "G4ShellData.hh"
#include "G4DataVector.hh"
#include "g4std/fstream"
#include "g4std/strstream"
// Constructor
G4ShellData::G4ShellData(G4int minZ, G4int maxZ)
: zMin(minZ), zMax(maxZ)
{ }
// Destructor
G4ShellData::~G4ShellData()
{
G4std::map<G4int,G4DataVector*,G4std::less<G4int> >::iterator pos;
for (pos = idMap.begin(); pos != idMap.end(); pos++)
{
G4DataVector* dataSet = (*pos).second;
delete dataSet;
}
for (pos = bindingMap.begin(); pos != bindingMap.end(); pos++)
{
G4DataVector* dataSet = (*pos).second;
delete dataSet;
}
}
size_t G4ShellData::NumberOfShells(G4int Z) const
{
G4int z = Z - 1;
G4int n = 0;
if (Z>= zMin && Z <= zMax)
{
n = nShells[z];
}
return n;
}
const G4DataVector& G4ShellData::ShellIdVector(G4int Z) const
{
G4std::map<G4int,G4DataVector*,G4std::less<G4int> >::const_iterator pos;
if (Z < zMin || Z > zMax)
G4Exception("G4ShellData::ShellIdVector - Z outside boundaries");
pos = idMap.find(Z);
G4DataVector* dataSet = (*pos).second;
return *dataSet;
}
G4int G4ShellData::ShellId(G4int Z, G4int shellIndex) const
{
G4int n = -1;
if (Z >= zMin && Z <= zMax)
{
G4std::map<G4int,G4DataVector*,G4std::less<G4int> >::const_iterator pos;
pos = idMap.find(Z);
if (pos!= idMap.end())
{
G4DataVector dataSet = *((*pos).second);
G4int nData = dataSet.size();
if (shellIndex >= 0 && shellIndex < nData)
{
n = (G4int) dataSet[shellIndex];
}
}
}
return n;
}
G4double G4ShellData::BindingEnergy(G4int Z, G4int shellIndex) const
{
G4double value = 0.;
if (Z >= zMin && Z <= zMax)
{
G4std::map<G4int,G4DataVector*,G4std::less<G4int> >::const_iterator pos;
pos = bindingMap.find(Z);
if (pos!= bindingMap.end())
{
G4DataVector dataSet = *((*pos).second);
G4int nData = dataSet.size();
if (shellIndex >= 0 && shellIndex < nData)
{
value = dataSet[shellIndex];
}
}
}
return value;
}
void G4ShellData::PrintData() const
{
for (G4int Z = zMin; Z <= zMax; Z++)
{
G4cout << "---- Shell data for Z = "
<< Z
<< " ---- "
<< G4endl;
G4int nSh = nShells[Z-1];
G4std::map<G4int,G4DataVector*,G4std::less<G4int> >::const_iterator posId;
posId = idMap.find(Z);
G4DataVector* ids = (*posId).second;
G4std::map<G4int,G4DataVector*,G4std::less<G4int> >::const_iterator posE;
posE = bindingMap.find(Z);
G4DataVector* energies = (*posE).second;
for (G4int i=0; i<nSh; i++)
{
G4int id = (G4int) (*ids)[i];
G4double e = (*energies)[i] / MeV;
G4cout << i <<") Shell id: " << id
<< " - Binding energy = "
<< e << " MeV " << G4endl;
}
G4cout << "-------------------------------------------------"
<< G4endl;
}
}
void G4ShellData::LoadData(const G4String& fileName)
{
// Build the complete string identifying the file with the data set
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
ost << fileName << ".dat";
G4String name(nameChar);
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4EMDataSet - G4LEDATA environment variable not set";
G4Exception(excep);
}
G4String pathString(path);
G4String dirFile = pathString + name;
G4std::ifstream file(dirFile);
G4std::filebuf* lsdp = file.rdbuf();
if (! (lsdp->is_open()) )
{
G4String excep = "G4ShellData - data file: " + dirFile + " not found";
G4Exception(excep);
}
G4double a = 0;
G4int k = 1;
G4int s = 0;
G4int Z = 1;
G4DataVector* energies = new G4DataVector;
G4DataVector* ids = new G4DataVector;
do {
file >> a;
G4int nColumns = 2;
if (a == -1)
{
if (s == 0)
{
// End of a shell data set
idMap[Z] = ids;
bindingMap[Z] = energies;
G4int n = ids->size();
nShells.push_back(n);
// Start of new shell data set
ids = new G4DataVector;
energies = new G4DataVector;
Z++;
}
s++;
if (s == nColumns)
{
s = 0;
}
}
else if (a == -2)
{
// End of file; delete the empty vectors created when encountering the last -1 -1 row
delete energies;
delete ids;
//nComponents = components.size();
}
else
{
// 1st column is shell id
if(k%nColumns != 0)
{
ids->push_back(a);
k++;
}
else if (k%nColumns == 0)
{
// 2nd column is binding energy
G4double e = a * MeV;
energies->push_back(e);
k = 1;
}
}
} while (a != -2); // end of file
file.close();
}
@@ -0,0 +1,203 @@
//
// ********************************************************************
// * 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: G4ShellEMDataSet.cc,v 1.7 2001/10/11 14:10:40 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// -----------
// 1 Aug 2001 MGP Created
// 09.10.01 V.Ivanchenko Add case z=0
//
// -------------------------------------------------------------------
#include "G4ShellEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "g4std/fstream"
#include "g4std/strstream"
G4ShellEMDataSet::G4ShellEMDataSet(G4int Z,
const G4VDataSetAlgorithm* interpolation,
G4double unitE, G4double unitData)
:z(Z), algorithm(interpolation)
{
nComponents = 0;
unit1 = unitE;
unit2 = unitData;
}
G4ShellEMDataSet::G4ShellEMDataSet(G4int Z, const G4String& dataFile,
const G4VDataSetAlgorithm* interpolation,
G4double unitE, G4double unitData)
:z(Z), algorithm(interpolation)
{
nComponents = 0;
unit1 = unitE;
unit2 = unitData;
LoadData(dataFile);
}
G4ShellEMDataSet::~G4ShellEMDataSet()
{
for (size_t i=0; i<nComponents; i++)
{
delete components[i];
}
delete algorithm;
}
G4double G4ShellEMDataSet::FindValue(G4double e, G4int id) const
{
// Returns the sum over the shells corresponding to e
G4double value = 0.;
for (size_t i=0; i<nComponents; i++)
{
G4VEMDataSet* component = components[i];
G4double shellValue = component->FindValue(e);
value = value + shellValue;
}
return value;
}
void G4ShellEMDataSet::PrintData() const
{
G4cout << "The data set has " << nComponents << " components" << G4endl;
for (size_t i=0; i<nComponents; i++)
{
G4cout << "--- Component " << i << " ---" << G4endl;
G4VEMDataSet* component = components[i];
component->PrintData();
}
}
void G4ShellEMDataSet::LoadData(const G4String& fileName)
{
// Build the complete string identifying the file with the data set
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
if (z != 0) ost << fileName << z << ".dat";
else ost << fileName << ".dat";
G4String name(nameChar);
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4ShellEMDataSet - G4LEDATA environment variable not set";
G4Exception(excep);
}
G4String pathString(path);
G4String dirFile = pathString + "/" + name;
G4std::ifstream file(dirFile);
G4std::filebuf* lsdp = file.rdbuf();
if (! (lsdp->is_open()) )
{
G4String excep = "G4ShellEMDataSet - data file: " + dirFile + " not found";
G4Exception(excep);
}
G4double a = 0;
G4int k = 1;
G4int s = 0;
G4int shellIndex = 0;
G4DataVector* energies = new G4DataVector;
G4DataVector* data = new G4DataVector;
do {
file >> a;
G4int nColumns = 2;
if (a == -1)
{
if (s == 0)
{
// End of a shell data set
G4VDataSetAlgorithm* algo = algorithm->Clone();
G4VEMDataSet* dataSet = new G4EMDataSet(shellIndex,energies,data,algo);
AddComponent(dataSet);
// Start of new shell data set
energies = new G4DataVector;
data = new G4DataVector;
shellIndex++;
}
s++;
if (s == nColumns)
{
s = 0;
}
}
else if (a == -2)
{
// End of file; delete the empty vectors created when encountering the last -1 -1 row
delete energies;
delete data;
}
else
{
// 1st column is energy
if(k%nColumns != 0)
{
G4double e = a * unit1;
energies->push_back(e);
k++;
}
else if (k%nColumns == 0)
{
// 2nd column is cross section
G4double value = a * unit2;
data->push_back(value);
k = 1;
}
}
} while (a != -2); // end of file
file.close();
}
void G4ShellEMDataSet::AddComponent(G4VEMDataSet* component)
{
components.push_back(component);
nComponents++;
}
const G4DataVector& G4ShellEMDataSet::GetEnergies(G4int i) const
{
const G4VEMDataSet* component = GetComponent(i);
return (component->GetEnergies(i));
}
const G4DataVector& G4ShellEMDataSet::GetData(G4int i) const
{
const G4VEMDataSet* component = GetComponent(i);
return (component->GetData(i));
}
@@ -0,0 +1,127 @@
//
// ********************************************************************
// * 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: G4ShellVacancy.cc
// GEANT4 tag $Name:
//
// Author: Elena Guardincerri (Elena.Guardincerri@ge.infn.it)
//
// History:
// -----------
// 21 Sept 2001 Elena Guardincerri Created
//
// -------------------------------------------------------------------
#include "G4ShellVacancy.hh"
#include "G4Material.hh"
#include "G4Poisson.hh"
#include "G4VEMDataSet.hh"
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)
{
xsis.push_back(set);
}
G4std::vector<G4int> G4ShellVacancy::GenerateNumberOfIonisations(const G4Material*
material,
G4double
incidentEnergy,
G4double eLoss) const
{
G4std::vector<G4int> numberOfIonisations;
size_t numberOfElements = material->GetNumberOfElements();
for (size_t i = 0; i<numberOfElements; i++)
{
const G4Element* element = material->GetElement(i);
G4int averageNumberOfIonisations = AverageNOfIonisations(material,
element,
incidentEnergy,
eLoss);
G4int ionisations = (G4int) G4Poisson(averageNumberOfIonisations);
numberOfIonisations.push_back(ionisations);
}
return numberOfIonisations;
}
G4int G4ShellVacancy::AverageNOfIonisations(const G4Material* material,
const G4Element* element,
G4double energy,
G4double eLoss) const
{
G4int indexOfElementInMaterial= -1;
G4double averageEnergy = energy - eLoss/2.;
G4String elementName = element->GetName();
size_t numberOfElements = material->GetNumberOfElements();
for (size_t i = 0; i<numberOfElements; i++)
{
const G4Element* anElement = material->GetElement(i);
G4String itsName = anElement->GetName();
if (itsName==elementName)
{
indexOfElementInMaterial=i;
break;
}
//else
//{break;}
}
size_t indexInMaterialTable = material->GetIndex();
G4VEMDataSet* aSetOfXsi = xsis[indexInMaterialTable];
G4double aXsi = aSetOfXsi->FindValue(averageEnergy,indexOfElementInMaterial);
G4int averageNumberOfIonisations = (G4int)(aXsi * eLoss);
return averageNumberOfIonisations;
}
@@ -0,0 +1,653 @@
//
// ********************************************************************
// * 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: G4VCrossSectionHandler.cc,v 1.8 2001/10/10 16:46:06 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// -----------
// 1 Aug 2001 MGP Created
// 09.10.01 V.Ivanchenko Add FindValue with 3 parameters
// + NumberOfComponents
//
// -------------------------------------------------------------------
#include "G4VCrossSectionHandler.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4LogLogInterpolation.hh"
#include "G4VEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4CompositeEMDataSet.hh"
#include "G4ShellEMDataSet.hh"
#include "G4MaterialTable.hh"
#include "G4Material.hh"
#include "G4Element.hh"
#include "Randomize.hh"
#include "g4std/map"
#include "g4std/vector"
#include "g4std/fstream"
#include "g4std/strstream"
G4VCrossSectionHandler::G4VCrossSectionHandler()
{
crossSections = 0;
interpolation = 0;
Initialise();
ActiveElements();
}
G4VCrossSectionHandler::G4VCrossSectionHandler(G4VDataSetAlgorithm* algorithm,
G4double minE,
G4double maxE,
G4int bins,
G4double unitE,
G4double unitData,
G4int minZ,
G4int maxZ)
: interpolation(algorithm), eMin(minE), eMax(maxE), nBins(bins),
unit1(unitE), unit2(unitData), zMin(minZ), zMax(maxZ)
{
crossSections = 0;
ActiveElements();
}
G4VCrossSectionHandler::~G4VCrossSectionHandler()
{
delete interpolation;
interpolation = 0;
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::iterator pos;
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
// the syntax pos->second
// G4VEMDataSet* dataSet = pos->second;
G4VEMDataSet* dataSet = (*pos).second;
delete dataSet;
}
if (crossSections != 0)
{
size_t n = crossSections->size();
for (size_t i=0; i<n; i++)
{
delete (*crossSections)[i];
}
delete crossSections;
crossSections = 0;
}
}
void G4VCrossSectionHandler::Initialise(G4VDataSetAlgorithm* algorithm,
G4double minE, G4double maxE,
G4int numberOfBins,
G4double unitE, G4double unitData,
G4int minZ, G4int maxZ)
{
if (algorithm != 0)
{
delete interpolation;
interpolation = algorithm;
}
else
{
interpolation = CreateInterpolation();
}
eMin = minE;
eMax = maxE;
nBins = numberOfBins;
unit1 = unitE;
unit2 = unitData;
zMin = minZ;
zMax = maxZ;
}
void G4VCrossSectionHandler::PrintData() const
{
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
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
// the syntax pos->first or pos->second
// G4int z = pos->first;
// G4VEMDataSet* dataSet = pos->second;
G4int z = (*pos).first;
G4VEMDataSet* dataSet = (*pos).second;
G4cout << "---- Data set for Z = "
<< z
<< G4endl;
dataSet->PrintData();
G4cout << "--------------------------------------------------" << G4endl;
}
}
void G4VCrossSectionHandler::LoadData(const G4String& fileName)
{
size_t nZ = activeZ.size();
for (size_t i=0; i<nZ; i++)
{
G4int Z = (G4int) activeZ[i];
// Build the complete string identifying the file with the data set
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
ost << fileName << Z << ".dat";
G4String name(nameChar);
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4VCrossSectionHandler - G4LEDATA environment variable not set";
G4Exception(excep);
}
G4String pathString(path);
G4String dirFile = pathString + "/" + name;
G4std::ifstream file(dirFile);
G4std::filebuf* lsdp = file.rdbuf();
if (! (lsdp->is_open()) )
{
G4String excep = "G4VCrossSectionHandler - data file: " + dirFile + " not found";
G4Exception(excep);
}
G4double a = 0;
G4int k = 1;
G4DataVector* energies = new G4DataVector;
G4DataVector* data = new G4DataVector;
do
{
file >> a;
G4int nColumns = 2;
// The file is organized into two columns:
// 1st column is the energy
// 2nd column is the corresponding value
// The file terminates with the pattern: -1 -1
// -2 -2
if (a == -1 || a == -2)
{
}
else
{
if (k%nColumns != 0)
{
G4double e = a * unit1;
energies->push_back(e);
k++;
}
else if (k%nColumns == 0)
{
G4double value = a * unit2;
data->push_back(value);
k = 1;
}
}
} while (a != -2); // end of file
file.close();
G4VDataSetAlgorithm* algo = interpolation->Clone();
G4VEMDataSet* dataSet = new G4EMDataSet(Z,energies,data,algo);
dataMap[Z] = dataSet;
}
}
void G4VCrossSectionHandler::LoadShellData(const G4String& fileName)
{
size_t nZ = activeZ.size();
for (size_t i=0; i<nZ; i++)
{
G4int Z = (G4int) activeZ[i];
// Build the complete string identifying the file with the data set
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
ost << fileName << Z << ".dat";
G4String name(nameChar);
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4VCrossSectionHandler - G4LEDATA environment variable not set";
G4Exception(excep);
}
G4String pathString(path);
G4String dirFile = pathString + "/" + name;
G4std::ifstream file(dirFile);
G4std::filebuf* lsdp = file.rdbuf();
if (! (lsdp->is_open()) )
{
G4String excep = "G4VCrossSectionHandler - data file: " + dirFile + " not found";
G4Exception(excep);
}
G4double a = 0;
G4int k = 1;
G4DataVector* energies = new G4DataVector;
G4DataVector* data = new G4DataVector;
do
{
file >> a;
G4int nColumns = 2;
// The file is organized into two columns:
// 1st column is the energy
// 2nd column is the corresponding value
// The file terminates with the pattern: -1 -1
// -2 -2
if (a == -1 || a == -2)
{
}
else
{
if (k%nColumns != 0)
{
G4double e = a * unit1;
energies->push_back(e);
k++;
}
else if (k%nColumns == 0)
{
G4double value = a * unit2;
data->push_back(value);
k = 1;
}
}
} while (a != -2); // end of file
file.close();
G4VDataSetAlgorithm* algo = interpolation->Clone();
G4VEMDataSet* dataSet = new G4ShellEMDataSet(Z,fileName,algo);
dataMap[Z] = dataSet;
}
}
void G4VCrossSectionHandler::Clear()
{
// Reset the map of data sets: remove the data sets from the map
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::iterator pos;
if(! dataMap.empty())
{
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
// the syntax pos->first or pos->second
// G4VEMDataSet* dataSet = pos->second;
G4VEMDataSet* dataSet = (*pos).second;
delete dataSet;
dataSet = 0;
G4int i = (*pos).first;
dataMap[i] = 0;
}
dataMap.clear();
}
activeZ.clear();
ActiveElements();
}
G4double G4VCrossSectionHandler::FindValue(G4int Z, G4double energy) const
{
G4double value = 0.;
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
pos = dataMap.find(Z);
if (pos!= dataMap.end())
{
// 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
// G4VEMDataSet* dataSet = pos->second;
G4VEMDataSet* dataSet = (*pos).second;
value = dataSet->FindValue(energy);
}
else
{
G4cout << "WARNING: G4VCrossSectionHandler::FindValue did not find Z = "
<< Z << G4endl;
}
return value;
}
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())
{
// 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
// G4VEMDataSet* dataSet = pos->second;
G4VEMDataSet* dataSet = (*pos).second;
if (shellIndex >= 0)
{
G4int nComponents = dataSet->NumberOfComponents();
if(shellIndex < nComponents)
// - MGP - Why doesn't it use G4VEMDataSet::FindValue directly?
value = dataSet->GetComponent(shellIndex)->FindValue(energy);
else
{
G4cout << "WARNING: G4VCrossSectionHandler::FindValue did not find"
<< " shellIndex= " << shellIndex
<< " for Z= "
<< Z << G4endl;
}
} else {
value = dataSet->FindValue(energy);
}
}
else
{
G4cout << "WARNING: G4VCrossSectionHandler::FindValue did not find Z = "
<< Z << G4endl;
}
return value;
}
G4double G4VCrossSectionHandler::ValueForMaterial(const G4Material* material,
G4double energy) const
{
G4double value = 0.;
const G4ElementVector* elementVector = material->GetElementVector();
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];
value += nAtomsVol * elementValue;
}
return value;
}
G4VEMDataSet* G4VCrossSectionHandler::BuildMeanFreePathForMaterials(
const G4DataVector* energyCuts)
{
// Builds a CompositeDataSet containing the mean free path for each material
// in the material table
G4DataVector energyVector;
G4double dBin = log10(eMax/eMin) / nBins;
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
if (crossSections != 0)
{ // Reset the list of cross sections
G4std::vector<G4VEMDataSet*>::iterator mat;
if (! crossSections->empty())
{
for (mat = crossSections->begin(); mat!= crossSections->end(); ++mat)
{
G4VEMDataSet* set = *mat;
delete set;
set = 0;
}
crossSections->clear();
delete crossSections;
crossSections = 0;
}
}
crossSections = BuildCrossSectionsForMaterials(energyVector,energyCuts);
if (crossSections == 0)
G4Exception("G4VCrossSectionHandler::BuildMeanFreePathForMaterials, crossSections = 0");
G4VDataSetAlgorithm* algo = CreateInterpolation();
G4VEMDataSet* materialSet = new G4CompositeEMDataSet(algo);
G4DataVector* energies;
G4DataVector* data;
size_t nMaterials = G4Material::GetNumberOfMaterials();
for (size_t m=0; m<nMaterials; m++)
{
energies = new G4DataVector;
data = new G4DataVector;
for (G4int bin=0; bin<nBins; bin++)
{
G4double energy = energyVector[bin];
energies->push_back(energy);
G4VEMDataSet* matCrossSet = (*crossSections)[m];
G4double materialCrossSection = matCrossSet->FindValue(energy);
if (materialCrossSection > 0.)
{
data->push_back(1./materialCrossSection);
}
else
{
data->push_back(DBL_MAX);
}
}
G4VDataSetAlgorithm* algo = CreateInterpolation();
G4VEMDataSet* dataSet = new G4EMDataSet(m,energies,data,algo,1.,1.);
materialSet->AddComponent(dataSet);
}
return materialSet;
}
G4int G4VCrossSectionHandler::SelectRandomAtom(const G4Material* material, G4double e) const
{
// Select randomly an element within the material, according to the weight
// determined by the cross sections in the data set
G4int nElements = material->GetNumberOfElements();
const G4ElementVector* elementVector = material->GetElementVector();
// Special case: the material consists of one element
if (nElements == 1)
{
G4int Z = (G4int) (*elementVector)[0]->GetZ();
return Z;
}
// Composite material
G4double materialCrossSection0 = ValueForMaterial(material,e);
// size_t materialIndex = material->GetIndex();
// G4VEMDataSet* materialSet = crossSections[materialIndex];
// G4double materialCrossSection = materialSet->FindValue(e);
G4double random = G4UniformRand() * materialCrossSection0;
const G4double* nAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4double partialSumSigma = 0.;
for ( G4int i=0 ; i < nElements ; i++ )
{
G4int Z = (G4int) (*elementVector)[i]->GetZ();
G4double crossSection = FindValue(Z,e);
partialSumSigma += nAtomsPerVolume[i] * crossSection;
if (random <= partialSumSigma) return Z;
}
// It should never get here
return 0;
}
const G4Element* G4VCrossSectionHandler::SelectRandomElement(const G4Material* material,
G4double e) const
{
// Select randomly an element within the material, according to the weight determined
// by the cross sections in the data set
G4Element* nullElement = 0;
G4int nElements = material->GetNumberOfElements();
const G4ElementVector* elementVector = material->GetElementVector();
// Special case: the material consists of one element
if (nElements == 1)
{
G4Element* element = (*elementVector)[0];
return element;
}
else
{
// Composite material
G4double materialCrossSection0 = ValueForMaterial(material,e);
// size_t materialIndex = material->GetIndex();
// G4VEMDataSet* materialSet = crossSections[materialIndex];
// G4double materialCrossSection = materialSet->FindValue(e);
G4double random = G4UniformRand() * materialCrossSection0;
const G4double* nAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
G4double partialSumSigma = 0.;
for ( G4int i=0 ; i < nElements ; i++ )
{
G4Element* element = (*elementVector)[i];
G4int Z = (G4int) element->GetZ();
G4double crossSection = FindValue(Z,e);
partialSumSigma += nAtomsPerVolume[i] * crossSection;
if (random <= partialSumSigma) return element;
}
}
// It should never end up here
G4cout << "G4VCrossSectionHandler::SelectRandomElement - no element found" << G4endl;
return nullElement;
}
G4int G4VCrossSectionHandler::SelectRandomShell(G4int Z, G4double e) const
{
// Select randomly a shell, according to the weight determined by the cross sections
// in the data set
// Note for later improvement: it would be useful to add a cache mechanism for already
// used shells to improve performance
G4int shell = 0;
G4double totCrossSection = FindValue(Z,e);
G4double random = G4UniformRand() * totCrossSection;
G4double partialSum = 0.;
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 syntax pos->first or pos->second
// if (pos != dataMap.end()) dataSet = pos->second;
if (pos != dataMap.end()) dataSet = (*pos).second;
size_t nShells = dataSet->NumberOfComponents();
for (size_t i=0; i<nShells; i++)
{
const G4VEMDataSet* shellDataSet = dataSet->GetComponent(i);
if (shellDataSet != 0)
{
G4double value = shellDataSet->FindValue(e);
partialSum += value;
if (random <= partialSum) return i;
}
}
// It should never get here
return shell;
}
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 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)
{
activeZ.push_back(Z);
}
}
}
}
G4VDataSetAlgorithm* G4VCrossSectionHandler::CreateInterpolation()
{
G4VDataSetAlgorithm* algorithm = new G4LogLogInterpolation;
return algorithm;
}
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())
{
G4VEMDataSet* dataSet = (*pos).second;
n = dataSet->NumberOfComponents();
}
else
{
G4cout << "WARNING: G4VCrossSectionHandler::NumberOfComponents did not "
<< "find Z = "
<< Z << G4endl;
}
return n;
}
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4VeLowEnergyLoss.cc,v 1.12.2.2 2001/06/28 20:19:31 gunter Exp $
// GEANT4 tag $Name: $
// $Id: G4VeLowEnergyLoss.cc,v 1.17 2001/11/23 11:45:29 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
//
// --------------------------------------------------------------
@@ -37,6 +37,7 @@
// 22/11/00 minor fix in fluctuations V.Ivanchenko
// 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
//
// --------------------------------------------------------------
@@ -95,16 +96,33 @@ G4VeLowEnergyLoss::G4VeLowEnergyLoss(G4VeLowEnergyLoss& right)
{
}
//
void G4VeLowEnergyLoss::SetRndmStep(G4bool value)
{
rndmStepFlag = value;
}
void G4VeLowEnergyLoss::SetEnlossFluc(G4bool value)
{
EnlossFlucFlag = value;
}
void G4VeLowEnergyLoss::SetStepFunction (G4double c1, G4double c2)
{
dRoverRange = c1;
finalRange = c2;
c1lim=dRoverRange;
c2lim=2.*(1-dRoverRange)*finalRange;
c3lim=-(1.-dRoverRange)*finalRange*finalRange;
}
G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeTable(
G4PhysicsTable* theDEDXTable,G4PhysicsTable* theRangeTable,
G4double lowestKineticEnergy,G4double highestKineticEnergy,G4int TotBin)
G4double lowestKineticEnergy,G4double highestKineticEnergy,
G4int TotBin)
// Build range table from the energy loss table
{
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(theRangeTable)
{ theRangeTable->clearAndDestroy();
@@ -236,9 +254,8 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildLabTimeTable(G4PhysicsTable* theDEDXTabl
G4double highestKineticEnergy,G4int TotBin)
{
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(theLabTimeTable)
{ theLabTimeTable->clearAndDestroy();
@@ -270,9 +287,8 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildProperTimeTable(G4PhysicsTable* theDEDXT
G4double highestKineticEnergy,G4int TotBin)
{
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(theProperTimeTable)
{ theProperTimeTable->clearAndDestroy();
@@ -312,7 +328,6 @@ void G4VeLowEnergyLoss::BuildLabTimeVector(G4PhysicsTable* theDEDXTable,
LowEdgeEnergy,tau,Value ;
G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
//const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
// low energy part first...
losslim = physicsVector->GetValue(tlim,isOut);
@@ -498,9 +513,8 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildInverseRangeTable(G4PhysicsTable* theRan
{
G4double SmallestRange,BiggestRange ;
G4bool isOut ;
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(theInverseRangeTable)
{ theInverseRangeTable->clearAndDestroy();
@@ -594,9 +608,8 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeCoeffATable(G4PhysicsTable* theRang
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "A"
{
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(theRangeCoeffATable)
{ theRangeCoeffATable->clearAndDestroy();
@@ -657,9 +670,8 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeCoeffBTable(G4PhysicsTable* theRang
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "B"
{
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(theRangeCoeffBTable)
{ theRangeCoeffBTable->clearAndDestroy();
@@ -719,9 +731,8 @@ G4PhysicsTable* G4VeLowEnergyLoss::BuildRangeCoeffCTable(G4PhysicsTable* theRang
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "C"
{
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(theRangeCoeffCTable)
{ theRangeCoeffCTable->clearAndDestroy();
@@ -806,7 +817,7 @@ G4double G4VeLowEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
ipotLogFluct = aMaterial->GetIonisation()->GetLogMeanExcEnergy();
}
G4double threshold,w1,w2,C,
beta2,suma,e0,loss,lossc ,w;
beta2,suma,e0,loss,lossc,w;
G4double a1,a2,a3;
G4int p1,p2,p3;
G4int nb;
@@ -823,7 +834,7 @@ G4double G4VeLowEnergyLoss::GetLossWithFluct(const G4DynamicParticle* aParticle,
// G4cout << "MGP -- Fluc Tkin " << Tkin/keV << " keV " << " MeanLoss = " << MeanLoss/keV << G4endl;
threshold =((*G4Electron::Electron()).GetCutsInEnergy())[imat];
threshold = G4Electron::Electron()->GetEnergyThreshold(aMaterial);
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);
@@ -0,0 +1,72 @@
//
// ********************************************************************
// * 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: G4VhShellCrossSection
//
// Author: V.Ivanchenko (Vladimir.Ivanchenko@cern.ch)
//
// History:
// -----------
// 20 Oct 2001 V.Ivanchenko 1st implementation
// 24 Oct 2001 MGP Minor clean-up
// 29 Oct 2001 VI Add delta energy
//
// -------------------------------------------------------------------
#include "G4VhShellCrossSection.hh"
#include "Randomize.hh"
G4VhShellCrossSection::G4VhShellCrossSection()
{ }
G4VhShellCrossSection::~G4VhShellCrossSection()
{ }
G4int G4VhShellCrossSection::SelectRandomShell(G4int Z,
G4double incidentEnergy,
G4double mass,
G4double deltaEnergy) const
{
G4std::vector<G4double> p = Probabilities(Z,incidentEnergy,mass,deltaEnergy);
G4int shell = 0;
size_t nShells = p.size();
G4double q = G4UniformRand();
for (size_t i=0; i<nShells; i++) {
if (p[i] >= q) {
shell = i;
break;
}
q -= p[i];
}
return shell;
}
@@ -0,0 +1,346 @@
//
// ********************************************************************
// * 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: G4eBremsstrahlungSpectrum.cc,v 1.5 2001/11/30 00:52:52 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4eBremsstrahlungSpectrum
//
// Author: V.Ivanchenko (Vladimir.Ivanchenko@cern.ch)
//
// Creation date: 29 September 2001
//
// 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
//
// -------------------------------------------------------------------
#include "G4eBremsstrahlungSpectrum.hh"
#include "G4BremsstrahlungParameters.hh"
#include "Randomize.hh"
G4eBremsstrahlungSpectrum::G4eBremsstrahlungSpectrum():
G4VEnergySpectrum(),
lowestE(0.1*eV),
length(15)
{
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);
}
verbose = 0;
}
G4eBremsstrahlungSpectrum::~G4eBremsstrahlungSpectrum()
{
delete theBRparam;
}
G4double G4eBremsstrahlungSpectrum::Probability(G4int Z,
G4double tmin,
G4double tmax,
G4double e,
G4int,
const G4ParticleDefinition*) const
{
G4double tm = G4std::min(tmax, e);
G4double t0 = G4std::max(tmin, lowestE);
if(t0 >= tm) return 0.0;
t0 /= e;
tm /= e;
G4double z = lowestE/e;
G4double x, y;
// Below 10 MeV EEDL data base spectrum
if(e < 1000000.*MeV) {
G4int iMax = 16;
G4DataVector p;
// Access parameters
for (G4int i=0; i<iMax; i++) {
p.push_back(theBRparam->Parameter(i, Z, e));
}
x = IntSpectrum(t0, tm, p);
y = IntSpectrum(z, 1.0, p);
p.clear();
// Above Bethe-Heitler formula
} else {
x = log(tm/t0) - tm + t0 + 0.375*(tm*tm - t0*t0);
y = log(1./z) - 1.0 + z + 0.375*(1. - z*z);
}
if(1 < verbose) {
G4cout << "tcut(MeV)= " << tmin/MeV
<< "; tMax(MeV)= " << tmax/MeV
<< "; t0= " << t0
<< "; tm= " << tm
<< "; xp[0]= " << xp[0]
<< "; z= " << z
<< "; val= " << x
<< "; nor= " << y
<< G4endl;
}
if(y > 0.0) x /= y;
else x = 0.0;
if(x < 0.0) x = 0.0;
return x;
}
G4double G4eBremsstrahlungSpectrum::AverageEnergy(G4int Z,
G4double tmin,
G4double tmax,
G4double e,
G4int,
const G4ParticleDefinition*) const
{
G4double tm = G4std::min(tmax, e);
G4double t0 = G4std::max(tmin, lowestE);
if(t0 >= tm) return 0.0;
G4double c = sqrt(theBRparam->ParameterC(Z));
t0 /= e;
tm /= e;
G4double z = lowestE/e;
G4double x, y, f;
// Below 10 MeV EEDL data base spectrum
if(e < 1000000.*MeV) {
G4int iMax = 16;
G4DataVector p;
// Access parameters
for (G4int i=0; i<iMax; i++) {
p.push_back(theBRparam->Parameter(i, Z, e));
}
x = AverageValue(t0, tm, p);
y = IntSpectrum(z, 1.0, p);
f = Function(z, p);
p.clear();
// Above Bethe-Heitler formula
} else {
x = tm - t0 - 0.5*(tm*tm - t0*t0) + 0.25*(tm*tm*tm - t0*t0*t0);
y = log(1./z) - 1.0 + z + 0.375*(1. - z*z);
f = 1. - x + 0.75*x*x;
}
x += 0.5*f*z*(z - c*atan(z/c));
x *= e;
if(1 < verbose) {
G4cout << "tcut(MeV)= " << tmin/MeV
<< "; tMax(MeV)= " << tmax/MeV
<< "; e(MeV)= " << e/MeV
<< "; t0= " << t0
<< "; tm= " << tm
<< "; y= " << y
<< "; x= " << x
<< G4endl;
}
if(y > 0.0) x /= y;
else x = 0.0;
if(x < 0.0) x = 0.0;
return x;
}
G4double G4eBremsstrahlungSpectrum::SampleEnergy(G4int Z,
G4double tmin,
G4double tmax,
G4double e,
G4int,
const G4ParticleDefinition*) const
{
G4double tm = G4std::min(tmax, e);
G4double t0 = G4std::max(tmin, lowestE);
if(t0 >= tm) return 0.0;
t0 /= e;
tm /= e;
G4int iMax = 16;
G4DataVector p;
G4double amaj;
// Below 10 MeV EEDL data base spectrum
if(e < 10000000.*MeV) {
for (G4int i=0; i<iMax; i++) {
p.push_back(theBRparam->Parameter(i, Z, e));
}
amaj = G4std::max(p[15], 1. - (p[1] - p[0])/9.);
} else {
amaj = 1.0;
}
G4double amax = log(tm);
G4double amin = log(t0);
G4double tgam, q, fun;
do {
G4double x = amin + G4UniformRand()*(amax - amin);
tgam = exp(x);
if(e < 10.*MeV) {
fun = Function(tgam, p);
} else {
fun = 1. - tgam + 0.75*tgam*tgam;
}
if(fun > amaj) {
G4cout << "WARNING in G4eBremsstrahlungSpectrum::SampleEnergy:"
<< " Majoranta " << amaj
<< " < " << fun
<< G4endl;
}
q = amaj * G4UniformRand();
} while (q > fun);
tgam *= e;
p.clear();
return tgam;
}
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 z1 = x1;
G4double z2 = x2;
G4double sum = 0.0;
if(x1 < x2) {
G4double k = (p[1] - p[0])/0.09;
sum += (1. - k*xp[0])*log(x2/x1) + k*(x2 - x1);
}
for (size_t i=0; i<length-1; i++) {
x1 = G4std::max(xMin, xp[i]);
x2 = G4std::min(xMax, xp[i+1]);
if(x1 < x2) {
z1 = p[i];
z2 = p[i+1];
sum += z2 - z1 + log(x2/x1)*(z1*x2 - z2*x1)/(x2 - x1);
}
}
if(sum < 0.0) sum = 0.0;
return sum;
}
G4double G4eBremsstrahlungSpectrum::AverageValue(G4double xMin,
G4double xMax,
const G4DataVector& p) const
{
G4double x1 = G4std::min(xMin, xp[0]);
G4double x2 = G4std::min(xMax, xp[0]);
G4double z1 = x1;
G4double z2 = x2;
G4double sum = 0.0;
if(x1 < x2) {
G4double k = (p[1] - p[0])/0.09;
sum += (z2 - z1)*(1. - k*xp[0]);
z1 *= x1;
z2 *= x2;
sum += 0.5*k*(z1 - z2);
}
for (size_t i=0; i<length-1; i++) {
x1 = G4std::max(xMin, xp[i]);
x2 = G4std::min(xMax, xp[i+1]);
if(x1 < x2) {
z1 = p[i];
z2 = p[i+1];
sum += 0.5*(z2 - z1)*(x2 + x1) + z1*x2 - z2*x1;
}
}
if(sum < 0.0) sum = 0.0;
return sum;
}
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;
} else {
for (size_t i=0; i<length-1; i++) {
if(x <= xp[i+1] && x >= xp[i]) {
f = p[i] + (p[i+1] - p[i])*(x - xp[i])/(xp[i+1] - xp[i]);
break;
}
}
}
if(f < 0.0) f = 0.0;
return f;
}
void G4eBremsstrahlungSpectrum::PrintData() const
{ theBRparam->PrintData(); }
@@ -0,0 +1,140 @@
//
// ********************************************************************
// * 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: G4eIonisationCrossSectionHandler.cc,v 1.6 2001/11/29 19:01:37 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4eIonisationCrossSectionHandler
//
// Author: V.Ivanchenko (Vladimir.Ivanchenko@cern.ch)
//
// Creation date: 25 Sept 2001
//
// Modifications:
// 10 Oct 2001 M.G. Pia Revision to improve code quality and consistency with design
//
// -------------------------------------------------------------------
#include "G4eIonisationCrossSectionHandler.hh"
#include "G4VEnergySpectrum.hh"
#include "G4DataVector.hh"
#include "G4CompositeEMDataSet.hh"
#include "G4VDataSetAlgorithm.hh"
#include "G4SemiLogInterpolation.hh"
#include "G4VEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4Material.hh"
#include "G4MaterialTable.hh"
G4eIonisationCrossSectionHandler::G4eIonisationCrossSectionHandler(
const G4VEnergySpectrum* spec, G4VDataSetAlgorithm* alg,
G4double emin, G4double emax, G4int nbin)
: G4VCrossSectionHandler(),
theParam(spec)
{
G4VCrossSectionHandler::Initialise(alg, emin, emax, nbin);
interp = new G4SemiLogInterpolation();
}
G4eIonisationCrossSectionHandler::~G4eIonisationCrossSectionHandler()
{
delete interp;
}
G4std::vector<G4VEMDataSet*>* G4eIonisationCrossSectionHandler::BuildCrossSectionsForMaterials(
const G4DataVector& energyVector,
const G4DataVector* energyCuts)
{
G4std::vector<G4VEMDataSet*>* set = new G4std::vector<G4VEMDataSet*>;
G4DataVector* energies;
G4DataVector* cs;
G4int nOfBins = energyVector.size();
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
if (materialTable == 0)
G4Exception("G4VCrossSectionHandler::G4VCrossSectionHandler - no MaterialTable found)");
G4int nMaterials = G4Material::GetNumberOfMaterials();
for (G4int m=0; m<nMaterials; m++) {
const G4Material* material = (*materialTable)[m];
const G4ElementVector* elementVector = material->GetElementVector();
//const G4double* nAtomsPerVolume = material->GetVecNbOfAtomsPerVolume();
const G4double* nAtomsPerVolume = material->GetAtomicNumDensityVector();
G4int nElements = material->GetNumberOfElements();
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;
cs = new G4DataVector;
G4double density = nAtomsPerVolume[i];
for (G4int bin=0; bin<nOfBins; bin++) {
G4double e = energyVector[bin];
energies->push_back(e);
G4double value = 0.0;
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);
value += cross * p * density;
/*
G4cout << "G4eIonisationCrossSectionHandler: e= " << e
<< " n= " << n
<< " cross= " << cross
<< " p= " << p
<< " value= " << value
<< 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;
}
@@ -0,0 +1,383 @@
//
// ********************************************************************
// * 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: G4eIonisationParameters.cc,v 1.17 2001/11/30 00:52:52 pia Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// Author: Maria Grazia Pia (Maria.Grazia.Pia@cern.ch)
//
// History:
// -----------
// 31 Jul 2001 MGP Created, with dummy implementation
// 12.09.01 V.Ivanchenko Add param and interpolation of parameters
// 04.10.01 V.Ivanchenko Add BindingEnergy method
// 25.10.01 MGP Many bug fixes, mostly related to the
// management of pointers
// 29.11.01 V.Ivanchenko New parametrisation + Excitation
//
// -------------------------------------------------------------------
#include "G4eIonisationParameters.hh"
#include "G4VEMDataSet.hh"
#include "G4ShellEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4CompositeEMDataSet.hh"
#include "G4LogLogInterpolation.hh"
#include "G4Material.hh"
#include "G4DataVector.hh"
#include "g4std/fstream"
#include "g4std/strstream"
G4eIonisationParameters:: G4eIonisationParameters(G4int minZ, G4int maxZ)
: zMin(minZ), zMax(maxZ),
length(7)
{
LoadData();
}
G4eIonisationParameters::~G4eIonisationParameters()
{
// 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)
{
G4VEMDataSet* dataSet = (*pos).second;
delete dataSet;
}
for (pos = excit.begin(); pos != excit.end(); ++pos)
{
G4VEMDataSet* dataSet = (*pos).second;
delete dataSet;
}
activeZ.clear();
}
G4double G4eIonisationParameters::Parameter(G4int Z, G4int shellIndex,
G4int parameterIndex,
G4double e) const
{
G4double value = 0.;
G4int id = Z*20 + parameterIndex;
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
pos = param.find(id);
if (pos!= param.end()) {
G4VEMDataSet* dataSet = (*pos).second;
G4int nShells = dataSet->NumberOfComponents();
if(shellIndex < nShells) {
const G4VEMDataSet* component = dataSet->GetComponent(shellIndex);
const G4DataVector ener = component->GetEnergies(0);
G4double ee = G4std::max(ener.front(),G4std::min(ener.back(),e));
value = component->FindValue(ee);
} else {
G4cout << "WARNING: G4IonisationParameters::FindParameter "
<< "has no parameters for shell= " << shellIndex
<< "; Z= " << Z
<< G4endl;
}
} else {
G4cout << "WARNING: G4IonisationParameters::Parameter "
<< "did not find ID = "
<< shellIndex << G4endl;
}
return value;
}
G4double G4eIonisationParameters::Excitation(G4int Z, G4double e) const
{
G4double value = 0.;
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
pos = excit.find(Z);
if (pos!= excit.end()) {
G4VEMDataSet* dataSet = (*pos).second;
const G4DataVector ener = dataSet->GetEnergies(0);
G4double ee = G4std::max(ener.front(),G4std::min(ener.back(),e));
value = dataSet->FindValue(ee);
} else {
G4cout << "WARNING: G4IonisationParameters::Excitation "
<< "did not find ID = "
<< Z << G4endl;
}
return value;
}
void G4eIonisationParameters::LoadData()
{
// ---------------------------------------
// Please document what are the parameters
// ---------------------------------------
// define active elements
const G4MaterialTable* materialTable = G4Material::GetMaterialTable();
if (materialTable == 0)
G4Exception("G4eIonisationParameters: no MaterialTable found)");
G4int nMaterials = G4Material::GetNumberOfMaterials();
for (G4int m=0; m<nMaterials; m++) {
const G4Material* material= (*materialTable)[m];
const G4ElementVector* elementVector = material->GetElementVector();
const size_t nElements = material->GetNumberOfElements();
for (size_t iEl=0; iEl<nElements; iEl++) {
G4Element* element = (*elementVector)[iEl];
G4double Z = element->GetZ();
if (!(activeZ.contains(Z))) {
activeZ.push_back(Z);
}
}
}
char* path = getenv("G4LEDATA");
if (!path)
{
G4String excep = "G4eIonisationParameters - G4LEDATA environment variable not set";
G4Exception(excep);
}
G4String pathString(path);
pathString += "/ioni/io-sp-";
G4double energy, sum;
size_t nZ = activeZ.size();
for (size_t i=0; i<nZ; i++) {
G4int Z = (G4int)activeZ[i];
char nameChar[100] = {""};
G4std::ostrstream ost(nameChar, 100, G4std::ios::out);
ost << pathString << Z << ".dat";
G4String name(nameChar);
G4std::ifstream file(name);
G4std::filebuf* lsdp = file.rdbuf();
if (! (lsdp->is_open()) ) {
G4String excep = "G4IonisationParameters - data file: "
+ name + " not found";
G4Exception(excep);
}
// - MGP - Please add some documentation about the parameters read
// The file is organized into...:
// 1st column is the energy
// The file terminates with the pattern: -1 -1
G4std::vector<G4VEMDataSet*> p;
for (size_t k=0; k<length; k++)
{
G4VDataSetAlgorithm* inter = new G4LogLogInterpolation();
G4VEMDataSet* composite = new G4CompositeEMDataSet(inter,1.,1.);
p.push_back(composite);
}
G4int shell = 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();
do {
file >> energy >> sum;
if (energy == -2) break;
if (energy > -1) {
e.push_back(energy);
a[0]->push_back(sum);
for (size_t j=0; j<length-1; j++) {
G4double qRead;
file >> qRead;
a[j + 1]->push_back(qRead);
}
} else {
// End of set for a shell, fill the map
for (size_t k=0; k<length; k++) {
// G4int id = Z*20 + k;
G4VDataSetAlgorithm* interp = new G4LogLogInterpolation();
G4DataVector* eVector = new G4DataVector;
size_t eSize = e.size();
for (size_t s=0; s<eSize; s++) {
eVector->push_back(e[s]);
}
G4VEMDataSet* set = new G4EMDataSet(shell,eVector,a[k],interp,1.,1.);
p[k]->AddComponent(set);
}
// clear vectors
for (size_t j2=0; j2<length; j2++) {
a[j2] = new G4DataVector();
}
shell++;
e.clear();
}
} while (energy > -2);
file.close();
for (size_t kk=0; kk<length; kk++)
{
G4int id = Z*20 + kk;
param[id] = p[kk];
}
}
G4String pathString_a(path);
G4String name_a = pathString_a + "/ioni/io-ex-av.dat";
G4std::ifstream file_a(name_a);
G4std::filebuf* lsdp_a = file_a.rdbuf();
G4String pathString_b(path);
G4String name_b = pathString_b + "/ioni/io-ex-sig.dat";
G4std::ifstream file_b(name_b);
G4std::filebuf* lsdp_b = file_b.rdbuf();
if (! (lsdp_a->is_open()) ) {
G4String excep = G4String("G4eIonisationParameters: cannot open file ")
+ name_a;
G4Exception(excep);
}
if (! (lsdp_b->is_open()) ) {
G4String excep = G4String("G4eIonisationParameters: cannot open file ")
+ name_b;
G4Exception(excep);
}
// The file is organized into two columns:
// 1st column is the energy
// 2nd column is the corresponding value
// The file terminates with the pattern: -1 -1
// -2 -2
G4double ener, ener1, sig, sig1;
G4int z = 0;
G4DataVector e;
e.clear();
G4DataVector d;
d.clear();
do {
file_a >> ener >> sig;
file_b >> ener1 >> sig1;
if(ener != ener1) {
G4cout << "G4eIonisationParameters: problem in excitation data "
<< "ener= " << ener
<< " ener1= " << ener1
<< G4endl;
}
// End of file
if (ener == -2) {
break;
// End of next element
} else if (ener == -1) {
z++;
G4double Z = (G4double)z;
// fill map if Z is used
if (activeZ.contains(Z)) {
G4VDataSetAlgorithm* inter = new G4LogLogInterpolation();
G4DataVector* eVector = new G4DataVector;
G4DataVector* dVector = new G4DataVector;
size_t eSize = e.size();
for (size_t s=0; s<eSize; s++) {
eVector->push_back(e[s]);
dVector->push_back(d[s]);
}
G4VEMDataSet* set = new G4EMDataSet(z,eVector,dVector,inter,1.,1.);
excit[z] = set;
}
e.clear();
d.clear();
} else {
e.push_back(ener);
d.push_back(sig1*sig*barn*MeV);
}
} while (ener != -2);
file_a.close();
}
void G4eIonisationParameters::PrintData() const
{
G4cout << G4endl;
G4cout << "===== G4eIonisationParameters =====" << G4endl;
G4cout << G4endl;
size_t nZ = activeZ.size();
G4std::map<G4int,G4VEMDataSet*,G4std::less<G4int> >::const_iterator pos;
for (size_t i=0; i<nZ; i++) {
G4int Z = (G4int)activeZ[i];
for (size_t j=0; j<length; j++) {
G4int index = Z*20 + j;
pos = param.find(index);
if (pos!= param.end()) {
G4VEMDataSet* dataSet = (*pos).second;
size_t nShells = dataSet->NumberOfComponents();
for (size_t k=0; k<nShells; k++) {
G4cout << "===== Z= " << Z << " shell= " << k
<< " parameter[" << j << "] ====="
<< G4endl;
const G4VEMDataSet* comp = dataSet->GetComponent(k);
comp->PrintData();
}
}
}
}
G4cout << "====================================" << G4endl;
}
@@ -0,0 +1,387 @@
//
// ********************************************************************
// * 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: G4eIonisationSpectrum.cc,v 1.12 2001/12/04 11:34:16 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// -------------------------------------------------------------------
//
// GEANT4 Class file
//
//
// File name: G4eIonisationSpectrum
//
// Author: V.Ivanchenko (Vladimir.Ivanchenko@cern.ch)
//
// Creation date: 29 September 2001
//
// Modifications:
// 10.10.2001 MGP Revision to improve code quality and
// consistency with design
// 02.11.2001 VI Optimize sampling of energy
// 29.11.2001 VI New parametrisation
//
// -------------------------------------------------------------------
//
#include "G4eIonisationSpectrum.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4AtomicShell.hh"
#include "G4eIonisationParameters.hh"
#include "G4DataVector.hh"
#include "Randomize.hh"
G4eIonisationSpectrum::G4eIonisationSpectrum():G4VEnergySpectrum(),
lowestE(0.1*eV),
verbose(0)
{
theParam = new G4eIonisationParameters();
}
G4eIonisationSpectrum::~G4eIonisationSpectrum()
{
delete theParam;
}
G4double G4eIonisationSpectrum::Probability(G4int Z,
G4double tMin,
G4double tMax,
G4double e,
G4int shell,
const G4ParticleDefinition* part) const
{
// Please comment what Probability does and what are the three
// functions mentioned below
// Describe the algorithms used
G4double eMax = MaxEnergyOfSecondaries(e);
G4double t0 = G4std::max(tMin, lowestE);
G4double tm = G4std::min(tMax, eMax);
if(t0 >= tm) return 0.0;
G4double bindingEnergy = (G4AtomicTransitionManager::Instance())->
Shell(Z, shell)->BindingEnergy();
G4double x1 = G4std::min(0.5,(t0 + bindingEnergy)/(e + bindingEnergy));
G4double x2 = G4std::min(0.5,(tm + bindingEnergy)/(e + bindingEnergy));
if(verbose > 1) {
G4cout << "G4eIonisationSpectrum::Probability: Z= " << Z
<< "; shell= " << shell
<< "; E(keV)= " << e/keV
<< "; x1= " << x1
<< "; x2= " << x2
<< G4endl;
}
G4int iMax = 7;
G4DataVector p;
// Access parameters
for (G4int i=0; i<iMax; i++)
{
p.push_back(theParam->Parameter(Z, shell, i, e));
}
G4double g = (e + bindingEnergy)/electron_mass_c2 + 1.;
p.push_back((2.0*g - 1.0)/(g*g));
G4double val = IntSpectrum(x1, x2, p);
G4double x0 = (lowestE + bindingEnergy)/(e + bindingEnergy);
G4double nor = IntSpectrum(x0, 0.5, p);
if(verbose > 1) {
G4cout << "tcut= " << tMin
<< "; tMax= " << tMax
<< "; x0= " << x0
<< "; x1= " << x1
<< "; x2= " << x2
<< "; val= " << val
<< "; nor= " << nor
<< "; sum= " << p[0]
<< "; a= " << p[1]
<< "; b= " << p[2]
<< "; c= " << p[3]
<< G4endl;
}
p.clear();
if(nor > 0.0) val /= nor;
else val = 0.0;
if(val < 0.0) val = 0.0;
return val;
}
G4double G4eIonisationSpectrum::AverageEnergy(G4int Z,
G4double tMin,
G4double tMax,
G4double e,
G4int shell,
const G4ParticleDefinition* part) const
{
// Please comment what AverageEnergy does and what are the three
// functions mentioned below
// Describe the algorithms used
G4double eMax = MaxEnergyOfSecondaries(e);
G4double t0 = G4std::max(tMin, lowestE);
G4double tm = G4std::min(tMax, eMax);
if(t0 >= tm) return 0.0;
G4double bindingEnergy = (G4AtomicTransitionManager::Instance())->
Shell(Z, shell)->BindingEnergy();
G4double x1 = G4std::min(0.5,(t0 + bindingEnergy)/(e + bindingEnergy));
G4double x2 = G4std::min(0.5,(tm + bindingEnergy)/(e + bindingEnergy));
if(verbose > 1) {
G4cout << "G4eIonisationSpectrum::AverageEnergy: Z= " << Z
<< "; shell= " << shell
<< "; E(keV)= " << e/keV
<< "; bindingE(keV)= " << bindingEnergy/keV
<< "; x1= " << x1
<< "; x2= " << x2
<< G4endl;
}
G4int iMax = 7;
G4DataVector p;
// Access parameters
for (G4int i=0; i<iMax; i++)
{
p.push_back(theParam->Parameter(Z, shell, i, e));
}
G4double g = (e + bindingEnergy)/electron_mass_c2 + 1.;
p.push_back((2.0*g - 1.0)/(g*g));
G4double val = AverageValue(x1, x2, p);
G4double x0 = (lowestE + bindingEnergy)/(e + bindingEnergy);
G4double nor = IntSpectrum(x0, 0.5, p);
val *= (e + bindingEnergy);
if(verbose > 1) {
G4cout << "tcut(MeV)= " << tMin/MeV
<< "; tMax(MeV)= " << tMax/MeV
<< "; x0= " << x0
<< "; x1= " << x1
<< "; x2= " << x2
<< "; val= " << val
<< "; nor= " << nor
<< "; sum= " << p[0]
<< "; a= " << p[1]
<< "; b= " << p[2]
<< "; c= " << p[3]
<< G4endl;
}
p.clear();
if(nor > 0.0) val /= nor;
else val = 0.0;
if(val < 0.0) val = 0.0;
return val;
}
G4double G4eIonisationSpectrum::SampleEnergy(G4int Z,
G4double tMin,
G4double tMax,
G4double e,
G4int shell,
const G4ParticleDefinition* part) const
{
// Please comment what SampleEnergy does
G4double tDelta = 0.0;
G4double t0 = G4std::max(tMin, lowestE);
G4double tm = G4std::min(tMax, MaxEnergyOfSecondaries(e));
if(t0 > tm) return tDelta;
G4double bindingEnergy = (G4AtomicTransitionManager::Instance())->
Shell(Z, shell)->BindingEnergy();
G4double x1 = G4std::min(0.5,(t0 + bindingEnergy)/(e + bindingEnergy));
G4double x2 = G4std::min(0.5,(tm + bindingEnergy)/(e + bindingEnergy));
if(x1 >= x2) return tDelta;
if(verbose > 1) {
G4cout << "G4eIonisationSpectrum::SampleEnergy: Z= " << Z
<< "; shell= " << shell
<< "; E(keV)= " << e/keV
<< G4endl;
}
// Access parameters
G4int iMax = 7;
G4DataVector p;
// Access parameters
for (G4int i=0; i<iMax; i++)
{
p.push_back(theParam->Parameter(Z, shell, i, e));
}
G4double g = (e + bindingEnergy)/electron_mass_c2 + 1.;
p.push_back((2.0*g - 1.0)/(g*g));
G4double aria1 = 0.0;
G4double a1 = G4std::min(x1,p[6]);
G4double a2 = G4std::min(x2,p[6]);
if(a1 < a2) aria1 = IntSpectrum(a1, a2, p);
G4double aria2 = 0.0;
G4double a3 = G4std::max(x1,p[6]);
G4double a4 = G4std::max(x2,p[6]);
if(a3 < a4) aria2 = IntSpectrum(a3, a4, p);
G4double aria = (aria1 + aria2)*G4UniformRand();
G4double amaj, fun, q, x;
//======= First aria to sample =====
if(aria <= aria1) {
amaj = p[4];
a1 = 1./a1;
a2 = 1./a2;
//======= Second aria to sample =====
} else {
amaj = p[5];
a1 = 1./a3;
a2 = 1./a4;
}
amaj *= 1.25;
do {
x = 1./(a2 + G4UniformRand()*(a1 - a2));
fun = Function(x, p);
if(fun > amaj) {
G4cout << "WARNING in G4eIonisationSpectrum::SampleEnergy:"
<< " Majoranta " << amaj
<< " < " << fun
<< G4endl;
}
q = amaj*G4UniformRand();
} while (q >= fun);
p.clear();
tDelta = x*(e + bindingEnergy) - bindingEnergy;
if(verbose > 1) {
G4cout << "tcut(MeV)= " << tMin/MeV
<< "; tMax(MeV)= " << tMax/MeV
<< "; x1= " << x1
<< "; x2= " << x2
<< "; a1= " << a1
<< "; a2= " << a2
<< "; x= " << x
<< "; be= " << bindingEnergy
<< "; e= " << e
<< "; tDelta= " << tDelta
<< G4endl;
}
return tDelta;
}
G4double G4eIonisationSpectrum::IntSpectrum(G4double xMin,
G4double xMax,
const G4DataVector& p) const
{
// Please comment what IntSpectrum does
G4double x1 = 1./xMin;
G4double x2 = 1./xMax;
G4double x = x1 - x2 - p[7]*log(xMax/xMin) + (1. - p[7])*(xMax - xMin)
+ 1./(1. - xMax) - 1./(1. - xMin)
+ p[7]*log((1. - xMax)/(1. - xMin))
+ 0.5*p[1]*p[3]*(x1*x1 - x2*x2);
if(x < 0.0) x = 0.0;
return x;
}
G4double G4eIonisationSpectrum::AverageValue(G4double xMin,
G4double xMax,
const G4DataVector& p) const
{
// G4double x1 = 1.;
// G4double x2 = 1.;
G4double x = log(xMax/xMin)
+ 0.5*(1. - p[7])*(xMax*xMax - xMin*xMin)
+ 1./(1. - xMax) - 1./(1. - xMin)
+ (1. + p[7])*log((1. - xMax)/(1. - xMin))
+ p[1]*p[3]*(1./xMin - 1./xMax);
if(x < 0.0) x = 0.0;
return x;
}
G4double G4eIonisationSpectrum::Function(G4double x,
const G4DataVector& p) const
{
// Please comment what Function does
// G4double x1 = 1.0;
G4double f = 1.0 - p[7]*x + x*x*(1.0 - p[7]
+ (1.0/(1.0 - x) - p[7])/(1.0 - x) )
+ p[1]*p[3]/x;
if(f < 0.0) f = 0.0;
return f;
}
G4double G4eIonisationSpectrum::Excitation(G4int Z, G4double e) const
{
return theParam->Excitation(Z, e);
}
void G4eIonisationSpectrum::PrintData() const
{
theParam->PrintData();
}
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4eLowEnergyLoss.cc,v 1.9.2.2 2001/06/28 20:19:32 gunter Exp $
// GEANT4 tag $Name: $
// $Id: G4eLowEnergyLoss.cc,v 1.23 2001/11/23 11:45:29 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// -----------------------------------------------------------
// GEANT 4 class implementation file
@@ -32,7 +32,6 @@
// ---------- G4eLowEnergyLoss physics process -----------
// by Laszlo Urban, 20 March 1997
// **************************************************************
// It is the first implementation of the NEW UNIFIED ENERGY LOSS PROCESS.
// It calculates the energy loss of e+/e-.
// --------------------------------------------------------------
//
@@ -48,7 +47,14 @@
// 10/02/00 modifications , new e.m. structure, L.Urban
// 11/04/00: Bug fix in dE/dx fluctuation simulation, Veronique Lefebure
// 19-09-00 change of fluctuation sampling V.Ivanchenko
// 20/09/00 update fluctuations V.Ivanchenko
// 20/09/00 update fluctuations V.Ivanchenko
// 18/10/01 add fluorescence AlongStepDoIt V.Ivanchenko
// 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
// 23/11/01 VI Move static member-functions from header to source
//
// --------------------------------------------------------------
#include "G4eLowEnergyLoss.hh"
@@ -137,6 +143,55 @@ G4eLowEnergyLoss::~G4eLowEnergyLoss()
}
}
void G4eLowEnergyLoss::SetNbOfProcesses(G4int nb)
{
NbOfProcesses=nb;
}
void G4eLowEnergyLoss::PlusNbOfProcesses()
{
NbOfProcesses++;
}
void G4eLowEnergyLoss::MinusNbOfProcesses()
{
NbOfProcesses--;
}
G4int G4eLowEnergyLoss::GetNbOfProcesses()
{
return NbOfProcesses;
}
void G4eLowEnergyLoss::SetLowerBoundEloss(G4double val)
{
LowerBoundEloss=val;
}
void G4eLowEnergyLoss::SetUpperBoundEloss(G4double val)
{
UpperBoundEloss=val;
}
void G4eLowEnergyLoss::SetNbinEloss(G4int nb)
{
NbinEloss=nb;
}
G4double G4eLowEnergyLoss::GetLowerBoundEloss()
{
return LowerBoundEloss;
}
G4double G4eLowEnergyLoss::GetUpperBoundEloss()
{
return UpperBoundEloss;
}
G4int G4eLowEnergyLoss::GetNbinEloss()
{
return NbinEloss;
}
//
void G4eLowEnergyLoss::BuildDEDXTable(
@@ -154,8 +209,7 @@ void G4eLowEnergyLoss::BuildDEDXTable(
// different processes.
//
const G4MaterialTable* theMaterialTable=G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
// create table for the total energy loss
@@ -334,15 +388,13 @@ G4VParticleChange* G4eLowEnergyLoss::AlongStepDoIt( const G4Track& trackData,
// get particle and material pointers from trackData
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle();
G4double E = aParticle->GetKineticEnergy() ;
// G4cout << "MGP -- Along eInit " << E/keV << " keV " << G4endl;
G4Material* aMaterial = trackData.GetMaterial();
// G4int index = aMaterial->GetIndex();
G4double Step = stepData.GetStepLength();
fParticleChange.Initialize(trackData);
aParticleChange.Initialize(trackData);
//fParticleChange.Initialize(trackData);
G4double MeanLoss, finalT;
@@ -386,18 +438,64 @@ G4VParticleChange* G4eLowEnergyLoss::AlongStepDoIt( const G4Track& trackData,
if (finalT <= 0. )
{
finalT = 0.;
if (Charge < 0.) fParticleChange.SetStatusChange(fStopAndKill);
else fParticleChange.SetStatusChange(fStopButAlive);
if (Charge < 0.) aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}
// MGP debug
// G4cout << "MGP AlongStepDoIt finalT = " << finalT/keV << " keV" << G4endl;
G4double edep = E - finalT;
aParticleChange.SetEnergyChange(finalT);
// Deexcitation of ionised atoms
G4std::vector<G4DynamicParticle*>* deexcitationProducts =
DeexciteAtom(aMaterial,E,edep);
fParticleChange.SetEnergyChange(finalT);
fParticleChange.SetLocalEnergyDeposit(E-finalT);
size_t nSecondaries = deexcitationProducts->size();
aParticleChange.SetNumberOfSecondaries(nSecondaries);
if (nSecondaries > 0) {
return &fParticleChange;
const G4StepPoint* preStep = stepData.GetPreStepPoint();
const G4StepPoint* postStep = stepData.GetPostStepPoint();
G4ThreeVector r = preStep->GetPosition();
G4ThreeVector deltaR = postStep->GetPosition();
deltaR -= r;
G4double t = preStep->GetGlobalTime();
G4double deltaT = postStep->GetGlobalTime();
deltaT -= t;
G4double time, q;
G4ThreeVector position;
for (size_t i=0; i<nSecondaries; i++) {
G4DynamicParticle* part = (*deexcitationProducts)[i];
if (part != 0) {
G4double eSecondary = part->GetKineticEnergy();
edep -= eSecondary;
if (edep > 0.)
{
q = G4UniformRand();
time = deltaT*q + t;
position = deltaR*q;
position += r;
G4Track* newTrack = new G4Track(part, time, position);
aParticleChange.AddSecondary(newTrack);
}
else
{
edep += eSecondary;
delete part;
part = 0;
}
}
}
}
delete deexcitationProducts;
aParticleChange.SetLocalEnergyDeposit(edep);
return &aParticleChange;
}
//
@@ -34,6 +34,7 @@
//
// Modifications:
// 20/07/2000 V.Ivanchenko First implementation
// 18/06/2001 V.Ivanchenko Continuation for eff.charge (small change of y)
//
// Class Description:
//
@@ -210,7 +211,7 @@ G4double G4hIonEffChargeSquare::IonEffChargeSquare(
} else {
for (G4int iel=0; iel<NumberOfElements; iel++)
{
const G4Element* element = (*theElementVector)(iel) ;
const G4Element* element = (*theElementVector)[iel] ;
G4double z2 = element->GetZ() ;
const G4double weight = theAtomicNumDensityVector[iel] ;
norm += weight ;
@@ -254,7 +255,7 @@ G4double G4hIonEffChargeSquare::IonEffChargeSquare(
// Slower than Fermi velocity
} else {
y = 0.75 * vF * (1.0 + 2.0*v1*v1/3.0 + v1*v1*v1*v1/15.0) / (z13*z13) ;
y = 0.6923 * vF * (1.0 + 2.0*v1*v1/3.0 + v1*v1*v1*v1/15.0) / (z13*z13) ;
}
G4double y3 = pow(y, 0.3) ;
@@ -65,6 +65,10 @@
// 10 May 2001 V.Ivanchenko Clean up againist Linux compilation with -Wall
// 23 May 2001 V.Ivanchenko Minor fix in PostStepDoIt
// 07 June 2001 V.Ivanchenko Clean up AntiProtonDEDX + add print out
// 18 June 2001 V.Ivanchenko Cleanup print out
// 18 Oct. 2001 V.Ivanchenko Add fluorescence
// 30 Oct. 2001 V.Ivanchenko Add minGammaEnergy and minElectronEnergy
// 07 Dec 2001 V.Ivanchenko Add SetFluorescence method
// -----------------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -80,6 +84,15 @@
#include "G4Material.hh"
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "G4AtomicDeexcitation.hh"
#include "G4ShellVacancy.hh"
#include "G4hShellCrossSection.hh"
#include "G4VEMDataSet.hh"
#include "G4EMDataSet.hh"
#include "G4CompositeEMDataSet.hh"
#include "G4Gamma.hh"
#include "G4LogLogInterpolation.hh"
#include "G4SemiLogInterpolation.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -98,7 +111,10 @@ G4hLowEnergyIonisation::G4hLowEnergyIonisation(const G4String& processName)
nStopping(true),
theBarkas(true),
theMeanFreePathTable(0),
paramStepLimit (0.005)
paramStepLimit (0.005),
shellVacancy(0),
shellCS(0),
theFluo(true)
{
InitializeMe();
}
@@ -110,11 +126,15 @@ void G4hLowEnergyIonisation::InitializeMe()
LowestKineticEnergy = 10.0*eV ;
HighestKineticEnergy = 100.0*TeV ;
MinKineticEnergy = 10.0*eV ;
TotBin = 200 ;
TotBin = 200 ;
protonLowEnergy = 1.*keV ;
protonHighEnergy = 2.*MeV ;
antiProtonLowEnergy = 1.*keV ;
antiProtonHighEnergy = 2.*MeV ;
minGammaEnergy = 25.*keV;
minElectronEnergy = 25.*keV;
verboseLevel = 0;
shellCS = new G4hShellCrossSection();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -132,6 +152,16 @@ G4hLowEnergyIonisation::~G4hLowEnergyIonisation()
if(theIonEffChargeModel)delete theIonEffChargeModel;
if(theIonChuFluctuationModel)delete theIonChuFluctuationModel;
if(theIonYangFluctuationModel)delete theIonYangFluctuationModel;
if(shellVacancy) delete shellVacancy;
if(shellCS) delete shellCS;
cutForDelta.clear();
G4int length = zFluoDataVector.size();
if(length) {
for(G4int i=0; i<length; i++) {
delete &(zFluoDataVector[i]);
}
zFluoDataVector.clear();
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -156,10 +186,6 @@ void G4hLowEnergyIonisation::InitializeParametrisation()
G4Proton* theProton = G4Proton::Proton();
G4AntiProton* theAntiProton = G4AntiProton::AntiProton();
// cuts for electron
G4Electron* theElectron = G4Electron::Electron();
deltaCutInKineticEnergy = theElectron->GetCutsInEnergy() ;
// Define models for parametrisation of electronic energy losses
theBetheBlochModel = new G4hBetheBlochModel("Bethe-Bloch") ;
theProtonModel = new G4hParametrisedLossModel(theProtonTable) ;
@@ -197,15 +223,55 @@ void G4hLowEnergyIonisation::BuildPhysicsTable(
G4cout << "G4hLowEnergyIonisation::BuildPhysicsTable for "
<< aParticleType.GetParticleName() << G4endl;
}
InitializeParametrisation() ;
G4Proton* theProton = G4Proton::Proton();
G4AntiProton* theAntiProton = G4AntiProton::AntiProton();
G4Electron* theElectron = G4Electron::Electron();
charge = aParticleType.GetPDGCharge()/eplus ;
chargeSquare = charge*charge ;
G4double electronCutInRange = theElectron->GetCuts();
// ---- 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 ----
// Define cuts
// create table
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
cutForDelta.clear();
cutForGamma.clear();
for (G4int j=0; j<numOfMaterials; j++) {
// get material parameters needed for the energy loss calculation
const G4Material* material= (*theMaterialTable)[j];
// the cut cannot be below lowest limit
G4double tCut = G4Electron::Electron()->GetEnergyThreshold(material);
if(tCut > HighestKineticEnergy) tCut = HighestKineticEnergy;
G4double excEnergy = material->GetIonisation()->GetMeanExcitationEnergy();
tCut = G4std::max(tCut,excEnergy);
cutForDelta.push_back(tCut);
// the cut cannot be below lowest limit
tCut = G4Gamma::Gamma()->GetEnergyThreshold(material);
if(tCut > HighestKineticEnergy) tCut = HighestKineticEnergy;
tCut = G4std::max(tCut,minGammaEnergy);
cutForGamma.push_back(tCut);
}
if(verboseLevel > 0) {
G4cout << "Cuts are defined " << G4endl;
}
if(0.0 < charge)
{
@@ -235,6 +301,7 @@ void G4hLowEnergyIonisation::BuildPhysicsTable(
}
BuildLambdaTable(aParticleType) ;
BuildDataForFluorescence(aParticleType);
if(verboseLevel > 0) {
G4cout << "G4hLowEnergyIonisation::BuildPhysicsTable: "
@@ -276,7 +343,7 @@ void G4hLowEnergyIonisation::BuildLossTable(
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
// create table
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if ( theLossTable) {
theLossTable->clearAndDestroy();
@@ -344,12 +411,140 @@ void G4hLowEnergyIonisation::BuildLossTable(
}
// now put the loss into the vector
if(verboseLevel > 1) {
G4cout << "E(MeV)= " << lowEdgeEnergy/MeV
<< " dE/dx(MeV/mm)= " << ionloss*mm/MeV
<< " in " << material->GetName() << G4endl;
}
aVector->PutValue(i,ionloss) ;
}
// Insert vector for this material into the table
theLossTable->insert(aVector) ;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyIonisation::BuildDataForFluorescence(
const G4ParticleDefinition& aParticleType)
{
if(verboseLevel > 1) {
G4cout << "G4hLowEnergyIonisation::BuildDataForFluorescence for "
<< aParticleType.GetParticleName() << " is started" << G4endl;
}
// fill data for fluorescence
G4double mass = aParticleType.GetPDGMass();
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
// create table
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if (shellVacancy != 0) delete shellVacancy;
shellVacancy = new G4ShellVacancy();
G4DataVector* ksi = 0;
G4DataVector* ksi1 = 0;
G4DataVector* energy = 0;
G4DataVector* energy1 = 0;
size_t binForFluo = TotBin/10;
G4int length = zFluoDataVector.size();
if(length > 0) {
for(G4int i=0; i<length; i++) {
G4VEMDataSet* x = zFluoDataVector[i];
delete x;
}
zFluoDataVector.clear();
}
G4PhysicsLogVector* bVector = new G4PhysicsLogVector(LowestKineticEnergy,
HighestKineticEnergy,
binForFluo);
G4AtomicTransitionManager* transitionManager =
G4AtomicTransitionManager::Instance();
G4double bindingEnergy;
// G4double x;
// G4double y;
// loop for materials
for (G4int 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() ;
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector();
G4VDataSetAlgorithm* interp = new G4SemiLogInterpolation();
G4VEMDataSet* xsis = new G4CompositeEMDataSet(interp, 1., 1.);
G4VDataSetAlgorithm* interp1 = new G4SemiLogInterpolation();
G4VEMDataSet* xsis1 = new G4CompositeEMDataSet(interp1, 1., 1.);
G4double tCut = cutForDelta[j];
G4double elDensity = 1.;
for (size_t iel=0; iel<NumberOfElements; iel++ ) {
G4int Z = (G4int)((*theElementVector)[iel]->GetZ());
energy = new G4DataVector();
ksi = new G4DataVector();
energy1= new G4DataVector();
ksi1 = new G4DataVector();
//if(NumberOfElements > 1)
elDensity = theAtomicNumDensityVector[iel];
for (size_t j = 0; j<binForFluo; j++) {
G4double tkin = bVector->GetLowEdgeEnergy(j);
G4double gamma = tkin/mass + 1.;
G4double r = electron_mass_c2/mass;
G4double tmax = 2.*mass*r*(gamma*gamma - 1.)/(1. + 2.*gamma*r + r*r);
G4double cross = 0.;
G4double cross1 = 0.;
G4double eAverage= 0.;
G4int nShells = transitionManager->NumberOfShells(Z);
G4double tmin = G4std::min(tCut,tmax);
for (G4int n=0; n<nShells; n++) {
bindingEnergy = transitionManager->Shell(Z, n)->BindingEnergy();
eAverage += elDensity*log(tmin/bindingEnergy + 1.);
cross += elDensity*tmin/((bindingEnergy + tmin)*bindingEnergy);
cross1 += elDensity*(tmax - tmin)/
((tmax + bindingEnergy)*(tmin + bindingEnergy));
}
energy1->push_back(tkin);
ksi1->push_back(cross1);
if(eAverage > 0.) cross /= eAverage;
else cross = 0.;
energy->push_back(tkin);
ksi->push_back(cross);
}
G4VDataSetAlgorithm* algo = interp->Clone();
G4VEMDataSet* set = new G4EMDataSet(Z,energy,ksi,algo,1.,1.);
xsis->AddComponent(set);
G4VDataSetAlgorithm* algo1 = interp1->Clone();
G4VEMDataSet* set1 = new G4EMDataSet(Z,energy1,ksi1,algo1,1.,1.);
xsis1->AddComponent(set1);
}
if(verboseLevel > 1) {
G4cout << "### Shell inverse cross sections for "
<< material->GetName() << G4endl;
xsis->PrintData();
G4cout << "### Atom cross sections for "
<< material->GetName() << G4endl;
xsis1->PrintData();
}
shellVacancy->AddXsiTable(xsis);
zFluoDataVector.push_back(xsis1);
}
delete bVector;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -361,13 +556,19 @@ void G4hLowEnergyIonisation::BuildLambdaTable(
// Build mean free path tables for the delta ray production process
// tables are built for MATERIALS
if(verboseLevel > 1) {
G4cout << "G4hLowEnergyIonisation::BuildLambdaTable for "
<< aParticleType.GetParticleName() << " is started" << G4endl;
}
G4double lowEdgeEnergy, value;
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
charge = aParticleType.GetPDGCharge()/eplus ;
chargeSquare = charge*charge ;
//create table
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if (theMeanFreePathTable) {
theMeanFreePathTable->clearAndDestroy();
@@ -375,11 +576,7 @@ void G4hLowEnergyIonisation::BuildLambdaTable(
}
theMeanFreePathTable = new G4PhysicsTable(numOfMaterials);
// get electron and particle cuts in kinetic energy
// deltaCutInKineticEnergy = theElectron->GetCutsInEnergy() ;
// loop for materials
for (G4int J=0 ; J < numOfMaterials; J++) {
@@ -397,15 +594,13 @@ void G4hLowEnergyIonisation::BuildLambdaTable(
const G4double* theAtomicNumDensityVector =
material->GetAtomicNumDensityVector();
const G4int NumberOfElements = material->GetNumberOfElements() ;
G4double excEnergy = material->GetIonisation()->GetMeanExcitationEnergy();
// get the electron kinetic energy cut for the actual material,
// it will be used in ComputeMicroscopicCrossSection
// ( it is the SAME for ALL the ELEMENTS in THIS MATERIAL )
// ------------------------------------------------------
// Cut in Delta energy is limited by exitation energy
G4double deltaCut = G4std::max(excEnergy,deltaCutInKineticEnergy[J]) ;
G4double deltaCut = cutForDelta[J];
for ( G4int i = 0 ; i < TotBin ; i++ ) {
lowEdgeEnergy = aVector->GetLowEdgeEnergy(i) ;
@@ -419,7 +614,7 @@ void G4hLowEnergyIonisation::BuildLambdaTable(
ComputeMicroscopicCrossSection(
aParticleType,
lowEdgeEnergy,
(*theElementVector)(iel)->GetZ(),
(*theElementVector)[iel]->GetZ(),
deltaCut ) ;
}
@@ -429,9 +624,10 @@ void G4hLowEnergyIonisation::BuildLambdaTable(
aVector->PutValue(i, value) ;
}
theMeanFreePathTable->insert(aVector);
}
}
@@ -492,6 +688,33 @@ G4double G4hLowEnergyIonisation::ComputeMicroscopicCrossSection(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4hLowEnergyIonisation::GetMeanFreePath(const G4Track& trackData,
G4double previousStepSize,
enum G4ForceCondition* condition)
{
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle() ;
G4Material* aMaterial = trackData.GetMaterial() ;
G4double meanFreePath;
G4bool isOutRange ;
*condition = NotForced ;
G4double kineticEnergy = aParticle->GetKineticEnergy() ;
if(kineticEnergy < LowestKineticEnergy) meanFreePath = DBL_MAX;
else {
if(kineticEnergy > HighestKineticEnergy)
kineticEnergy = HighestKineticEnergy ;
meanFreePath = ((*theMeanFreePathTable)(aMaterial->GetIndex()))->
GetValue(kineticEnergy,isOutRange) ;
}
return meanFreePath ;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4hLowEnergyIonisation::GetConstraints(
const G4DynamicParticle* particle,
const G4Material* material)
@@ -569,8 +792,9 @@ G4double G4hLowEnergyIonisation::GetConstraints(
// Normal energy
} else {
fRangeNow = G4EnergyLossTables::GetRange(theAntiProton, tscaled, material) ;
dx = G4EnergyLossTables::GetRange(theAntiProton, highEnergy, material) ;
fRangeNow = G4EnergyLossTables::GetRange(theAntiProton, tscaled,
material);
dx = G4EnergyLossTables::GetRange(theAntiProton, highEnergy, material);
if(tscaled > highEnergy) {
fdEdx = G4EnergyLossTables::GetDEDX(theAntiProton, tscaled, material)
@@ -578,7 +802,7 @@ G4double G4hLowEnergyIonisation::GetConstraints(
// For Bragg's peak dE/dx is recalculated
} else {
fdEdx = AntiProtonParametrisedDEDX(material, tscaled) * chargeSquare ;
fdEdx = AntiProtonParametrisedDEDX(material, tscaled) * chargeSquare;
}
}
}
@@ -620,6 +844,7 @@ G4VParticleChange* G4hLowEnergyIonisation::AlongStepDoIt(
G4double finalT = 0.0 ;
aParticleChange.Initialize(trackData) ;
G4Material* material = trackData.GetMaterial() ;
// get the actual (true) Step length from stepData
@@ -652,9 +877,17 @@ G4VParticleChange* G4hLowEnergyIonisation::AlongStepDoIt(
G4double eFinal = kineticEnergy - step*fdEdx - nloss ;
if(0.0 < eFinal) {
eloss = (fdEdx +
ProtonParametrisedDEDX(material,eFinal*massRatio)*chargeSquare)
* step * 0.5 ;
G4double ts = eFinal*massRatio;
G4double fdEdx1 = ProtonParametrisedDEDX(material,ts)*chargeSquare;
// Correction for positive ions
//if(theBarkas && 1.0 < charge) {
// fdEdx1 += BarkasTerm(material,ts)*(charge -1.0) * chargeSquare ;
// fdEdx1 += BlochTerm(material,ts,chargeSquare) ;
// fdEdx1 -= BlochTerm(material,ts,1.0) ;
// }
eloss = (fdEdx + fdEdx1) * step * 0.5 ;
} else {
eloss = kineticEnergy - nloss ;
}
@@ -707,29 +940,84 @@ G4VParticleChange* G4hLowEnergyIonisation::AlongStepDoIt(
eloss = step*fdEdx ;
}
}
if(eloss < 0.0) eloss = 0.0;
finalT = kineticEnergy - eloss - nloss ;
finalT = kineticEnergy - eloss - nloss;
if( EnlossFlucFlag && 0.0 < eloss ) {
// now the electron loss with fluctuation
eloss = ElectronicLossFluctuation(particle, material, eloss, step) ;
finalT = kineticEnergy - eloss - nloss ;
if(eloss < 0.0) eloss = 0.0;
finalT = kineticEnergy - eloss - nloss;
}
// stop particle if the kinetic energy <= MinKineticEnergy
if (finalT <= MinKineticEnergy )
{
finalT = 0.0 ;
if( "proton" == (particle->GetDefinition()->GetParticleName()) )
if (finalT <= MinKineticEnergy ) {
finalT = 0.0;
if( "proton" == (particle->GetDefinition()->GetParticleName()) )
aParticleChange.SetStatusChange(fStopAndKill);
else
else
aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetEnergyChange( finalT ) ;
aParticleChange.SetLocalEnergyDeposit(kineticEnergy-finalT) ;
}
aParticleChange.SetEnergyChange( finalT );
G4double edep = kineticEnergy-finalT;
// Deexcitation only of ionised atoms
eloss = G4std::min(edep, eloss);
G4double hMass = particle->GetMass();
G4std::vector<G4DynamicParticle*>* newpart = 0;
G4DynamicParticle* part = 0;
if(theFluo) newpart = DeexciteAtom(material, kineticEnergy, hMass, eloss);
if(newpart != 0) {
size_t nSecondaries = newpart->size();
aParticleChange.SetNumberOfSecondaries(nSecondaries);
G4Track* newtrack = 0;
const G4StepPoint* preStep = stepData.GetPreStepPoint();
const G4StepPoint* postStep = stepData.GetPostStepPoint();
G4ThreeVector r = preStep->GetPosition();
G4ThreeVector deltaR = postStep->GetPosition();
deltaR -= r;
G4double t = preStep->GetGlobalTime();
G4double deltaT = postStep->GetGlobalTime();
deltaT -= t;
G4double time, q, e;
G4ThreeVector position;
for(size_t i=0; i<nSecondaries; i++) {
part = (*newpart)[i];
if(part) {
e = part->GetKineticEnergy();
if(e <= edep) {
edep -= e;
q = G4UniformRand();
time = deltaT*q + t;
position = deltaR*q;
position += r;
newtrack = new G4Track(part, time, position);
aParticleChange.AddSecondary(newtrack);
} else {
delete part;
}
}
}
delete newpart;
}
aParticleChange.SetLocalEnergyDeposit(edep);
return &aParticleChange ;
}
@@ -755,7 +1043,7 @@ G4double G4hLowEnergyIonisation::ProtonParametrisedDEDX(
// Delta rays energy
eloss -= DeltaRaysEnergy(material,kineticEnergy,proton_mass_c2) ;
if(verboseLevel > 1) {
if(verboseLevel > 2) {
G4cout << "p E(MeV)= " << kineticEnergy/MeV
<< " dE/dx(MeV/mm)= " << eloss*mm/MeV
<< " for " << material->GetName()
@@ -805,7 +1093,7 @@ G4double G4hLowEnergyIonisation::AntiProtonParametrisedDEDX(
// Delta rays energy
eloss -= DeltaRaysEnergy(material,kineticEnergy,proton_mass_c2) ;
if(verboseLevel > 0) {
if(verboseLevel > 2) {
G4cout << "pbar E(MeV)= " << kineticEnergy/MeV
<< " dE/dx(MeV/mm)= " << eloss*mm/MeV
<< " for " << material->GetName()
@@ -826,7 +1114,7 @@ G4double G4hLowEnergyIonisation::DeltaRaysEnergy(
{
G4double dloss = 0.0 ;
G4double deltaCutNow = deltaCutInKineticEnergy[(material->GetIndex())] ;
G4double deltaCutNow = cutForDelta[(material->GetIndex())] ;
G4double electronDensity = material->GetElectronDensity();
G4double eexc = material->GetIonisation()->GetMeanExcitationEnergy();
@@ -861,58 +1149,43 @@ G4VParticleChange* G4hLowEnergyIonisation::PostStepDoIt(
{
// Units are expressed in GEANT4 internal units.
G4double KineticEnergy,TotalEnergy,TotalMomentum,
betasquare,MaxKineticEnergyTransfer,
G4double KineticEnergy,TotalEnergy,TotalMomentum,betasquare,
DeltaKineticEnergy,DeltaTotalMomentum,costheta,sintheta,phi,
dirx,diry,dirz,finalKineticEnergy,finalPx,finalPy,finalPz,
x,xc,grej,Psquare,Esquare,summass,rate,finalMomentum ;
x,xc,grej,Psquare,Esquare,rate,finalMomentum ;
aParticleChange.Initialize(trackData) ;
G4Material* aMaterial = trackData.GetMaterial() ;
G4double Eexc = aMaterial->GetIonisation()->GetMeanExcitationEnergy();
const G4DynamicParticle* aParticle = trackData.GetDynamicParticle() ;
// some kinematics
ParticleMass=aParticle->GetDefinition()->GetPDGMass();
KineticEnergy=aParticle->GetKineticEnergy();
TotalEnergy=KineticEnergy + ParticleMass ;
Psquare=KineticEnergy*(TotalEnergy+ParticleMass) ;
Esquare=TotalEnergy*TotalEnergy ;
summass = ParticleMass + electron_mass_c2 ;
G4ParticleMomentum ParticleDirection = aParticle->GetMomentumDirection() ;
Esquare=TotalEnergy*TotalEnergy;
betasquare=Psquare/Esquare;
G4ThreeVector ParticleDirection = aParticle->GetMomentumDirection() ;
// get kinetic energy cut for the electron....
G4double DeltaCutInKineticEnergyNow =
deltaCutInKineticEnergy[aMaterial->GetIndex()];
// some kinematics......................
G4double gamma= KineticEnergy/ParticleMass + 1.;
G4double r = electron_mass_c2/ParticleMass;
G4double tmax = 2.*ParticleMass*r*(gamma*gamma - 1.)/(1. + 2.*gamma*r + r*r);
betasquare=Psquare/Esquare ;
MaxKineticEnergyTransfer = 2.*electron_mass_c2*Psquare
/(summass*summass+2.*electron_mass_c2*KineticEnergy);
// Validity range for delta electron cross section
G4double DeltaCut = G4std::max(DeltaCutInKineticEnergyNow,Eexc);
G4double DeltaCut = cutForDelta[aMaterial->GetIndex()];
// This should not be a case
if(DeltaCut >= tmax)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
// sampling kinetic energy of the delta ray
if( MaxKineticEnergyTransfer <= DeltaCut )
{
// pathological case (it should not happen ,
// there is no change at all).....
xc = DeltaCut / tmax;
rate = tmax / TotalEnergy;
rate = rate*rate ;
G4double spin = aParticle->GetDefinition()->GetPDGSpin() ;
return &aParticleChange;
//return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
else
{
// normal case ......................................
xc = DeltaCut / MaxKineticEnergyTransfer ;
rate = MaxKineticEnergyTransfer / TotalEnergy ;
rate = rate*rate ;
G4double spin = aParticle->GetDefinition()->GetPDGSpin() ;
// sampling follows ...
// sampling follows ...
do {
x=xc/(1.-(1.-xc)*G4UniformRand());
@@ -929,13 +1202,10 @@ G4VParticleChange* G4hLowEnergyIonisation::PostStepDoIt(
}
} while( G4UniformRand() > grej );
}
DeltaKineticEnergy = x * MaxKineticEnergyTransfer ;
if(DeltaKineticEnergy <= 0.)
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
DeltaKineticEnergy = x * tmax;
DeltaTotalMomentum = sqrt(DeltaKineticEnergy * (DeltaKineticEnergy +
2. * electron_mass_c2 )) ;
TotalMomentum = sqrt(Psquare) ;
@@ -950,7 +1220,7 @@ G4VParticleChange* G4hLowEnergyIonisation::PostStepDoIt(
// direction of the delta electron ........
phi = twopi * G4UniformRand() ;
sintheta = sqrt((1.+costheta)*(1.-costheta));
sintheta = sqrt(1. - costheta*costheta);
dirx = sintheta * cos(phi) ;
diry = sintheta * sin(phi) ;
dirz = costheta ;
@@ -968,8 +1238,69 @@ G4VParticleChange* G4hLowEnergyIonisation::PostStepDoIt(
// fill aParticleChange
finalKineticEnergy = KineticEnergy - DeltaKineticEnergy ;
G4double Edep = 0 ;
// Generation of Fluorescence and Auger
size_t nSecondaries = 0;
size_t totalNumber = 1;
G4std::vector<G4DynamicParticle*>* secondaryVector = 0;
G4DynamicParticle* aSecondary = 0;
G4ParticleDefinition* type = 0;
// Select atom and shell
G4int Z = SelectRandomAtom(aMaterial, KineticEnergy);
G4int shell = shellCS->SelectRandomShell(Z, KineticEnergy,
ParticleMass,DeltaKineticEnergy);
const G4AtomicShell* atomicShell =
(G4AtomicTransitionManager::Instance())->Shell(Z, shell);
G4double bindingEnergy = atomicShell->BindingEnergy();
if(verboseLevel > 1) {
G4cout << "PostStep Z= " << Z << " shell= " << shell
<< " bindingE(keV)= " << bindingEnergy/keV
<< " finalE(keV)= " << finalKineticEnergy/keV
<< G4endl;
}
// Fluorescence data start from element 6
if (theFluo && Z > 5 && finalKineticEnergy >= bindingEnergy
&& (bindingEnergy >= minGammaEnergy
|| bindingEnergy >= minElectronEnergy) ) {
G4int shellId = atomicShell->ShellId();
secondaryVector = deexcitationManager.GenerateParticles(Z, shellId);
if (secondaryVector != 0) {
nSecondaries = secondaryVector->size();
for (size_t i = 0; i<nSecondaries; i++) {
aSecondary = (*secondaryVector)[i];
if (aSecondary) {
G4double e = aSecondary->GetKineticEnergy();
type = aSecondary->GetDefinition();
if (e < finalKineticEnergy &&
((type == G4Gamma::Gamma() && e > minGammaEnergy ) ||
(type == G4Electron::Electron() && e > minElectronEnergy ))) {
finalKineticEnergy -= e;
totalNumber++;
} else {
delete aSecondary;
(*secondaryVector)[i] = 0;
}
}
}
}
}
// Save delta-electrons
G4double edep = 0.0;
if (finalKineticEnergy > MinKineticEnergy)
{
finalPx = TotalMomentum*ParticleDirection.x()
@@ -988,23 +1319,191 @@ G4VParticleChange* G4hLowEnergyIonisation::PostStepDoIt(
}
else
{
finalKineticEnergy = 0. ;
Edep = finalKineticEnergy ;
edep = finalKineticEnergy;
finalKineticEnergy = 0.;
aParticleChange.SetMomentumChange(ParticleDirection.x(),
ParticleDirection.y(),ParticleDirection.z());
if (aParticle->GetDefinition()->GetParticleName() == "proton")
aParticleChange.SetStatusChange(fStopAndKill);
else aParticleChange.SetStatusChange(fStopButAlive);
}
aParticleChange.SetEnergyChange( finalKineticEnergy );
aParticleChange.SetNumberOfSecondaries(1);
aParticleChange.AddSecondary( theDeltaRay );
aParticleChange.SetLocalEnergyDeposit (Edep);
aParticleChange.SetLocalEnergyDeposit (edep);
aParticleChange.SetNumberOfSecondaries(totalNumber);
aParticleChange.AddSecondary(theDeltaRay);
// Save Fluorescence and Auger
if (secondaryVector) {
for (size_t l = 0; l < nSecondaries; l++) {
aSecondary = (*secondaryVector)[l];
if(aSecondary) aParticleChange.AddSecondary(aSecondary);
}
delete secondaryVector;
}
return G4VContinuousDiscreteProcess::PostStepDoIt(trackData,stepData);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4std::vector<G4DynamicParticle*>*
G4hLowEnergyIonisation::DeexciteAtom(const G4Material* material,
G4double incidentEnergy,
G4double hMass,
G4double eLoss)
{
if (verboseLevel > 1) {
G4cout << "DeexciteAtom: cutForPhotons(keV)= " << minGammaEnergy/keV
<< " cutForElectrons(keV)= " << minElectronEnergy/keV
<< " eLoss(MeV)= " << eLoss
<< G4endl;
}
if(eLoss < minGammaEnergy && eLoss < minElectronEnergy) return 0;
G4int index = material->GetIndex();
G4double eexc = material->GetIonisation()->GetMeanExcitationEnergy();
G4double x = cutForDelta[index]/eexc;
G4double deltaEnergy = eexc*(x + 1)*log(x + 1)/x;
G4AtomicTransitionManager* transitionManager =
G4AtomicTransitionManager::Instance();
size_t nElements = material->GetNumberOfElements();
const G4ElementVector* theElementVector = material->GetElementVector();
G4bool stop = true;
for (size_t j=0; j<nElements; j++) {
G4int Z = (G4int)((*theElementVector)[j]->GetZ());
G4double maxE = transitionManager->Shell(Z, 0)->BindingEnergy();
if (Z>5 && (maxE>minGammaEnergy || maxE>minElectronEnergy) ) {
stop = false;
break;
}
}
if(stop) return 0;
// create vector of tracks of secondary particles
G4std::vector<G4DynamicParticle*>* partVector =
new G4std::vector<G4DynamicParticle*>;
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,
incidentEnergy, eLoss);
for (size_t i=0; i<nElements; i++) {
size_t nVacancies = n[i];
G4int Z = (G4int)((*theElementVector)[i]->GetZ());
G4double maxE = transitionManager->Shell(Z, 0)->BindingEnergy();
if (nVacancies && Z>5 && (maxE>minGammaEnergy || maxE>minElectronEnergy)) {
for(size_t j=0; j<nVacancies; j++) {
shell = shellCS->SelectRandomShell(Z,incidentEnergy,hMass,deltaEnergy);
shellId = transitionManager->Shell(Z, shell)->ShellId();
G4double maxE = transitionManager->Shell(Z, shell)->BindingEnergy();
if (maxE>minGammaEnergy || maxE>minElectronEnergy ) {
secVector = deexcitationManager.GenerateParticles(Z, shellId);
} else {
secVector = 0;
}
if (secVector) {
for (size_t l = 0; l<secVector->size(); l++) {
aSecondary = (*secVector)[l];
if(aSecondary) {
e = aSecondary->GetKineticEnergy();
type = aSecondary->GetDefinition();
if ( etot + e <= eLoss &&
(type == G4Gamma::Gamma() && e > minGammaEnergy ) ||
(type == G4Electron::Electron() && e > minElectronEnergy)) {
etot += e;
partVector->push_back(aSecondary);
} else {
delete aSecondary;
}
}
}
delete secVector;
}
}
}
}
if(partVector->empty()) {
delete partVector;
return 0;
}
return partVector;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4int G4hLowEnergyIonisation::SelectRandomAtom(const G4Material* material,
G4double kineticEnergy) const
{
G4int nElements = material->GetNumberOfElements();
G4int Z = 0;
if(nElements == 1) {
Z = (G4int)(material->GetZ());
return Z;
}
const G4ElementVector* theElementVector = material->GetElementVector();
G4std::vector<G4double> p;
G4int index = material->GetIndex();
G4double norm = 0.0;
for (G4int j=0; j<nElements; j++) {
const G4VEMDataSet* set = (zFluoDataVector[index])->GetComponent(j);
G4double cross = set->FindValue(kineticEnergy);
p.push_back(cross);
norm += cross;
}
G4double q = norm*G4UniformRand();
for (G4int i=0; i<nElements; i++) {
if(p[i] > q) {
Z = (G4int)((*theElementVector)[i]->GetZ());
break;
}
q -= p[i];
}
return Z;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4hLowEnergyIonisation::ComputeDEDX(
const G4ParticleDefinition* aParticle,
const G4Material* material,
@@ -1113,8 +1612,8 @@ G4double G4hLowEnergyIonisation::BarkasTerm(const G4Material* material,
for (G4int i = 0; i<numberOfElements; i++) {
AMaterial = (*theElementVector)(i)->GetA()*mole/g;
ZMaterial = (*theElementVector)(i)->GetZ();
AMaterial = (*theElementVector)[i]->GetA()*mole/g;
ZMaterial = (*theElementVector)[i]->GetZ();
G4double X = 137.0 * 137.0 * beta2 / ZMaterial;
@@ -1213,7 +1712,7 @@ G4double G4hLowEnergyIonisation::ElectronicLossFluctuation(
// get particle data
G4double tkin = particle->GetKineticEnergy();
G4double particleMass = particle->GetMass() ;
G4double deltaCutInKineticEnergyNow = deltaCutInKineticEnergy[imaterial];
G4double deltaCutInKineticEnergyNow = cutForDelta[imaterial];
// shortcut for very very small loss
if(meanLoss < minLoss) return meanLoss ;
@@ -1431,6 +1930,20 @@ G4double G4hLowEnergyIonisation::ElectronicLossFluctuation(
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyIonisation::SetCutForSecondaryPhotons(G4double cut)
{
minGammaEnergy = cut;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyIonisation::SetCutForAugerElectrons(G4double cut)
{
minElectronEnergy = cut;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyIonisation::PrintInfoDefinition() const
{
G4String comments = " Knock-on electron cross sections . ";
@@ -1461,14 +1974,14 @@ void G4hLowEnergyIonisation::PrintInfoDefinition() const
G4bool printHead = true;
const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
// loop for materials
for (G4int j=0 ; j < numOfMaterials; j++) {
const G4Material* material= (*theMaterialTable)[j];
G4double deltaCutNow = deltaCutInKineticEnergy[(material->GetIndex())] ;
G4double deltaCutNow = cutForDelta[(material->GetIndex())] ;
G4double eexc = material->GetIonisation()->GetMeanExcitationEnergy();
if(eexc > deltaCutNow) {
@@ -21,8 +21,8 @@
// ********************************************************************
//
//
// $Id: G4hLowEnergyLoss.cc,v 1.9.2.2 2001/06/28 20:19:34 gunter Exp $
// GEANT4 tag $Name: $
// $Id: G4hLowEnergyLoss.cc,v 1.14 2001/11/23 11:45:29 vnivanch Exp $
// GEANT4 tag $Name: geant4-04-00 $
//
// -----------------------------------------------------------
// GEANT 4 class implementation file
@@ -44,6 +44,7 @@
// 31/03/00 rename to lowenergy as G4hLowEnergyLoss.cc V.Ivanchenko
// 05/11/00 new method to calculate particle ranges
// 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
// --------------------------------------------------------------
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -161,6 +162,66 @@ G4hLowEnergyLoss::~G4hLowEnergyLoss()
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4int G4hLowEnergyLoss::GetNumberOfProcesses()
{
return NumberOfProcesses;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyLoss::SetNumberOfProcesses(G4int number)
{
NumberOfProcesses=number;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyLoss::PlusNumberOfProcesses()
{
NumberOfProcesses++;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyLoss::MinusNumberOfProcesses()
{
NumberOfProcesses--;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyLoss::SetdRoverRange(G4double value)
{
dRoverRange = value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyLoss::SetRndmStep (G4bool value)
{
rndmStepFlag = value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyLoss::SetEnlossFluc (G4bool value)
{
EnlossFlucFlag = value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyLoss::SetStepFunction (G4double c1, G4double c2)
{
dRoverRange = c1;
finalRange = c2;
c1lim=dRoverRange;
c2lim=2.*(1-dRoverRange)*finalRange;
c3lim=-(1.-dRoverRange)*finalRange*finalRange;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4hLowEnergyLoss::BuildDEDXTable(
@@ -178,7 +239,12 @@ void G4hLowEnergyLoss::BuildDEDXTable(
// create table if there is no table or there is a new cut value
G4bool MakeTable = false ;
G4double ElectronCutInRange = G4Electron::Electron()->GetCuts();
// ---- 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
Charge = aParticleType.GetPDGCharge()/eplus;
@@ -196,9 +262,8 @@ void G4hLowEnergyLoss::BuildDEDXTable(
)
MakeTable = true ;
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if( MakeTable )
{
@@ -316,9 +381,8 @@ void G4hLowEnergyLoss::BuildRangeTable(
// Build range table from the energy loss table
{
Mass = proton_mass_c2;
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if( Charge >0.)
{
@@ -355,9 +419,8 @@ void G4hLowEnergyLoss::BuildRangeTable(
void G4hLowEnergyLoss::BuildTimeTables(
const G4ParticleDefinition& aParticleType)
{
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(&aParticleType == G4Proton::Proton())
{
@@ -455,7 +518,6 @@ void G4hLowEnergyLoss::BuildLabTimeVector(G4int materialIndex,
LowEdgeEnergy,tau,Value ;
G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
//const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
// low energy part first...
losslim = physicsVector->GetValue(tlim,isOut);
@@ -515,8 +577,7 @@ void G4hLowEnergyLoss::BuildProperTimeVector(G4int materialIndex,
LowEdgeEnergy,tau,Value ;
G4PhysicsVector* physicsVector= (*theDEDXTable)[materialIndex];
//const G4MaterialTable* theMaterialTable = G4Material::GetMaterialTable() ;
// low energy part first...
losslim = physicsVector->GetValue(tlim,isOut);
taulim=tlim/ParticleMass ;
@@ -699,9 +760,8 @@ void G4hLowEnergyLoss::BuildRangeCoeffATable(
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "A"
{
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(Charge>0.)
{
@@ -772,9 +832,8 @@ void G4hLowEnergyLoss::BuildRangeCoeffBTable(
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "B"
{
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(Charge>0.)
{
@@ -844,9 +903,8 @@ void G4hLowEnergyLoss::BuildRangeCoeffCTable(
// Build tables of coefficients for the energy loss calculation
// create table for coefficients "C"
{
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(Charge>0.)
{
@@ -917,9 +975,8 @@ void G4hLowEnergyLoss::BuildInverseRangeTable(
{
G4double SmallestRange,BiggestRange ;
G4bool isOut ;
const G4MaterialTable* theMaterialTable=
G4Material::GetMaterialTable();
G4int numOfMaterials = theMaterialTable->length();
G4int numOfMaterials = G4Material::GetNumberOfMaterials();
if(&aParticleType == G4Proton::Proton())
{
if(theInverseRangepTable)
@@ -57,6 +57,7 @@
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "G4ElementVector.hh"
#include "G4Material.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -101,7 +102,7 @@ void G4hNuclearStoppingModel::InitializeMe()
}
// Default is nuclear stopping fluctuations On
nStopingPowerTable->SetNuclearStoppingFluctuationsOn();
nStopingPowerTable->SetNuclearStoppingFluctuationsOff();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -165,8 +166,8 @@ G4double G4hNuclearStoppingModel::StoppingPower(
G4double nloss = 0.0;
for (G4int iel=0; iel<NumberOfElements; iel++) {
const G4Element* element = (*theElementVector)(iel) ;
G4double z2 = element->GetZ() ;
const G4Element* element = (*theElementVector)[iel] ;
G4double z2 = element->GetZ();
G4double m2 = element->GetA()*mole/g ;
nloss += (nStopingPowerTable->
NuclearStoppingPower(kineticEnergy, z1, z2, m1, m2))
@@ -60,6 +60,7 @@
#include "G4DynamicParticle.hh"
#include "G4ParticleDefinition.hh"
#include "G4ElementVector.hh"
#include "G4Material.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -251,7 +252,7 @@ G4double G4hParametrisedLossModel::StoppingPower(
// loop for the elements in the material
for (G4int i=0; i<numberOfElements; i++) {
const G4Element* element = (*theElementVector)(i) ;
const G4Element* element = (*theElementVector)[i] ;
G4double z = element->GetZ() ;
eloss +=(eStopingPowerTable->ElectronicStoppingPower(z,kineticEnergy))
* theAtomicNumDensityVector[i] ;
@@ -270,7 +271,7 @@ G4double G4hParametrisedLossModel::StoppingPower(
// loop for the elements in the material
for (G4int i=0; i<numberOfElements; i++)
{
const G4Element* element = (*theElementVector)(i) ;
const G4Element* element = (*theElementVector)[i] ;
G4double z = element->GetZ() ;
eloss += (eStopingPowerTable->ElectronicStoppingPower(z,kineticEnergy))
* theAtomicNumDensityVector[i];
@@ -0,0 +1,107 @@
//
// ********************************************************************
// * 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: G4hShellCrossSection
//
// Author: S. Dussoni and A. Mantero (Alfonso.Mantero@ge.infn.it)
//
// History:
// -----------
// 23 Oct 2001 A. Mantero 1st implementation
// 24 Oct 2001 MGP Cleaned up
// 30 Oct 2001 V.Ivanchenko Include formula (53)
//
// -------------------------------------------------------------------
#include "globals.hh"
#include "G4hShellCrossSection.hh"
#include "G4AtomicTransitionManager.hh"
#include "G4Electron.hh"
G4hShellCrossSection::G4hShellCrossSection()
{ }
G4hShellCrossSection::~G4hShellCrossSection()
{ }
G4std::vector<G4double> G4hShellCrossSection::Probabilities(
G4int Z,
G4double incidentEnergy,
G4double hMass,
G4double deltaEnergy) const
{
// Cross-sections for proton ionization calculated as in
// "M. Gryzinski, Two-Particle Collisions. I. General Relations for
// Collisions in the Laboratory system, Phys.Rev. 138 A305"
// Other reference papers are Gryzinski's "Paper I" and "Paper II"
// V.Ivanchenko add only implementation of the formula (53)
// last factor neglected because it is 1 with a good accuracy
G4AtomicTransitionManager* transitionManager =
G4AtomicTransitionManager::Instance();
size_t nShells = transitionManager->NumberOfShells(Z);
// Vector that stores the calculated cross-sections for each shell:
G4std::vector<G4double> crossSections;
// Partial and total cross-section used for normalization of crossSections:
G4double aCrossSection = 0.;
G4double totalCrossSection = 0.;
// In this loop we calculate cross-section for every shell in the atom
for (size_t k=0; k<nShells; k++)
{
G4double bindingEnergy = transitionManager->Shell(Z,k)->BindingEnergy();
G4double xDelta = deltaEnergy/bindingEnergy;
G4double y = incidentEnergy*electron_mass_c2/(bindingEnergy*hMass);
G4double x = 1.0 + xDelta;
aCrossSection = (x/(xDelta*(1. + 1./y))
+ 4.*log(2.7 + sqrt(y))/3.)/ (x*x*x);
// Calculation of total cross-section
totalCrossSection += aCrossSection;
// Fill the vector of cross sections with the value just calculated
crossSections.push_back(aCrossSection);
}
// Normalization of relative cross-sections to 1
for (size_t j=0; j<nShells; j++)
{
crossSections[j] = crossSections[j] / totalCrossSection;
}
// Returns the normalized vector
return crossSections;
}