Import Geant4 9.5.0 source tree
This commit is contained in:
@@ -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 ;
|
||||
}
|
||||
+543
@@ -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;
|
||||
}
|
||||
|
||||
+514
@@ -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
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);
|
||||
}
|
||||
}
|
||||
+488
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user