Import Geant4 9.5.0 source tree

This commit is contained in:
Gabriele Cosmo
2016-06-09 16:46:55 +02:00
parent 89a9605df1
commit b1eb5424d2
10957 changed files with 888481 additions and 160139 deletions
@@ -0,0 +1,322 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNABornExcitationModel.cc,v 1.10 2010-08-24 13:51:06 sincerti Exp $
// GEANT4 tag $Name: not supported by cvs2svn $
//
#include "G4DNABornExcitationModel.hh"
#include "G4DNAChemistryManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNABornExcitationModel::G4DNABornExcitationModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
nistwater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if( verboseLevel>0 )
{
G4cout << "Born excitation model is constructed " << G4endl;
}
fParticleChangeForGamma = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNABornExcitationModel::~G4DNABornExcitationModel()
{
// Cross section
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
for (pos = tableData.begin(); pos != tableData.end(); ++pos)
{
G4DNACrossSectionDataSet* table = pos->second;
delete table;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNABornExcitationModel::Initialise(const G4ParticleDefinition* particle,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNABornExcitationModel::Initialise()" << G4endl;
G4String fileElectron("dna/sigma_excitation_e_born");
G4String fileProton("dna/sigma_excitation_p_born");
G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
G4String electron;
G4String proton;
G4double scaleFactor = (1.e-22 / 3.343) * m*m;
// *** ELECTRON
electron = electronDef->GetParticleName();
tableFile[electron] = fileElectron;
lowEnergyLimit[electron] = 9. * eV;
highEnergyLimit[electron] = 1. * MeV;
// Cross section
G4DNACrossSectionDataSet* tableE = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
tableE->LoadData(fileElectron);
tableData[electron] = tableE;
// *** PROTON
proton = protonDef->GetParticleName();
tableFile[proton] = fileProton;
lowEnergyLimit[proton] = 500. * keV;
highEnergyLimit[proton] = 100. * MeV;
// Cross section
G4DNACrossSectionDataSet* tableP = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
tableP->LoadData(fileProton);
tableData[proton] = tableP;
//
if (particle==electronDef)
{
SetLowEnergyLimit(lowEnergyLimit[electron]);
SetHighEnergyLimit(highEnergyLimit[electron]);
}
if (particle==protonDef)
{
SetLowEnergyLimit(lowEnergyLimit[proton]);
SetHighEnergyLimit(highEnergyLimit[proton]);
}
if( verboseLevel>0 )
{
G4cout << "Born excitation model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / keV << " keV for "
<< particle->GetParticleName()
<< G4endl;
}
if (isInitialised) { return; }
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNABornExcitationModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double ekin,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNABornExcitationModel" << G4endl;
if (
particleDefinition != G4Proton::ProtonDefinition()
&&
particleDefinition != G4Electron::ElectronDefinition()
)
return 0;
// Calculate total cross section for model
G4double lowLim = 0;
G4double highLim = 0;
G4double sigma=0;
if (material == nistwater || material->GetBaseMaterial() == nistwater)
{
const G4String& particleName = particleDefinition->GetParticleName();
std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
pos1 = lowEnergyLimit.find(particleName);
if (pos1 != lowEnergyLimit.end())
{
lowLim = pos1->second;
}
std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
pos2 = highEnergyLimit.find(particleName);
if (pos2 != highEnergyLimit.end())
{
highLim = pos2->second;
}
if (ekin >= lowLim && ekin < highLim)
{
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
pos = tableData.find(particleName);
if (pos != tableData.end())
{
G4DNACrossSectionDataSet* table = pos->second;
if (table != 0)
{
sigma = table->FindValue(ekin);
}
}
else
{
G4Exception("G4DNABornExcitationModel::CrossSectionPerVolume","em0002",
FatalException,"Model not applicable to particle type.");
}
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if (waterMaterial)
return sigma*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNABornExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
const G4MaterialCutsCouple* /*couple*/,
const G4DynamicParticle* aDynamicParticle,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNABornExcitationModel" << G4endl;
G4double k = aDynamicParticle->GetKineticEnergy();
const G4String& particleName = aDynamicParticle->GetDefinition()->GetParticleName();
G4int level = RandomSelect(k,particleName);
G4double excitationEnergy = waterStructure.ExcitationEnergy(level);
G4double newEnergy = k - excitationEnergy;
if (newEnergy > 0)
{
fParticleChangeForGamma->ProposeMomentumDirection(aDynamicParticle->GetMomentumDirection());
fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
}
const G4Track * theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack();
G4DNAChemistryManager::Instance()->CreateWaterMolecule(fExcitedMolecule,
level,
theIncomingTrack);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNABornExcitationModel::RandomSelect(G4double k, const G4String& particle)
{
G4int level = 0;
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
pos = tableData.find(particle);
if (pos != tableData.end())
{
G4DNACrossSectionDataSet* table = pos->second;
if (table != 0)
{
G4double* valuesBuffer = new G4double[table->NumberOfComponents()];
const size_t n(table->NumberOfComponents());
size_t i(n);
G4double value = 0.;
while (i>0)
{
i--;
valuesBuffer[i] = table->GetComponent(i)->FindValue(k);
value += valuesBuffer[i];
}
value *= G4UniformRand();
i = n;
while (i > 0)
{
i--;
if (valuesBuffer[i] > value)
{
delete[] valuesBuffer;
return i;
}
value -= valuesBuffer[i];
}
if (valuesBuffer) delete[] valuesBuffer;
}
}
else
{
G4Exception("G4DNABornExcitationModel::RandomSelect","em0002",
FatalException,"Model not applicable to particle type.");
}
return level;
}
@@ -0,0 +1,754 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNABornIonisationModel.cc,v 1.18 2010-11-03 12:22:36 sincerti Exp $
// GEANT4 tag $Name: not supported by cvs2svn $
//
#include "G4DNABornIonisationModel.hh"
#include "G4UAtomicDeexcitation.hh"
#include "G4LossTableManager.hh"
#include "G4DNAChemistryManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNABornIonisationModel::G4DNABornIonisationModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
nistwater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if( verboseLevel>0 )
{
G4cout << "Born ionisation model is constructed " << G4endl;
}
//Mark this model as "applicable" for atomic deexcitation
SetDeexcitationFlag(true);
fParticleChangeForGamma = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNABornIonisationModel::~G4DNABornIonisationModel()
{
// Cross section
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
for (pos = tableData.begin(); pos != tableData.end(); ++pos)
{
G4DNACrossSectionDataSet* table = pos->second;
delete table;
}
// Final state
eVecm.clear();
pVecm.clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNABornIonisationModel::Initialise(const G4ParticleDefinition* particle,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNABornIonisationModel::Initialise()" << G4endl;
// Energy limits
G4String fileElectron("dna/sigma_ionisation_e_born");
G4String fileProton("dna/sigma_ionisation_p_born");
G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
G4String electron;
G4String proton;
G4double scaleFactor = (1.e-22 / 3.343) * m*m;
char *path = getenv("G4LEDATA");
// *** ELECTRON
electron = electronDef->GetParticleName();
tableFile[electron] = fileElectron;
lowEnergyLimit[electron] = 11. * eV;
highEnergyLimit[electron] = 1. * MeV;
// Cross section
G4DNACrossSectionDataSet* tableE = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
tableE->LoadData(fileElectron);
tableData[electron] = tableE;
// Final state
std::ostringstream eFullFileName;
eFullFileName << path << "/dna/sigmadiff_ionisation_e_born.dat";
std::ifstream eDiffCrossSection(eFullFileName.str().c_str());
if (!eDiffCrossSection)
{
G4Exception("G4DNABornIonisationModel::Initialise","em0003",
FatalException,"Missing data file:/dna/sigmadiff_ionisation_e_born.dat");
}
eTdummyVec.push_back(0.);
while(!eDiffCrossSection.eof())
{
double tDummy;
double eDummy;
eDiffCrossSection>>tDummy>>eDummy;
if (tDummy != eTdummyVec.back()) eTdummyVec.push_back(tDummy);
for (int j=0; j<5; j++)
{
eDiffCrossSection>>eDiffCrossSectionData[j][tDummy][eDummy];
// SI - only if eof is not reached !
if (!eDiffCrossSection.eof()) eDiffCrossSectionData[j][tDummy][eDummy]*=scaleFactor;
eVecm[tDummy].push_back(eDummy);
}
}
// *** PROTON
proton = protonDef->GetParticleName();
tableFile[proton] = fileProton;
lowEnergyLimit[proton] = 500. * keV;
highEnergyLimit[proton] = 100. * MeV;
// Cross section
G4DNACrossSectionDataSet* tableP = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
tableP->LoadData(fileProton);
tableData[proton] = tableP;
// Final state
std::ostringstream pFullFileName;
pFullFileName << path << "/dna/sigmadiff_ionisation_p_born.dat";
std::ifstream pDiffCrossSection(pFullFileName.str().c_str());
if (!pDiffCrossSection)
{
G4Exception("G4DNABornIonisationModel::Initialise","em0003",
FatalException,"Missing data file:/dna/sigmadiff_ionisation_p_born.dat");
}
pTdummyVec.push_back(0.);
while(!pDiffCrossSection.eof())
{
double tDummy;
double eDummy;
pDiffCrossSection>>tDummy>>eDummy;
if (tDummy != pTdummyVec.back()) pTdummyVec.push_back(tDummy);
for (int j=0; j<5; j++)
{
pDiffCrossSection>>pDiffCrossSectionData[j][tDummy][eDummy];
// SI - only if eof is not reached !
if (!pDiffCrossSection.eof()) pDiffCrossSectionData[j][tDummy][eDummy]*=scaleFactor;
pVecm[tDummy].push_back(eDummy);
}
}
//
if (particle==electronDef)
{
SetLowEnergyLimit(lowEnergyLimit[electron]);
SetHighEnergyLimit(highEnergyLimit[electron]);
}
if (particle==protonDef)
{
SetLowEnergyLimit(lowEnergyLimit[proton]);
SetHighEnergyLimit(highEnergyLimit[proton]);
}
if( verboseLevel>0 )
{
G4cout << "Born ionisation model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / keV << " keV for "
<< particle->GetParticleName()
<< G4endl;
}
//
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
if (isInitialised) { return; }
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNABornIonisationModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double ekin,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNABornIonisationModel" << G4endl;
if (
particleDefinition != G4Proton::ProtonDefinition()
&&
particleDefinition != G4Electron::ElectronDefinition()
)
return 0;
// Calculate total cross section for model
G4double lowLim = 0;
G4double highLim = 0;
G4double sigma=0;
if (material == nistwater || material->GetBaseMaterial() == nistwater)
{
const G4String& particleName = particleDefinition->GetParticleName();
std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
pos1 = lowEnergyLimit.find(particleName);
if (pos1 != lowEnergyLimit.end())
{
lowLim = pos1->second;
}
std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
pos2 = highEnergyLimit.find(particleName);
if (pos2 != highEnergyLimit.end())
{
highLim = pos2->second;
}
if (ekin >= lowLim && ekin < highLim)
{
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
pos = tableData.find(particleName);
if (pos != tableData.end())
{
G4DNACrossSectionDataSet* table = pos->second;
if (table != 0)
{
sigma = table->FindValue(ekin);
}
}
else
{
G4Exception("G4DNABornIonisationModel::CrossSectionPerVolume","em0002",
FatalException,"Model not applicable to particle type.");
}
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if (waterMaterial)
return sigma*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNABornIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* ,//must be set!
const G4DynamicParticle* particle,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNABornIonisationModel" << G4endl;
G4double lowLim = 0;
G4double highLim = 0;
G4double k = particle->GetKineticEnergy();
const G4String& particleName = particle->GetDefinition()->GetParticleName();
std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
pos1 = lowEnergyLimit.find(particleName);
if (pos1 != lowEnergyLimit.end())
{
lowLim = pos1->second;
}
std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
pos2 = highEnergyLimit.find(particleName);
if (pos2 != highEnergyLimit.end())
{
highLim = pos2->second;
}
if (k >= lowLim && k < highLim)
{
G4ParticleMomentum primaryDirection = particle->GetMomentumDirection();
G4double particleMass = particle->GetDefinition()->GetPDGMass();
G4double totalEnergy = k + particleMass;
G4double pSquare = k * (totalEnergy + particleMass);
G4double totalMomentum = std::sqrt(pSquare);
G4int ionizationShell = RandomSelect(k,particleName);
// sample deexcitation
// here we assume that H_{2}O electronic levels are the same of Oxigen.
// this can be considered true with a rough 10% error in energy on K-shell,
G4int secNumberInit = 0; // need to know at a certain point the enrgy of secondaries
G4int secNumberFinal = 0; // So I'll make the diference and then sum the energies
G4double bindingEnergy = 0;
bindingEnergy = waterStructure.IonisationEnergy(ionizationShell);
if(fAtomDeexcitation) {
G4int Z = 8;
G4AtomicShellEnumerator as = fKShell;
if (ionizationShell <5 && ionizationShell >1)
{
as = G4AtomicShellEnumerator(4-ionizationShell);
}
else if (ionizationShell <2)
{
as = G4AtomicShellEnumerator(3);
}
// FOR DEBUG ONLY
// if (ionizationShell == 4) {
//
// G4cout << "Z: " << Z << " as: " << as
// << " ionizationShell: " << ionizationShell << " bindingEnergy: "<< bindingEnergy/eV << G4endl;
// G4cout << "Press <Enter> key to continue..." << G4endl;
// G4cin.ignore();
// }
const G4AtomicShell* shell = fAtomDeexcitation->GetAtomicShell(Z, as);
secNumberInit = fvect->size();
fAtomDeexcitation->GenerateParticles(fvect, shell, Z, 0, 0);
secNumberFinal = fvect->size();
}
G4double secondaryKinetic = RandomizeEjectedElectronEnergy(particle->GetDefinition(),k,ionizationShell);
G4double cosTheta = 0.;
G4double phi = 0.;
RandomizeEjectedElectronDirection(particle->GetDefinition(), k,secondaryKinetic, cosTheta, phi);
G4double sinTheta = std::sqrt(1.-cosTheta*cosTheta);
G4double dirX = sinTheta*std::cos(phi);
G4double dirY = sinTheta*std::sin(phi);
G4double dirZ = cosTheta;
G4ThreeVector deltaDirection(dirX,dirY,dirZ);
deltaDirection.rotateUz(primaryDirection);
if (particle->GetDefinition() == G4Electron::ElectronDefinition())
{
G4double deltaTotalMomentum = std::sqrt(secondaryKinetic*(secondaryKinetic + 2.*electron_mass_c2 ));
G4double finalPx = totalMomentum*primaryDirection.x() - deltaTotalMomentum*deltaDirection.x();
G4double finalPy = totalMomentum*primaryDirection.y() - deltaTotalMomentum*deltaDirection.y();
G4double finalPz = totalMomentum*primaryDirection.z() - deltaTotalMomentum*deltaDirection.z();
G4double finalMomentum = std::sqrt(finalPx*finalPx + finalPy*finalPy + finalPz*finalPz);
finalPx /= finalMomentum;
finalPy /= finalMomentum;
finalPz /= finalMomentum;
G4ThreeVector direction;
direction.set(finalPx,finalPy,finalPz);
fParticleChangeForGamma->ProposeMomentumDirection(direction.unit()) ;
}
else fParticleChangeForGamma->ProposeMomentumDirection(primaryDirection) ;
// note thta secondaryKinetic is the nergy of the delta ray, not of all secondaries.
G4double scatteredEnergy = k-bindingEnergy-secondaryKinetic;
G4double deexSecEnergy = 0;
for (G4int j=secNumberInit; j < secNumberFinal; j++) {
deexSecEnergy = deexSecEnergy + (*fvect)[j]->GetKineticEnergy();
}
fParticleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(k-scatteredEnergy-secondaryKinetic-deexSecEnergy);
G4DynamicParticle* dp = new G4DynamicParticle (G4Electron::Electron(),deltaDirection,secondaryKinetic) ;
fvect->push_back(dp);
const G4Track * theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack();
G4DNAChemistryManager::Instance()->CreateWaterMolecule(fIonizedMolecule,
ionizationShell,
theIncomingTrack);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNABornIonisationModel::RandomizeEjectedElectronEnergy(G4ParticleDefinition* particleDefinition,
G4double k, G4int shell)
{
if (particleDefinition == G4Electron::ElectronDefinition())
{
G4double maximumEnergyTransfer=0.;
if ((k+waterStructure.IonisationEnergy(shell))/2. > k) maximumEnergyTransfer=k;
else maximumEnergyTransfer = (k+waterStructure.IonisationEnergy(shell))/2.;
// SI : original method
/*
G4double crossSectionMaximum = 0.;
for(G4double value=waterStructure.IonisationEnergy(shell); value<=maximumEnergyTransfer; value+=0.1*eV)
{
G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k/eV, value/eV, shell);
if(differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
}
*/
// SI : alternative method
G4double crossSectionMaximum = 0.;
G4double minEnergy = waterStructure.IonisationEnergy(shell);
G4double maxEnergy = maximumEnergyTransfer;
G4int nEnergySteps = 50;
G4double value(minEnergy);
G4double stpEnergy(std::pow(maxEnergy/value, 1./static_cast<G4double>(nEnergySteps-1)));
G4int step(nEnergySteps);
while (step>0)
{
step--;
G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k/eV, value/eV, shell);
if(differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
value*=stpEnergy;
}
//
G4double secondaryElectronKineticEnergy=0.;
do
{
secondaryElectronKineticEnergy = G4UniformRand() * (maximumEnergyTransfer-waterStructure.IonisationEnergy(shell));
} while(G4UniformRand()*crossSectionMaximum >
DifferentialCrossSection(particleDefinition, k/eV,(secondaryElectronKineticEnergy+waterStructure.IonisationEnergy(shell))/eV,shell));
return secondaryElectronKineticEnergy;
}
if (particleDefinition == G4Proton::ProtonDefinition())
{
G4double maximumKineticEnergyTransfer = 4.* (electron_mass_c2 / proton_mass_c2) * k;
G4double crossSectionMaximum = 0.;
for (G4double value = waterStructure.IonisationEnergy(shell);
value<=4.*waterStructure.IonisationEnergy(shell) ;
value+=0.1*eV)
{
G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k/eV, value/eV, shell);
if (differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
}
G4double secondaryElectronKineticEnergy = 0.;
do
{
secondaryElectronKineticEnergy = G4UniformRand() * maximumKineticEnergyTransfer;
} while(G4UniformRand()*crossSectionMaximum >=
DifferentialCrossSection(particleDefinition, k/eV,(secondaryElectronKineticEnergy+waterStructure.IonisationEnergy(shell))/eV,shell));
return secondaryElectronKineticEnergy;
}
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
void G4DNABornIonisationModel::RandomizeEjectedElectronDirection(G4ParticleDefinition* particleDefinition,
G4double k,
G4double secKinetic,
G4double & cosTheta,
G4double & phi )
{
if (particleDefinition == G4Electron::ElectronDefinition())
{
phi = twopi * G4UniformRand();
if (secKinetic < 50.*eV) cosTheta = (2.*G4UniformRand())-1.;
else if (secKinetic <= 200.*eV)
{
if (G4UniformRand() <= 0.1) cosTheta = (2.*G4UniformRand())-1.;
else cosTheta = G4UniformRand()*(std::sqrt(2.)/2);
}
else
{
G4double sin2O = (1.-secKinetic/k) / (1.+secKinetic/(2.*electron_mass_c2));
cosTheta = std::sqrt(1.-sin2O);
}
}
if (particleDefinition == G4Proton::ProtonDefinition())
{
G4double maxSecKinetic = 4.* (electron_mass_c2 / proton_mass_c2) * k;
phi = twopi * G4UniformRand();
// cosTheta = std::sqrt(secKinetic / maxSecKinetic);
// Restriction below 100 eV from Emfietzoglou (2000)
if (secKinetic>100*eV) cosTheta = std::sqrt(secKinetic / maxSecKinetic);
else cosTheta = (2.*G4UniformRand())-1.;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
double G4DNABornIonisationModel::DifferentialCrossSection(G4ParticleDefinition * particleDefinition,
G4double k,
G4double energyTransfer,
G4int ionizationLevelIndex)
{
G4double sigma = 0.;
if (energyTransfer >= waterStructure.IonisationEnergy(ionizationLevelIndex))
{
G4double valueT1 = 0;
G4double valueT2 = 0;
G4double valueE21 = 0;
G4double valueE22 = 0;
G4double valueE12 = 0;
G4double valueE11 = 0;
G4double xs11 = 0;
G4double xs12 = 0;
G4double xs21 = 0;
G4double xs22 = 0;
if (particleDefinition == G4Electron::ElectronDefinition())
{
// k should be in eV and energy transfer eV also
std::vector<double>::iterator t2 = std::upper_bound(eTdummyVec.begin(),eTdummyVec.end(), k);
std::vector<double>::iterator t1 = t2-1;
// SI : the following condition avoids situations where energyTransfer >last vector element
if (energyTransfer <= eVecm[(*t1)].back() && energyTransfer <= eVecm[(*t2)].back() )
{
std::vector<double>::iterator e12 = std::upper_bound(eVecm[(*t1)].begin(),eVecm[(*t1)].end(), energyTransfer);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e22 = std::upper_bound(eVecm[(*t2)].begin(),eVecm[(*t2)].end(), energyTransfer);
std::vector<double>::iterator e21 = e22-1;
valueT1 =*t1;
valueT2 =*t2;
valueE21 =*e21;
valueE22 =*e22;
valueE12 =*e12;
valueE11 =*e11;
xs11 = eDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE11];
xs12 = eDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE12];
xs21 = eDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE21];
xs22 = eDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE22];
}
}
if (particleDefinition == G4Proton::ProtonDefinition())
{
// k should be in eV and energy transfer eV also
std::vector<double>::iterator t2 = std::upper_bound(pTdummyVec.begin(),pTdummyVec.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator e12 = std::upper_bound(pVecm[(*t1)].begin(),pVecm[(*t1)].end(), energyTransfer);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e22 = std::upper_bound(pVecm[(*t2)].begin(),pVecm[(*t2)].end(), energyTransfer);
std::vector<double>::iterator e21 = e22-1;
valueT1 =*t1;
valueT2 =*t2;
valueE21 =*e21;
valueE22 =*e22;
valueE12 =*e12;
valueE11 =*e11;
xs11 = pDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE11];
xs12 = pDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE12];
xs21 = pDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE21];
xs22 = pDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE22];
}
G4double xsProduct = xs11 * xs12 * xs21 * xs22;
if (xsProduct != 0.)
{
sigma = QuadInterpolator( valueE11, valueE12,
valueE21, valueE22,
xs11, xs12,
xs21, xs22,
valueT1, valueT2,
k, energyTransfer);
}
}
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNABornIonisationModel::LogLogInterpolate(G4double e1,
G4double e2,
G4double e,
G4double xs1,
G4double xs2)
{
G4double a = (std::log10(xs2)-std::log10(xs1)) / (std::log10(e2)-std::log10(e1));
G4double b = std::log10(xs2) - a*std::log10(e2);
G4double sigma = a*std::log10(e) + b;
G4double value = (std::pow(10.,sigma));
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNABornIonisationModel::QuadInterpolator(G4double e11, G4double e12,
G4double e21, G4double e22,
G4double xs11, G4double xs12,
G4double xs21, G4double xs22,
G4double t1, G4double t2,
G4double t, G4double e)
{
G4double interpolatedvalue1 = LogLogInterpolate(e11, e12, e, xs11, xs12);
G4double interpolatedvalue2 = LogLogInterpolate(e21, e22, e, xs21, xs22);
G4double value = LogLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNABornIonisationModel::RandomSelect(G4double k, const G4String& particle )
{
G4int level = 0;
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
pos = tableData.find(particle);
if (pos != tableData.end())
{
G4DNACrossSectionDataSet* table = pos->second;
if (table != 0)
{
G4double* valuesBuffer = new G4double[table->NumberOfComponents()];
const size_t n(table->NumberOfComponents());
size_t i(n);
G4double value = 0.;
while (i>0)
{
i--;
valuesBuffer[i] = table->GetComponent(i)->FindValue(k);
value += valuesBuffer[i];
}
value *= G4UniformRand();
i = n;
while (i > 0)
{
i--;
if (valuesBuffer[i] > value)
{
delete[] valuesBuffer;
return i;
}
value -= valuesBuffer[i];
}
if (valuesBuffer) delete[] valuesBuffer;
}
}
else
{
G4Exception("G4DNABornIonisationModel::RandomSelect","em0002",
FatalException,"Model not applicable to particle type.");
}
return level;
}
@@ -0,0 +1,439 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAChampionElasticModel.cc,v 1.16 2010-11-11 22:32:22 sincerti Exp $
// GEANT4 tag $Name: not supported by cvs2svn $
//
#include "G4DNAChampionElasticModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAChampionElasticModel::G4DNAChampionElasticModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
nistwater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
killBelowEnergy = 4*eV;
lowEnergyLimit = 0 * eV;
highEnergyLimit = 1. * MeV;
SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if( verboseLevel>0 )
{
G4cout << "Champion Elastic model is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / eV << " eV - "
<< highEnergyLimit / MeV << " MeV"
<< G4endl;
}
fParticleChangeForGamma = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAChampionElasticModel::~G4DNAChampionElasticModel()
{
// For total cross section
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
for (pos = tableData.begin(); pos != tableData.end(); ++pos)
{
G4DNACrossSectionDataSet* table = pos->second;
delete table;
}
// For final state
eVecm.clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAChampionElasticModel::Initialise(const G4ParticleDefinition* /*particle*/,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNAChampionElasticModel::Initialise()" << G4endl;
// Energy limits
if (LowEnergyLimit() < lowEnergyLimit)
{
G4cout << "G4DNAChampionElasticModel: low energy limit increased from " <<
LowEnergyLimit()/eV << " eV to " << lowEnergyLimit/eV << " eV" << G4endl;
SetLowEnergyLimit(lowEnergyLimit);
}
if (HighEnergyLimit() > highEnergyLimit)
{
G4cout << "G4DNAChampionElasticModel: high energy limit decreased from " <<
HighEnergyLimit()/MeV << " MeV to " << highEnergyLimit/MeV << " MeV" << G4endl;
SetHighEnergyLimit(highEnergyLimit);
}
// Reading of data files
G4double scaleFactor = 1e-16*cm*cm;
G4String fileElectron("dna/sigma_elastic_e_champion");
G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
G4String electron;
// *** ELECTRON
// For total cross section
electron = electronDef->GetParticleName();
tableFile[electron] = fileElectron;
G4DNACrossSectionDataSet* tableE = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
tableE->LoadData(fileElectron);
tableData[electron] = tableE;
// For final state
char *path = getenv("G4LEDATA");
if (!path)
{
G4Exception("G4ChampionElasticModel::Initialise","em0006",
FatalException,"G4LEDATA environment variable not set.");
return;
}
std::ostringstream eFullFileName;
eFullFileName << path << "/dna/sigmadiff_cumulatedshort_elastic_e_champion.dat";
std::ifstream eDiffCrossSection(eFullFileName.str().c_str());
if (!eDiffCrossSection)
G4Exception("G4DNAChampionElasticModel::Initialise","em0003",
FatalException,"Missing data file:/dna/sigmadiff_cumulatedshort_elastic_e_champion.dat");
eTdummyVec.push_back(0.);
while(!eDiffCrossSection.eof())
{
double tDummy;
double eDummy;
eDiffCrossSection>>tDummy>>eDummy;
// SI : mandatory eVecm initialization
if (tDummy != eTdummyVec.back())
{
eTdummyVec.push_back(tDummy);
eVecm[tDummy].push_back(0.);
}
eDiffCrossSection>>eDiffCrossSectionData[tDummy][eDummy];
if (eDummy != eVecm[tDummy].back()) eVecm[tDummy].push_back(eDummy);
}
// End final state
if (verboseLevel > 2)
G4cout << "Loaded cross section files for Champion Elastic model" << G4endl;
if( verboseLevel>0 )
{
G4cout << "Champion Elastic model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / MeV << " MeV"
<< G4endl;
}
if (isInitialised) { return; }
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* p,
G4double ekin,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNAChampionElasticModel" << G4endl;
// Calculate total cross section for model
G4double sigma=0;
if (material == nistwater || material->GetBaseMaterial() == nistwater)
{
const G4String& particleName = p->GetParticleName();
if (ekin < highEnergyLimit)
{
//SI : XS must not be zero otherwise sampling of secondaries method ignored
if (ekin < killBelowEnergy) return DBL_MAX;
//
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
pos = tableData.find(particleName);
if (pos != tableData.end())
{
G4DNACrossSectionDataSet* table = pos->second;
if (table != 0)
{
sigma = table->FindValue(ekin);
}
}
else
{
G4Exception("G4DNAChampionElasticModel::ComputeCrossSectionPerVolume","em0002",
FatalException,"Model not applicable to particle type.");
}
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
}
return sigma*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAChampionElasticModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
const G4MaterialCutsCouple* /*couple*/,
const G4DynamicParticle* aDynamicElectron,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNAChampionElasticModel" << G4endl;
G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
if (electronEnergy0 < killBelowEnergy)
{
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(electronEnergy0);
return ;
}
if (electronEnergy0>= killBelowEnergy && electronEnergy0 < highEnergyLimit)
{
G4double cosTheta = RandomizeCosTheta(electronEnergy0);
G4double phi = 2. * pi * G4UniformRand();
G4ThreeVector zVers = aDynamicElectron->GetMomentumDirection();
G4ThreeVector xVers = zVers.orthogonal();
G4ThreeVector yVers = zVers.cross(xVers);
G4double xDir = std::sqrt(1. - cosTheta*cosTheta);
G4double yDir = xDir;
xDir *= std::cos(phi);
yDir *= std::sin(phi);
G4ThreeVector zPrimeVers((xDir*xVers + yDir*yVers + cosTheta*zVers));
fParticleChangeForGamma->ProposeMomentumDirection(zPrimeVers.unit()) ;
fParticleChangeForGamma->SetProposedKineticEnergy(electronEnergy0);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::Theta
(G4ParticleDefinition * particleDefinition, G4double k, G4double integrDiff)
{
G4double theta = 0.;
G4double valueT1 = 0;
G4double valueT2 = 0;
G4double valueE21 = 0;
G4double valueE22 = 0;
G4double valueE12 = 0;
G4double valueE11 = 0;
G4double xs11 = 0;
G4double xs12 = 0;
G4double xs21 = 0;
G4double xs22 = 0;
if (particleDefinition == G4Electron::ElectronDefinition())
{
std::vector<double>::iterator t2 = std::upper_bound(eTdummyVec.begin(),eTdummyVec.end(), k);
std::vector<double>::iterator t1 = t2-1;
std::vector<double>::iterator e12 = std::upper_bound(eVecm[(*t1)].begin(),eVecm[(*t1)].end(), integrDiff);
std::vector<double>::iterator e11 = e12-1;
std::vector<double>::iterator e22 = std::upper_bound(eVecm[(*t2)].begin(),eVecm[(*t2)].end(), integrDiff);
std::vector<double>::iterator e21 = e22-1;
valueT1 =*t1;
valueT2 =*t2;
valueE21 =*e21;
valueE22 =*e22;
valueE12 =*e12;
valueE11 =*e11;
xs11 = eDiffCrossSectionData[valueT1][valueE11];
xs12 = eDiffCrossSectionData[valueT1][valueE12];
xs21 = eDiffCrossSectionData[valueT2][valueE21];
xs22 = eDiffCrossSectionData[valueT2][valueE22];
}
if (xs11==0 && xs12==0 && xs21==0 && xs22==0) return (0.);
theta = QuadInterpolator ( valueE11, valueE12,
valueE21, valueE22,
xs11, xs12,
xs21, xs22,
valueT1, valueT2,
k, integrDiff );
return theta;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::LinLogInterpolate(G4double e1,
G4double e2,
G4double e,
G4double xs1,
G4double xs2)
{
G4double d1 = std::log(xs1);
G4double d2 = std::log(xs2);
G4double value = std::exp(d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::LinLinInterpolate(G4double e1,
G4double e2,
G4double e,
G4double xs1,
G4double xs2)
{
G4double d1 = xs1;
G4double d2 = xs2;
G4double value = (d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::LogLogInterpolate(G4double e1,
G4double e2,
G4double e,
G4double xs1,
G4double xs2)
{
G4double a = (std::log10(xs2)-std::log10(xs1)) / (std::log10(e2)-std::log10(e1));
G4double b = std::log10(xs2) - a*std::log10(e2);
G4double sigma = a*std::log10(e) + b;
G4double value = (std::pow(10.,sigma));
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::QuadInterpolator(G4double e11, G4double e12,
G4double e21, G4double e22,
G4double xs11, G4double xs12,
G4double xs21, G4double xs22,
G4double t1, G4double t2,
G4double t, G4double e)
{
// Log-Log
/*
G4double interpolatedvalue1 = LogLogInterpolate(e11, e12, e, xs11, xs12);
G4double interpolatedvalue2 = LogLogInterpolate(e21, e22, e, xs21, xs22);
G4double value = LogLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
// Lin-Log
G4double interpolatedvalue1 = LinLogInterpolate(e11, e12, e, xs11, xs12);
G4double interpolatedvalue2 = LinLogInterpolate(e21, e22, e, xs21, xs22);
G4double value = LinLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
*/
// Lin-Lin
G4double interpolatedvalue1 = LinLinInterpolate(e11, e12, e, xs11, xs12);
G4double interpolatedvalue2 = LinLinInterpolate(e21, e22, e, xs21, xs22);
G4double value = LinLinInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAChampionElasticModel::RandomizeCosTheta(G4double k)
{
G4double integrdiff=0;
G4double uniformRand=G4UniformRand();
integrdiff = uniformRand;
G4double theta=0.;
G4double cosTheta=0.;
theta = Theta(G4Electron::ElectronDefinition(),k/eV,integrdiff);
cosTheta= std::cos(theta*pi/180);
return cosTheta;
}
@@ -0,0 +1,147 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "G4DNADiffusionControlledModel.hh"
#include "Randomize.hh"
#include "G4Track.hh"
#include "G4DNAMolecularReactionTable.hh"
G4DNADiffusionControlledModel::G4DNADiffusionControlledModel() : G4VDNAReactionModel()
{
fReactionData = 0 ;
}
G4DNADiffusionControlledModel::G4DNADiffusionControlledModel(const G4DNADiffusionControlledModel& __right) :
G4VDNAReactionModel(__right)
{
fReactionData = 0 ;
}
G4DNADiffusionControlledModel& G4DNADiffusionControlledModel::operator=(const G4DNADiffusionControlledModel& right)
{
if(this == &right) return *this;
fReactionData = 0;
return *this;
}
G4DNADiffusionControlledModel::~G4DNADiffusionControlledModel()
{
fReactionData = 0 ;
}
void G4DNADiffusionControlledModel::Initialise(const G4Molecule* __molecule, const G4Track&)
{
fReactionData = fReactionTable->GetReactionData(__molecule);
}
void G4DNADiffusionControlledModel::InitialiseToPrint(const G4Molecule* __molecule)
{
fReactionData = fReactionTable->GetReactionData(__molecule);
}
G4double G4DNADiffusionControlledModel::GetReactionRadius(const G4Molecule* mol1,
const G4Molecule* mol2)
{
G4double __output = fReactionTable -> GetReactionData(mol1,mol2)->GetReducedReactionRadius();
return __output ;
}
G4double G4DNADiffusionControlledModel::GetReactionRadius(const G4int __i)
{
G4double __output = (*fReactionData)[__i] -> GetReducedReactionRadius();
return __output ;
}
G4bool G4DNADiffusionControlledModel::FindReaction(const G4Track& __trackA,
const G4Track& __trackB,
const G4double __R,
G4double& __r,
const G4bool __alongStepReaction)
{
G4double __postStepSeparation = 0;
bool __do_break = false ;
G4double __R2 = __R*__R ;
int k = 0 ;
for(; k < 3 ; k++)
{
__postStepSeparation += std::pow(__trackA.GetPosition()[k] - __trackB.GetPosition()[k],2);
if(__postStepSeparation > __R2)
{
__do_break = true ;
break ;
}
}
if(__do_break == false)
{
// The loop was not break
// => __r^2 < __R^2
__r = std::sqrt(__postStepSeparation);
return true;
}
else if(__alongStepReaction == true)
{
//G4cout << "alongStepReaction==true" << G4endl;
//Along step cheack and
// the loop has break
// Continue loop
for(; k < 3 ; k++)
{
__postStepSeparation += std::pow(__trackA.GetPosition()[k] - __trackB.GetPosition()[k],2);
}
// Use Green approach : the Brownian bridge
__r = (__postStepSeparation = std::sqrt(__postStepSeparation) );
G4Molecule* __moleculeA = GetMolecule(__trackA);
G4Molecule* __moleculeB = GetMolecule(__trackB);
G4double __D = __moleculeA->GetDiffusionCoefficient() + __moleculeB->GetDiffusionCoefficient();
G4ThreeVector __preStepPositionA = __trackA.GetStep()->GetPreStepPoint() ->GetPosition();
G4ThreeVector __preStepPositionB = __trackB.GetStep()->GetPreStepPoint() ->GetPosition();
if(__preStepPositionA == __trackA.GetPosition())
{
G4ExceptionDescription exceptionDescription ;
exceptionDescription << "The molecule : " << __moleculeA->GetName();
exceptionDescription << " did not move since the previous step ";
G4Exception("G4DNADiffusionControlledModel::FindReaction","G4DNADiffusionControlledModel001",
FatalErrorInArgument,exceptionDescription);
}
G4double __preStepSeparation = (__preStepPositionA - __preStepPositionB).mag();
G4double __probabiltyOfEncounter = std::exp(-(__preStepSeparation - __R)*(__postStepSeparation - __R)
/ (__D* (__trackB.GetStep()->GetDeltaTime())));
G4double __selectedPOE = G4UniformRand();
if(__selectedPOE<=__probabiltyOfEncounter) return true;
}
return false ;
}
@@ -0,0 +1,543 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNADingfelderChargeDecreaseModel.cc,v 1.9 2010-04-06 11:00:35 sincerti Exp $
// GEANT4 tag $Name: not supported by cvs2svn $
//
#include "G4DNADingfelderChargeDecreaseModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNADingfelderChargeDecreaseModel::G4DNADingfelderChargeDecreaseModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
nistwater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
numberOfPartialCrossSections[0] = 0;
numberOfPartialCrossSections[1] = 0;
numberOfPartialCrossSections[2] = 0;
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if( verboseLevel>0 )
{
G4cout << "Dingfelder charge decrease model is constructed " << G4endl;
}
fParticleChangeForGamma = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNADingfelderChargeDecreaseModel::~G4DNADingfelderChargeDecreaseModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNADingfelderChargeDecreaseModel::Initialise(const G4ParticleDefinition* particle,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNADingfelderChargeDecreaseModel::Initialise()" << G4endl;
// Energy limits
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
G4ParticleDefinition* alphaPlusPlusDef = instance->GetIon("alpha++");
G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
G4String proton;
G4String alphaPlusPlus;
G4String alphaPlus;
// LIMITS
proton = protonDef->GetParticleName();
lowEnergyLimit[proton] = 100. * eV;
highEnergyLimit[proton] = 100. * MeV;
alphaPlusPlus = alphaPlusPlusDef->GetParticleName();
lowEnergyLimit[alphaPlusPlus] = 1. * keV;
highEnergyLimit[alphaPlusPlus] = 400. * MeV;
alphaPlus = alphaPlusDef->GetParticleName();
lowEnergyLimit[alphaPlus] = 1. * keV;
highEnergyLimit[alphaPlus] = 400. * MeV;
//
if (particle==protonDef)
{
SetLowEnergyLimit(lowEnergyLimit[proton]);
SetHighEnergyLimit(highEnergyLimit[proton]);
}
if (particle==alphaPlusPlusDef)
{
SetLowEnergyLimit(lowEnergyLimit[alphaPlusPlus]);
SetHighEnergyLimit(highEnergyLimit[alphaPlusPlus]);
}
if (particle==alphaPlusDef)
{
SetLowEnergyLimit(lowEnergyLimit[alphaPlus]);
SetHighEnergyLimit(highEnergyLimit[alphaPlus]);
}
// Final state
//PROTON
f0[0][0]=1.;
a0[0][0]=-0.180;
a1[0][0]=-3.600;
b0[0][0]=-18.22;
b1[0][0]=-1.997;
c0[0][0]=0.215;
d0[0][0]=3.550;
x0[0][0]=3.450;
x1[0][0]=5.251;
numberOfPartialCrossSections[0] = 1;
//ALPHA++
f0[0][1]=1.; a0[0][1]=0.95;
a1[0][1]=-2.75;
b0[0][1]=-23.00;
c0[0][1]=0.215;
d0[0][1]=2.95;
x0[0][1]=3.50;
f0[1][1]=1.;
a0[1][1]=0.95;
a1[1][1]=-2.75;
b0[1][1]=-23.73;
c0[1][1]=0.250;
d0[1][1]=3.55;
x0[1][1]=3.72;
x1[0][1]=-1.;
b1[0][1]=-1.;
x1[1][1]=-1.;
b1[1][1]=-1.;
numberOfPartialCrossSections[1] = 2;
// ALPHA+
f0[0][2]=1.;
a0[0][2]=0.65;
a1[0][2]=-2.75;
b0[0][2]=-21.81;
c0[0][2]=0.232;
d0[0][2]=2.95;
x0[0][2]=3.53;
x1[0][2]=-1.;
b1[0][2]=-1.;
numberOfPartialCrossSections[2] = 1;
//
if( verboseLevel>0 )
{
G4cout << "Dingfelder charge decrease model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / keV << " keV - "
<< HighEnergyLimit() / MeV << " MeV for "
<< particle->GetParticleName()
<< G4endl;
}
if (isInitialised) { return; }
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNADingfelderChargeDecreaseModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double k,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNADingfelderChargeDecreaseModel" << G4endl;
// Calculate total cross section for model
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (
particleDefinition != G4Proton::ProtonDefinition()
&&
particleDefinition != instance->GetIon("alpha++")
&&
particleDefinition != instance->GetIon("alpha+")
)
return 0;
G4double lowLim = 0;
G4double highLim = 0;
G4double crossSection = 0.;
if (material == nistwater || material->GetBaseMaterial() == nistwater)
{
const G4String& particleName = particleDefinition->GetParticleName();
std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
pos1 = lowEnergyLimit.find(particleName);
if (pos1 != lowEnergyLimit.end())
{
lowLim = pos1->second;
}
std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
pos2 = highEnergyLimit.find(particleName);
if (pos2 != highEnergyLimit.end())
{
highLim = pos2->second;
}
if (k >= lowLim && k < highLim)
{
crossSection = Sum(k,particleDefinition);
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << crossSection/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << crossSection*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
}
return crossSection*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNADingfelderChargeDecreaseModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* /*couple*/,
const G4DynamicParticle* aDynamicParticle,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNADingfelderChargeDecreaseModel" << G4endl;
G4double inK = aDynamicParticle->GetKineticEnergy();
G4ParticleDefinition* definition = aDynamicParticle->GetDefinition();
G4double particleMass = definition->GetPDGMass();
G4int finalStateIndex = RandomSelect(inK,definition);
G4int n = NumberOfFinalStates(definition, finalStateIndex);
G4double waterBindingEnergy = WaterBindingEnergyConstant(definition, finalStateIndex);
G4double outgoingParticleBindingEnergy = OutgoingParticleBindingEnergyConstant(definition, finalStateIndex);
G4double outK = 0.;
if (definition==G4Proton::Proton())
outK = inK - n*(inK*electron_mass_c2/proton_mass_c2) - waterBindingEnergy + outgoingParticleBindingEnergy;
else
outK = inK - n*(inK*electron_mass_c2/particleMass) - waterBindingEnergy + outgoingParticleBindingEnergy;
if (outK<0)
{
G4Exception("G4DNADingfelderChargeDecreaseModel::SampleSecondaries","em0004",
FatalException,"Final kinetic energy is negative.");
}
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(waterBindingEnergy);
G4DynamicParticle* dp = new G4DynamicParticle (OutgoingParticleDefinition(definition, finalStateIndex),
aDynamicParticle->GetMomentumDirection(),
outK) ;
fvect->push_back(dp);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNADingfelderChargeDecreaseModel::NumberOfFinalStates(G4ParticleDefinition* particleDefinition,
G4int finalStateIndex )
{
if (particleDefinition == G4Proton::Proton()) return 1;
G4DNAGenericIonsManager*instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == instance->GetIon("alpha++") )
{
if (finalStateIndex==0) return 1;
return 2;
}
if (particleDefinition == instance->GetIon("alpha+") ) return 1;
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4ParticleDefinition* G4DNADingfelderChargeDecreaseModel::OutgoingParticleDefinition (G4ParticleDefinition* particleDefinition,
G4int finalStateIndex)
{
G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
if (particleDefinition == G4Proton::Proton()) return instance->GetIon("hydrogen");
if (particleDefinition == instance->GetIon("alpha++") )
{
if (finalStateIndex == 0) return instance->GetIon("alpha+");
return instance->GetIon("helium");
}
if (particleDefinition == instance->GetIon("alpha+") ) return instance->GetIon("helium");
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNADingfelderChargeDecreaseModel::WaterBindingEnergyConstant(G4ParticleDefinition* particleDefinition,
G4int finalStateIndex )
{
// Ionization energy of first water shell
// Rad. Phys. Chem. 59 p.267 by Dingf. et al.
// W + 10.79 eV -> W+ + e-
G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
if(particleDefinition == G4Proton::Proton()) return 10.79*eV;
if (particleDefinition == instance->GetIon("alpha++") )
{
// Binding energy for W+ -> W++ + e- 10.79 eV
// Binding energy for W -> W+ + e- 10.79 eV
//
// Ionization energy of first water shell
// Rad. Phys. Chem. 59 p.267 by Dingf. et al.
if (finalStateIndex == 0) return 10.79*eV;
return 10.79*2*eV;
}
if (particleDefinition == instance->GetIon("alpha+") )
{
// Binding energy for W+ -> W++ + e- 10.79 eV
// Binding energy for W -> W+ + e- 10.79 eV
//
// Ionization energy of first water shell
// Rad. Phys. Chem. 59 p.267 by Dingf. et al.
return 10.79*eV;
}
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNADingfelderChargeDecreaseModel::OutgoingParticleBindingEnergyConstant(G4ParticleDefinition* particleDefinition,
G4int finalStateIndex)
{
G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
if(particleDefinition == G4Proton::Proton()) return 13.6*eV;
if (particleDefinition == instance->GetIon("alpha++") )
{
// Binding energy for He+ -> He++ + e- 54.509 eV
// Binding energy for He -> He+ + e- 24.587 eV
if (finalStateIndex==0) return 54.509*eV;
return (54.509 + 24.587)*eV;
}
if (particleDefinition == instance->GetIon("alpha+") )
{
// Binding energy for He+ -> He++ + e- 54.509 eV
// Binding energy for He -> He+ + e- 24.587 eV
return 24.587*eV;
}
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNADingfelderChargeDecreaseModel::PartialCrossSection(G4double k, G4int index,
const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == G4Proton::ProtonDefinition()) particleTypeIndex=0;
if (particleDefinition == instance->GetIon("alpha++")) particleTypeIndex=1;
if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=2;
//
// sigma(T) = f0 10 ^ y(log10(T/eV))
//
// / a0 x + b0 x < x0
// |
// y(x) = < a0 x + b0 - c0 (x - x0)^d0 x0 <= x < x1
// |
// \ a1 x + b1 x >= x1
//
//
// f0, a0, a1, b0, b1, c0, d0, x0, x1 are parameters that change for protons and helium (0, +, ++)
//
// f0 has been added to the code in order to manage partial (shell-dependent) cross sections (if no shell dependence is present. f0=1. Sum of f0 over the considered shells should give 1)
//
// From Rad. Phys. and Chem. 59 (2000) 255-275, M. Dingfelder et al.
// Inelastic-collision cross sections of liquid water for interactions of energetic proton
//
if (x1[index][particleTypeIndex]<x0[index][particleTypeIndex])
{
//
// if x1 < x0 means that x1 and b1 will be calculated with the following formula (this piece of code is run on all alphas and not on protons)
//
// x1 = x0 + ((a0 - a1)/(c0 * d0)) ^ (1 / (d0 - 1))
//
// b1 = (a0 - a1) * x1 + b0 - c0 * (x1 - x0) ^ d0
//
x1[index][particleTypeIndex]=x0[index][particleTypeIndex] + std::pow((a0[index][particleTypeIndex] - a1[index][particleTypeIndex])
/ (c0[index][particleTypeIndex] * d0[index][particleTypeIndex]), 1. / (d0[index][particleTypeIndex] - 1.));
b1[index][particleTypeIndex]=(a0[index][particleTypeIndex] - a1[index][particleTypeIndex]) * x1[index][particleTypeIndex]
+ b0[index][particleTypeIndex] - c0[index][particleTypeIndex] * std::pow(x1[index][particleTypeIndex]
- x0[index][particleTypeIndex], d0[index][particleTypeIndex]);
}
G4double x(std::log10(k/eV));
G4double y;
if (x<x0[index][particleTypeIndex])
y=a0[index][particleTypeIndex] * x + b0[index][particleTypeIndex];
else if (x<x1[index][particleTypeIndex])
y=a0[index][particleTypeIndex] * x + b0[index][particleTypeIndex] - c0[index][particleTypeIndex]
* std::pow(x - x0[index][particleTypeIndex], d0[index][particleTypeIndex]);
else
y=a1[index][particleTypeIndex] * x + b1[index][particleTypeIndex];
return f0[index][particleTypeIndex] * std::pow(10., y)*m*m;
}
G4int G4DNADingfelderChargeDecreaseModel::RandomSelect(G4double k,
const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == G4Proton::ProtonDefinition()) particleTypeIndex = 0;
if (particleDefinition == instance->GetIon("alpha++")) particleTypeIndex = 1;
if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex = 2;
const G4int n = numberOfPartialCrossSections[particleTypeIndex];
G4double* values(new G4double[n]);
G4double value(0);
G4int i = n;
while (i>0)
{
i--;
values[i]=PartialCrossSection(k, i, particleDefinition);
value+=values[i];
}
value*=G4UniformRand();
i=n;
while (i>0)
{
i--;
if (values[i]>value)
break;
value-=values[i];
}
delete[] values;
return i;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNADingfelderChargeDecreaseModel::Sum(G4double k, const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == G4Proton::ProtonDefinition()) particleTypeIndex=0;
if (particleDefinition == instance->GetIon("alpha++")) particleTypeIndex=1;
if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=2;
G4double totalCrossSection = 0.;
for (G4int i=0; i<numberOfPartialCrossSections[particleTypeIndex]; i++)
{
totalCrossSection += PartialCrossSection(k,i,particleDefinition);
}
return totalCrossSection;
}
@@ -0,0 +1,514 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNADingfelderChargeIncreaseModel.cc,v 1.9 2010-04-06 11:00:35 sincerti Exp $
// GEANT4 tag $Name: not supported by cvs2svn $
//
#include "G4DNADingfelderChargeIncreaseModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNADingfelderChargeIncreaseModel::G4DNADingfelderChargeIncreaseModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
nistwater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
numberOfPartialCrossSections[0]=0;
numberOfPartialCrossSections[1]=0;
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if( verboseLevel>0 )
{
G4cout << "Dingfelder charge increase model is constructed " << G4endl;
}
fParticleChangeForGamma = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNADingfelderChargeIncreaseModel::~G4DNADingfelderChargeIncreaseModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNADingfelderChargeIncreaseModel::Initialise(const G4ParticleDefinition* particle,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNADingfelderChargeIncreaseModel::Initialise()" << G4endl;
// Energy limits
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
G4ParticleDefinition* hydrogenDef = instance->GetIon("hydrogen");
G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
G4ParticleDefinition* heliumDef = instance->GetIon("helium");
G4String hydrogen;
G4String alphaPlus;
G4String helium;
// LIMITS
hydrogen = hydrogenDef->GetParticleName();
lowEnergyLimit[hydrogen] = 100. * eV;
highEnergyLimit[hydrogen] = 100. * MeV;
alphaPlus = alphaPlusDef->GetParticleName();
lowEnergyLimit[alphaPlus] = 1. * keV;
highEnergyLimit[alphaPlus] = 400. * MeV;
helium = heliumDef->GetParticleName();
lowEnergyLimit[helium] = 1. * keV;
highEnergyLimit[helium] = 400. * MeV;
//
if (particle==hydrogenDef)
{
SetLowEnergyLimit(lowEnergyLimit[hydrogen]);
SetHighEnergyLimit(highEnergyLimit[hydrogen]);
}
if (particle==alphaPlusDef)
{
SetLowEnergyLimit(lowEnergyLimit[alphaPlus]);
SetHighEnergyLimit(highEnergyLimit[alphaPlus]);
}
if (particle==heliumDef)
{
SetLowEnergyLimit(lowEnergyLimit[helium]);
SetHighEnergyLimit(highEnergyLimit[helium]);
}
// Final state
//ALPHA+
f0[0][0]=1.;
a0[0][0]=2.25;
a1[0][0]=-0.75;
b0[0][0]=-32.10;
c0[0][0]=0.600;
d0[0][0]=2.40;
x0[0][0]=4.60;
x1[0][0]=-1.;
b1[0][0]=-1.;
numberOfPartialCrossSections[0]=1;
//HELIUM
f0[0][1]=1.;
a0[0][1]=2.25;
a1[0][1]=-0.75;
b0[0][1]=-30.93;
c0[0][1]=0.590;
d0[0][1]=2.35;
x0[0][1]=4.29;
f0[1][1]=1.;
a0[1][1]=2.25;
a1[1][1]=-0.75;
b0[1][1]=-32.61;
c0[1][1]=0.435;
d0[1][1]=2.70;
x0[1][1]=4.45;
x1[0][1]=-1.;
b1[0][1]=-1.;
x1[1][1]=-1.;
b1[1][1]=-1.;
numberOfPartialCrossSections[1]=2;
//
if( verboseLevel>0 )
{
G4cout << "Dingfelder charge increase model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / keV << " keV - "
<< HighEnergyLimit() / MeV << " MeV for "
<< particle->GetParticleName()
<< G4endl;
}
if (isInitialised) { return; }
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNADingfelderChargeIncreaseModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double k,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNADingfelderChargeIncreaseModel" << G4endl;
// Calculate total cross section for model
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (
particleDefinition != instance->GetIon("hydrogen")
&&
particleDefinition != instance->GetIon("alpha+")
&&
particleDefinition != instance->GetIon("helium")
)
return 0;
G4double lowLim = 0;
G4double highLim = 0;
G4double totalCrossSection = 0.;
if (material == nistwater || material->GetBaseMaterial() == nistwater)
{
const G4String& particleName = particleDefinition->GetParticleName();
std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
pos1 = lowEnergyLimit.find(particleName);
if (pos1 != lowEnergyLimit.end())
{
lowLim = pos1->second;
}
std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
pos2 = highEnergyLimit.find(particleName);
if (pos2 != highEnergyLimit.end())
{
highLim = pos2->second;
}
if (k >= lowLim && k < highLim)
{
//HYDROGEN
if (particleDefinition == instance->GetIon("hydrogen"))
{
const G4double aa = 2.835;
const G4double bb = 0.310;
const G4double cc = 2.100;
const G4double dd = 0.760;
const G4double fac = 1.0e-18;
const G4double rr = 13.606 * eV;
G4double t = k / (proton_mass_c2/electron_mass_c2);
G4double x = t / rr;
G4double temp = 4.0 * pi * Bohr_radius/nm * Bohr_radius/nm * fac;
G4double sigmal = temp * cc * (std::pow(x,dd));
G4double sigmah = temp * (aa * std::log(1.0 + x) + bb) / x;
totalCrossSection = 1.0/(1.0/sigmal + 1.0/sigmah) *m*m;
}
else
{
totalCrossSection = Sum(k,particleDefinition);
}
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << totalCrossSection/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << totalCrossSection*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
}
return totalCrossSection*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNADingfelderChargeIncreaseModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
const G4MaterialCutsCouple* /*couple*/,
const G4DynamicParticle* aDynamicParticle,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNADingfelderChargeIncreaseModel" << G4endl;
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(0.);
G4ParticleDefinition* definition = aDynamicParticle->GetDefinition();
G4double particleMass = definition->GetPDGMass();
G4double inK = aDynamicParticle->GetKineticEnergy();
G4int finalStateIndex = RandomSelect(inK,definition);
G4int n = NumberOfFinalStates(definition,finalStateIndex);
G4double outK = inK - IncomingParticleBindingEnergyConstant(definition,finalStateIndex);
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
G4double electronK;
if (definition == instance->GetIon("hydrogen")) electronK = inK*electron_mass_c2/proton_mass_c2;
else electronK = inK*electron_mass_c2/(particleMass);
if (outK<0)
{
G4Exception("G4DNADingfelderChargeIncreaseModel::SampleSecondaries","em0004",
FatalException,"Final kinetic energy is negative.");
}
G4DynamicParticle* dp = new G4DynamicParticle
(OutgoingParticleDefinition(definition,finalStateIndex),
aDynamicParticle->GetMomentumDirection(),
outK) ;
fvect->push_back(dp);
n = n - 1;
while (n>0)
{
n--;
fvect->push_back(new G4DynamicParticle
(G4Electron::Electron(), aDynamicParticle->GetMomentumDirection(), electronK) );
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNADingfelderChargeIncreaseModel::NumberOfFinalStates(G4ParticleDefinition* particleDefinition,
G4int finalStateIndex )
{
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == instance->GetIon("hydrogen")) return 2;
if (particleDefinition == instance->GetIon("alpha+")) return 2;
if (particleDefinition == instance->GetIon("helium"))
{ if (finalStateIndex==0) return 2;
return 3;
}
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4ParticleDefinition* G4DNADingfelderChargeIncreaseModel::OutgoingParticleDefinition (G4ParticleDefinition* particleDefinition,
G4int finalStateIndex)
{
G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
if (particleDefinition == instance->GetIon("hydrogen")) return G4Proton::Proton();
if (particleDefinition == instance->GetIon("alpha+")) return instance->GetIon("alpha++");
if (particleDefinition == instance->GetIon("helium"))
{
if (finalStateIndex==0) return instance->GetIon("alpha+");
return instance->GetIon("alpha++");
}
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNADingfelderChargeIncreaseModel::IncomingParticleBindingEnergyConstant(G4ParticleDefinition* particleDefinition,
G4int finalStateIndex )
{
G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
if(particleDefinition == instance->GetIon("hydrogen")) return 13.6*eV;
if(particleDefinition == instance->GetIon("alpha+"))
{
// Binding energy for He+ -> He++ + e- 54.509 eV
// Binding energy for He -> He+ + e- 24.587 eV
return 54.509*eV;
}
if(particleDefinition == instance->GetIon("helium"))
{
// Binding energy for He+ -> He++ + e- 54.509 eV
// Binding energy for He -> He+ + e- 24.587 eV
if (finalStateIndex==0) return 24.587*eV;
return (54.509 + 24.587)*eV;
}
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNADingfelderChargeIncreaseModel::PartialCrossSection(G4double k, G4int index,
const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=0;
if (particleDefinition == instance->GetIon("helium")) particleTypeIndex=1;
//
// sigma(T) = f0 10 ^ y(log10(T/eV))
//
// / a0 x + b0 x < x0
// |
// y(x) = < a0 x + b0 - c0 (x - x0)^d0 x0 <= x < x1
// |
// \ a1 x + b1 x >= x1
//
//
// f0, a0, a1, b0, b1, c0, d0, x0, x1 are parameters that change for protons and helium (0, +, ++)
//
// f0 has been added to the code in order to manage partial (shell-dependent) cross sections (if no shell dependence is present. f0=1. Sum of f0 over the considered shells should give 1)
//
// From Rad. Phys. and Chem. 59 (2000) 255-275, M. Dingfelder et al.
// Inelastic-collision cross sections of liquid water for interactions of energetic proton
//
if (x1[index][particleTypeIndex]<x0[index][particleTypeIndex])
{
//
// if x1 < x0 means that x1 and b1 will be calculated with the following formula (this piece of code is run on all alphas and not on protons)
//
// x1 = x0 + ((a0 - a1)/(c0 * d0)) ^ (1 / (d0 - 1))
//
// b1 = (a0 - a1) * x1 + b0 - c0 * (x1 - x0) ^ d0
//
x1[index][particleTypeIndex]=x0[index][particleTypeIndex] + std::pow((a0[index][particleTypeIndex] - a1[index][particleTypeIndex]) / (c0[index][particleTypeIndex] * d0[index][particleTypeIndex]), 1. / (d0[index][particleTypeIndex] - 1.));
b1[index][particleTypeIndex]=(a0[index][particleTypeIndex] - a1[index][particleTypeIndex]) * x1[index][particleTypeIndex] + b0[index][particleTypeIndex] - c0[index][particleTypeIndex] * std::pow(x1[index][particleTypeIndex] - x0[index][particleTypeIndex], d0[index][particleTypeIndex]);
}
G4double x(std::log10(k/eV));
G4double y;
if (x<x0[index][particleTypeIndex])
y=a0[index][particleTypeIndex] * x + b0[index][particleTypeIndex];
else if (x<x1[index][particleTypeIndex])
y=a0[index][particleTypeIndex] * x + b0[index][particleTypeIndex] - c0[index][particleTypeIndex] * std::pow(x - x0[index][particleTypeIndex], d0[index][particleTypeIndex]);
else
y=a1[index][particleTypeIndex] * x + b1[index][particleTypeIndex];
return f0[index][particleTypeIndex] * std::pow(10., y)*m*m;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNADingfelderChargeIncreaseModel::RandomSelect(G4double k,
const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == instance->GetIon("hydrogen")) return 0;
if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=0;
if (particleDefinition == instance->GetIon("helium")) particleTypeIndex=1;
const G4int n = numberOfPartialCrossSections[particleTypeIndex];
G4double* values(new G4double[n]);
G4double value = 0;
G4int i = n;
while (i>0)
{
i--;
values[i]=PartialCrossSection(k, i, particleDefinition);
value+=values[i];
}
value*=G4UniformRand();
i=n;
while (i>0)
{
i--;
if (values[i]>value)
break;
value-=values[i];
}
delete[] values;
return i;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNADingfelderChargeIncreaseModel::Sum(G4double k, const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=0;
if (particleDefinition == instance->GetIon("helium")) particleTypeIndex=1;
G4double totalCrossSection = 0.;
for (G4int i=0; i<numberOfPartialCrossSections[particleTypeIndex]; i++)
{
totalCrossSection += PartialCrossSection(k,i,particleDefinition);
}
return totalCrossSection;
}
@@ -0,0 +1,283 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAEmfietzoglouExcitationModel.cc,v 1.10 2010-06-08 21:50:00 sincerti Exp $
// GEANT4 tag $Name: not supported by cvs2svn $
//
#include "G4DNAEmfietzoglouExcitationModel.hh"
#include "G4DNAChemistryManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAEmfietzoglouExcitationModel::G4DNAEmfietzoglouExcitationModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
nistwater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
lowEnergyLimit = 8.23 * eV;
highEnergyLimit = 10 * MeV;
SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
nLevels = waterExcitation.NumberOfLevels();
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if (verboseLevel > 3)
if( verboseLevel>0 )
{
G4cout << "Emfietzoglou Excitation model is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / eV << " eV - "
<< highEnergyLimit / MeV << " MeV"
<< G4endl;
}
fParticleChangeForGamma = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAEmfietzoglouExcitationModel::~G4DNAEmfietzoglouExcitationModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAEmfietzoglouExcitationModel::Initialise(const G4ParticleDefinition* /*particle*/,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNAEmfietzoglouExcitationModel::Initialise()" << G4endl;
// Energy limits
if (LowEnergyLimit() < lowEnergyLimit)
{
G4cout << "G4DNAEmfietzoglouExcitationModel: low energy limit increased from " <<
LowEnergyLimit()/eV << " eV to " << lowEnergyLimit/eV << " eV" << G4endl;
SetLowEnergyLimit(lowEnergyLimit);
}
if (HighEnergyLimit() > highEnergyLimit)
{
G4cout << "G4DNAEmfietzoglouExcitationModel: high energy limit decreased from " <<
HighEnergyLimit()/MeV << " MeV to " << highEnergyLimit/MeV << " MeV" << G4endl;
SetHighEnergyLimit(highEnergyLimit);
}
//
if( verboseLevel>0 )
{
G4cout << "Emfietzoglou Excitation model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / MeV << " MeV"
<< G4endl;
}
if (isInitialised) { return; }
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAEmfietzoglouExcitationModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double ekin,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNAEmfietzoglouExcitationModel" << G4endl;
// Calculate total cross section for model
G4double sigma=0;
if (material == nistwater || material->GetBaseMaterial() == nistwater)
{
if (particleDefinition == G4Electron::ElectronDefinition())
{
if (ekin >= lowEnergyLimit && ekin < highEnergyLimit)
{
sigma = Sum(ekin);
}
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
}
return sigma*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAEmfietzoglouExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
const G4MaterialCutsCouple* /*couple*/,
const G4DynamicParticle* aDynamicElectron,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNAEmfietzoglouExcitationModel" << G4endl;
G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
G4int level = RandomSelect(electronEnergy0);
G4double excitationEnergy = waterExcitation.ExcitationEnergy(level);
G4double newEnergy = electronEnergy0 - excitationEnergy;
if (electronEnergy0 < highEnergyLimit)
{
if (newEnergy >= lowEnergyLimit)
{
fParticleChangeForGamma->ProposeMomentumDirection(aDynamicElectron->GetMomentumDirection());
fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
}
else
{
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(electronEnergy0);
}
const G4Track * theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack();
G4DNAChemistryManager::Instance()->CreateWaterMolecule(fExcitedMolecule,
level,
theIncomingTrack);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAEmfietzoglouExcitationModel::PartialCrossSection(G4double t, G4int level)
{
// Aj T
// Sigma(T) = ------------- (Bj / T) ln(Cj ---) [1 - Bj / T]^Pj
// 2 pi alpha0 R
//
// Sigma is the macroscopic cross section = N sigma, where N = number of target particles per unit volume
// and sigma is the microscopic cross section
// T is the incoming electron kinetic energy
// alpha0 is the Bohr Radius (Bohr_radius)
// Aj, Bj, Cj & Pj are parameters that can be found in Emfietzoglou's papers
//
// From Phys. Med. Biol. 48 (2003) 2355-2371, D.Emfietzoglou,
// Monte Carlo Simulation of the energy loss of low energy electrons in liquid Water
//
// Scaling for macroscopic cross section: number of water moleculs per unit volume
// const G4double sigma0 = (10. / 3.343e22) * cm2;
const G4double density = 3.34192e+19 * mm3;
const G4double aj[]={0.0205, 0.0209, 0.0130, 0.0026, 0.0025};
const G4double cj[]={4.9801, 3.3850, 2.8095, 1.9242, 3.4624};
const G4double pj[]={0.4757, 0.3483, 0.4443, 0.3429, 0.4379};
const G4double r = 13.6 * eV;
G4double sigma = 0.;
G4double exc = waterExcitation.ExcitationEnergy(level);
if (t >= exc)
{
G4double excitationSigma = ( aj[level] / (2.*pi*Bohr_radius))
* (exc / t)
* std::log(cj[level]*(t/r))
* std::pow((1.- (exc/t)), pj[level]);
sigma = excitationSigma / density;
}
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNAEmfietzoglouExcitationModel::RandomSelect(G4double k)
{
G4int i = nLevels;
G4double value = 0.;
std::deque<double> values;
while (i > 0)
{
i--;
G4double partial = PartialCrossSection(k,i);
values.push_front(partial);
value += partial;
}
value *= G4UniformRand();
i = nLevels;
while (i > 0)
{
i--;
if (values[i] > value) return i;
value -= values[i];
}
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAEmfietzoglouExcitationModel::Sum(G4double k)
{
G4double totalCrossSection = 0.;
for (G4int i=0; i<nLevels; i++)
{
totalCrossSection += PartialCrossSection(k,i);
}
return totalCrossSection;
}
@@ -0,0 +1,234 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAMeltonAttachmentModel.cc,v 1.2 2010-09-15 05:47:33 sincerti Exp $
// GEANT4 tag $Name: not supported by cvs2svn $
//
// Created by Z. Francis
#include "G4DNAMeltonAttachmentModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAMeltonAttachmentModel::G4DNAMeltonAttachmentModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
nistwater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
lowEnergyLimit = 4 * eV;
lowEnergyLimitOfModel = 4 * eV;
highEnergyLimit = 13 * eV;
SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if( verboseLevel>0 )
{
G4cout << "Melton Attachment model is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / eV << " eV - "
<< highEnergyLimit / eV << " eV"
<< G4endl;
}
fParticleChangeForGamma = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAMeltonAttachmentModel::~G4DNAMeltonAttachmentModel()
{
// For total cross section
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
for (pos = tableData.begin(); pos != tableData.end(); ++pos)
{
G4DNACrossSectionDataSet* table = pos->second;
delete table;
}
// For final state
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAMeltonAttachmentModel::Initialise(const G4ParticleDefinition* /*particle*/,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNAMeltonAttachmentModel::Initialise()" << G4endl;
// Energy limits
if (LowEnergyLimit() < lowEnergyLimit)
{
G4cout << "G4DNAMeltonAttachmentModel: low energy limit increased from " <<
LowEnergyLimit()/eV << " eV to " << lowEnergyLimit/eV << " eV" << G4endl;
SetLowEnergyLimit(lowEnergyLimit);
}
if (HighEnergyLimit() > highEnergyLimit)
{
G4cout << "G4DNAMeltonAttachmentModel: high energy limit decreased from " <<
HighEnergyLimit()/eV << " eV to " << highEnergyLimit/eV << " eV" << G4endl;
SetHighEnergyLimit(highEnergyLimit);
}
// Reading of data files
G4double scaleFactor = 1e-18*cm*cm;
G4String fileElectron("dna/sigma_attachment_e_melton");
G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
G4String electron;
// ELECTRON
// For total cross section
electron = electronDef->GetParticleName();
tableFile[electron] = fileElectron;
G4DNACrossSectionDataSet* tableE = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV,scaleFactor );
tableE->LoadData(fileElectron);
tableData[electron] = tableE;
//
if (verboseLevel > 2)
G4cout << "Loaded cross section data for Melton Attachment model" << G4endl;
if( verboseLevel>0 )
{
G4cout << "Melton Attachment model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / eV << " eV"
<< G4endl;
}
if (isInitialised) { return; }
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAMeltonAttachmentModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* p,
G4double ekin,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNAMeltonAttachmentModel" << G4endl;
// Calculate total cross section for model
G4double sigma=0;
if (material == nistwater || material->GetBaseMaterial() == nistwater)
{
const G4String& particleName = p->GetParticleName();
if (ekin >= lowEnergyLimit && ekin < highEnergyLimit)
{
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
pos = tableData.find(particleName);
if (pos != tableData.end())
{
G4DNACrossSectionDataSet* table = pos->second;
if (table != 0)
{
sigma = table->FindValue(ekin);
}
}
else
{
G4Exception("G4DNAMeltonAttachmentModel::ComputeCrossSectionPerVolume","em0002",
FatalException,"Model not applicable to particle type.");
}
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if water
return sigma*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAMeltonAttachmentModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
const G4MaterialCutsCouple* /*couple*/,
const G4DynamicParticle* aDynamicElectron,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNAMeltonAttachmentModel" << G4endl;
// Electron is killed
G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(electronEnergy0);
return ;
}
@@ -0,0 +1,618 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAMillerGreenExcitationModel.cc,v 1.11 2010/10/08 08:53:17 sincerti Exp $
// GEANT4 tag $Name: $
//
#include "G4DNAMillerGreenExcitationModel.hh"
#include "G4DNAChemistryManager.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAMillerGreenExcitationModel::G4DNAMillerGreenExcitationModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
nistwater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
nLevels=0;
kineticEnergyCorrection[0]=0.;
kineticEnergyCorrection[1]=0.;
kineticEnergyCorrection[2]=0.;
kineticEnergyCorrection[3]=0.;
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if( verboseLevel>0 )
{
G4cout << "Miller & Green excitation model is constructed " << G4endl;
}
fParticleChangeForGamma = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAMillerGreenExcitationModel::~G4DNAMillerGreenExcitationModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAMillerGreenExcitationModel::Initialise(const G4ParticleDefinition* particle,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNAMillerGreenExcitationModel::Initialise()" << G4endl;
// Energy limits
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
G4ParticleDefinition* hydrogenDef = instance->GetIon("hydrogen");
G4ParticleDefinition* alphaPlusPlusDef = instance->GetIon("alpha++");
G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
G4ParticleDefinition* heliumDef = instance->GetIon("helium");
G4String proton;
G4String hydrogen;
G4String alphaPlusPlus;
G4String alphaPlus;
G4String helium;
// LIMITS AND CONSTANTS
proton = protonDef->GetParticleName();
lowEnergyLimit[proton] = 10. * eV;
highEnergyLimit[proton] = 500. * keV;
kineticEnergyCorrection[0] = 1.;
slaterEffectiveCharge[0][0] = 0.;
slaterEffectiveCharge[1][0] = 0.;
slaterEffectiveCharge[2][0] = 0.;
sCoefficient[0][0] = 0.;
sCoefficient[1][0] = 0.;
sCoefficient[2][0] = 0.;
hydrogen = hydrogenDef->GetParticleName();
lowEnergyLimit[hydrogen] = 10. * eV;
highEnergyLimit[hydrogen] = 500. * keV;
kineticEnergyCorrection[0] = 1.;
slaterEffectiveCharge[0][0] = 0.;
slaterEffectiveCharge[1][0] = 0.;
slaterEffectiveCharge[2][0] = 0.;
sCoefficient[0][0] = 0.;
sCoefficient[1][0] = 0.;
sCoefficient[2][0] = 0.;
alphaPlusPlus = alphaPlusPlusDef->GetParticleName();
lowEnergyLimit[alphaPlusPlus] = 1. * keV;
highEnergyLimit[alphaPlusPlus] = 400. * MeV;
kineticEnergyCorrection[1] = 0.9382723/3.727417;
slaterEffectiveCharge[0][1]=0.;
slaterEffectiveCharge[1][1]=0.;
slaterEffectiveCharge[2][1]=0.;
sCoefficient[0][1]=0.;
sCoefficient[1][1]=0.;
sCoefficient[2][1]=0.;
alphaPlus = alphaPlusDef->GetParticleName();
lowEnergyLimit[alphaPlus] = 1. * keV;
highEnergyLimit[alphaPlus] = 400. * MeV;
kineticEnergyCorrection[2] = 0.9382723/3.727417;
slaterEffectiveCharge[0][2]=2.0;
// Following values provided by M. Dingfelder
slaterEffectiveCharge[1][2]=2.00;
slaterEffectiveCharge[2][2]=2.00;
//
sCoefficient[0][2]=0.7;
sCoefficient[1][2]=0.15;
sCoefficient[2][2]=0.15;
helium = heliumDef->GetParticleName();
lowEnergyLimit[helium] = 1. * keV;
highEnergyLimit[helium] = 400. * MeV;
kineticEnergyCorrection[3] = 0.9382723/3.727417;
slaterEffectiveCharge[0][3]=1.7;
slaterEffectiveCharge[1][3]=1.15;
slaterEffectiveCharge[2][3]=1.15;
sCoefficient[0][3]=0.5;
sCoefficient[1][3]=0.25;
sCoefficient[2][3]=0.25;
//
if (particle==protonDef)
{
SetLowEnergyLimit(lowEnergyLimit[proton]);
SetHighEnergyLimit(highEnergyLimit[proton]);
}
if (particle==hydrogenDef)
{
SetLowEnergyLimit(lowEnergyLimit[hydrogen]);
SetHighEnergyLimit(highEnergyLimit[hydrogen]);
}
if (particle==alphaPlusPlusDef)
{
SetLowEnergyLimit(lowEnergyLimit[alphaPlusPlus]);
SetHighEnergyLimit(highEnergyLimit[alphaPlusPlus]);
}
if (particle==alphaPlusDef)
{
SetLowEnergyLimit(lowEnergyLimit[alphaPlus]);
SetHighEnergyLimit(highEnergyLimit[alphaPlus]);
}
if (particle==heliumDef)
{
SetLowEnergyLimit(lowEnergyLimit[helium]);
SetHighEnergyLimit(highEnergyLimit[helium]);
}
//
nLevels = waterExcitation.NumberOfLevels();
//
if( verboseLevel>0 )
{
G4cout << "Miller & Green excitation model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / keV << " keV for "
<< particle->GetParticleName()
<< G4endl;
}
if (isInitialised) { return; }
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAMillerGreenExcitationModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double k,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNAMillerGreenExcitationModel" << G4endl;
// Calculate total cross section for model
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (
particleDefinition != G4Proton::ProtonDefinition()
&&
particleDefinition != instance->GetIon("hydrogen")
&&
particleDefinition != instance->GetIon("alpha++")
&&
particleDefinition != instance->GetIon("alpha+")
&&
particleDefinition != instance->GetIon("helium")
)
return 0;
G4double lowLim = 0;
G4double highLim = 0;
G4double crossSection = 0.;
if (material == nistwater || material->GetBaseMaterial() == nistwater)
{
const G4String& particleName = particleDefinition->GetParticleName();
std::map< G4String,G4double,std::less<G4String> >::iterator pos1;
pos1 = lowEnergyLimit.find(particleName);
if (pos1 != lowEnergyLimit.end())
{
lowLim = pos1->second;
}
std::map< G4String,G4double,std::less<G4String> >::iterator pos2;
pos2 = highEnergyLimit.find(particleName);
if (pos2 != highEnergyLimit.end())
{
highLim = pos2->second;
}
if (k >= lowLim && k < highLim)
{
crossSection = Sum(k,particleDefinition);
// add ONE or TWO electron-water excitation for alpha+ and helium
/*
if ( particleDefinition == instance->GetIon("alpha+")
||
particleDefinition == instance->GetIon("helium")
)
{
G4DNAEmfietzoglouExcitationModel * excitationXS = new G4DNAEmfietzoglouExcitationModel();
excitationXS->Initialise(G4Electron::ElectronDefinition());
G4double sigmaExcitation=0;
G4double tmp =0.;
if (k*0.511/3728 > 8.23*eV && k*0.511/3728 < 10*MeV ) sigmaExcitation =
excitationXS->CrossSectionPerVolume(material,G4Electron::ElectronDefinition(),k*0.511/3728,tmp,tmp)
/material->GetAtomicNumDensityVector()[1];
if ( particleDefinition == instance->GetIon("alpha+") )
crossSection = crossSection + sigmaExcitation ;
if ( particleDefinition == instance->GetIon("helium") )
crossSection = crossSection + 2*sigmaExcitation ;
delete excitationXS;
// Alternative excitation model
G4DNABornExcitationModel * excitationXS = new G4DNABornExcitationModel();
excitationXS->Initialise(G4Electron::ElectronDefinition());
G4double sigmaExcitation=0;
G4double tmp=0;
if (k*0.511/3728 > 9*eV && k*0.511/3728 < 1*MeV ) sigmaExcitation =
excitationXS->CrossSectionPerVolume(material,G4Electron::ElectronDefinition(),k*0.511/3728,tmp,tmp)
/material->GetAtomicNumDensityVector()[1];
if ( particleDefinition == instance->GetIon("alpha+") )
crossSection = crossSection + sigmaExcitation ;
if ( particleDefinition == instance->GetIon("helium") )
crossSection = crossSection + 2*sigmaExcitation ;
delete excitationXS;
}
*/
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << k/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << crossSection/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << crossSection*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
}
return crossSection*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAMillerGreenExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
const G4MaterialCutsCouple* /*couple*/,
const G4DynamicParticle* aDynamicParticle,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNAMillerGreenExcitationModel" << G4endl;
G4double particleEnergy0 = aDynamicParticle->GetKineticEnergy();
G4int level = RandomSelect(particleEnergy0,aDynamicParticle->GetDefinition());
// G4double excitationEnergy = waterExcitation.ExcitationEnergy(level);
// Dingfelder's excitation levels
const G4double excitation[]={ 8.17*eV, 10.13*eV, 11.31*eV, 12.91*eV, 14.50*eV};
G4double excitationEnergy = excitation[level];
G4double newEnergy = particleEnergy0 - excitationEnergy;
if (newEnergy>0)
{
fParticleChangeForGamma->ProposeMomentumDirection(aDynamicParticle->GetMomentumDirection());
fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
const G4Track * theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack();
G4DNAChemistryManager::Instance()->CreateWaterMolecule(fExcitedMolecule,
level,
theIncomingTrack);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAMillerGreenExcitationModel::PartialCrossSection(G4double k, G4int excitationLevel,
const G4ParticleDefinition* particleDefinition)
{
// ( ( z * aj ) ^ omegaj ) * ( t - ej ) ^ nu
// sigma(t) = zEff^2 * sigma0 * --------------------------------------------
// jj ^ ( omegaj + nu ) + t ^ ( omegaj + nu )
//
// where t is the kinetic energy corrected by Helium mass over proton mass for Helium ions
//
// zEff is:
// 1 for protons
// 2 for alpha++
// and 2 - c1 S_1s - c2 S_2s - c3 S_2p for alpha+ and He
//
// Dingfelder et al., RPC 59, 255-275, 2000 from Miller and Green (1973)
// Formula (34) and Table 2
const G4double sigma0(1.E+8 * barn);
const G4double nu(1.);
const G4double aj[]={876.*eV, 2084.* eV, 1373.*eV, 692.*eV, 900.*eV};
const G4double jj[]={19820.*eV, 23490.*eV, 27770.*eV, 30830.*eV, 33080.*eV};
const G4double omegaj[]={0.85, 0.88, 0.88, 0.78, 0.78};
// Dingfelder's excitation levels
const G4double Eliq[5]={ 8.17*eV, 10.13*eV, 11.31*eV, 12.91*eV, 14.50*eV};
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == G4Proton::ProtonDefinition()) particleTypeIndex=0;
if (particleDefinition == instance->GetIon("hydrogen")) particleTypeIndex=0;
if (particleDefinition == instance->GetIon("alpha++")) particleTypeIndex=1;
if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=2;
if (particleDefinition == instance->GetIon("helium")) particleTypeIndex=3;
G4double tCorrected;
tCorrected = k * kineticEnergyCorrection[particleTypeIndex];
// SI - added protection
if (tCorrected < Eliq[excitationLevel]) return 0;
//
G4int z = 10;
G4double numerator;
numerator = std::pow(z * aj[excitationLevel], omegaj[excitationLevel]) *
std::pow(tCorrected - Eliq[excitationLevel], nu);
// H case : see S. Uehara et al. IJRB 77, 2, 139-154 (2001) - section 3.3
if (particleDefinition == instance->GetIon("hydrogen"))
numerator = std::pow(z * 0.75*aj[excitationLevel], omegaj[excitationLevel]) *
std::pow(tCorrected - Eliq[excitationLevel], nu);
G4double power;
power = omegaj[excitationLevel] + nu;
G4double denominator;
denominator = std::pow(jj[excitationLevel], power) + std::pow(tCorrected, power);
G4double zEff = particleDefinition->GetPDGCharge() / eplus + particleDefinition->GetLeptonNumber();
zEff -= ( sCoefficient[0][particleTypeIndex] * S_1s(k, Eliq[excitationLevel], slaterEffectiveCharge[0][particleTypeIndex], 1.) +
sCoefficient[1][particleTypeIndex] * S_2s(k, Eliq[excitationLevel], slaterEffectiveCharge[1][particleTypeIndex], 2.) +
sCoefficient[2][particleTypeIndex] * S_2p(k, Eliq[excitationLevel], slaterEffectiveCharge[2][particleTypeIndex], 2.) );
if (particleDefinition == instance->GetIon("hydrogen")) zEff = 1.;
G4double cross = sigma0 * zEff * zEff * numerator / denominator;
return cross;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNAMillerGreenExcitationModel::RandomSelect(G4double k,const G4ParticleDefinition* particle)
{
G4int i = nLevels;
G4double value = 0.;
std::deque<double> values;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if ( particle == instance->GetIon("alpha++") ||
particle == G4Proton::ProtonDefinition()||
particle == instance->GetIon("hydrogen") ||
particle == instance->GetIon("alpha+") ||
particle == instance->GetIon("helium")
)
{
while (i > 0)
{
i--;
G4double partial = PartialCrossSection(k,i,particle);
values.push_front(partial);
value += partial;
}
value *= G4UniformRand();
i = nLevels;
while (i > 0)
{
i--;
if (values[i] > value) return i;
value -= values[i];
}
}
/*
// add ONE or TWO electron-water excitation for alpha+ and helium
if ( particle == instance->GetIon("alpha+")
||
particle == instance->GetIon("helium")
)
{
while (i>0)
{
i--;
G4DNAEmfietzoglouExcitationModel * excitationXS = new G4DNAEmfietzoglouExcitationModel();
excitationXS->Initialise(G4Electron::ElectronDefinition());
G4double sigmaExcitation=0;
if (k*0.511/3728 > 8.23*eV && k*0.511/3728 < 10*MeV ) sigmaExcitation = excitationXS->PartialCrossSection(k*0.511/3728,i);
G4double partial = PartialCrossSection(k,i,particle);
if (particle == instance->GetIon("alpha+")) partial = PartialCrossSection(k,i,particle) + sigmaExcitation;
if (particle == instance->GetIon("helium")) partial = PartialCrossSection(k,i,particle) + 2*sigmaExcitation;
values.push_front(partial);
value += partial;
delete excitationXS;
}
value*=G4UniformRand();
i=5;
while (i>0)
{
i--;
if (values[i]>value) return i;
value-=values[i];
}
}
*/
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAMillerGreenExcitationModel::Sum(G4double k, const G4ParticleDefinition* particle)
{
G4double totalCrossSection = 0.;
for (G4int i=0; i<nLevels; i++)
{
totalCrossSection += PartialCrossSection(k,i,particle);
}
return totalCrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAMillerGreenExcitationModel::S_1s(G4double t,
G4double energyTransferred,
G4double slaterEffectiveCharge,
G4double shellNumber)
{
// 1 - e^(-2r) * ( 1 + 2 r + 2 r^2)
// Dingfelder, in Chattanooga 2005 proceedings, formula (7)
G4double r = R(t, energyTransferred, slaterEffectiveCharge, shellNumber);
G4double value = 1. - std::exp(-2 * r) * ( ( 2. * r + 2. ) * r + 1. );
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAMillerGreenExcitationModel::S_2s(G4double t,
G4double energyTransferred,
G4double slaterEffectiveCharge,
G4double shellNumber)
{
// 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 2 r^4)
// Dingfelder, in Chattanooga 2005 proceedings, formula (8)
G4double r = R(t, energyTransferred, slaterEffectiveCharge, shellNumber);
G4double value = 1. - std::exp(-2 * r) * (((2. * r * r + 2.) * r + 2.) * r + 1.);
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAMillerGreenExcitationModel::S_2p(G4double t,
G4double energyTransferred,
G4double slaterEffectiveCharge,
G4double shellNumber)
{
// 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 4/3 r^3 + 2/3 r^4)
// Dingfelder, in Chattanooga 2005 proceedings, formula (9)
G4double r = R(t, energyTransferred, slaterEffectiveCharge, shellNumber);
G4double value = 1. - std::exp(-2 * r) * (((( 2./3. * r + 4./3.) * r + 2.) * r + 2.) * r + 1.);
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAMillerGreenExcitationModel::R(G4double t,
G4double energyTransferred,
G4double slaterEffectiveCharge,
G4double shellNumber)
{
// tElectron = m_electron / m_alpha * t
// Dingfelder, in Chattanooga 2005 proceedings, p 4
G4double tElectron = 0.511/3728. * t;
// The following is provided by M. Dingfelder
G4double H = 2.*13.60569172 * eV;
G4double value = std::sqrt ( 2. * tElectron / H ) / ( energyTransferred / H ) * (slaterEffectiveCharge/shellNumber);
return value;
}
@@ -0,0 +1,206 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// Author: Mathieu Karamitros (kara@cenbg.in2p3.fr)
//
// WARNING : This class is released as a prototype.
// It might strongly evolve or even disapear in the next releases.
//
// History:
// -----------
// 10 Oct 2011 M.Karamitros created
//
// -------------------------------------------------------------------
#include "G4DNAMolecularReaction.hh"
#include "G4DNAMolecularReactionTable.hh"
#include "G4VDNAReactionModel.hh"
#include "G4ITManager.hh"
#include "G4UnitsTable.hh"
using namespace std;
G4DNAMolecularReaction::G4DNAMolecularReaction():G4VITReactionProcess(),
fMolReactionTable(reference_cast<const G4DNAMolecularReactionTable*>(fReactionTable))
{
//ctor
fVerbose = 0;
fReactionModel = 0;
fReactionRadius = -1;
fDistance = -1;
}
G4DNAMolecularReaction::~G4DNAMolecularReaction()
{
//dtor
if(fChanges) delete fChanges;
}
G4DNAMolecularReaction::G4DNAMolecularReaction(const G4DNAMolecularReaction& other):G4VITReactionProcess(other),
fMolReactionTable(reference_cast<const G4DNAMolecularReactionTable*>(fReactionTable))
{
//copy ctor
fVerbose = other.fVerbose ;
fMolReactionTable = other.fMolReactionTable;
fReactionModel = 0;
fReactionRadius = -1;
fDistance = -1;
}
G4DNAMolecularReaction& G4DNAMolecularReaction::operator=(const G4DNAMolecularReaction& rhs)
{
if (this == &rhs) return *this; // handle self assignment
fVerbose = rhs.fVerbose ;
fMolReactionTable = rhs.fMolReactionTable;
fReactionRadius = -1;
fDistance = -1;
//assignment operator
return *this;
}
G4bool G4DNAMolecularReaction::TestReactibility(const G4Track& trackA,
const G4Track& trackB,
const double currentStepTime,
const double /*previousStepTime*/,
bool userStepTimeLimit) /*const*/
{
G4Molecule* moleculeA = GetMolecule(trackA);
G4Molecule* moleculeB = GetMolecule(trackB);
if(!fReactionModel)
{
G4ExceptionDescription exceptionDescription ("You have to give a reaction model to the molecular reaction process");
G4Exception("G4DNAMolecularReaction::TestReactibility","MolecularReaction001",
FatalErrorInArgument,exceptionDescription);
return false; // makes coverity happy
}
if(fMolReactionTable==0)
{
G4ExceptionDescription exceptionDescription ("You have to give a reaction table to the molecular reaction process");
G4Exception("G4DNAMolecularReaction::TestReactibility","MolecularReaction002",
FatalErrorInArgument,exceptionDescription);
return false; // makes coverity happy
}
// Retrieve reaction range
fReactionRadius = -1 ; // reaction Range
fReactionRadius = fReactionModel -> GetReactionRadius(moleculeA, moleculeB);
fDistance = -1 ; // separation distance
if(currentStepTime == 0.)
{
userStepTimeLimit = false;
}
G4bool output = fReactionModel->FindReaction(trackA, trackB, fReactionRadius,fDistance, userStepTimeLimit);
#ifdef G4VERBOSE
// DEBUG
if(fVerbose > 1)
{
G4cout << "\033[1;39;36m" << "G4MolecularReaction "<< G4endl;
G4cout << "FindReaction returned : " << G4BestUnit(output,"Length") << G4endl;
G4cout << " reaction radius : " << G4BestUnit(fReactionRadius,"Length")
<< " real distance : " << G4BestUnit((trackA.GetPosition() - trackB.GetPosition()).mag(), "Length")
<< " calculated distance by model (= -1 if real distance > reaction radius and the user limitation step is not reached) : "
<< G4BestUnit(fDistance,"Length")
<< G4endl;
G4cout << "TrackID A : " << trackA.GetTrackID()
<< ", TrackID B : " << trackB.GetTrackID()
<< " | MolA " << moleculeA->GetName()
<< ", MolB " << moleculeB->GetName()
<<"\033[0m\n"
<< G4endl;
G4cout << "--------------------------------------------" << G4endl;
}
#endif
return output ;
}
G4ITReactionChange* G4DNAMolecularReaction::MakeReaction(const G4Track& trackA, const G4Track& trackB)
{
fChanges = new G4ITReactionChange();
fChanges->Initialize(trackA, trackB);
G4Molecule* moleculeA = GetMolecule(trackA);
G4Molecule* moleculeB = GetMolecule(trackB);
#ifdef G4VERBOSE
// DEBUG
if(fVerbose)
{
G4cout << "G4DNAMolecularReaction::MakeReaction" << G4endl;
G4cout<<"TrackA n°" << trackA.GetTrackID()
<<"\t | Track B n°" << trackB.GetTrackID() << G4endl;
G4cout<<"Track A : Position : " << G4BestUnit(trackA.GetPosition(),"Length")
<<"\t Global Time : " << G4BestUnit(trackA.GetGlobalTime(), "Time")<< G4endl;
G4cout<<"Track B : Position : " << G4BestUnit(trackB.GetPosition() ,"Length")
<<"\t Global Time : " << G4BestUnit(trackB.GetGlobalTime(), "Time")<< G4endl;
G4cout<<"Reaction range : " << G4BestUnit(fReactionRadius,"Length")
<< " \t Separation distance : " << G4BestUnit(fDistance,"Length")<< G4endl;
G4cout << "--------------------------------------------" << G4endl;
}
#endif
const G4DNAMolecularReactionData* reactionData = fMolReactionTable->GetReactionData(moleculeA, moleculeB);
G4int nbProducts = reactionData->GetNbProducts();
if (nbProducts)
{
G4double D1 = moleculeA->GetDiffusionCoefficient();
G4double D2 = moleculeB->GetDiffusionCoefficient();
G4double sqrD1 = sqrt(D1);
G4double sqrD2 = sqrt(D2);
G4double numerator = sqrD1 + sqrD2;
G4ThreeVector reactionSite = sqrD1/numerator * trackA.GetPosition()
+ sqrD2/numerator * trackB.GetPosition() ;
for (G4int j=0 ; j < nbProducts; j++)
{
G4Molecule* product = new G4Molecule(*reactionData->GetProduct(j));
G4Track* productTrack = product->BuildTrack(trackA.GetGlobalTime(),
reactionSite);
productTrack->SetTrackStatus(fAlive);
fChanges->AddSecondary(productTrack);
G4ITManager<G4Molecule>::Instance()->Push(productTrack);
}
}
fChanges->KillParents(true);
return fChanges;
}
@@ -0,0 +1,71 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "G4DNAMolecularStepByStepModel.hh"
#include "G4VDNAReactionModel.hh"
G4DNAMolecularStepByStepModel::G4DNAMolecularStepByStepModel(const G4String& name) :
G4VITModel(name),
fMolecularReactionTable(reference_cast<const G4DNAMolecularReactionTable*>(fReactionTable))
{
fTimeStepper = new G4DNAMoleculeEncounterStepper();
fReactionProcess = new G4DNAMolecularReaction();
fType1 = G4Molecule::ITType();
fType2 = G4Molecule::ITType();
fReactionModel = 0;
}
G4DNAMolecularStepByStepModel::~G4DNAMolecularStepByStepModel()
{
if(fReactionModel) delete fReactionModel;
}
G4DNAMolecularStepByStepModel::G4DNAMolecularStepByStepModel(const G4DNAMolecularStepByStepModel& right):
G4VITModel(right),
fMolecularReactionTable(reference_cast<const G4DNAMolecularReactionTable*>(fReactionTable))
{
fReactionTable = right.fReactionTable;
if(right.fReactionModel)
{
fReactionModel = right.fReactionModel->Clone();
((G4DNAMolecularReaction*) fReactionProcess)->SetReactionModel(fReactionModel);
((G4DNAMoleculeEncounterStepper*) fTimeStepper)->SetReactionModel(fReactionModel);
}
else fReactionModel = 0;
}
void G4DNAMolecularStepByStepModel::Initialize()
{
fReactionModel ->SetReactionTable((const G4DNAMolecularReactionTable*)fReactionTable);
G4VITModel::Initialize();
}
void G4DNAMolecularStepByStepModel::PrintInfo()
{
#ifdef G4VERBOSE
G4cout << "DNAMolecularStepByStepModel will be used" << G4endl;
#endif
}
@@ -0,0 +1,380 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// Author: Mathieu Karamitros (kara@cenbg.in2p3.fr)
//
// WARNING : This class is released as a prototype.
// It might strongly evolve or even disapear in the next releases.
//
// History:
// -----------
// 10 Oct 2011 M.Karamitros created
//
// -------------------------------------------------------------------
#include "G4DNAMoleculeEncounterStepper.hh"
#include "G4VDNAReactionModel.hh"
#include "G4DNAMolecularReactionTable.hh"
#include "G4H2O.hh"
#include "G4UnitsTable.hh"
using namespace std;
G4DNAMoleculeEncounterStepper::G4DNAMoleculeEncounterStepper() :
G4VITTimeStepper(),
fMolecularReactionTable(reference_cast<const G4DNAMolecularReactionTable*>(fReactionTable)),
fReactionModel(0),fVerbose(0)
{}
G4DNAMoleculeEncounterStepper& G4DNAMoleculeEncounterStepper::operator=(const G4DNAMoleculeEncounterStepper& rhs)
{
if(this == &rhs) return *this;
fReactionModel = 0;
fVerbose = rhs.fVerbose;
fMolecularReactionTable = rhs.fMolecularReactionTable;
return *this;
}
G4DNAMoleculeEncounterStepper::~G4DNAMoleculeEncounterStepper()
{}
G4DNAMoleculeEncounterStepper::G4DNAMoleculeEncounterStepper(const G4DNAMoleculeEncounterStepper& right) :
G4VITTimeStepper(right),
fMolecularReactionTable(reference_cast<const G4DNAMolecularReactionTable*>(fReactionTable))
{
fVerbose = right.fVerbose ;
fMolecularReactionTable = right.fMolecularReactionTable;
fReactionModel = 0;
}
void G4DNAMoleculeEncounterStepper::PrepareForAllProcessors()
{
// DEBUG
// G4cout << "G4DNAMoleculeEncounterStepper::PrepareForAllProcessors" << G4endl;
G4ITManager<G4Molecule>::Instance()->UpdatePositionMap();
}
G4double G4DNAMoleculeEncounterStepper::CalculateStep(const G4Track& trackA, const G4double& userMinTimeStep)
{
// DEBUG
// G4cout << "G4MoleculeEncounterStepper::CalculateStep, time :" << G4ITStepManager::Instance()->GetGlobalTime() << G4endl;
G4Molecule* moleculeA = GetMolecule(trackA);
#ifdef G4VERBOSE
if(fVerbose)
{
G4cout << "_______________________________________________________________________" << G4endl;
G4cout << "G4DNAMoleculeEncounterStepper::CalculateStep" << G4endl;
G4cout << "Incident molecule : " << moleculeA->GetName()
<< " (" << trackA.GetTrackID() << ") "
<< G4endl;
}
#endif
//__________________________________________________________________
// Retrieve general informations for making reactions
const vector<const G4Molecule*>* reactivesVector =
fMolecularReactionTable -> CanReactWith(moleculeA);
if(!reactivesVector)
{
#ifdef G4VERBOSE
// DEBUG
if(fVerbose > 1)
{
G4cout << "!!!!!!!!!!!!!!!!!!!!"<<G4endl;
G4cout << "!!! WARNING" << G4endl;
G4cout << "G4MoleculeEncounterStepper::CalculateStep will return infinity for the reaction because the molecule "
<< moleculeA->GetName()
<< " does not have any reactants given in the reaction table."
<< G4endl;
G4cout << "!!!!!!!!!!!!!!!!!!!!"<<G4endl;
}
#endif
return DBL_MAX;
}
G4int nbReactives = reactivesVector->size();
if(nbReactives == 0)
{
#ifdef G4VERBOSE
// DEBUG
if(fVerbose)
{
G4cout << "!!!!!!!!!!!!!!!!!!!!"<<G4endl;
G4cout << "!!! WARNING" << G4endl;
G4cout << "G4MoleculeEncounterStepper::CalculateStep will return infinity for the reaction because the molecule "
<< moleculeA->GetName()
<< " does not have any reactants given in the reaction table."
<< "This message can also result from a wrong implementation of the reaction table."
<< G4endl;
G4cout << "!!!!!!!!!!!!!!!!!!!!"<<G4endl;
}
#endif
return DBL_MAX;
}
// DEBUG
// else
// {
// G4cout << "nb reactants : " << nbReactives << " pour mol "<< moleculeA -> GetName () << G4endl;
// for(int k=0 ; k < nbReactives ; k++)
// {
// G4cout << (*reactivesVector)[k]->GetName() << G4endl;
// }
// }
fUserMinTimeStep = userMinTimeStep ;
if(fReactants) fReactants = 0 ;
fReactants = new vector<G4Track*>();
fSampledMinTimeStep = DBL_MAX;
fHasAlreadyReachedNullTime = false;
fReactionModel -> Initialise(moleculeA, trackA) ;
//__________________________________________________________________
// Start looping on possible reactants
for (G4int i=0 ; i<nbReactives ; i++)
{
const G4Molecule* moleculeB = (*reactivesVector)[i];
//______________________________________________________________
// Retrieve reaction range
G4double R = -1 ; // reaction Range
R = fReactionModel -> GetReactionRadius(i);
//______________________________________________________________
// Use KdTree algorithm to find closest reactants
G4KDTreeResultHandle results (G4ITManager<G4Molecule>::Instance()
-> FindNearest(moleculeA, moleculeB));
RetrieveResults(trackA,moleculeA,moleculeB,R,results, true);
}
#ifdef G4VERBOSE
// DEBUG
if(fVerbose)
{
G4cout << "G4MoleculeEncounterStepper::CalculateStep will finally return :"
<< G4BestUnit(fSampledMinTimeStep, "Time")<< G4endl;
if(fVerbose > 1)
{
G4cout << "TrackA: " << moleculeA->GetName() << " (" << trackA.GetTrackID() << ") can react with: ";
vector<G4Track*>::iterator it;
for(it = fReactants->begin() ; it != fReactants->end() ; it++)
{
G4Track* trackB = *it;
G4cout << GetMolecule(trackB)->GetName() << " ("
<< trackB->GetTrackID() << ") \t ";
}
G4cout << G4endl;
}
}
#endif
return fSampledMinTimeStep ;
}
void G4DNAMoleculeEncounterStepper::RetrieveResults(const G4Track& trackA, const G4Molecule* moleculeA,
const G4Molecule* moleculeB, const G4double R,
G4KDTreeResultHandle& results, G4bool iterate)
{
if(!results)
{
#ifdef G4VERBOSE
// DEBUG
if(fVerbose > 1)
{
G4cout << "No molecule " << moleculeB->GetName()
<< " found to react with "
<< moleculeA->GetName()
<< G4endl;
}
#endif
return ;
}
G4double DA = moleculeA->GetDiffusionCoefficient() ;
G4double DB = moleculeB->GetDiffusionCoefficient() ;
for(results->Rewind();
!results->End();
results->Next())
{
G4IT* reactiveB = (G4IT*) results->GetItemData() ;
if (reactiveB==0)
{
// DEBUG
// G4cout<<"Continue 1"<<G4endl;
continue ;
}
G4Track *trackB = reactiveB->GetTrack();
if(trackB == 0)
{
G4ExceptionDescription exceptionDescription ;
exceptionDescription << "The reactant B found using the ITManager does not have a valid track "
<< " attached to it. If this is done on purpose, please do not record this "
<< " molecule in the ITManager."
<< G4endl;
G4Exception("G4DNAMoleculeEncounterStepper::RetrieveResults","MoleculeEncounterStepper001",
FatalErrorInArgument,exceptionDescription);
continue ;
}
if (trackB->GetTrackStatus() != fAlive)
{
G4ExceptionDescription exceptionDescription ;
exceptionDescription << "The track status of one of the nearby reactants is not fAlive" << G4endl;
exceptionDescription << "The incomming trackID "
<< "(trackA entering in G4DNAMoleculeEncounterStepper and "
<< "for which you are looking reactant for) is : "
<< trackA.GetTrackID() << G4endl;
exceptionDescription << "And the trackID of the reactant (trackB) is: "
<< trackB->GetTrackID() << G4endl;
G4Exception("G4DNAMoleculeEncounterStepper::RetrieveResults","MoleculeEncounterStepper002",
FatalErrorInArgument,exceptionDescription);
continue ;
}
if(trackB == &trackA)
{
// DEBUG
G4ExceptionDescription exceptionDescription ;
exceptionDescription << "A track is reacting with itself (which is impossible) ie trackA == trackB"
<< G4endl ;
exceptionDescription << "Molecule A (and B) is of type : "
<< moleculeA->GetName()
<< " with trackID : "
<< trackA.GetTrackID() << G4endl;
G4Exception("G4DNAMoleculeEncounterStepper::RetrieveResults","MoleculeEncounterStepper003",
FatalErrorInArgument,exceptionDescription);
}
if(fabs(trackB->GetGlobalTime() - trackA.GetGlobalTime()) > trackA.GetGlobalTime()*(1-1/100) )
{
// DEBUG
G4ExceptionDescription exceptionDescription;
exceptionDescription << "The interacting tracks are not synchronized in time"<< G4endl;
exceptionDescription<< "trackB->GetGlobalTime() != trackA.GetGlobalTime()"
<< G4endl;
exceptionDescription << "trackA : trackID : " << trackA.GetTrackID()
<< "\t Name :" << moleculeA->GetName()
<<"\t trackA->GetGlobalTime() = "
<< G4BestUnit(trackA.GetGlobalTime(), "Time") << G4endl;
exceptionDescription << "trackB : trackID : " << trackB->GetTrackID()
<< "\t Name :" << moleculeB->GetName()
<< "\t trackB->GetGlobalTime() = "
<< G4BestUnit(trackB->GetGlobalTime(), "Time")<< G4endl;
G4Exception("G4DNAMoleculeEncounterStepper::RetrieveResults","MoleculeEncounterStepper004",
FatalErrorInArgument,exceptionDescription);
}
G4double r2 = results->GetDistanceSqr() ;
#ifdef G4VERBOSE
if(fVerbose > 1)
{
G4cout << "\t ************************************************** " << G4endl;
G4cout <<"\t Reaction between "
<< moleculeA->GetName() << " (" << trackA.GetTrackID() << ") "
<< " & " << moleculeB->GetName() << " (" << trackB->GetTrackID() << "), "
<< "Interaction Range = "
<< G4BestUnit(R, "Length")<<G4endl;
G4cout <<"\t Real distance between reactants = "
<< G4BestUnit((trackA.GetPosition() - trackB->GetPosition()).mag(), "Length")<<G4endl;
G4cout <<"\t Distance between reactants calculated by nearest neighbor algorithm = "
<< G4BestUnit(sqrt(r2), "Length")<<G4endl;
// G4cout << " ***** " << G4endl;
}
#endif
if(r2 <= R*R)
{
// Entering in this condition may due to the fact that molecules are very close
// to each other
// Therefore, if we consider only the nearby reactant, this one may have already
// react. Instead, we will take all possible reactants that satisfy the condition r<R
if(fHasAlreadyReachedNullTime == false)
{
fReactants->clear();
fHasAlreadyReachedNullTime = true;
}
if(iterate) // First call (call from outside this method)
{
fSampledMinTimeStep = 0.;
G4KDTreeResultHandle results2 (G4ITManager<G4Molecule>::Instance()
-> FindNearestInRange(moleculeA, moleculeB,R));
RetrieveResults(trackA, moleculeA, moleculeB, R, results2, false);
}
else // Other calls (call from this method)
{
fReactants->push_back(trackB);
}
continue;
}
else
{
G4double r = sqrt(r2);
G4double tempMinET = pow(r - R,2)
/(16 * (DA + DB + 2*sqrt(DA*DB)));
if(tempMinET <= fSampledMinTimeStep)
{
if(tempMinET <= fUserMinTimeStep)
{
if(fSampledMinTimeStep > fUserMinTimeStep)
fReactants->clear();
fSampledMinTimeStep = fUserMinTimeStep;
fReactants->push_back(trackB);
}
else
{
fSampledMinTimeStep = tempMinET;
if(tempMinET < fSampledMinTimeStep)
fReactants->clear();
fReactants->push_back(trackB);
}
}
}
}
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,312 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNASancheExcitationModel.cc,v 1.4 2010-11-11 22:32:22 sincerti Exp $
// GEANT4 tag $Name: not supported by cvs2svn $
//
// Created by Z. Francis
#include "G4DNASancheExcitationModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNASancheExcitationModel::G4DNASancheExcitationModel(const G4ParticleDefinition*,
const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
nistwater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
lowEnergyLimit = 2 * eV;
highEnergyLimit = 100 * eV;
SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
nLevels = 9;
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if (verboseLevel > 0)
{
G4cout << "Sanche Excitation model is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / eV << " eV - "
<< highEnergyLimit / eV << " eV"
<< G4endl;
}
fParticleChangeForGamma = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNASancheExcitationModel::~G4DNASancheExcitationModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNASancheExcitationModel::Initialise(const G4ParticleDefinition* /*particle*/,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNASancheExcitationModel::Initialise()" << G4endl;
// Energy limits
if (LowEnergyLimit() < lowEnergyLimit)
{
G4cout << "G4DNASancheExcitationModel: low energy limit increased from " <<
LowEnergyLimit()/eV << " eV to " << lowEnergyLimit/eV << " eV" << G4endl;
SetLowEnergyLimit(lowEnergyLimit);
}
if (HighEnergyLimit() > highEnergyLimit)
{
G4cout << "G4DNASancheExcitationModel: high energy limit decreased from " <<
HighEnergyLimit()/eV << " eV to " << highEnergyLimit/eV << " eV" << G4endl;
SetHighEnergyLimit(highEnergyLimit);
}
//
if (verboseLevel > 0)
G4cout << "Sanche Excitation model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / eV << " eV"
<< G4endl;
if (isInitialised) { return; }
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
char *path = getenv("G4LEDATA");
std::ostringstream eFullFileName;
eFullFileName << path << "/dna/sigma_excitationvib_e_sanche.dat";
std::ifstream input(eFullFileName.str().c_str());
if (!input)
{
G4Exception("G4DNASancheExcitationModel::Initialise","em0003",
FatalException,"Missing data file:/dna/sigma_excitationvib_e_sanche.dat");
}
while(!input.eof())
{
double t;
input>>t;
tdummyVec.push_back(t);
input>>map1[t][0]>>map1[t][1]>>map1[t][2]>>map1[t][3]>>map1[t][4]>>map1[t][5]>>map1[t][6]>>map1[t][7]>>map1[t][8];
//G4cout<<t<<" "<<map1[t][0]<<map1[t][1]<<map1[t][2]<<map1[t][3]<<map1[t][4]<<map1[t][5]<<map1[t][6]<<map1[t][7]<<map1[t][8]<<G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNASancheExcitationModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
G4double ekin,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNASancheExcitationModel" << G4endl;
// Calculate total cross section for model
G4double sigma=0;
if (material == nistwater || material->GetBaseMaterial() == nistwater)
{
if (particleDefinition == G4Electron::ElectronDefinition())
{
if (ekin >= lowEnergyLimit && ekin < highEnergyLimit)
{
sigma = Sum(ekin);
}
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
} // if water
return sigma*2*material->GetAtomicNumDensityVector()[1];
// see papers for factor 2 description
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNASancheExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>*,
const G4MaterialCutsCouple*,
const G4DynamicParticle* aDynamicElectron,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNASancheExcitationModel" << G4endl;
G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
G4int level = RandomSelect(electronEnergy0);
G4double excitationEnergy = VibrationEnergy(level); // levels go from 0 to 8
G4double newEnergy = electronEnergy0 - excitationEnergy;
/*
if (electronEnergy0 < highEnergyLimit)
{
if (newEnergy >= lowEnergyLimit)
{
fParticleChangeForGamma->ProposeMomentumDirection(aDynamicElectron->GetMomentumDirection());
fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
}
else
{
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(electronEnergy0);
}
}
*/
if (electronEnergy0 < highEnergyLimit && newEnergy>0.)
{
fParticleChangeForGamma->ProposeMomentumDirection(aDynamicElectron->GetMomentumDirection());
fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
}
//
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNASancheExcitationModel::PartialCrossSection(G4double t, G4int level)
{
std::vector<double>::iterator t2 = std::upper_bound(tdummyVec.begin(),tdummyVec.end(), t/eV);
std::vector<double>::iterator t1 = t2-1;
double sigma = LinInterpolate((*t1), (*t2), t/eV, map1[*t1][level], map1[*t2][level]);
sigma*=1e-16*cm*cm;
if(sigma==0.)sigma=1e-30;
return (sigma);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNASancheExcitationModel::VibrationEnergy(G4int level)
{
G4double energies[9] = {0.01, 0.024, 0.061, 0.092, 0.204, 0.417, 0.460, 0.500, 0.835};
return(energies[level]*eV);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNASancheExcitationModel::RandomSelect(G4double k)
{
// Level Selection Counting can be done here !
G4int i = nLevels;
G4double value = 0.;
std::deque<double> values;
while (i > 0)
{
i--;
G4double partial = PartialCrossSection(k,i);
values.push_front(partial);
value += partial;
}
value *= G4UniformRand();
i = nLevels;
while (i > 0)
{
i--;
if (values[i] > value)
{
//outcount<<i<<" "<<VibrationEnergy(i)<<G4endl;
return i;
}
value -= values[i];
}
//outcount<<0<<" "<<VibrationEnergy(0)<<G4endl;
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNASancheExcitationModel::Sum(G4double k)
{
G4double totalCrossSection = 0.;
for (G4int i=0; i<nLevels; i++)
{
totalCrossSection += PartialCrossSection(k,i);
}
return totalCrossSection;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNASancheExcitationModel::LinInterpolate(G4double e1,
G4double e2,
G4double e,
G4double xs1,
G4double xs2)
{
G4double a = (xs2 - xs1) / (e2 - e1);
G4double b = xs2 - a*e2;
G4double value = a*e + b;
// G4cout<<"interP >> "<<e1<<" "<<e2<<" "<<e<<" "<<xs1<<" "<<xs2<<" "<<a<<" "<<b<<" "<<value<<G4endl;
return value;
}
@@ -0,0 +1,188 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
//
// Author: Mathieu Karamitros (kara (AT) cenbg . in2p3 . fr)
//
// WARNING : This class is released as a prototype.
// It might strongly evolve or even disapear in the next releases.
//
// History:
// -----------
// 10 Oct 2011 M.Karamitros created
//
// -------------------------------------------------------------------
#include "G4DNASancheSolvatationModel.hh"
#include "G4WaterExcitationStructure.hh"
#include "G4ParticleChangeForGamma.hh"
#include "G4Electron.hh"
#include "G4NistManager.hh"
#include "G4DNAChemistryManager.hh"
G4DNASancheSolvatationModel::G4DNASancheSolvatationModel(const G4ParticleDefinition*,
const G4String& nam):
G4VEmModel(nam),fIsInitialised(false)
{
fVerboseLevel = 0 ;
SetLowEnergyLimit(0.025*eV);
G4WaterExcitationStructure exStructure ;
SetHighEnergyLimit(exStructure.ExcitationEnergy(0));
fParticleChangeForGamma = 0;
}
//______________________________________________________________________
G4DNASancheSolvatationModel::~G4DNASancheSolvatationModel()
{}
//______________________________________________________________________
void G4DNASancheSolvatationModel::Initialise(const G4ParticleDefinition* particleDefinition,
const G4DataVector&)
{
#ifdef G4VERBOSE
if (fVerboseLevel)
G4cout << "Calling G4SancheSolvatationModel::Initialise()" << G4endl;
#endif
if (particleDefinition != G4Electron::ElectronDefinition())
{
G4ExceptionDescription exceptionDescription ;
exceptionDescription << "Attempting to calculate cross section for wrong particle";
G4Exception("G4DNASancheSolvatationModel::CrossSectionPerVolume","G4DNASancheSolvatationModel001",
FatalErrorInArgument,exceptionDescription);
return;
}
if(!fIsInitialised)
{
fIsInitialised = true;
fParticleChangeForGamma = GetParticleChangeForGamma();
fNistWater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
}
}
//______________________________________________________________________
G4double G4DNASancheSolvatationModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition*,
G4double ekin,
G4double,
G4double)
{
#ifdef G4VERBOSE
if (fVerboseLevel > 1)
G4cout << "Calling CrossSectionPerVolume() of G4SancheSolvatationModel" << G4endl;
#endif
if(ekin > HighEnergyLimit())
{
return 0.0;
}
if (material == fNistWater || material->GetBaseMaterial() == fNistWater)
{
if (ekin <= HighEnergyLimit())
{
return DBL_MAX;
}
}
return 0. ;
}
//______________________________________________________________________
G4ThreeVector G4DNASancheSolvatationModel::RadialDistributionOfProducts(G4double expectationValue) const
{
G4double sigma = std::sqrt(1.57)/2*expectationValue;
G4double XValueForfMax = std::sqrt(2.*sigma*sigma);
G4double fMaxValue = std::sqrt(2./3.14) * 1./(sigma*sigma*sigma) *
(XValueForfMax*XValueForfMax)*
std::exp(-1./2. * (XValueForfMax*XValueForfMax)/(sigma*sigma));
G4double R;
do
{
G4double aRandomfValue = fMaxValue*G4UniformRand();
G4double sign;
if(G4UniformRand() > 0.5)
{
sign = +1.;
}
else
{
sign = -1;
}
R = expectationValue + sign*3.*sigma* G4UniformRand();
G4double f = std::sqrt(2./3.14) * 1/std::pow(sigma, 3) * R*R * std::exp(-1./2. * R*R/(sigma*sigma));
if(aRandomfValue < f)
{
break;
}
}
while(1);
G4double costheta = (2.*G4UniformRand()-1.);
G4double theta = std::acos (costheta);
G4double phi = 2.*pi*G4UniformRand();
G4double xDirection = R*std::cos(phi)* std::sin(theta);
G4double yDirection = R*std::sin(theta)*std::sin(phi);
G4double zDirection = R*costheta;
G4ThreeVector RandDirection = G4ThreeVector(xDirection, yDirection, zDirection);
return RandDirection;
}
//______________________________________________________________________
void G4DNASancheSolvatationModel::SampleSecondaries(std::vector<G4DynamicParticle*>*,
const G4MaterialCutsCouple*,
const G4DynamicParticle* particle,
G4double,
G4double)
{
#ifdef G4VERBOSE
if (fVerboseLevel)
G4cout << "Calling SampleSecondaries() of G4SancheSolvatationModel" << G4endl;
#endif
G4double k = particle->GetKineticEnergy();
if (k <= HighEnergyLimit())
{
G4double r_mean =
(-0.003*std::pow(k/eV,6) + 0.0749*std::pow(k/eV,5) - 0.7197*std::pow(k/eV,4)
+ 3.1384*std::pow(k/eV,3) - 5.6926*std::pow(k/eV,2) + 5.6237*k/eV - 0.7883)*nanometer;
G4ThreeVector displacement = RadialDistributionOfProducts (r_mean);
//______________________________________________________________
const G4Track * theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack();
G4ThreeVector finalPosition(theIncomingTrack->GetPosition()+displacement);
G4DNAChemistryManager::Instance()->CreateSolvatedElectron(theIncomingTrack,&finalPosition);
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(k);
}
}
@@ -0,0 +1,488 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// $Id: G4DNAScreenedRutherfordElasticModel.cc,v 1.15 2010-11-11 22:32:22 sincerti Exp $
// GEANT4 tag $Name: not supported by cvs2svn $
//
#include "G4DNAScreenedRutherfordElasticModel.hh"
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAScreenedRutherfordElasticModel::G4DNAScreenedRutherfordElasticModel
(const G4ParticleDefinition*, const G4String& nam)
:G4VEmModel(nam),isInitialised(false)
{
nistwater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
killBelowEnergy = 9*eV;
lowEnergyLimit = 0 * eV;
intermediateEnergyLimit = 200 * eV; // Switch between two final state models
highEnergyLimit = 1. * MeV;
SetLowEnergyLimit(lowEnergyLimit);
SetHighEnergyLimit(highEnergyLimit);
verboseLevel= 0;
// Verbosity scale:
// 0 = nothing
// 1 = warning for energy non-conservation
// 2 = details of energy budget
// 3 = calculation of cross sections, file openings, sampling of atoms
// 4 = entering in methods
if( verboseLevel>0 )
{
G4cout << "Screened Rutherford Elastic model is constructed " << G4endl
<< "Energy range: "
<< lowEnergyLimit / eV << " eV - "
<< highEnergyLimit / MeV << " MeV"
<< G4endl;
}
fParticleChangeForGamma = 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNAScreenedRutherfordElasticModel::~G4DNAScreenedRutherfordElasticModel()
{}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAScreenedRutherfordElasticModel::Initialise(const G4ParticleDefinition* /*particle*/,
const G4DataVector& /*cuts*/)
{
if (verboseLevel > 3)
G4cout << "Calling G4DNAScreenedRutherfordElasticModel::Initialise()" << G4endl;
// Energy limits
if (LowEnergyLimit() < lowEnergyLimit)
{
G4cout << "G4DNAScreenedRutherfordElasticModel: low energy limit increased from " <<
LowEnergyLimit()/eV << " eV to " << lowEnergyLimit/eV << " eV" << G4endl;
SetLowEnergyLimit(lowEnergyLimit);
}
if (HighEnergyLimit() > highEnergyLimit)
{
G4cout << "G4DNAScreenedRutherfordElasticModel: high energy limit decreased from " <<
HighEnergyLimit()/MeV << " MeV to " << highEnergyLimit/MeV << " MeV" << G4endl;
SetHighEnergyLimit(highEnergyLimit);
}
// Constants for final stae by Brenner & Zaider
betaCoeff.push_back(7.51525);
betaCoeff.push_back(-0.41912);
betaCoeff.push_back(7.2017E-3);
betaCoeff.push_back(-4.646E-5);
betaCoeff.push_back(1.02897E-7);
deltaCoeff.push_back(2.9612);
deltaCoeff.push_back(-0.26376);
deltaCoeff.push_back(4.307E-3);
deltaCoeff.push_back(-2.6895E-5);
deltaCoeff.push_back(5.83505E-8);
gamma035_10Coeff.push_back(-1.7013);
gamma035_10Coeff.push_back(-1.48284);
gamma035_10Coeff.push_back(0.6331);
gamma035_10Coeff.push_back(-0.10911);
gamma035_10Coeff.push_back(8.358E-3);
gamma035_10Coeff.push_back(-2.388E-4);
gamma10_100Coeff.push_back(-3.32517);
gamma10_100Coeff.push_back(0.10996);
gamma10_100Coeff.push_back(-4.5255E-3);
gamma10_100Coeff.push_back(5.8372E-5);
gamma10_100Coeff.push_back(-2.4659E-7);
gamma100_200Coeff.push_back(2.4775E-2);
gamma100_200Coeff.push_back(-2.96264E-5);
gamma100_200Coeff.push_back(-1.20655E-7);
//
if( verboseLevel>0 )
{
G4cout << "Screened Rutherford elastic model is initialized " << G4endl
<< "Energy range: "
<< LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / MeV << " MeV"
<< G4endl;
}
if (isInitialised) { return; }
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAScreenedRutherfordElasticModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition*,
G4double ekin,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNAScreenedRutherfordElasticModel" << G4endl;
// Calculate total cross section for model
G4double sigma=0;
if (material == nistwater || material->GetBaseMaterial() == nistwater)
{
if (ekin < highEnergyLimit)
{
if (ekin < killBelowEnergy) return DBL_MAX;
G4double z = 10.;
G4double n = ScreeningFactor(ekin,z);
G4double crossSection = RutherfordCrossSection(ekin, z);
sigma = pi * crossSection / (n * (n + 1.));
}
if (verboseLevel > 3)
{
G4cout << "---> Kinetic energy(eV)=" << ekin/eV << G4endl;
G4cout << " - Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
}
}
return sigma*material->GetAtomicNumDensityVector()[1];
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAScreenedRutherfordElasticModel::RutherfordCrossSection(G4double k, G4double z)
{
//
// e^4 / K + m_e c^2 \^2
// sigma_Ruth(K) = Z (Z+1) -------------------- | --------------------- |
// (4 pi epsilon_0)^2 \ K * (K + 2 m_e c^2) /
//
// Where K is the electron non-relativistic kinetic energy
//
// NIM 155, pp. 145-156, 1978
G4double length =(e_squared * (k + electron_mass_c2)) / (4 * pi *epsilon0 * k * ( k + 2 * electron_mass_c2));
G4double cross = z * ( z + 1) * length * length;
return cross;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAScreenedRutherfordElasticModel::ScreeningFactor(G4double k, G4double z)
{
//
// alpha_1 + beta_1 ln(K/eV) constK Z^(2/3)
// n(T) = -------------------------- -----------------
// K/(m_e c^2) 2 + K/(m_e c^2)
//
// Where K is the electron non-relativistic kinetic energy
//
// n(T) > 0 for T < ~ 400 MeV
//
// NIM 155, pp. 145-156, 1978
// Formulae (2) and (5)
const G4double alpha_1(1.64);
const G4double beta_1(-0.0825);
const G4double constK(1.7E-5);
G4double numerator = (alpha_1 + beta_1 * std::log(k/eV)) * constK * std::pow(z, 2./3.);
k /= electron_mass_c2;
G4double denominator = k * (2 + k);
G4double value = 0.;
if (denominator > 0.) value = numerator / denominator;
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNAScreenedRutherfordElasticModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
const G4MaterialCutsCouple* /*couple*/,
const G4DynamicParticle* aDynamicElectron,
G4double,
G4double)
{
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNAScreenedRutherfordElasticModel" << G4endl;
G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
if (electronEnergy0 < killBelowEnergy)
{
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(electronEnergy0);
return ;
}
G4double cosTheta = 0.;
if (electronEnergy0>= killBelowEnergy && electronEnergy0 < highEnergyLimit)
{
if (electronEnergy0<intermediateEnergyLimit)
{
if (verboseLevel > 3) G4cout << "---> Using Brenner & Zaider model" << G4endl;
cosTheta = BrennerZaiderRandomizeCosTheta(electronEnergy0);
}
if (electronEnergy0>=intermediateEnergyLimit)
{
if (verboseLevel > 3) G4cout << "---> Using Screened Rutherford model" << G4endl;
G4double z = 10.;
cosTheta = ScreenedRutherfordRandomizeCosTheta(electronEnergy0,z);
}
G4double phi = 2. * pi * G4UniformRand();
G4ThreeVector zVers = aDynamicElectron->GetMomentumDirection();
G4ThreeVector xVers = zVers.orthogonal();
G4ThreeVector yVers = zVers.cross(xVers);
G4double xDir = std::sqrt(1. - cosTheta*cosTheta);
G4double yDir = xDir;
xDir *= std::cos(phi);
yDir *= std::sin(phi);
G4ThreeVector zPrimeVers((xDir*xVers + yDir*yVers + cosTheta*zVers));
fParticleChangeForGamma->ProposeMomentumDirection(zPrimeVers.unit()) ;
fParticleChangeForGamma->SetProposedKineticEnergy(electronEnergy0);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNAScreenedRutherfordElasticModel::BrennerZaiderRandomizeCosTheta(G4double k)
{
// d sigma_el 1 beta(K)
// ------------ (K) ~ --------------------------------- + ---------------------------------
// d Omega (1 + 2 gamma(K) - cos(theta))^2 (1 + 2 delta(K) + cos(theta))^2
//
// Maximum is < 1/(4 gamma(K)^2) + beta(K)/((2+2delta(K))^2)
//
// Phys. Med. Biol. 29 N.4 (1983) 443-447
// gamma(K), beta(K) and delta(K) are polynomials with coefficients for energy measured in eV
k /= eV;
G4double beta = std::exp(CalculatePolynomial(k,betaCoeff));
G4double delta = std::exp(CalculatePolynomial(k,deltaCoeff));
G4double gamma;
if (k > 100.)
{
gamma = CalculatePolynomial(k, gamma100_200Coeff);
// Only in this case it is not the exponent of the polynomial
}
else
{
if (k>10)
{
gamma = std::exp(CalculatePolynomial(k, gamma10_100Coeff));
}
else
{
gamma = std::exp(CalculatePolynomial(k, gamma035_10Coeff));
}
}
// ***** Original method
G4double oneOverMax = 1. / (1./(4.*gamma*gamma) + beta/( (2.+2.*delta)*(2.+2.*delta) ));
G4double cosTheta = 0.;
G4double leftDenominator = 0.;
G4double rightDenominator = 0.;
G4double fCosTheta = 0.;
do
{
cosTheta = 2. * G4UniformRand() - 1.;
leftDenominator = (1. + 2.*gamma - cosTheta);
rightDenominator = (1. + 2.*delta + cosTheta);
if ( (leftDenominator * rightDenominator) != 0. )
{
fCosTheta = oneOverMax * (1./(leftDenominator*leftDenominator) + beta/(rightDenominator*rightDenominator));
}
}
while (fCosTheta < G4UniformRand());
return cosTheta;
// ***** Alternative method using cumulative probability
/*
G4double cosTheta = -1;
G4double cumul = 0;
G4double value = 0;
G4double leftDenominator = 0.;
G4double rightDenominator = 0.;
// Number of integration steps in the -1,1 range
G4int iMax=200;
G4double random = G4UniformRand();
// Cumulate differential cross section
for (G4int i=0; i<iMax; i++)
{
cosTheta = -1 + i*2./(iMax-1);
leftDenominator = (1. + 2.*gamma - cosTheta);
rightDenominator = (1. + 2.*delta + cosTheta);
if ( (leftDenominator * rightDenominator) != 0. )
{
cumul = cumul + (1./(leftDenominator*leftDenominator) + beta/(rightDenominator*rightDenominator));
}
}
// Select cosTheta
for (G4int i=0; i<iMax; i++)
{
cosTheta = -1 + i*2./(iMax-1);
leftDenominator = (1. + 2.*gamma - cosTheta);
rightDenominator = (1. + 2.*delta + cosTheta);
if (cumul !=0 && (leftDenominator * rightDenominator) != 0.)
value = value + (1./(leftDenominator*leftDenominator) + beta/(rightDenominator*rightDenominator)) / cumul;
if (random < value) break;
}
return cosTheta;
*/
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAScreenedRutherfordElasticModel::CalculatePolynomial(G4double k, std::vector<G4double>& vec)
{
// Sum_{i=0}^{size-1} vector_i k^i
//
// Phys. Med. Biol. 29 N.4 (1983) 443-447
G4double result = 0.;
size_t size = vec.size();
while (size>0)
{
size--;
result *= k;
result += vec[size];
}
return result;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNAScreenedRutherfordElasticModel::ScreenedRutherfordRandomizeCosTheta(G4double k, G4double z)
{
// d sigma_el sigma_Ruth(K)
// ------------ (K) ~ -----------------------------
// d Omega (1 + 2 n(K) - cos(theta))^2
//
// We extract cos(theta) distributed as (1 + 2 n(K) - cos(theta))^-2
//
// Maximum is for theta=0: 1/(4 n(K)^2) (When n(K) is positive, that is always satisfied within the validity of the process)
//
// Phys. Med. Biol. 45 (2000) 3171-3194
// ***** Original method
G4double n = ScreeningFactor(k, z);
G4double oneOverMax = (4.*n*n);
G4double cosTheta = 0.;
G4double fCosTheta;
do
{
cosTheta = 2. * G4UniformRand() - 1.;
fCosTheta = (1 + 2.*n - cosTheta);
if (fCosTheta !=0.) fCosTheta = oneOverMax / (fCosTheta*fCosTheta);
}
while (fCosTheta < G4UniformRand());
return cosTheta;
// ***** Alternative method using cumulative probability
/*
G4double cosTheta = -1;
G4double cumul = 0;
G4double value = 0;
G4double n = ScreeningFactor(k, z);
G4double fCosTheta;
// Number of integration steps in the -1,1 range
G4int iMax=200;
G4double random = G4UniformRand();
// Cumulate differential cross section
for (G4int i=0; i<iMax; i++)
{
cosTheta = -1 + i*2./(iMax-1);
fCosTheta = (1 + 2.*n - cosTheta);
if (fCosTheta !=0.) cumul = cumul + 1./(fCosTheta*fCosTheta);
}
// Select cosTheta
for (G4int i=0; i<iMax; i++)
{
cosTheta = -1 + i*2./(iMax-1);
fCosTheta = (1 + 2.*n - cosTheta);
if (cumul !=0.) value = value + (1./(fCosTheta*fCosTheta)) / cumul;
if (random < value) break;
}
return cosTheta;
*/
}
@@ -0,0 +1,121 @@
//
// ********************************************************************
// * License and Disclaimer *
// * *
// * The Geant4 software is copyright of the Copyright Holders of *
// * the Geant4 Collaboration. It is provided under the terms and *
// * conditions of the Geant4 Software License, included in the file *
// * LICENSE and available at http://cern.ch/geant4/license . These *
// * include a list of copyright holders. *
// * *
// * 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. Please see the license in the file LICENSE and URL above *
// * for the full disclaimer and the limitation of liability. *
// * *
// * This code implementation is the result of the scientific and *
// * technical work of the GEANT4 collaboration. *
// * By using, copying, modifying or distributing the software (or *
// * any work based on the software) you agree to acknowledge its *
// * use in resulting scientific publications, and indicate your *
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
#include "G4DNATransformElectronModel.hh"
#include "G4ParticleChangeForGamma.hh"
#include "G4Electron.hh"
#include "G4NistManager.hh"
#include "G4DNAChemistryManager.hh"
G4DNATransformElectronModel::G4DNATransformElectronModel(const G4ParticleDefinition*,
const G4String& nam):
G4VEmModel(nam),fIsInitialised(false)
{
fVerboseLevel = 0 ;
SetLowEnergyLimit(0.*eV);
SetHighEnergyLimit(0.025*eV);
fParticleChangeForGamma = 0;
}
//______________________________________________________________________
G4DNATransformElectronModel::~G4DNATransformElectronModel()
{}
//______________________________________________________________________
void G4DNATransformElectronModel::Initialise(const G4ParticleDefinition* particleDefinition,
const G4DataVector&)
{
#ifdef G4VERBOSE
if (fVerboseLevel)
G4cout << "Calling G4DNATransformElectronModel::Initialise()" << G4endl;
#endif
if (particleDefinition != G4Electron::ElectronDefinition())
{
G4ExceptionDescription exceptionDescription ;
exceptionDescription << "Attempting to calculate cross section for wrong particle";
G4Exception("G4DNATransformElectronModel::CrossSectionPerVolume","G4DNATransformElectronModel001",
FatalErrorInArgument,exceptionDescription);
return;
}
if(!fIsInitialised)
{
fIsInitialised = true;
fParticleChangeForGamma = GetParticleChangeForGamma();
fNistWater = G4NistManager::Instance()->FindOrBuildMaterial("G4_WATER");
}
}
//______________________________________________________________________
G4double G4DNATransformElectronModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition*,
G4double ekin,
G4double,
G4double)
{
#if G4VERBOSE
if (fVerboseLevel > 1)
G4cout << "Calling CrossSectionPerVolume() of G4DNATransformElectronModel" << G4endl;
#endif
if(ekin > HighEnergyLimit())
{
return 0.0;
}
if (material == fNistWater || material->GetBaseMaterial() == fNistWater)
{
if (ekin <= HighEnergyLimit())
{
return DBL_MAX;
}
}
return 0.0 ;
}
//______________________________________________________________________
void G4DNATransformElectronModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
const G4MaterialCutsCouple*,
const G4DynamicParticle* particle,
G4double,
G4double)
{
#if G4VERBOSE
if (fVerboseLevel)
G4cout << "Calling SampleSecondaries() of G4DNATransformElectronModel" << G4endl;
#endif
G4double k = particle->GetKineticEnergy();
if (k <= HighEnergyLimit())
{
const G4Track * track = fParticleChangeForGamma->GetCurrentTrack();
G4DNAChemistryManager::Instance()->CreateSolvatedElectron(track);
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(k);
}
}