Import Geant4 10.4.0.beta source tree
This commit is contained in:
@@ -0,0 +1,657 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// CPA100 elastic model class for electrons
|
||||
//
|
||||
// Based on the work of M. Terrissol and M. C. Bordage
|
||||
//
|
||||
// Users are requested to cite the following papers:
|
||||
// - M. Terrissol, A. Baudre, Radiat. Prot. Dosim. 31 (1990) 175-177
|
||||
// - M.C. Bordage, J. Bordes, S. Edel, M. Terrissol, X. Franceries,
|
||||
// M. Bardies, N. Lampe, S. Incerti, Phys. Med. 32 (2016) 1833-1840
|
||||
//
|
||||
// Authors of this class:
|
||||
// M.C. Bordage, M. Terrissol, S. Edel, J. Bordes, S. Incerti
|
||||
//
|
||||
// 15.01.2014: creation
|
||||
//
|
||||
|
||||
#include "G4DNACPA100ElasticModel.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
using namespace std;
|
||||
|
||||
// #define CPA100_VERBOSE
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNACPA100ElasticModel::G4DNACPA100ElasticModel(const G4ParticleDefinition*,
|
||||
const G4String& nam)
|
||||
:G4VEmModel(nam),isInitialised(false)
|
||||
{
|
||||
|
||||
//killBelowEnergy = 11. * eV; // Default
|
||||
//killBelowEnergy = 10.481 * eV;
|
||||
//lowEnergyLimit = 11 * eV;
|
||||
//highEnergyLimit = 255955 * eV;
|
||||
SetLowEnergyLimit(11*eV);
|
||||
SetHighEnergyLimit(255955 * eV);
|
||||
|
||||
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
|
||||
|
||||
#ifdef UEHARA_VERBOSE
|
||||
if( verboseLevel>0 )
|
||||
{
|
||||
G4cout << "CPA100 Elastic model is constructed " << G4endl
|
||||
<< "Energy range: "
|
||||
<< lowEnergyLimit / eV << " eV - "
|
||||
<< highEnergyLimit / keV << " keV"
|
||||
<< G4endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
fParticleChangeForGamma = 0;
|
||||
fpMolWaterDensity = 0;
|
||||
|
||||
// Selection of stationary mode
|
||||
|
||||
statCode = false;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNACPA100ElasticModel::~G4DNACPA100ElasticModel()
|
||||
{
|
||||
// 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 G4DNACPA100ElasticModel::Initialise(const G4ParticleDefinition*
|
||||
particle,
|
||||
const G4DataVector& /*cuts*/)
|
||||
{
|
||||
|
||||
#ifdef UEHARA_VERBOSE
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling G4DNACPA100ElasticModel::Initialise()" << G4endl;
|
||||
#endif
|
||||
|
||||
if(particle->GetParticleName() != "e-")
|
||||
{
|
||||
G4Exception("*** WARNING: the G4DNACPA100ElasticModel is "
|
||||
"not intented to be used with another particle than the electron",
|
||||
"",FatalException,"") ;
|
||||
}
|
||||
|
||||
// Energy limits
|
||||
|
||||
if (LowEnergyLimit() < 11.*eV)
|
||||
{
|
||||
G4cout << "G4DNACPA100ElasticModel: low energy limit increased from " <<
|
||||
LowEnergyLimit()/eV << " eV to " << 11 << " eV" << G4endl;
|
||||
SetLowEnergyLimit(11.*eV);
|
||||
}
|
||||
|
||||
if (HighEnergyLimit() > 255955.*eV)
|
||||
{
|
||||
G4cout << "G4DNACPA100ElasticModel: high energy limit decreased from " <<
|
||||
HighEnergyLimit()/keV << " keV to " << 255.955 << " keV"
|
||||
<< G4endl;
|
||||
SetHighEnergyLimit(255955.*eV);
|
||||
}
|
||||
|
||||
// Reading of data files
|
||||
|
||||
G4double scaleFactor = 1e-20*m*m;
|
||||
|
||||
G4String fileElectron("dna/sigma_elastic_e_cpa100");
|
||||
|
||||
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 );
|
||||
|
||||
/*
|
||||
G4DNACrossSectionDataSet* tableE =
|
||||
new G4DNACrossSectionDataSet(new G4DNACPA100LogLogInterpolation,
|
||||
eV,scaleFactor );
|
||||
*/
|
||||
|
||||
tableE->LoadData(fileElectron);
|
||||
|
||||
tableData[electron] = tableE;
|
||||
|
||||
// For final state
|
||||
|
||||
char *path = getenv("G4LEDATA");
|
||||
|
||||
if (!path)
|
||||
{
|
||||
G4Exception("G4DNACPA100ElasticModel::Initialise","em0006",
|
||||
FatalException,"G4LEDATA environment variable not set.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::ostringstream eFullFileName;
|
||||
|
||||
eFullFileName << path
|
||||
<< "/dna/sigmadiff_cumulated_elastic_e_cpa100.dat";
|
||||
std::ifstream eDiffCrossSection(eFullFileName.str().c_str());
|
||||
|
||||
if (!eDiffCrossSection)
|
||||
G4Exception("G4DNACPA100ElasticModel::Initialise","em0003",
|
||||
FatalException,
|
||||
"Missing data file:/dna/sigmadiff_cumulated_elastic_e_cpa100.dat");
|
||||
|
||||
// March 25th, 2014 - Vaclav Stepan, Sebastien Incerti
|
||||
// Added clear for MT
|
||||
|
||||
eTdummyVec.clear();
|
||||
eVecm.clear();
|
||||
eDiffCrossSectionData.clear();
|
||||
|
||||
//
|
||||
|
||||
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
|
||||
|
||||
#ifdef UEHARA_VERBOSE
|
||||
if (verboseLevel > 2)
|
||||
G4cout << "Loaded cross section files for CPA100 Elastic model" << G4endl;
|
||||
#endif
|
||||
|
||||
#ifdef UEHARA_VERBOSE
|
||||
if( verboseLevel>0 )
|
||||
{
|
||||
G4cout << "CPA100 Elastic model is initialized " << G4endl
|
||||
<< "Energy range: "
|
||||
<< LowEnergyLimit() / eV << " eV - "
|
||||
<< HighEnergyLimit() / keV << " keV"
|
||||
<< G4endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Initialize water density pointer
|
||||
fpMolWaterDensity = G4DNAMolecularMaterial::Instance()
|
||||
->GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
|
||||
|
||||
if (isInitialised) { return; }
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
isInitialised = true;
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNACPA100ElasticModel::CrossSectionPerVolume
|
||||
(const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double ekin,
|
||||
G4double,
|
||||
G4double)
|
||||
{
|
||||
|
||||
#ifdef UEHARA_VERBOSE
|
||||
if (verboseLevel > 3)
|
||||
G4cout <<
|
||||
"Calling CrossSectionPerVolume() of G4DNACPA100ElasticModel" << G4endl;
|
||||
#endif
|
||||
|
||||
// Calculate total cross section for model
|
||||
|
||||
G4double sigma=0;
|
||||
|
||||
G4double waterDensity = (*fpMolWaterDensity)[material->GetIndex()];
|
||||
|
||||
if(waterDensity!= 0.0)
|
||||
{
|
||||
const G4String& particleName = p->GetParticleName();
|
||||
|
||||
if (ekin < HighEnergyLimit() && ekin >= LowEnergyLimit())
|
||||
{
|
||||
//SI : XS must not be zero otherwise sampling of secondaries
|
||||
// method ignored
|
||||
|
||||
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);
|
||||
|
||||
//
|
||||
//Dump in non-MT mode
|
||||
//
|
||||
/*
|
||||
G4double minEnergy = 10.481 * eV;
|
||||
G4double maxEnergy = 255955. * eV;
|
||||
G4int nEnergySteps = 1000;
|
||||
G4double energy(minEnergy);
|
||||
G4double
|
||||
stpEnergy(std::pow(maxEnergy/energy,
|
||||
1./static_cast<G4double>(nEnergySteps-1)));
|
||||
G4int step(nEnergySteps);
|
||||
system ("rm -rf elastic-cpa100.out");
|
||||
FILE* myFile=fopen("elastic-cpa100.out","a");
|
||||
while (step>0)
|
||||
{
|
||||
step--;
|
||||
fprintf (myFile,"%16.9le %16.9le\n",
|
||||
energy/eV,
|
||||
table->FindValue(energy)/(1e-20*m*m));
|
||||
energy*=stpEnergy;
|
||||
}
|
||||
fclose (myFile);
|
||||
abort();
|
||||
*/
|
||||
//
|
||||
// end of dump
|
||||
//
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
G4Exception("G4DNACPA100ElasticModel::ComputeCrossSectionPerVolume",
|
||||
"em0002",
|
||||
FatalException,"Model not applicable to particle type.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef UEHARA_VERBOSE
|
||||
if (verboseLevel > 2)
|
||||
{
|
||||
G4cout << "__________________________________" << G4endl;
|
||||
G4cout << "G4DNACPA100ElasticModel - XS INFO START" << G4endl;
|
||||
G4cout << "Kinetic energy(eV)=" << ekin/eV << " particle : " << particleName << G4endl;
|
||||
G4cout << "Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
|
||||
G4cout << "Cross section per water molecule (cm^-1)=" << sigma*waterDensity/(1./cm) << G4endl;
|
||||
// G4cout << " - Cross section per water molecule (cm^-1)="
|
||||
// << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
|
||||
G4cout << "G4DNACPA100ElasticModel - XS INFO END" << G4endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return sigma*waterDensity;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNACPA100ElasticModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
|
||||
const G4MaterialCutsCouple* /*couple*/,
|
||||
const G4DynamicParticle* aDynamicElectron,
|
||||
G4double,
|
||||
G4double)
|
||||
{
|
||||
#ifdef UEHARA_VERBOSE
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling SampleSecondaries() of G4DNACPA100ElasticModel" << G4endl;
|
||||
#endif
|
||||
|
||||
G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
|
||||
|
||||
{
|
||||
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);
|
||||
|
||||
// Computation of scattering angles (from Subroutine DIRAN in CPA100)
|
||||
|
||||
G4double CT1, ST1, CF1, SF1, CT2, ST2, CF2, SF2;
|
||||
G4double sinTheta = std::sqrt (1-cosTheta*cosTheta);
|
||||
|
||||
CT1=0;
|
||||
ST1=0;
|
||||
CF1=0;
|
||||
SF1=0;
|
||||
CT2=0;
|
||||
ST2=0;
|
||||
CF2=0;
|
||||
SF2=0;
|
||||
|
||||
CT1 = zVers.z();
|
||||
ST1=std::sqrt(1.-CT1*CT1);
|
||||
|
||||
if (ST1!=0) CF1 = zVers.x()/ST1; else CF1 = std::cos(2. * pi * G4UniformRand());
|
||||
if (ST1!=0) SF1 = zVers.y()/ST1; else SF1 = std::sqrt(1.-CF1*CF1);
|
||||
|
||||
G4double A3, A4, A5, A2, A1;
|
||||
A3=0;
|
||||
A4=0;
|
||||
A5=0;
|
||||
A2=0;
|
||||
A1=0;
|
||||
|
||||
A3 = sinTheta*std::cos(phi);
|
||||
A4 = A3*CT1 + ST1*cosTheta;
|
||||
A5 = sinTheta * std::sin(phi);
|
||||
A2 = A4 * SF1 + A5 * CF1;
|
||||
A1 = A4 * CF1 - A5 * SF1;
|
||||
|
||||
CT2 = CT1*cosTheta - ST1*A3;
|
||||
ST2 = std::sqrt(1.-CT2*CT2);
|
||||
|
||||
if (ST2==0) ST2=1E-6;
|
||||
CF2 = A1/ST2;
|
||||
SF2 = A2/ST2;
|
||||
|
||||
/*
|
||||
G4cout << "CT1=" << CT1 << G4endl;
|
||||
G4cout << "ST1=" << ST1 << G4endl;
|
||||
G4cout << "CF1=" << CF1 << G4endl;
|
||||
G4cout << "SF1=" << SF1 << G4endl;
|
||||
G4cout << "cosTheta=" << cosTheta << G4endl;
|
||||
G4cout << "sinTheta=" << sinTheta << G4endl;
|
||||
G4cout << "cosPhi=" << std::cos(phi) << G4endl;
|
||||
G4cout << "sinPhi=" << std::sin(phi) << G4endl;
|
||||
G4cout << "CT2=" << CT2 << G4endl;
|
||||
G4cout << "ST2=" << ST2 << G4endl;
|
||||
G4cout << "CF2=" << CF2 << G4endl;
|
||||
G4cout << "SF2=" << SF2 << G4endl;
|
||||
*/
|
||||
|
||||
G4ThreeVector zPrimeVers(ST2*CF2,ST2*SF2,CT2);
|
||||
|
||||
//
|
||||
|
||||
fParticleChangeForGamma->ProposeMomentumDirection(zPrimeVers.unit()) ;
|
||||
|
||||
//fParticleChangeForGamma->SetProposedKineticEnergy(electronEnergy0);
|
||||
|
||||
if (!statCode)
|
||||
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy
|
||||
(electronEnergy0-1.214E-4*(1.-cosTheta)*electronEnergy0);
|
||||
|
||||
else fParticleChangeForGamma->SetProposedKineticEnergy(electronEnergy0);
|
||||
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(1.214E-4*(1.-cosTheta)*electronEnergy0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNACPA100ElasticModel::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];
|
||||
|
||||
//FOR CPA100
|
||||
//if(k==valueT1) xs22 = eDiffCrossSectionData[valueT1][valueE12];
|
||||
|
||||
}
|
||||
|
||||
if (xs11==0 && xs12==0 && xs21==0 && xs22==0) return (0.);
|
||||
|
||||
// FOR CPA100
|
||||
|
||||
|
||||
theta = QuadInterpolator ( valueE11, valueE12,
|
||||
valueE21, valueE22,
|
||||
xs11, xs12,
|
||||
xs21, xs22,
|
||||
valueT1, valueT2,
|
||||
k, integrDiff );
|
||||
|
||||
return theta;
|
||||
|
||||
|
||||
//FOR CPA100
|
||||
//return xs22;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNACPA100ElasticModel::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 G4DNACPA100ElasticModel::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 G4DNACPA100ElasticModel::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 G4DNACPA100ElasticModel::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 G4DNACPA100ElasticModel::RandomizeCosTheta(G4double k)
|
||||
{
|
||||
|
||||
G4double integrdiff=0; // PROBABILITY between 0 and 1.
|
||||
G4double uniformRand=G4UniformRand();
|
||||
integrdiff = uniformRand;
|
||||
|
||||
G4double cosTheta=0.;
|
||||
|
||||
// 1 - COS THETA is read from the data file
|
||||
cosTheta = 1 - Theta(G4Electron::ElectronDefinition(),k/eV,integrdiff);
|
||||
|
||||
//
|
||||
//
|
||||
//Dump
|
||||
//
|
||||
//G4cout << "theta=" << theta << G4endl;
|
||||
//G4cout << "cos theta=" << std::cos(theta*pi/180) << G4endl;
|
||||
//G4cout << "sin theta=" << std::sin(theta*pi/180) << G4endl;
|
||||
//G4cout << "acos(cos theta)=" << std::acos(cosTheta) << G4endl;
|
||||
//G4cout << "cos theta="<< cosTheta << G4endl;
|
||||
//G4cout << "1 - cos theta="<< 1. - cosTheta << G4endl;
|
||||
//G4cout << "sin theta=" << std::sqrt(1-cosTheta*cosTheta) << G4endl;
|
||||
//
|
||||
/*
|
||||
G4double minProb = 0; // we scan probability between 0 and one
|
||||
G4double maxProb = 1;
|
||||
G4int nProbSteps = 100;
|
||||
G4double prob(minProb);
|
||||
G4double stepProb((maxProb-minProb)/static_cast<G4double>(nProbSteps));
|
||||
G4int step(nProbSteps);
|
||||
system ("rm -rf elastic-cumul-cpa100-100keV.out");
|
||||
FILE* myFile=fopen("elastic-cumul-cpa100-100keV.out","a");
|
||||
while (step>=0)
|
||||
{
|
||||
step--;
|
||||
fprintf (myFile,"%16.9le %16.9le\n",
|
||||
prob,
|
||||
Theta(G4Electron::ElectronDefinition(),100000,prob)); // SELECT NRJ IN eV !!!
|
||||
prob=prob+stepProb;
|
||||
}
|
||||
fclose (myFile);
|
||||
abort();
|
||||
*/
|
||||
//
|
||||
// end of dump
|
||||
//
|
||||
|
||||
return cosTheta;
|
||||
}
|
||||
@@ -0,0 +1,469 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// CPA100 excitation model class for electrons
|
||||
//
|
||||
// Based on the work of M. Terrissol and M. C. Bordage
|
||||
//
|
||||
// Users are requested to cite the following papers:
|
||||
// - M. Terrissol, A. Baudre, Radiat. Prot. Dosim. 31 (1990) 175-177
|
||||
// - M.C. Bordage, J. Bordes, S. Edel, M. Terrissol, X. Franceries,
|
||||
// M. Bardies, N. Lampe, S. Incerti, Phys. Med. 32 (2016) 1833-1840
|
||||
//
|
||||
// Authors of this class:
|
||||
// M.C. Bordage, M. Terrissol, S. Edel, J. Bordes, S. Incerti
|
||||
//
|
||||
// 15.01.2014: creation
|
||||
//
|
||||
|
||||
#include "G4DNACPA100ExcitationModel.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
using namespace std;
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNACPA100ExcitationModel::G4DNACPA100ExcitationModel(const G4ParticleDefinition*,
|
||||
const G4String& nam)
|
||||
:G4VEmModel(nam),isInitialised(false)
|
||||
{
|
||||
fpMolWaterDensity = 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 << "CPA100 excitation model is constructed " << G4endl;
|
||||
}
|
||||
fParticleChangeForGamma = 0;
|
||||
|
||||
// Selection of stationary mode
|
||||
|
||||
statCode = false;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNACPA100ExcitationModel::~G4DNACPA100ExcitationModel()
|
||||
{
|
||||
// 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 G4DNACPA100ExcitationModel::Initialise(const G4ParticleDefinition* particle,
|
||||
const G4DataVector& /*cuts*/)
|
||||
{
|
||||
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling G4DNACPA100ExcitationModel::Initialise()" << G4endl;
|
||||
|
||||
G4String fileElectron("dna/sigma_excitation_e_cpa100");
|
||||
|
||||
G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
|
||||
|
||||
G4String electron;
|
||||
|
||||
G4double scaleFactor = 1.e-20 *m*m;
|
||||
|
||||
// *** ELECTRON
|
||||
|
||||
electron = electronDef->GetParticleName();
|
||||
|
||||
tableFile[electron] = fileElectron;
|
||||
|
||||
lowEnergyLimit[electron] = 11 * eV; // Default low enetgy limit
|
||||
//lowEnergyLimit[electron] = 10.481 * eV; // From sigexi2 file by MCB
|
||||
highEnergyLimit[electron] = 255955 * eV; // idem
|
||||
|
||||
// Cross section
|
||||
|
||||
G4DNACrossSectionDataSet* tableE
|
||||
= new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV, scaleFactor );
|
||||
|
||||
/*
|
||||
G4DNACrossSectionDataSet* tableE =
|
||||
new G4DNACrossSectionDataSet(new G4DNACPA100LogLogInterpolation, eV, scaleFactor );
|
||||
*/
|
||||
|
||||
tableE->LoadData(fileElectron);
|
||||
|
||||
tableData[electron] = tableE;
|
||||
|
||||
//
|
||||
|
||||
if (particle==electronDef)
|
||||
{
|
||||
SetLowEnergyLimit(lowEnergyLimit[electron]);
|
||||
SetHighEnergyLimit(highEnergyLimit[electron]);
|
||||
}
|
||||
|
||||
|
||||
// if( verboseLevel>0 )
|
||||
{
|
||||
G4cout << "CPA100 excitation model is initialized " << G4endl
|
||||
<< "Energy range: "
|
||||
<< LowEnergyLimit() / eV << " eV - "
|
||||
<< HighEnergyLimit() / keV << " keV for "
|
||||
<< particle->GetParticleName()
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
// Initialize water density pointer
|
||||
fpMolWaterDensity =
|
||||
G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
|
||||
|
||||
if (isInitialised) { return; }
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
isInitialised = true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNACPA100ExcitationModel::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* particleDefinition,
|
||||
G4double ekin,
|
||||
G4double,
|
||||
G4double)
|
||||
{
|
||||
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling CrossSectionPerVolume() of G4DNACPA100ExcitationModel" << G4endl;
|
||||
|
||||
if (particleDefinition != G4Electron::ElectronDefinition()) return 0;
|
||||
|
||||
// Calculate total cross section for model
|
||||
|
||||
G4double lowLim = 0;
|
||||
G4double highLim = 0;
|
||||
G4double sigma=0;
|
||||
|
||||
G4double waterDensity = (*fpMolWaterDensity)[material->GetIndex()];
|
||||
|
||||
if(waterDensity!= 0.0)
|
||||
{
|
||||
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("G4DNACPA100ExcitationModel::CrossSectionPerVolume","em0002",
|
||||
FatalException,"Model not applicable to particle type.");
|
||||
}
|
||||
}
|
||||
|
||||
if (verboseLevel > 2)
|
||||
{
|
||||
G4cout << "__________________________________" << G4endl;
|
||||
G4cout << "G4DNACPA100ExcitationModel - XS INFO START" << G4endl;
|
||||
G4cout << "Kinetic energy(eV)=" << ekin/eV << " particle : " << particleName << G4endl;
|
||||
G4cout << "Cross section per water molecule (cm^2)=" << sigma/cm/cm << G4endl;
|
||||
G4cout << "Cross section per water molecule (cm^-1)=" << sigma*waterDensity/(1./cm) << G4endl;
|
||||
// G4cout << " - Cross section per water molecule (cm^-1)=" << sigma*material->GetAtomicNumDensityVector()[1]/(1./cm) << G4endl;
|
||||
G4cout << "G4DNACPA100ExcitationModel - XS INFO END" << G4endl;
|
||||
}
|
||||
|
||||
} // if (waterMaterial)
|
||||
|
||||
return sigma*waterDensity;
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNACPA100ExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* ,
|
||||
const G4MaterialCutsCouple*,
|
||||
const G4DynamicParticle* aDynamicParticle,
|
||||
G4double,
|
||||
G4double)
|
||||
{
|
||||
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling SampleSecondaries() of G4DNACPA100ExcitationModel" << 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());
|
||||
|
||||
// We take into account direction change as described page 87 (II.92) in thesis by S. Edel
|
||||
|
||||
G4double cosTheta =
|
||||
|
||||
(excitationEnergy/k) / (1. + (k/(2*electron_mass_c2))*(1.-excitationEnergy/k) );
|
||||
|
||||
cosTheta = std::sqrt(1.-cosTheta);
|
||||
|
||||
G4double phi = 2. * pi * G4UniformRand();
|
||||
|
||||
G4ThreeVector zVers = aDynamicParticle->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));
|
||||
|
||||
// Computation of scattering angles (from Subroutine DIRAN in CPA100)
|
||||
|
||||
G4double CT1, ST1, CF1, SF1, CT2, ST2, CF2, SF2;
|
||||
G4double sinTheta = std::sqrt (1-cosTheta*cosTheta);
|
||||
|
||||
CT1=0;
|
||||
ST1=0;
|
||||
CF1=0;
|
||||
SF1=0;
|
||||
CT2=0;
|
||||
ST2=0;
|
||||
CF2=0;
|
||||
SF2=0;
|
||||
|
||||
CT1 = zVers.z();
|
||||
ST1=std::sqrt(1.-CT1*CT1);
|
||||
|
||||
if (ST1!=0) CF1 = zVers.x()/ST1; else CF1 = std::cos(2. * pi * G4UniformRand());
|
||||
if (ST1!=0) SF1 = zVers.y()/ST1; else SF1 = std::sqrt(1.-CF1*CF1);
|
||||
|
||||
G4double A3, A4, A5, A2, A1;
|
||||
A3=0;
|
||||
A4=0;
|
||||
A5=0;
|
||||
A2=0;
|
||||
A1=0;
|
||||
|
||||
A3 = sinTheta*std::cos(phi);
|
||||
A4 = A3*CT1 + ST1*cosTheta;
|
||||
A5 = sinTheta * std::sin(phi);
|
||||
A2 = A4 * SF1 + A5 * CF1;
|
||||
A1 = A4 * CF1 - A5 * SF1;
|
||||
|
||||
CT2 = CT1*cosTheta - ST1*A3;
|
||||
ST2 = std::sqrt(1.-CT2*CT2);
|
||||
|
||||
if (ST2==0) ST2=1E-6;
|
||||
CF2 = A1/ST2;
|
||||
SF2 = A2/ST2;
|
||||
|
||||
/*
|
||||
G4cout << "CT1=" << CT1 << G4endl;
|
||||
G4cout << "ST1=" << ST1 << G4endl;
|
||||
G4cout << "CF1=" << CF1 << G4endl;
|
||||
G4cout << "SF1=" << SF1 << G4endl;
|
||||
G4cout << "cosTheta=" << cosTheta << G4endl;
|
||||
G4cout << "sinTheta=" << sinTheta << G4endl;
|
||||
G4cout << "cosPhi=" << std::cos(phi) << G4endl;
|
||||
G4cout << "sinPhi=" << std::sin(phi) << G4endl;
|
||||
G4cout << "CT2=" << CT2 << G4endl;
|
||||
G4cout << "ST2=" << ST2 << G4endl;
|
||||
G4cout << "CF2=" << CF2 << G4endl;
|
||||
G4cout << "SF2=" << SF2 << G4endl;
|
||||
*/
|
||||
|
||||
G4ThreeVector zPrimeVers(ST2*CF2,ST2*SF2,CT2);
|
||||
|
||||
//
|
||||
|
||||
fParticleChangeForGamma->ProposeMomentumDirection(zPrimeVers.unit()) ;
|
||||
|
||||
//
|
||||
|
||||
if (!statCode) fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
|
||||
else fParticleChangeForGamma->SetProposedKineticEnergy(k);
|
||||
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
|
||||
}
|
||||
|
||||
// Chemistry
|
||||
|
||||
const G4Track * theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack();
|
||||
G4DNAChemistryManager::Instance()->CreateWaterMolecule(eExcitedMolecule,
|
||||
level,
|
||||
theIncomingTrack);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4int G4DNACPA100ExcitationModel::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.;
|
||||
|
||||
//Verification
|
||||
/*
|
||||
G4double tmp=10.481*eV;
|
||||
G4cout << table->GetComponent(0)->FindValue(tmp)/(1e-20*m*m) << G4endl;
|
||||
G4cout << table->GetComponent(1)->FindValue(tmp)/(1e-20*m*m) << G4endl;
|
||||
G4cout << table->GetComponent(2)->FindValue(tmp)/(1e-20*m*m) << G4endl;
|
||||
G4cout << table->GetComponent(3)->FindValue(tmp)/(1e-20*m*m) << G4endl;
|
||||
G4cout << table->GetComponent(4)->FindValue(tmp)/(1e-20*m*m) << G4endl;
|
||||
G4cout <<
|
||||
table->GetComponent(0)->FindValue(tmp)/(1e-20*m*m) +
|
||||
table->GetComponent(1)->FindValue(tmp)/(1e-20*m*m) +
|
||||
table->GetComponent(2)->FindValue(tmp)/(1e-20*m*m) +
|
||||
table->GetComponent(3)->FindValue(tmp)/(1e-20*m*m) +
|
||||
table->GetComponent(4)->FindValue(tmp)/(1e-20*m*m)
|
||||
<< G4endl;
|
||||
abort();
|
||||
*/
|
||||
//
|
||||
//Dump
|
||||
//
|
||||
/*
|
||||
G4double minEnergy = 10.481 * eV;
|
||||
G4double maxEnergy = 255955. * eV;
|
||||
G4int nEnergySteps = 1000;
|
||||
G4double energy(minEnergy);
|
||||
G4double stpEnergy(std::pow(maxEnergy/energy, 1./static_cast<G4double>(nEnergySteps-1)));
|
||||
G4int step(nEnergySteps);
|
||||
system ("rm -rf excitation-cap100.out");
|
||||
FILE* myFile=fopen("excitation-cpa100.out","a");
|
||||
while (step>0)
|
||||
{
|
||||
step--;
|
||||
fprintf (myFile,"%16.9le %16.9le %16.9le %16.9le %16.9le %16.9le %16.9le \n",
|
||||
energy/eV,
|
||||
table->GetComponent(0)->FindValue(energy)/(1e-20*m*m),
|
||||
table->GetComponent(1)->FindValue(energy)/(1e-20*m*m),
|
||||
table->GetComponent(2)->FindValue(energy)/(1e-20*m*m),
|
||||
table->GetComponent(3)->FindValue(energy)/(1e-20*m*m),
|
||||
table->GetComponent(4)->FindValue(energy)/(1e-20*m*m),
|
||||
table->GetComponent(0)->FindValue(energy)/(1e-20*m*m)+
|
||||
table->GetComponent(1)->FindValue(energy)/(1e-20*m*m)+
|
||||
table->GetComponent(2)->FindValue(energy)/(1e-20*m*m)+
|
||||
table->GetComponent(3)->FindValue(energy)/(1e-20*m*m)+
|
||||
table->GetComponent(4)->FindValue(energy)/(1e-20*m*m)
|
||||
);
|
||||
energy*=stpEnergy;
|
||||
}
|
||||
fclose (myFile);
|
||||
abort();
|
||||
*/
|
||||
//
|
||||
// end of dump
|
||||
//
|
||||
|
||||
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("G4DNACPA100ExcitationModel::RandomSelect","em0002",
|
||||
FatalException,"Model not applicable to particle type.");
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// Contact authors: S. Meylan, C. Villagrasa
|
||||
//
|
||||
// email: sylvain.meylan@symalgo-tech.com, carmen.villagrasa@irsn.fr
|
||||
|
||||
#include "../include/G4DNADummyModel.hh"
|
||||
|
||||
#include "G4SystemOfUnits.hh"
|
||||
|
||||
G4DNADummyModel::G4DNADummyModel(const G4String& applyToMaterial, const G4ParticleDefinition* p, const G4String& nam, G4VEmModel* emModel)
|
||||
: G4VDNAModel(nam, applyToMaterial)
|
||||
{
|
||||
fpEmModel = emModel;
|
||||
fpParticleDef = p;
|
||||
}
|
||||
|
||||
G4DNADummyModel::~G4DNADummyModel()
|
||||
{
|
||||
// There is no need to delete the model because it will be done in some G4 class.
|
||||
//if(fpEmModel) delete fpEmModel;
|
||||
}
|
||||
|
||||
void G4DNADummyModel::Initialise(const G4ParticleDefinition* particle, const G4DataVector& v, G4ParticleChangeForGamma* changeForGamme)
|
||||
{
|
||||
fMaterialMolPerVol = G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER") );
|
||||
|
||||
fpEmModel->SetParticleChange(changeForGamme, nullptr);
|
||||
fpEmModel->Initialise(particle, v);
|
||||
|
||||
// MatManagSys
|
||||
EnableForMaterialAndParticle("G4_WATER", fpParticleDef->GetParticleName() );
|
||||
SetLowELimit("G4_WATER", fpParticleDef->GetParticleName(), fpEmModel->LowEnergyLimit() );
|
||||
SetHighELimit("G4_WATER",fpParticleDef->GetParticleName(), fpEmModel->HighEnergyLimit() );
|
||||
}
|
||||
|
||||
G4double G4DNADummyModel::CrossSectionPerVolume(const G4Material* material, const G4String& /*materialName*/, const G4ParticleDefinition* p, G4double ekin, G4double emin, G4double emax)
|
||||
{
|
||||
G4double crossSectionTimesDensity = fpEmModel->CrossSectionPerVolume(material, p, ekin, emin, emax);
|
||||
G4double crossSection = crossSectionTimesDensity / GetNumMoleculePerVolumeUnitForMaterial(G4Material::GetMaterial("G4_WATER") );
|
||||
|
||||
return crossSection;
|
||||
}
|
||||
|
||||
void G4DNADummyModel::SampleSecondaries(std::vector<G4DynamicParticle*>* a, const G4MaterialCutsCouple* b, const G4String& /*materialName*/, const G4DynamicParticle* c, G4ParticleChangeForGamma* /*particleChangeForGamma*/, G4double tmin, G4double tmax)
|
||||
{
|
||||
fpEmModel->SampleSecondaries(a, b, c, tmin, tmax);
|
||||
}
|
||||
|
||||
G4double G4DNADummyModel::GetNumMoleculePerVolumeUnitForMaterial(const G4Material* mat)
|
||||
{
|
||||
return fMaterialMolPerVol->at(mat->GetIndex() );
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,646 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// Contact authors: S. Meylan, C. Villagrasa
|
||||
//
|
||||
// email: sylvain.meylan@symalgo-tech.com, carmen.villagrasa@irsn.fr
|
||||
|
||||
#include "G4DNAModelInterface.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
|
||||
|
||||
G4DNAModelInterface::G4DNAModelInterface(const G4String &nam)
|
||||
: G4VEmModel(nam), fName(nam), fpParticleChangeForGamma(0), fSampledMat("")
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNAModelInterface::~G4DNAModelInterface()
|
||||
{
|
||||
// Loop on all the registered models to properly delete them (free the memory)
|
||||
for(unsigned int i=0, ie = fRegisteredModels.size(); i<ie; ++i)
|
||||
{
|
||||
if(fRegisteredModels.at(i) != nullptr) delete fRegisteredModels.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAModelInterface::Initialise(const G4ParticleDefinition* particle,
|
||||
const G4DataVector& cuts)
|
||||
{
|
||||
// Those two statements are necessary to override the energy limits set in the G4DNAProcesses (ionisation, elastic, etc...).
|
||||
// Indeed, with the ModelInterface system, the model define themselves their energy limits per material and particle.
|
||||
// Therefore, such a limit should not be in the G4DNAProcess classes.
|
||||
//
|
||||
SetLowEnergyLimit(0.);
|
||||
SetHighEnergyLimit(DBL_MAX);
|
||||
|
||||
fpParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
|
||||
// Loop on all the registered models to initialise them
|
||||
for(unsigned int i=0, ie = fRegisteredModels.size(); i<ie; ++i)
|
||||
{
|
||||
fRegisteredModels.at(i)->Initialise(particle, cuts, fpParticleChangeForGamma);
|
||||
}
|
||||
|
||||
|
||||
// Build the [material][particle]=Models table
|
||||
// used to retrieve the model corresponding to the current material/particle couple
|
||||
BuildMaterialParticleModelTable(particle);
|
||||
|
||||
BuildMaterialMolPerVolTable();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAModelInterface::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double ekin,
|
||||
G4double emin,
|
||||
G4double emax)
|
||||
{
|
||||
// Method to return the crossSection * nbMoleculePerUnitVolume to the process class.
|
||||
// Process class then calculates the path.
|
||||
// The cross section is calculated in the registered model(s) and this class just call the method
|
||||
// Two cases are handled here: normal material and composite material.
|
||||
//
|
||||
// Idea:
|
||||
// *** Simple material ***
|
||||
// Ask for the cross section of the chosen model.
|
||||
// Multiply it by the number of medium molecules per volume unit.
|
||||
// Return the value.
|
||||
// *** Composite material ***
|
||||
// Ask for the cross section of the chosen model for each component.
|
||||
// Apply a factor to each cross section and sum the results. The factor is the molecule number of component per composite volume unit.
|
||||
// The total cross section is returned.
|
||||
|
||||
// To reset the sampledMat variable.
|
||||
// Can be used by user to retrieve current component
|
||||
fSampledMat = "";
|
||||
|
||||
// This is the value to be sum up and to be returned at then end
|
||||
G4double crossSectionTimesNbMolPerVol (0);
|
||||
|
||||
// Reset the map saving the material and the cumulated corresponding cross section
|
||||
// Used in SampleSecondaries if the interaction is selected for the step and if the material is a composite
|
||||
fMaterialCS.clear();
|
||||
|
||||
// This is the value to be used by SampleSecondaries
|
||||
fCSsumTot = 0;
|
||||
|
||||
// *****************************
|
||||
// Material is not a composite
|
||||
// *****************************
|
||||
//
|
||||
if(material->GetMatComponents().empty())
|
||||
{
|
||||
// Get the material name
|
||||
const G4String& materialName = material->GetName();
|
||||
|
||||
// Use the table to get the model
|
||||
G4VDNAModel* model = GetDNAModel(materialName, p->GetParticleName(), ekin);
|
||||
|
||||
// Get the nunber of molecules per volume unit for that material
|
||||
G4double nbOfMoleculePerVolumeUnit = GetNumMoleculePerVolumeUnitForMaterial(material);
|
||||
|
||||
// Calculate the cross section times the number of molecules
|
||||
if(model != 0)
|
||||
crossSectionTimesNbMolPerVol = nbOfMoleculePerVolumeUnit * model->CrossSectionPerVolume(material, materialName, p, ekin, emin, emax);
|
||||
else // no model was selected, we are out of the energy ranges
|
||||
crossSectionTimesNbMolPerVol = 0.;
|
||||
}
|
||||
|
||||
// ********************************
|
||||
// Material is a composite
|
||||
// ********************************
|
||||
//
|
||||
else
|
||||
{
|
||||
// Copy the map in a local variable
|
||||
// Otherwise we get segmentation fault and iterator pointing to nowhere: do not know why...
|
||||
// Maybe MatComponents map is overrided by something somewhere ?
|
||||
std::map<G4Material*, G4double> componentsMap = material->GetMatComponents();
|
||||
|
||||
// Retrieve the iterator
|
||||
std::map<G4Material*, G4double>::const_iterator it = componentsMap.begin();
|
||||
|
||||
// Get the size
|
||||
unsigned int componentNumber = componentsMap.size();
|
||||
|
||||
// Loop on all the components
|
||||
//for(it = material->GetMatComponents().begin(); it!=material->GetMatComponents().end();++it)
|
||||
for(unsigned int i=0; i<componentNumber; ++i)
|
||||
{
|
||||
// Get the current component
|
||||
G4Material* component = it->first;
|
||||
|
||||
// Get the current component mass fraction
|
||||
//G4double massFraction = it->second;
|
||||
|
||||
// Get the number of component molecules in a volume unit of composite material
|
||||
G4double nbMoleculeOfComponentInCompositeMat = GetNumMolPerVolUnitForComponentInComposite(component, material);
|
||||
|
||||
// Get the current component name
|
||||
const G4String componentName = component->GetName();
|
||||
|
||||
// Retrieve the model corresponding to the current component (ie material)
|
||||
G4VDNAModel* model = GetDNAModel(componentName, p->GetParticleName(), ekin);
|
||||
|
||||
// Add the component part of the cross section to the cross section variable.
|
||||
// The component cross section is multiplied by the total molecule number in the composite scaled by the mass fraction.
|
||||
if(model != 0)
|
||||
crossSectionTimesNbMolPerVol =
|
||||
nbMoleculeOfComponentInCompositeMat * model->CrossSectionPerVolume(component, componentName, p, ekin, emin, emax);
|
||||
else // no model was selected, we are out of the energy ranges
|
||||
crossSectionTimesNbMolPerVol = 0.;
|
||||
|
||||
// Save the component name and its calculated crossSectionTimesNbMolPerVol
|
||||
// To be used by sampling secondaries if the interaction is selected for the step
|
||||
fMaterialCS[componentName] = crossSectionTimesNbMolPerVol;
|
||||
|
||||
// Save the component name and its calculated crossSectionTimesNbMolPerVol
|
||||
// To be used by sampling secondaries if the interaction is selected for the step
|
||||
fCSsumTot += crossSectionTimesNbMolPerVol;
|
||||
|
||||
// Move forward the iterator
|
||||
++it;
|
||||
}
|
||||
|
||||
crossSectionTimesNbMolPerVol = fCSsumTot;
|
||||
|
||||
}
|
||||
|
||||
// return the cross section times the number of molecules
|
||||
// the path of the interaction will be calculated using that value
|
||||
return crossSectionTimesNbMolPerVol;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAModelInterface::SampleSecondaries(std::vector<G4DynamicParticle*>* fVect,
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* aDynamicParticle,
|
||||
G4double tmin,
|
||||
G4double tmax)
|
||||
{
|
||||
// To call the sampleSecondaries method of the registered model(s)
|
||||
// In the case of composite material, we need to choose a component to call the method from.
|
||||
// To do so we use a random sampling on the crossSectionTimesNbMolPerVol used in CrossSectionPerVolume method.
|
||||
// If we enter that method it means the corresponding interaction (and process) has been chosen for the current step.
|
||||
|
||||
G4String materialName;
|
||||
|
||||
// *******************************
|
||||
// Material is not a composite
|
||||
// *******************************
|
||||
//
|
||||
if(couple->GetMaterial()->GetMatComponents().empty())
|
||||
{
|
||||
materialName = couple->GetMaterial()->GetName();
|
||||
}
|
||||
|
||||
// ****************************
|
||||
// Material is a composite
|
||||
// ****************************
|
||||
//
|
||||
else
|
||||
{
|
||||
// Material is a composite
|
||||
// We need to select a component
|
||||
|
||||
// We select a random number between 0 and fCSSumTot
|
||||
G4double rand = G4UniformRand()*fCSsumTot;
|
||||
|
||||
G4double cumulCS (0);
|
||||
|
||||
G4bool result = false;
|
||||
|
||||
// We loop on each component cumulated cross section
|
||||
//
|
||||
// Retrieve the iterators
|
||||
std::map<const G4String , G4double>::const_iterator it = fMaterialCS.begin();
|
||||
std::map<const G4String , G4double>::const_iterator ite = fMaterialCS.end();
|
||||
// While this is true we do not have found our component.
|
||||
while(rand>cumulCS)
|
||||
{
|
||||
// Check if the sampling is ok
|
||||
if(it==ite)
|
||||
{
|
||||
G4Exception("G4DNAModelManager::SampleSecondaries","em0006",
|
||||
FatalException,
|
||||
"The random component selection has failed: we ran into the end of the map without having a selected component");
|
||||
return; // to make some compilers happy
|
||||
}
|
||||
|
||||
// Set the cumulated value for the iteration
|
||||
cumulCS += it->second;
|
||||
|
||||
// Check if we have reach the material to be selected
|
||||
// The DBL_MAX is here to take into account a return DBL_MAX in CSPerVol for the elastic model
|
||||
// to force elastic sampleSecondaries where the particle can be killed.
|
||||
// Used when paticle energy is lower than limit.
|
||||
if(rand<cumulCS || cumulCS >= DBL_MAX)
|
||||
{
|
||||
// we have our selected material
|
||||
materialName = it->first;
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// make the iterator move forward
|
||||
++it;
|
||||
}
|
||||
|
||||
// Check that we get a result
|
||||
if(!result)
|
||||
{
|
||||
// it is possible to end up here if the return DBL_MAX of CSPerVol in the elastic model is not taken into account
|
||||
|
||||
G4Exception("G4DNAModelManager::SampleSecondaries","em0006",
|
||||
FatalException,
|
||||
"The random component selection has failed: while loop ended without a selected component.");
|
||||
return; // to make some compilers happy
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// **************************************
|
||||
// Call the SampleSecondaries method
|
||||
// **************************************
|
||||
|
||||
// Rename material if modified NIST material
|
||||
// This is needed when material is obtained from G4MaterialCutsCouple
|
||||
if(materialName.find("_MODIFIED")!=G4String::npos)
|
||||
{
|
||||
materialName = materialName.substr(0,materialName.size()-9);
|
||||
}
|
||||
|
||||
fSampledMat = materialName;
|
||||
|
||||
G4VDNAModel* model = GetDNAModel(materialName,
|
||||
aDynamicParticle->GetParticleDefinition()->GetParticleName(),
|
||||
aDynamicParticle->GetKineticEnergy() );
|
||||
//fMaterialParticleModelTable[materialName][aDynamicParticle->GetDefinition()->GetParticleName()][0];
|
||||
|
||||
model->SampleSecondaries(fVect, couple, materialName, aDynamicParticle, fpParticleChangeForGamma, tmin, tmax);
|
||||
}
|
||||
|
||||
void G4DNAModelInterface::RegisterModel(G4VDNAModel* model)
|
||||
{
|
||||
fRegisteredModels.push_back(model);
|
||||
}
|
||||
|
||||
void G4DNAModelInterface::RegisterModel(G4VEmModel* model, const G4ParticleDefinition* particle)
|
||||
{
|
||||
G4DNADummyModel* dummyWrapper = new G4DNADummyModel("G4_WATER", particle, model->GetName(), model);
|
||||
|
||||
RegisterModel(dummyWrapper);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAModelInterface::BuildMaterialParticleModelTable(const G4ParticleDefinition* p)
|
||||
{
|
||||
// Method to build a map: [material][particle] = Model*.
|
||||
// The map is used to retrieve the correct model for the current particle/material couple.
|
||||
|
||||
// Get the current particle name
|
||||
const G4String& pName = p->GetParticleName();
|
||||
|
||||
// Retrieve the iterator
|
||||
G4MaterialTable::iterator it;
|
||||
|
||||
// Loop on all materials registered in the simulation
|
||||
for(it = G4Material::GetMaterialTable()->begin(); it!=G4Material::GetMaterialTable()->end(); ++it)
|
||||
{
|
||||
// Get the material pointer
|
||||
G4Material* mat = *it;
|
||||
|
||||
// Get the map
|
||||
std::map<G4Material*, G4double> componentMap = mat->GetMatComponents();
|
||||
|
||||
// Get the number of component within the composite
|
||||
unsigned int compositeSize = componentMap.size();
|
||||
|
||||
// Check that the material is not a composite material
|
||||
if(componentMap.empty())
|
||||
{
|
||||
// Get the material name
|
||||
const G4String& matName = mat->GetName();
|
||||
|
||||
// Insert the model in the table.
|
||||
InsertModelInTable(matName, pName);
|
||||
}
|
||||
// if the material is a composite material then we need to loop on all its components to register them
|
||||
else
|
||||
{
|
||||
// Retrieve the component map begin iterator
|
||||
std::map<G4Material*, G4double>::const_iterator itComp = componentMap.begin();
|
||||
|
||||
// Loop on all the components of the material
|
||||
//for(itComp = mat->GetMatComponents().begin(); itComp != eitComp; ++itComp)
|
||||
for(unsigned int k=0; k<compositeSize; ++k)
|
||||
{
|
||||
G4Material* component = itComp->first;
|
||||
|
||||
// // Check that the component is not itself a composite
|
||||
// if(component->GetMatComponents().size()!=0)
|
||||
// {
|
||||
// std::ostringstream oss;
|
||||
// oss<<"Material "<<mat->GetName()<<" is a composite and its component ";
|
||||
// oss<<component->GetName()<<" is also a composite material. Building composite with other composites is not implemented yet";
|
||||
// oss<<G4endl;
|
||||
// G4Exception("G4DNAModelManager::BuildMaterialParticleModelTable","em0006",
|
||||
// FatalException, oss.str().c_str());
|
||||
// return; // to make some compilers happy
|
||||
// }
|
||||
|
||||
// Get the current component name
|
||||
const G4String compName = component->GetName();
|
||||
|
||||
// If there is a model then insert the model corresponding to the component in the table
|
||||
// contains a if statement to check we have not registered the material as a component or a normal material before.
|
||||
InsertModelInTable(compName, pName);
|
||||
|
||||
// move forward the iterator
|
||||
++itComp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAModelInterface::BuildMaterialMolPerVolTable()
|
||||
{
|
||||
// To be sure the G4DNAMolecularMaterial is initialized
|
||||
G4DNAMolecularMaterial::Instance()->Initialize();
|
||||
|
||||
G4MaterialTable* materialTable = G4Material::GetMaterialTable();
|
||||
|
||||
// Loop on all the materials inside the "materialTable"
|
||||
for(size_t i=0, ie=materialTable->size(); i<ie; i++)
|
||||
{
|
||||
// Current material
|
||||
G4Material* currentMaterial = materialTable->at(i);
|
||||
|
||||
// Current material name
|
||||
const G4String& currentMatName = currentMaterial->GetName();
|
||||
|
||||
// Will the material be used in this interface instance ?
|
||||
// Loop on all the materials that can be dealt with in this class
|
||||
MaterialParticleModelTable::iterator it = fMaterialParticleModelTable.begin();
|
||||
MaterialParticleModelTable::iterator ite = fMaterialParticleModelTable.end();
|
||||
for(; it != ite; it++)
|
||||
{
|
||||
const G4String& materialName = it->first;
|
||||
|
||||
if(materialName == currentMatName)
|
||||
{
|
||||
const std::vector<double>* numMolPerVolForMat = G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(currentMaterial);
|
||||
fMaterialMolPerVol[materialName] = numMolPerVolForMat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAModelInterface::InsertModelInTable(const G4String& matName, const G4String& pName)
|
||||
{
|
||||
// To insert the model(s) in the table Material Particule -> Model(s)
|
||||
|
||||
// First, we need to check if the current material has already been inserted in the table.
|
||||
// This is possible because of the composite material. We could add a component M1 and then try to add the independant M1 material.
|
||||
// This case must be avoided. Checking if M1 is already in the table is the way to avoid it.
|
||||
//
|
||||
// Chech if the current material and particle are already in the table.
|
||||
// If they are: do nothing.
|
||||
// If they are not: add the model(s)
|
||||
//
|
||||
// Check for the material
|
||||
if(fMaterialParticleModelTable.find(matName) == fMaterialParticleModelTable.end())
|
||||
{
|
||||
// Check for the particle
|
||||
if(fMaterialParticleModelTable[matName].find(pName) == fMaterialParticleModelTable[matName].end())
|
||||
{
|
||||
G4int modelNbForMaterial (0);
|
||||
|
||||
// Loop on all models registered in the simulation to check:
|
||||
// 1- if they can be applied to the current material
|
||||
// 2- if they can be applied to the current particle
|
||||
for(unsigned int i=0, ie=fRegisteredModels.size(); i<ie; ++i)
|
||||
{
|
||||
// check if the model is correct for material and particle (previous 1 and 2)
|
||||
if(fRegisteredModels[i]->IsParticleExistingInModelForMaterial(pName, matName))
|
||||
{
|
||||
// if yes then add the model in the map
|
||||
fMaterialParticleModelTable[matName][pName].push_back(fRegisteredModels[i]);
|
||||
|
||||
// and add one to the "there is a model" material flag
|
||||
++modelNbForMaterial;
|
||||
}
|
||||
}
|
||||
|
||||
// The model(s) applicable to the currently selected material should be in the map.
|
||||
// We check if there are several models for the material.
|
||||
if(modelNbForMaterial>1)
|
||||
{
|
||||
// If there are several models for a given material and particle couple it could be
|
||||
// because of the energy ranges. We will check if the energy ranges are coherent.
|
||||
|
||||
// Get the models (vector)
|
||||
std::vector<G4VDNAModel*>& models = fMaterialParticleModelTable[matName][pName];
|
||||
|
||||
// Declare a map to sort the limits (G4double) and a model "id" (G4int).
|
||||
// The model id is created on the fly here.
|
||||
// The idea is to fill a map with [limit] = counter. This map will be auto-sorted
|
||||
// and we will check by iterating on it that the counter order is maintained.
|
||||
|
||||
// Delcare the map
|
||||
std::map<G4double, G4int, std::less<G4double> > sortMap;
|
||||
|
||||
G4double smallDiff = 0.01 *eV;
|
||||
|
||||
// Loop on all the model for the current couple
|
||||
// and fill a map with [lim] = modelNumber
|
||||
for(unsigned int ii=0, em=models.size(); ii<em; ++ii)
|
||||
{
|
||||
G4double lowLim = models[ii]->GetLowELimit(matName, pName);
|
||||
G4double highLim = models[ii]->GetHighELimit(matName, pName);
|
||||
|
||||
if(sortMap.find(lowLim) != sortMap.end() )
|
||||
{
|
||||
lowLim += smallDiff;
|
||||
}
|
||||
|
||||
sortMap[lowLim] = ii;
|
||||
|
||||
if(sortMap.find(highLim) != sortMap.end() )
|
||||
{
|
||||
highLim -= smallDiff;
|
||||
}
|
||||
|
||||
sortMap[highLim] = ii;
|
||||
}
|
||||
|
||||
// The map has been created and ordered at this point.
|
||||
// We will check the map order.
|
||||
|
||||
// Loop on the sortMap with iterator and check the order is correct.
|
||||
std::map<G4double, G4int>::iterator it = sortMap.begin();
|
||||
|
||||
// First energy limit value
|
||||
G4double dummyLim = it->first - smallDiff;
|
||||
|
||||
// Loop on all the models again.
|
||||
// The goal is to check if for each limit pairs we have the same model number
|
||||
// and that the upper and lower limit are consistent.
|
||||
for(unsigned int ii=0, eii=models.size(); ii<eii; ++ii)
|
||||
{
|
||||
G4double lim1 = it->first - smallDiff;
|
||||
G4int count1 = it->second;
|
||||
|
||||
// Iterate
|
||||
++it;
|
||||
|
||||
G4double lim2 = it->first + smallDiff;
|
||||
G4int count2 = it->second;
|
||||
|
||||
// Iterate
|
||||
++it;
|
||||
|
||||
// Check model number and energy limit consistency
|
||||
// std::abs(dummyLim - lim1) > 1.*eV because we cannot do (dummyLim != lim1)
|
||||
// without experimenting precision loss. Therefore, the std::abs(...) > tolerance is the usual way of avoiding
|
||||
// the issue.
|
||||
if( (count1 != count2) || ( std::abs(dummyLim - lim1) > 1.*eV ) )
|
||||
{
|
||||
// Error
|
||||
|
||||
std::ostringstream oss;
|
||||
oss<<"The material "<<matName<<" and the particle "<<pName;
|
||||
oss<<" have several models registered for the "<<fName<<" interaction and their energy ranges ";
|
||||
oss<<"do not match. \nEnergy ranges: \n";
|
||||
|
||||
for(int iii=0, eiii=models.size(); iii<eiii; ++iii)
|
||||
{
|
||||
oss<<models[iii]->GetName()<<"\n";
|
||||
oss<<"low: "<<models[iii]->GetLowELimit(matName, pName)/eV<<" eV \n";
|
||||
oss<<"high: "<<models[iii]->GetHighELimit(matName, pName)/eV<<" eV \n";
|
||||
}
|
||||
|
||||
G4Exception("G4DNAModelManager::InsertModelInTable","em0006",
|
||||
FatalException, oss.str().c_str());
|
||||
return; // to make some compilers happy
|
||||
}
|
||||
|
||||
dummyLim = lim2;
|
||||
}
|
||||
|
||||
// If we are here then everything was ok.
|
||||
}
|
||||
// no model for the material case
|
||||
else if(modelNbForMaterial==0)
|
||||
{
|
||||
// std::ostringstream oss;
|
||||
// oss<<"The material "<<matName<<" and the particle "<<pName;
|
||||
// oss<<" does not have any model registered for the "<<fName<<" interaction. ";
|
||||
|
||||
// G4Exception("G4DNAModelManager::InsertModelInTable","em0006",
|
||||
// FatalException, oss.str().c_str());
|
||||
// return; // to make some compilers happy
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
G4VDNAModel *G4DNAModelInterface::GetDNAModel(const G4String &material, const G4String &particle, G4double ekin)
|
||||
{
|
||||
// Output pointer
|
||||
G4VDNAModel* model = 0;
|
||||
|
||||
// Get a reference to all the models for the couple (material and particle)
|
||||
std::vector<G4VDNAModel*>& models = fMaterialParticleModelTable[material][particle];
|
||||
|
||||
// We must choose one of the model(s) accordingly to the particle energy and the model energy range(s)
|
||||
|
||||
//G4bool isOneModelSelected = false;
|
||||
|
||||
// Loop on all the models within the models vector and check if ekin is within the energy range.
|
||||
for(int i=0, ie=models.size(); i<ie; ++i)
|
||||
{
|
||||
// ekin is in the energy range: we select the model and stop the loop.
|
||||
if( ekin >= models[i]->GetLowELimit(material, particle)
|
||||
&& ekin < models[i]->GetHighELimit(material, particle) )
|
||||
{
|
||||
// Select the model
|
||||
model = models[i];
|
||||
|
||||
// Boolean flag
|
||||
//isOneModelSelected = true;
|
||||
|
||||
// Quit the for loop
|
||||
break;
|
||||
}
|
||||
|
||||
// ekin is not in the energy range: we continue the loop.
|
||||
}
|
||||
|
||||
// // If no model was selected then fatal error
|
||||
// if(!isOneModelSelected)
|
||||
// {
|
||||
// G4String msg = "No model has ";
|
||||
// msg += ekin/eV;
|
||||
// msg += " eV in its energy range. Therefore nothing was selected.";
|
||||
|
||||
// G4Exception("G4DNAModelManager::GetDNAModel","em0006",
|
||||
// FatalException,
|
||||
// msg);
|
||||
// }
|
||||
|
||||
// Return a pointer to the selected model
|
||||
return model;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAModelInterface::GetNumMoleculePerVolumeUnitForMaterial(const G4Material* mat)
|
||||
{
|
||||
return fMaterialMolPerVol[mat->GetName()]->at(mat->GetIndex() );
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAModelInterface::GetNumMolPerVolUnitForComponentInComposite(const G4Material* component, const G4Material* composite)
|
||||
{
|
||||
return fMaterialMolPerVol[component->GetName() ]->at(composite->GetIndex() );
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4DNAOneStepThermalizationModel.cc 102637 2017-02-10 11:08:17Z gcosmo $
|
||||
// $Id: G4DNAOneStepThermalizationModel.cc 101807 2016-11-30 13:42:28Z gunter $
|
||||
//
|
||||
// Author: Mathieu Karamitros
|
||||
//
|
||||
@@ -141,7 +141,7 @@ namespace DNA{ namespace Penetration{
|
||||
size_t lowBin, upBin;
|
||||
|
||||
if(k_eV >= 1.){
|
||||
lowBin=floor(k_eV)+1;
|
||||
lowBin=std::floor(k_eV)+1;
|
||||
upBin=std::min(lowBin+1, size_t(10));
|
||||
}
|
||||
else{
|
||||
@@ -183,7 +183,7 @@ namespace DNA{ namespace Penetration{
|
||||
static constexpr double factor = 2.20496999539;
|
||||
// 1./(3. - 8./CLHEP::pi);
|
||||
|
||||
double sigma1D = sqrt(pow(sigma3D, 2.)*factor);
|
||||
double sigma1D = std::sqrt(std::pow(sigma3D, 2.)*factor);
|
||||
|
||||
// G4cout << "sigma1D = " << sigma1D/CLHEP::nanometer << G4endl;
|
||||
|
||||
|
||||
@@ -0,0 +1,204 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Authors: S. Meylan and C. Villagrasa (IRSN, France)
|
||||
// Models come from
|
||||
// M. Bug et al, Rad. Phys and Chem. 130, 459-479 (2017)
|
||||
//
|
||||
|
||||
#include "G4DNAPTBAugerModel.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "Randomize.hh"
|
||||
#include "G4Electron.hh"
|
||||
|
||||
#include "G4Material.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
G4DNAPTBAugerModel::G4DNAPTBAugerModel(const G4String& modelAugerName): modelName(modelAugerName)
|
||||
{
|
||||
// To inform the user that the Auger model is enabled
|
||||
G4cout << modelName <<" is constructed" << G4endl;
|
||||
}
|
||||
|
||||
G4DNAPTBAugerModel::~G4DNAPTBAugerModel()
|
||||
{
|
||||
if( verboseLevel>0 ) G4cout << modelName <<" is deleted" << G4endl;
|
||||
}
|
||||
|
||||
void G4DNAPTBAugerModel::Initialise()
|
||||
{
|
||||
verboseLevel = 0;
|
||||
|
||||
if( verboseLevel>0 )
|
||||
{
|
||||
G4cout << "PTB Auger model is initialised " << G4endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAPTBAugerModel::ComputeAugerEffect(std::vector<G4DynamicParticle*>* fvect, const G4String& materialNameIni, G4double bindingEnergy)
|
||||
{
|
||||
// Rename material if modified NIST material
|
||||
// This is needed when material is obtained from G4MaterialCutsCouple
|
||||
G4String materialName = materialNameIni;
|
||||
if(materialName.find("_MODIFIED")){
|
||||
materialName = materialName.substr(0,materialName.size()-9);
|
||||
}
|
||||
|
||||
// check if there is a k-shell ionisation and find the ionised atom
|
||||
G4int atomId(0);
|
||||
|
||||
atomId = DetermineIonisedAtom(atomId, materialName, bindingEnergy);
|
||||
|
||||
if(atomId!=0)
|
||||
{
|
||||
G4double kineticEnergy = CalculAugerEnergyFor(atomId);
|
||||
|
||||
if(kineticEnergy<0)
|
||||
{
|
||||
G4cerr<<"**************************"<<G4endl;
|
||||
G4cerr<<"FatalError. Auger kineticEnergy: "<<kineticEnergy<<G4endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(atomId==1 || atomId==2 || atomId==3)
|
||||
{
|
||||
GenerateAugerWithRandomDirection(fvect, kineticEnergy);
|
||||
}
|
||||
else if(atomId==4)
|
||||
{
|
||||
GenerateAugerWithRandomDirection(fvect, kineticEnergy);
|
||||
GenerateAugerWithRandomDirection(fvect, kineticEnergy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4int G4DNAPTBAugerModel::DetermineIonisedAtom(G4int atomId, const G4String& materialName, G4double bindingEnergy)
|
||||
{
|
||||
if(materialName=="THF" || materialName=="backbone_THF"){
|
||||
if(bindingEnergy==305.07){
|
||||
atomId=1; //"carbon";
|
||||
}
|
||||
else if(bindingEnergy==557.94){
|
||||
atomId=2; //"oxygen";
|
||||
}
|
||||
}
|
||||
else if(materialName=="PY" || materialName=="PU"
|
||||
|| materialName=="cytosine_PY" || materialName=="thymine_PY"
|
||||
|| materialName=="adenine_PU" || materialName=="guanine_PU"
|
||||
)
|
||||
{
|
||||
if(bindingEnergy==307.52){
|
||||
atomId=1; //"carbon";
|
||||
}
|
||||
else if(bindingEnergy==423.44){
|
||||
atomId=4; //"nitrogen";
|
||||
}
|
||||
}
|
||||
else if(materialName=="TMP"|| materialName=="backbone_TMP"){
|
||||
if(bindingEnergy==209.59 || bindingEnergy==152.4)
|
||||
atomId=3; //"carbonTMP";
|
||||
}
|
||||
|
||||
return atomId;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAPTBAugerModel::CalculAugerEnergyFor(G4int atomId)
|
||||
{
|
||||
G4double kineticEnergy;
|
||||
|
||||
if(atomId==2) // oxygen
|
||||
{
|
||||
kineticEnergy = 495*eV;
|
||||
}
|
||||
else
|
||||
{
|
||||
G4double f1, f2, f3, g1, g2, Y;
|
||||
|
||||
Y = G4UniformRand();
|
||||
|
||||
if(atomId == 1){ // carbon
|
||||
f1 = -7.331e-2;
|
||||
f2 = -3.306e-5;
|
||||
f3 = 2.433e0;
|
||||
g1 = 4.838e-1;
|
||||
g2 = 3.886e0;
|
||||
}
|
||||
else if(atomId == 4){ // nitrogen
|
||||
f1 = -7.518e-2;
|
||||
f2 = 1.178e-4;
|
||||
f3 = 2.600e0;
|
||||
g1 = 4.639e-1;
|
||||
g2 = 3.770e0;
|
||||
}
|
||||
else// if(atomId == 3) // carbon_TMP
|
||||
{
|
||||
f1 = -5.700e-2;
|
||||
f2 = 1.200e-4;
|
||||
f3 = 2.425e0;
|
||||
g1 = 5.200e-1;
|
||||
g2 = 2.560e0;
|
||||
}
|
||||
|
||||
kineticEnergy = pow(10, f1*pow( abs( log10(Y) ) , g1) + f2*pow( abs( log10(Y) ) , g2) + f3 )*eV;
|
||||
}
|
||||
|
||||
return kineticEnergy;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAPTBAugerModel::SetCutForAugerElectrons(G4double cut)
|
||||
{
|
||||
minElectronEnergy = cut;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAPTBAugerModel::GenerateAugerWithRandomDirection(std::vector<G4DynamicParticle*>* fvect, G4double kineticEnergy)
|
||||
{
|
||||
// Isotropic angular distribution for the outcoming e-
|
||||
G4double newcosTh = 1.-2.*G4UniformRand();
|
||||
G4double newsinTh = std::sqrt(1.-newcosTh*newcosTh);
|
||||
G4double newPhi = twopi*G4UniformRand();
|
||||
|
||||
G4double xDir = newsinTh*std::sin(newPhi);
|
||||
G4double yDir = newsinTh*std::cos(newPhi);
|
||||
G4double zDir = newcosTh;
|
||||
|
||||
G4ThreeVector ElectronDirection(xDir,yDir,zDir);
|
||||
|
||||
// generation of new particle
|
||||
G4DynamicParticle* dp = new G4DynamicParticle (G4Electron::Electron(), ElectronDirection, kineticEnergy) ;
|
||||
fvect->push_back(dp);
|
||||
}
|
||||
@@ -0,0 +1,546 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Authors: S. Meylan and C. Villagrasa (IRSN, France)
|
||||
// Models come from
|
||||
// M. Bug et al, Rad. Phys and Chem. 130, 459-479 (2017)
|
||||
//
|
||||
|
||||
#include "G4DNAPTBElasticModel.hh"
|
||||
#include "G4DNAChampionElasticModel.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
#include "G4Proton.hh"
|
||||
|
||||
G4DNAPTBElasticModel::G4DNAPTBElasticModel(const G4String& applyToMaterial, const G4ParticleDefinition*,
|
||||
const G4String& nam)
|
||||
: G4VDNAModel(nam, applyToMaterial)
|
||||
{
|
||||
fKillBelowEnergy = 10*eV; // will be override by the limits defined for each material
|
||||
|
||||
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 << "PTB Elastic model is constructed " << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNAPTBElasticModel::~G4DNAPTBElasticModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAPTBElasticModel::Initialise(const G4ParticleDefinition* particle,
|
||||
const G4DataVector& /*cuts*/, G4ParticleChangeForGamma*)
|
||||
{
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling G4DNAPTBElasticModel::Initialise()" << G4endl;
|
||||
|
||||
G4double scaleFactor = 1e-16*cm*cm;
|
||||
|
||||
G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
|
||||
|
||||
//*******************************************************
|
||||
// Cross section data
|
||||
//*******************************************************
|
||||
|
||||
if(particle == electronDef)
|
||||
{
|
||||
G4String particleName = particle->GetParticleName();
|
||||
|
||||
AddCrossSectionData("THF",
|
||||
particleName,
|
||||
"dna/sigma_elastic_e-_PTB_THF",
|
||||
"dna/sigmadiff_cumulated_elastic_e-_PTB_THF",
|
||||
scaleFactor);
|
||||
SetLowELimit("THF", particleName, 10*eV);
|
||||
SetHighELimit("THF", particleName, 1*keV);
|
||||
|
||||
AddCrossSectionData("PY",
|
||||
particleName,
|
||||
"dna/sigma_elastic_e-_PTB_PY",
|
||||
"dna/sigmadiff_cumulated_elastic_e-_PTB_PY",
|
||||
scaleFactor);
|
||||
SetLowELimit("PY", particleName, 10*eV);
|
||||
SetHighELimit("PY", particleName, 1*keV);
|
||||
|
||||
AddCrossSectionData("PU",
|
||||
particleName,
|
||||
"dna/sigma_elastic_e-_PTB_PU",
|
||||
"dna/sigmadiff_cumulated_elastic_e-_PTB_PU",
|
||||
scaleFactor);
|
||||
SetLowELimit("PU", particleName, 10*eV);
|
||||
SetHighELimit("PU", particleName, 1*keV);
|
||||
|
||||
AddCrossSectionData("TMP",
|
||||
particleName,
|
||||
"dna/sigma_elastic_e-_PTB_TMP",
|
||||
"dna/sigmadiff_cumulated_elastic_e-_PTB_TMP",
|
||||
scaleFactor);
|
||||
SetLowELimit("TMP", particleName, 10*eV);
|
||||
SetHighELimit("TMP", particleName, 1*keV);
|
||||
|
||||
AddCrossSectionData("G4_WATER",
|
||||
particleName,
|
||||
"dna/sigma_elastic_e_champion",
|
||||
"dna/sigmadiff_cumulated_elastic_e_champion",
|
||||
scaleFactor);
|
||||
SetLowELimit("G4_WATER", particleName, 10*eV);
|
||||
SetHighELimit("G4_WATER", particleName, 1*keV);
|
||||
|
||||
// DNA materials
|
||||
//
|
||||
AddCrossSectionData("backbone_THF",
|
||||
particleName,
|
||||
"dna/sigma_elastic_e-_PTB_THF",
|
||||
"dna/sigmadiff_cumulated_elastic_e-_PTB_THF",
|
||||
scaleFactor*33./30);
|
||||
SetLowELimit("backbone_THF", particleName, 10*eV);
|
||||
SetHighELimit("backbone_THF", particleName, 1*keV);
|
||||
|
||||
AddCrossSectionData("cytosine_PY",
|
||||
particleName,
|
||||
"dna/sigma_elastic_e-_PTB_PY",
|
||||
"dna/sigmadiff_cumulated_elastic_e-_PTB_PY",
|
||||
scaleFactor*42./30);
|
||||
SetLowELimit("cytosine_PY", particleName, 10*eV);
|
||||
SetHighELimit("cytosine_PY", particleName, 1*keV);
|
||||
|
||||
AddCrossSectionData("thymine_PY",
|
||||
particleName,
|
||||
"dna/sigma_elastic_e-_PTB_PY",
|
||||
"dna/sigmadiff_cumulated_elastic_e-_PTB_PY",
|
||||
scaleFactor*48./30);
|
||||
SetLowELimit("thymine_PY", particleName, 10*eV);
|
||||
SetHighELimit("thymine_PY", particleName, 1*keV);
|
||||
|
||||
AddCrossSectionData("adenine_PU",
|
||||
particleName,
|
||||
"dna/sigma_elastic_e-_PTB_PU",
|
||||
"dna/sigmadiff_cumulated_elastic_e-_PTB_PU",
|
||||
scaleFactor*50./44);
|
||||
SetLowELimit("adenine_PU", particleName, 10*eV);
|
||||
SetHighELimit("adenine_PU", particleName, 1*keV);
|
||||
|
||||
AddCrossSectionData("guanine_PU",
|
||||
particleName,
|
||||
"dna/sigma_elastic_e-_PTB_PU",
|
||||
"dna/sigmadiff_cumulated_elastic_e-_PTB_PU",
|
||||
scaleFactor*56./44);
|
||||
SetLowELimit("guanine_PU", particleName, 10*eV);
|
||||
SetHighELimit("guanine_PU", particleName, 1*keV);
|
||||
|
||||
AddCrossSectionData("backbone_TMP",
|
||||
particleName,
|
||||
"dna/sigma_elastic_e-_PTB_TMP",
|
||||
"dna/sigmadiff_cumulated_elastic_e-_PTB_TMP",
|
||||
scaleFactor*33./50);
|
||||
SetLowELimit("backbone_TMP", particleName, 10*eV);
|
||||
SetHighELimit("backbone_TMP", particleName, 1*keV);
|
||||
}
|
||||
|
||||
//*******************************************************
|
||||
// Load the data
|
||||
//*******************************************************
|
||||
|
||||
LoadCrossSectionData(particle->GetParticleName() );
|
||||
|
||||
//*******************************************************
|
||||
// Verbose output
|
||||
//*******************************************************
|
||||
|
||||
if (verboseLevel > 2)
|
||||
G4cout << "Loaded cross section files for PTB Elastic model" << G4endl;
|
||||
|
||||
if( verboseLevel>0 )
|
||||
{
|
||||
G4cout << "PTB Elastic model is initialized " << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAPTBElasticModel::ReadDiffCSFile(const G4String& materialName,
|
||||
const G4String& particleName,
|
||||
const G4String& file,
|
||||
const G4double)
|
||||
{
|
||||
// Method to read and save the information contained within the differential cross section files.
|
||||
// This method is not yet standard.
|
||||
|
||||
// get the path of the G4LEDATA data folder
|
||||
char *path = getenv("G4LEDATA");
|
||||
// if it is not found then quit and print error message
|
||||
if(!path)
|
||||
{
|
||||
G4Exception("G4DNAPTBElasticModel::ReadAllDiffCSFiles","em0006",
|
||||
FatalException,"G4LEDATA environment variable not set.");
|
||||
return;
|
||||
}
|
||||
|
||||
// build the fullFileName path of the data file
|
||||
std::ostringstream fullFileName;
|
||||
fullFileName << path <<"/"<< file<<".dat";
|
||||
|
||||
// open the data file
|
||||
std::ifstream diffCrossSection (fullFileName.str().c_str());
|
||||
// error if file is not there
|
||||
std::stringstream endPath;
|
||||
if (!diffCrossSection)
|
||||
{
|
||||
endPath << "Missing data file: "<<file;
|
||||
G4Exception("G4DNAPTBElasticModel::Initialise","em0003",
|
||||
FatalException, endPath.str().c_str());
|
||||
}
|
||||
|
||||
tValuesVec[materialName][particleName].push_back(0.);
|
||||
|
||||
G4String line;
|
||||
|
||||
// read the file line by line until we reach the end of file point
|
||||
while(std::getline(diffCrossSection, line))
|
||||
{
|
||||
// check if the line is comment or empty
|
||||
//
|
||||
std::istringstream testIss(line);
|
||||
G4String test;
|
||||
testIss >> test;
|
||||
// check first caracter to determine if following information is data or comments
|
||||
if(test=="#")
|
||||
{
|
||||
// skip the line by beginning a new while loop.
|
||||
continue;
|
||||
}
|
||||
// check if line is empty
|
||||
else if(line.empty())
|
||||
{
|
||||
// skip the line by beginning a new while loop.
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// end of the check
|
||||
|
||||
// transform the line into a iss
|
||||
std::istringstream iss(line);
|
||||
|
||||
// Variables to be filled by the input file
|
||||
double tDummy;
|
||||
double eDummy;
|
||||
|
||||
// fill the variables with the content of the line
|
||||
iss>>tDummy>>eDummy;
|
||||
|
||||
// SI : mandatory Vecm initialization
|
||||
|
||||
// Fill two vectors contained in maps of types:
|
||||
// [materialName][particleName]=vector
|
||||
// [materialName][particleName][T]=vector
|
||||
// to list all the incident energies (tValues) and all the output energies (eValues) within the file
|
||||
//
|
||||
// Check if we already have the current T value in the vector.
|
||||
// If not then add it
|
||||
if (tDummy != tValuesVec[materialName][particleName].back())
|
||||
{
|
||||
// Add the current T value
|
||||
tValuesVec[materialName][particleName].push_back(tDummy);
|
||||
|
||||
// Make it correspond to a default zero E value
|
||||
eValuesVect[materialName][particleName][tDummy].push_back(0.);
|
||||
}
|
||||
|
||||
// Put the differential cross section value of the input file within the diffCrossSectionData map
|
||||
iss>>diffCrossSectionData[materialName][particleName][tDummy][eDummy];
|
||||
|
||||
// If the current E value (eDummy) is different from the one already registered in the eVector then add it to the vector
|
||||
if (eDummy != eValuesVect[materialName][particleName][tDummy].back()) eValuesVect[materialName][particleName][tDummy].push_back(eDummy);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAPTBElasticModel::CrossSectionPerVolume(const G4Material* /*material*/,
|
||||
const G4String& materialName,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double ekin,
|
||||
G4double /*emin*/,
|
||||
G4double /*emax*/)
|
||||
{
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling CrossSectionPerVolume() of G4DNAPTBElasticModel" << G4endl;
|
||||
|
||||
// Get the name of the current particle
|
||||
const G4String& particleName = p->GetParticleName();
|
||||
|
||||
// set killBelowEnergy value for current material
|
||||
fKillBelowEnergy = GetLowELimit(materialName, particleName);
|
||||
|
||||
// initialise the return value (cross section) to zero
|
||||
G4double sigma(0);
|
||||
|
||||
// check if we are below the high energy limit
|
||||
if (ekin < GetHighELimit(materialName, particleName) )
|
||||
{
|
||||
// This is used to kill the particle if its kinetic energy is below fKillBelowEnergy.
|
||||
// If the energy is lower then we return a maximum cross section and thus the SampleSecondaries method will be called for sure.
|
||||
// SampleSecondaries will remove the particle from the simulation.
|
||||
//
|
||||
//SI : XS must not be zero otherwise sampling of secondaries method ignored
|
||||
if (ekin < fKillBelowEnergy) return DBL_MAX;
|
||||
|
||||
// Get the tables with the cross section data
|
||||
TableMapData* tableData = GetTableData();
|
||||
|
||||
// Retrieve the cross section value
|
||||
sigma = (*tableData)[materialName][particleName]->FindValue(ekin);
|
||||
}
|
||||
|
||||
if (verboseLevel > 2)
|
||||
{
|
||||
G4cout << "__________________________________" << G4endl;
|
||||
G4cout << "°°° G4DNAPTBElasticModel - XS INFO START" << G4endl;
|
||||
G4cout << "°°° Kinetic energy(eV)=" << ekin/eV << " particle : " << particleName << G4endl;
|
||||
G4cout << "°°° Cross section per molecule (cm^2)=" << sigma/cm/cm << G4endl;
|
||||
G4cout << "°°° G4DNAPTBElasticModel - XS INFO END" << G4endl;
|
||||
}
|
||||
|
||||
// Return the cross section
|
||||
return sigma;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAPTBElasticModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
|
||||
const G4MaterialCutsCouple* /*couple*/,
|
||||
const G4String& materialName,
|
||||
const G4DynamicParticle* aDynamicElectron,
|
||||
G4ParticleChangeForGamma* particleChangeForGamma,
|
||||
G4double /*tmin*/,
|
||||
G4double /*tmax*/)
|
||||
{
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling SampleSecondaries() of G4DNAPTBElasticModel" << G4endl;
|
||||
|
||||
G4double electronEnergy0 = aDynamicElectron->GetKineticEnergy();
|
||||
|
||||
const G4String& particleName = aDynamicElectron->GetParticleDefinition()->GetParticleName();
|
||||
|
||||
// set killBelowEnergy value for material
|
||||
fKillBelowEnergy = GetLowELimit(materialName, particleName);
|
||||
|
||||
// If the particle (electron here) energy is below the kill limit then we remove it from the simulation
|
||||
if (electronEnergy0 < fKillBelowEnergy)
|
||||
{
|
||||
particleChangeForGamma->SetProposedKineticEnergy(0.);
|
||||
particleChangeForGamma->ProposeTrackStatus(fStopAndKill);
|
||||
particleChangeForGamma->ProposeLocalEnergyDeposit(electronEnergy0);
|
||||
}
|
||||
// If we are above the kill limite and below the high limit then we proceed
|
||||
else if (electronEnergy0>= fKillBelowEnergy && electronEnergy0 < GetHighELimit(materialName, particleName) )
|
||||
{
|
||||
// Random sampling of the cosTheta
|
||||
G4double cosTheta = RandomizeCosTheta(electronEnergy0, materialName);
|
||||
|
||||
// Random sampling of phi
|
||||
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);
|
||||
|
||||
// Particle direction after ModelInterface
|
||||
G4ThreeVector zPrikeVers((xDir*xVers + yDir*yVers + cosTheta*zVers));
|
||||
|
||||
// Give the new direction
|
||||
particleChangeForGamma->ProposeMomentumDirection(zPrikeVers.unit()) ;
|
||||
|
||||
// Update the energy which does not change here
|
||||
particleChangeForGamma->SetProposedKineticEnergy(electronEnergy0);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAPTBElasticModel::Theta
|
||||
(G4ParticleDefinition * particleDefinition, G4double k, G4double integrDiff, const G4String& materialName)
|
||||
{
|
||||
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;
|
||||
G4String particleName = particleDefinition->GetParticleName();
|
||||
|
||||
if (particleDefinition == G4Electron::ElectronDefinition())
|
||||
{
|
||||
std::vector<double>::iterator t2 = std::upper_bound(tValuesVec[materialName][particleName].begin(),tValuesVec[materialName][particleName].end(), k);
|
||||
std::vector<double>::iterator t1 = t2-1;
|
||||
|
||||
std::vector<double>::iterator e12 = std::upper_bound(eValuesVect[materialName][particleName][(*t1)].begin(),eValuesVect[materialName][particleName][(*t1)].end(), integrDiff);
|
||||
std::vector<double>::iterator e11 = e12-1;
|
||||
|
||||
std::vector<double>::iterator e22 = std::upper_bound(eValuesVect[materialName][particleName][(*t2)].begin(),eValuesVect[materialName][particleName][(*t2)].end(), integrDiff);
|
||||
std::vector<double>::iterator e21 = e22-1;
|
||||
|
||||
valueT1 =*t1;
|
||||
valueT2 =*t2;
|
||||
valueE21 =*e21;
|
||||
valueE22 =*e22;
|
||||
valueE12 =*e12;
|
||||
valueE11 =*e11;
|
||||
|
||||
xs11 = diffCrossSectionData[materialName][particleName][valueT1][valueE11];
|
||||
xs12 = diffCrossSectionData[materialName][particleName][valueT1][valueE12];
|
||||
xs21 = diffCrossSectionData[materialName][particleName][valueT2][valueE21];
|
||||
xs22 = diffCrossSectionData[materialName][particleName][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 G4DNAPTBElasticModel::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 G4DNAPTBElasticModel::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 G4DNAPTBElasticModel::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 G4DNAPTBElasticModel::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 G4DNAPTBElasticModel::RandomizeCosTheta(G4double k, const G4String& materialName)
|
||||
{
|
||||
G4double integrdiff=0;
|
||||
G4double uniformRand=G4UniformRand();
|
||||
integrdiff = uniformRand;
|
||||
|
||||
G4double theta=0.;
|
||||
G4double cosTheta=0.;
|
||||
theta = Theta(G4Electron::ElectronDefinition(),k/eV,integrdiff, materialName);
|
||||
|
||||
cosTheta= std::cos(theta*pi/180);
|
||||
|
||||
return cosTheta;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
+287
@@ -0,0 +1,287 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Authors: S. Meylan and C. Villagrasa (IRSN, France)
|
||||
// Models come from
|
||||
// M. Bug et al, Rad. Phys and Chem. 130, 459-479 (2017)
|
||||
//
|
||||
|
||||
#include "G4DNAPTBExcitationModel.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
|
||||
G4DNAPTBExcitationModel::G4DNAPTBExcitationModel(const G4String& applyToMaterial, const G4ParticleDefinition*,
|
||||
const G4String& nam)
|
||||
: G4VDNAModel(nam, applyToMaterial)
|
||||
{
|
||||
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
|
||||
|
||||
// initialisation of mean energy loss for each material
|
||||
tableMeanEnergyPTB["THF"] = 8.01*eV;
|
||||
tableMeanEnergyPTB["PY"] = 7.61*eV;
|
||||
tableMeanEnergyPTB["PU"] = 7.61*eV;
|
||||
tableMeanEnergyPTB["TMP"] = 8.01*eV;
|
||||
|
||||
if( verboseLevel>0 )
|
||||
{
|
||||
G4cout << "PTB excitation model is constructed " << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNAPTBExcitationModel::~G4DNAPTBExcitationModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAPTBExcitationModel::Initialise(const G4ParticleDefinition* particle,
|
||||
const G4DataVector& /*cuts*/, G4ParticleChangeForGamma*)
|
||||
{
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling G4DNAPTBExcitationModel::Initialise()" << G4endl;
|
||||
|
||||
G4double scaleFactor = 1e-16*cm*cm;
|
||||
G4double scaleFactorBorn = (1.e-22 / 3.343) * m*m;
|
||||
|
||||
G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
|
||||
|
||||
//*******************************************************
|
||||
// Cross section data
|
||||
//*******************************************************
|
||||
|
||||
if(particle == electronDef)
|
||||
{
|
||||
G4String particleName = particle->GetParticleName();
|
||||
|
||||
AddCrossSectionData("THF",
|
||||
particleName,
|
||||
"dna/sigma_excitation_e-_PTB_THF",
|
||||
scaleFactor);
|
||||
SetLowELimit("THF", particleName, 9.*eV);
|
||||
SetHighELimit("THF", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("PY",
|
||||
particleName,
|
||||
"dna/sigma_excitation_e-_PTB_PY",
|
||||
scaleFactor);
|
||||
SetLowELimit("PY", particleName, 9.*eV);
|
||||
SetHighELimit("PY", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("PU",
|
||||
particleName,
|
||||
"dna/sigma_excitation_e-_PTB_PU",
|
||||
scaleFactor);
|
||||
SetLowELimit("PU", particleName, 9.*eV);
|
||||
SetHighELimit("PU", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("TMP",
|
||||
particleName,
|
||||
"dna/sigma_excitation_e-_PTB_TMP",
|
||||
scaleFactor);
|
||||
SetLowELimit("TMP", particleName, 9.*eV);
|
||||
SetHighELimit("TMP", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("G4_WATER",
|
||||
particleName,
|
||||
"dna/sigma_excitation_e_born",
|
||||
scaleFactorBorn);
|
||||
SetLowELimit("G4_WATER", particleName, 9.*eV);
|
||||
SetHighELimit("G4_WATER", particleName, 1.*keV);
|
||||
|
||||
// DNA materials
|
||||
//
|
||||
AddCrossSectionData("backbone_THF",
|
||||
particleName,
|
||||
"dna/sigma_excitation_e-_PTB_THF",
|
||||
scaleFactor*33./30);
|
||||
SetLowELimit("backbone_THF", particleName, 9.*eV);
|
||||
SetHighELimit("backbone_THF", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("cytosine_PY",
|
||||
particleName,
|
||||
"dna/sigma_excitation_e-_PTB_PY",
|
||||
scaleFactor*42./30);
|
||||
SetLowELimit("cytosine_PY", particleName, 9.*eV);
|
||||
SetHighELimit("cytosine_PY", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("thymine_PY",
|
||||
particleName,
|
||||
"dna/sigma_excitation_e-_PTB_PY",
|
||||
scaleFactor*48./30);
|
||||
SetLowELimit("thymine_PY", particleName, 9.*eV);
|
||||
SetHighELimit("thymine_PY", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("adenine_PU",
|
||||
particleName,
|
||||
"dna/sigma_excitation_e-_PTB_PU",
|
||||
scaleFactor*50./44);
|
||||
SetLowELimit("adenine_PU", particleName, 9.*eV);
|
||||
SetHighELimit("adenine_PU", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("guanine_PU",
|
||||
particleName,
|
||||
"dna/sigma_excitation_e-_PTB_PU",
|
||||
scaleFactor*56./44);
|
||||
SetLowELimit("guanine_PU", particleName, 9.*eV);
|
||||
SetHighELimit("guanine_PU", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("backbone_TMP",
|
||||
particleName,
|
||||
"dna/sigma_excitation_e-_PTB_TMP",
|
||||
scaleFactor*33./50);
|
||||
SetLowELimit("backbone_TMP", particleName, 9.*eV);
|
||||
SetHighELimit("backbone_TMP", particleName, 1.*keV);
|
||||
}
|
||||
|
||||
//*******************************************************
|
||||
// Load data
|
||||
//*******************************************************
|
||||
|
||||
LoadCrossSectionData(particle->GetParticleName() );
|
||||
|
||||
//*******************************************************
|
||||
// Verbose
|
||||
//*******************************************************
|
||||
|
||||
if( verboseLevel>0 )
|
||||
{
|
||||
G4cout << "PTB excitation model is initialized " << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAPTBExcitationModel::CrossSectionPerVolume(const G4Material* /*material*/,
|
||||
const G4String& materialName,
|
||||
const G4ParticleDefinition* particleDefinition,
|
||||
G4double ekin,
|
||||
G4double /*emin*/,
|
||||
G4double /*emax*/)
|
||||
{
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling CrossSectionPerVolume() of G4DNAPTBExcitationModel" << G4endl;
|
||||
|
||||
// Get the name of the current particle
|
||||
G4String particleName = particleDefinition->GetParticleName();
|
||||
|
||||
// initialise variables
|
||||
G4double lowLim = 0;
|
||||
G4double highLim = 0;
|
||||
G4double sigma=0;
|
||||
|
||||
// Get the low energy limit for the current particle
|
||||
lowLim = GetLowELimit(materialName, particleName);
|
||||
|
||||
// Get the high energy limit for the current particle
|
||||
highLim = GetHighELimit(materialName, particleName);
|
||||
|
||||
// Check that we are in the correct energy range
|
||||
if (ekin >= lowLim && ekin < highLim)
|
||||
{
|
||||
// Get the map with all the data tables
|
||||
TableMapData* tableData = GetTableData();
|
||||
|
||||
// Retrieve the cross section value
|
||||
sigma = (*tableData)[materialName][particleName]->FindValue(ekin);
|
||||
|
||||
if (verboseLevel > 2)
|
||||
{
|
||||
G4cout << "__________________________________" << G4endl;
|
||||
G4cout << "°°° G4DNAPTBExcitationModel - XS INFO START" << G4endl;
|
||||
G4cout << "°°° Kinetic energy(eV)=" << ekin/eV << " particle : " << particleName << G4endl;
|
||||
G4cout << "°°° Cross section per "<< materialName <<" molecule (cm^2)=" << sigma/cm/cm << G4endl;
|
||||
G4cout << "°°° G4DNAPTBExcitationModel - XS INFO END" << G4endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Return the cross section value
|
||||
return sigma;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAPTBExcitationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
|
||||
const G4MaterialCutsCouple* /*couple*/,
|
||||
const G4String& materialName,
|
||||
const G4DynamicParticle* aDynamicParticle,
|
||||
G4ParticleChangeForGamma* particleChangeForGamma,
|
||||
G4double /*tmin*/,
|
||||
G4double /*tmax*/)
|
||||
{
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling SampleSecondaries() of G4DNAPTBExcitationModel" << G4endl;
|
||||
|
||||
// Get the incident particle kinetic energy
|
||||
G4double k = aDynamicParticle->GetKineticEnergy();
|
||||
|
||||
if(materialName!="G4_WATER")
|
||||
{
|
||||
// Retrieve the excitation energy for the current material
|
||||
G4double excitationEnergy = tableMeanEnergyPTB[materialName];
|
||||
|
||||
// Calculate the new energy of the particle
|
||||
G4double newEnergy = k - excitationEnergy;
|
||||
|
||||
// Check that the new energy is above zero before applying it the particle.
|
||||
// Otherwise, do nothing.
|
||||
if (newEnergy > 0)
|
||||
{
|
||||
particleChangeForGamma->ProposeMomentumDirection(aDynamicParticle->GetMomentumDirection());
|
||||
particleChangeForGamma->SetProposedKineticEnergy(newEnergy);
|
||||
particleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const G4String& particleName = aDynamicParticle->GetDefinition()->GetParticleName();
|
||||
|
||||
G4int level = RandomSelectShell(k,particleName, materialName);
|
||||
G4double excitationEnergy = waterStructure.ExcitationEnergy(level);
|
||||
G4double newEnergy = k - excitationEnergy;
|
||||
|
||||
if (newEnergy > 0)
|
||||
{
|
||||
particleChangeForGamma->ProposeMomentumDirection(aDynamicParticle->GetMomentumDirection());
|
||||
particleChangeForGamma->SetProposedKineticEnergy(newEnergy);
|
||||
particleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
|
||||
}
|
||||
|
||||
const G4Track * theIncomingTrack = particleChangeForGamma->GetCurrentTrack();
|
||||
G4DNAChemistryManager::Instance()->CreateWaterMolecule(eExcitedMolecule,
|
||||
level,
|
||||
theIncomingTrack);
|
||||
}
|
||||
}
|
||||
+996
@@ -0,0 +1,996 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Authors: S. Meylan and C. Villagrasa (IRSN, France)
|
||||
// Models come from
|
||||
// M. Bug et al, Rad. Phys and Chem. 130, 459-479 (2017)
|
||||
//
|
||||
|
||||
#include "G4DNAPTBIonisationModel.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4UAtomicDeexcitation.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
|
||||
G4DNAPTBIonisationModel::G4DNAPTBIonisationModel(const G4String& applyToMaterial,
|
||||
const G4ParticleDefinition*,
|
||||
const G4String& nam, const G4bool isAuger)
|
||||
: G4VDNAModel(nam, applyToMaterial)
|
||||
{
|
||||
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 << "PTB ionisation model is constructed " << G4endl;
|
||||
}
|
||||
|
||||
if(isAuger)
|
||||
{
|
||||
// create the PTB Auger model
|
||||
fDNAPTBAugerModel = new G4DNAPTBAugerModel("e-_G4DNAPTBAugerModel");
|
||||
}
|
||||
else
|
||||
{
|
||||
// no PTB Auger model
|
||||
fDNAPTBAugerModel = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNAPTBIonisationModel::~G4DNAPTBIonisationModel()
|
||||
{
|
||||
// To delete the DNAPTBAugerModel created at initialisation of the ionisation class
|
||||
if(fDNAPTBAugerModel) delete fDNAPTBAugerModel;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAPTBIonisationModel::Initialise(const G4ParticleDefinition* particle,
|
||||
const G4DataVector& /*cuts*/, G4ParticleChangeForGamma*)
|
||||
{
|
||||
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling G4DNAPTBIonisationModel::Initialise()" << G4endl;
|
||||
|
||||
G4double scaleFactor = 1e-16 * cm*cm;
|
||||
G4double scaleFactorBorn = (1.e-22 / 3.343) * m*m;
|
||||
|
||||
G4ParticleDefinition* electronDef = G4Electron::ElectronDefinition();
|
||||
G4ParticleDefinition* protonDef= G4Proton::ProtonDefinition();
|
||||
|
||||
//*******************************************************
|
||||
// Cross section data
|
||||
//*******************************************************
|
||||
|
||||
if(particle == electronDef)
|
||||
{
|
||||
G4String particleName = particle->GetParticleName();
|
||||
|
||||
// Raw materials
|
||||
//
|
||||
AddCrossSectionData("THF",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e-_PTB_THF",
|
||||
"dna/sigmadiff_cumulated_ionisation_e-_PTB_THF",
|
||||
scaleFactor);
|
||||
SetLowELimit("THF", particleName, 12.*eV);
|
||||
SetHighELimit("THF", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("PY",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e-_PTB_PY",
|
||||
"dna/sigmadiff_cumulated_ionisation_e-_PTB_PY",
|
||||
scaleFactor);
|
||||
SetLowELimit("PY", particleName, 12.*eV);
|
||||
SetHighELimit("PY", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("PU",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e-_PTB_PU",
|
||||
"dna/sigmadiff_cumulated_ionisation_e-_PTB_PU",
|
||||
scaleFactor);
|
||||
SetLowELimit("PU", particleName, 12.*eV);
|
||||
SetHighELimit("PU", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("TMP",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e-_PTB_TMP",
|
||||
"dna/sigmadiff_cumulated_ionisation_e-_PTB_TMP",
|
||||
scaleFactor);
|
||||
SetLowELimit("TMP", particleName, 12.*eV);
|
||||
SetHighELimit("TMP", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("G4_WATER",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e_born",
|
||||
"dna/sigmadiff_ionisation_e_born",
|
||||
scaleFactorBorn);
|
||||
SetLowELimit("G4_WATER", particleName, 12.*eV);
|
||||
SetHighELimit("G4_WATER", particleName, 1.*keV);
|
||||
|
||||
// DNA materials
|
||||
//
|
||||
AddCrossSectionData("backbone_THF",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e-_PTB_THF",
|
||||
"dna/sigmadiff_cumulated_ionisation_e-_PTB_THF",
|
||||
scaleFactor*33./30);
|
||||
SetLowELimit("backbone_THF", particleName, 12.*eV);
|
||||
SetHighELimit("backbone_THF", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("cytosine_PY",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e-_PTB_PY",
|
||||
"dna/sigmadiff_cumulated_ionisation_e-_PTB_PY",
|
||||
scaleFactor*42./30);
|
||||
SetLowELimit("cytosine_PY", particleName, 12.*eV);
|
||||
SetHighELimit("cytosine_PY", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("thymine_PY",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e-_PTB_PY",
|
||||
"dna/sigmadiff_cumulated_ionisation_e-_PTB_PY",
|
||||
scaleFactor*48./30);
|
||||
SetLowELimit("thymine_PY", particleName, 12.*eV);
|
||||
SetHighELimit("thymine_PY", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("adenine_PU",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e-_PTB_PU",
|
||||
"dna/sigmadiff_cumulated_ionisation_e-_PTB_PU",
|
||||
scaleFactor*50./44);
|
||||
SetLowELimit("adenine_PU", particleName, 12.*eV);
|
||||
SetHighELimit("adenine_PU", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("guanine_PU",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e-_PTB_PU",
|
||||
"dna/sigmadiff_cumulated_ionisation_e-_PTB_PU",
|
||||
scaleFactor*56./44);
|
||||
SetLowELimit("guanine_PU", particleName, 12.*eV);
|
||||
SetHighELimit("guanine_PU", particleName, 1.*keV);
|
||||
|
||||
AddCrossSectionData("backbone_TMP",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e-_PTB_TMP",
|
||||
"dna/sigmadiff_cumulated_ionisation_e-_PTB_TMP",
|
||||
scaleFactor*33./50);
|
||||
SetLowELimit("backbone_TMP", particleName, 12.*eV);
|
||||
SetHighELimit("backbone_TMP", particleName, 1.*keV);
|
||||
}
|
||||
|
||||
else if (particle == protonDef)
|
||||
{
|
||||
G4String particleName = particle->GetParticleName();
|
||||
|
||||
// Raw materials
|
||||
//
|
||||
AddCrossSectionData("THF",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_p_HKS_THF",
|
||||
"dna/sigmadiff_cumulated_ionisation_p_PTB_THF",
|
||||
scaleFactor);
|
||||
SetLowELimit("THF", particleName, 70.*keV);
|
||||
SetHighELimit("THF", particleName, 10.*MeV);
|
||||
|
||||
|
||||
AddCrossSectionData("PY",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_p_HKS_PY",
|
||||
"dna/sigmadiff_cumulated_ionisation_p_PTB_PY",
|
||||
scaleFactor);
|
||||
SetLowELimit("PY", particleName, 70.*keV);
|
||||
SetHighELimit("PY", particleName, 10.*MeV);
|
||||
|
||||
/*
|
||||
AddCrossSectionData("PU",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_e-_PTB_PU",
|
||||
"dna/sigmadiff_cumulated_ionisation_e-_PTB_PU",
|
||||
scaleFactor);
|
||||
SetLowELimit("PU", particleName2, 70.*keV);
|
||||
SetHighELimit("PU", particleName2, 10.*keV);
|
||||
*/
|
||||
|
||||
AddCrossSectionData("TMP",
|
||||
particleName,
|
||||
"dna/sigma_ionisation_p_HKS_TMP",
|
||||
"dna/sigmadiff_cumulated_ionisation_p_PTB_TMP",
|
||||
scaleFactor);
|
||||
SetLowELimit("TMP", particleName, 70.*keV);
|
||||
SetHighELimit("TMP", particleName, 10.*MeV);
|
||||
}
|
||||
|
||||
// *******************************************************
|
||||
// deal with composite materials
|
||||
// *******************************************************
|
||||
|
||||
LoadCrossSectionData(particle->GetParticleName() );
|
||||
|
||||
// *******************************************************
|
||||
// Verbose
|
||||
// *******************************************************
|
||||
|
||||
// initialise DNAPTBAugerModel
|
||||
if(fDNAPTBAugerModel) fDNAPTBAugerModel->Initialise();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAPTBIonisationModel::CrossSectionPerVolume(const G4Material* /*material*/,
|
||||
const G4String& materialName,
|
||||
const G4ParticleDefinition* p,
|
||||
G4double ekin,
|
||||
G4double /*emin*/,
|
||||
G4double /*emax*/)
|
||||
{
|
||||
if(verboseLevel > 3)
|
||||
G4cout << "Calling CrossSectionPerVolume() of G4DNAPTBIonisationModel" << G4endl;
|
||||
|
||||
// initialise the cross section value (output value)
|
||||
G4double sigma(0);
|
||||
|
||||
// Get the current particle name
|
||||
const G4String& particleName = p->GetParticleName();
|
||||
|
||||
// Set the low and high energy limits
|
||||
G4double lowLim = GetLowELimit(materialName, particleName);
|
||||
G4double highLim = GetHighELimit(materialName, particleName);
|
||||
|
||||
// Check that we are in the correct energy range
|
||||
if (ekin >= lowLim && ekin < highLim)
|
||||
{
|
||||
// Get the map with all the model data tables
|
||||
TableMapData* tableData = GetTableData();
|
||||
|
||||
// Retrieve the cross section value for the current material, particle and energy values
|
||||
sigma = (*tableData)[materialName][particleName]->FindValue(ekin);
|
||||
|
||||
if (verboseLevel > 2)
|
||||
{
|
||||
G4cout << "__________________________________" << G4endl;
|
||||
G4cout << "°°° G4DNAPTBIonisationModel - XS INFO START" << G4endl;
|
||||
G4cout << "°°° Kinetic energy(eV)=" << ekin/eV << " particle : " << particleName << G4endl;
|
||||
G4cout << "°°° Cross section per "<< materialName <<" molecule (cm^2)=" << sigma/cm/cm << G4endl;
|
||||
G4cout << "°°° G4DNAPTBIonisationModel - XS INFO END" << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the cross section value
|
||||
return sigma;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAPTBIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
|
||||
const G4MaterialCutsCouple* /*couple*/,
|
||||
const G4String& materialName,
|
||||
const G4DynamicParticle* aDynamicParticle,
|
||||
G4ParticleChangeForGamma* particleChangeForGamma,
|
||||
G4double /*tmin*/,
|
||||
G4double /*tmax*/)
|
||||
{
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling SampleSecondaries() of G4DNAPTBIonisationModel" << G4endl;
|
||||
|
||||
// Get the current particle energy
|
||||
G4double k = aDynamicParticle->GetKineticEnergy();
|
||||
|
||||
// Get the current particle name
|
||||
const G4String& particleName = aDynamicParticle->GetDefinition()->GetParticleName();
|
||||
|
||||
// Get the energy limits
|
||||
G4double lowLim = GetLowELimit(materialName, particleName);
|
||||
G4double highLim = GetHighELimit(materialName, particleName);
|
||||
|
||||
// Check if we are in the correct energy range
|
||||
if (k >= lowLim && k < highLim)
|
||||
{
|
||||
G4ParticleMomentum primaryDirection = aDynamicParticle->GetMomentumDirection();
|
||||
G4double particleMass = aDynamicParticle->GetDefinition()->GetPDGMass();
|
||||
G4double totalEnergy = k + particleMass;
|
||||
G4double pSquare = k * (totalEnergy + particleMass);
|
||||
G4double totalMomentum = std::sqrt(pSquare);
|
||||
|
||||
// Get the ionisation shell from a random sampling
|
||||
G4int ionizationShell = RandomSelectShell(k, particleName, materialName);
|
||||
|
||||
// Get the binding energy from the ptbStructure class
|
||||
G4double bindingEnergy = ptbStructure.IonisationEnergy(ionizationShell, materialName);
|
||||
|
||||
// Initialize the secondary kinetic energy to a negative value.
|
||||
G4double secondaryKinetic (-1000*eV);
|
||||
|
||||
if(materialName!="G4_WATER")
|
||||
{
|
||||
// Get the energy of the secondary particle
|
||||
secondaryKinetic = RandomizeEjectedElectronEnergyFromCumulated(aDynamicParticle->GetDefinition(),k/eV,ionizationShell, materialName);
|
||||
}
|
||||
else
|
||||
{
|
||||
secondaryKinetic = RandomizeEjectedElectronEnergy(aDynamicParticle->GetDefinition(),k,ionizationShell, materialName);
|
||||
}
|
||||
|
||||
if(secondaryKinetic<=0)
|
||||
{
|
||||
G4cout<<"Fatal error *************************************** "<<secondaryKinetic/eV<<G4endl;
|
||||
G4cout<<"secondaryKinetic: "<<secondaryKinetic/eV<<G4endl;
|
||||
G4cout<<"k: "<<k/eV<<G4endl;
|
||||
G4cout<<"shell: "<<ionizationShell<<G4endl;
|
||||
G4cout<<"material:"<<materialName<<G4endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
G4double cosTheta = 0.;
|
||||
G4double phi = 0.;
|
||||
RandomizeEjectedElectronDirection(aDynamicParticle->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);
|
||||
|
||||
// The model is written only for electron and thus we want the change the direction of the incident electron
|
||||
// after each ionization. However, if other particle are going to be introduced within this model the following should be added:
|
||||
//
|
||||
// Check if the particle is an electron
|
||||
if(aDynamicParticle->GetDefinition() == G4Electron::ElectronDefinition() )
|
||||
{
|
||||
// If yes do the following code until next commented "else" statement
|
||||
|
||||
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(finalPx,finalPy,finalPz);
|
||||
if(direction.unit().getX()>1||direction.unit().getY()>1||direction.unit().getZ()>1)
|
||||
{
|
||||
G4cout<<"Fatal error ****************************"<<G4endl;
|
||||
G4cout<<"direction problem "<<direction.unit()<<G4endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Give the new direction to the particle
|
||||
particleChangeForGamma->ProposeMomentumDirection(direction.unit()) ;
|
||||
}
|
||||
// If the particle is not an electron
|
||||
else particleChangeForGamma->ProposeMomentumDirection(primaryDirection) ;
|
||||
|
||||
// note that secondaryKinetic is the energy of the delta ray, not of all secondaries.
|
||||
G4double scatteredEnergy = k-bindingEnergy-secondaryKinetic;
|
||||
|
||||
if(scatteredEnergy<=0)
|
||||
{
|
||||
G4cout<<"Fatal error ****************************"<<G4endl;
|
||||
G4cout<<"k: "<<k/eV<<G4endl;
|
||||
G4cout<<"secondaryKinetic: "<<secondaryKinetic/eV<<G4endl;
|
||||
G4cout<<"shell: "<<ionizationShell<<G4endl;
|
||||
G4cout<<"bindingEnergy: "<<bindingEnergy/eV<<G4endl;
|
||||
G4cout<<"scatteredEnergy: "<<scatteredEnergy/eV<<G4endl;
|
||||
G4cout<<"material: "<<materialName<<G4endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Set the new energy of the particle
|
||||
particleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy);
|
||||
|
||||
// Set the energy deposited by the ionization
|
||||
particleChangeForGamma->ProposeLocalEnergyDeposit(k-scatteredEnergy-secondaryKinetic);
|
||||
|
||||
// Create the new particle with its characteristics
|
||||
G4DynamicParticle* dp = new G4DynamicParticle (G4Electron::Electron(),deltaDirection,secondaryKinetic) ;
|
||||
fvect->push_back(dp);
|
||||
|
||||
// Check if the auger model is activated (ie instanciated)
|
||||
if(fDNAPTBAugerModel)
|
||||
{
|
||||
// run the PTB Auger model
|
||||
if(materialName!="G4_WATER") fDNAPTBAugerModel->ComputeAugerEffect(fvect, materialName, bindingEnergy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAPTBIonisationModel::ReadDiffCSFile(const G4String& materialName,
|
||||
const G4String& particleName,
|
||||
const G4String& file,
|
||||
const G4double scaleFactor)
|
||||
{
|
||||
// To read and save the informations contained within the differential cross section files
|
||||
|
||||
// get the path of the G4LEDATA data folder
|
||||
char *path = getenv("G4LEDATA");
|
||||
// if it is not found then quit and print error message
|
||||
if(!path)
|
||||
{
|
||||
G4Exception("G4DNAPTBIonisationModel::ReadAllDiffCSFiles","em0006",
|
||||
FatalException,"G4LEDATA environment variable not set.");
|
||||
return;
|
||||
}
|
||||
|
||||
// build the fullFileName path of the data file
|
||||
std::ostringstream fullFileName;
|
||||
fullFileName << path <<"/"<< file<<".dat";
|
||||
|
||||
// open the data file
|
||||
std::ifstream diffCrossSection (fullFileName.str().c_str());
|
||||
// error if file is not there
|
||||
std::stringstream endPath;
|
||||
if (!diffCrossSection)
|
||||
{
|
||||
endPath << "Missing data file: "<<file;
|
||||
G4Exception("G4DNAPTBIonisationModel::Initialise","em0003",
|
||||
FatalException, endPath.str().c_str());
|
||||
}
|
||||
|
||||
// load data from the file
|
||||
fTMapWithVec[materialName][particleName].push_back(0.);
|
||||
|
||||
G4String line;
|
||||
|
||||
// read the file until we reach the end of file point
|
||||
// fill fTMapWithVec, diffCrossSectionData, fEnergyTransferData, fProbaShellMap and fEMapWithVector
|
||||
while(std::getline(diffCrossSection, line))
|
||||
{
|
||||
// check if the line is comment or empty
|
||||
//
|
||||
std::istringstream testIss(line);
|
||||
G4String test;
|
||||
testIss >> test;
|
||||
// check first caracter to determine if following information is data or comments
|
||||
if(test=="#")
|
||||
{
|
||||
// skip the line by beginning a new while loop.
|
||||
continue;
|
||||
}
|
||||
// check if line is empty
|
||||
else if(line.empty())
|
||||
{
|
||||
// skip the line by beginning a new while loop.
|
||||
continue;
|
||||
}
|
||||
//
|
||||
// end of the check
|
||||
|
||||
// transform the line into a iss
|
||||
std::istringstream iss(line);
|
||||
|
||||
// Initialise the variables to be filled
|
||||
double T;
|
||||
double E;
|
||||
|
||||
// Filled T and E with the first two numbers of each file line
|
||||
iss>>T>>E;
|
||||
|
||||
// Fill the fTMapWithVec container with all the different T values contained within the file.
|
||||
// Duplicate must be avoided and this is the purpose of the if statement
|
||||
if (T != fTMapWithVec[materialName][particleName].back()) fTMapWithVec[materialName][particleName].push_back(T);
|
||||
|
||||
// iterate on each shell of the corresponding material
|
||||
for (int shell=0, eshell=ptbStructure.NumberOfLevels(materialName); shell<eshell; ++shell)
|
||||
{
|
||||
// map[material][particle][shell][T][E]=diffCrossSectionValue
|
||||
// Fill the map with the informations of the input file
|
||||
iss>>diffCrossSectionData[materialName][particleName][shell][T][E];
|
||||
|
||||
if(materialName!="G4_WATER")
|
||||
{
|
||||
// map[material][particle][shell][T][CS]=E
|
||||
// Fill the map
|
||||
fEnergySecondaryData[materialName][particleName][shell][T][diffCrossSectionData[materialName][particleName][shell][T][E] ]=E;
|
||||
|
||||
// map[material][particle][shell][T]=CS_vector
|
||||
// Fill the vector within the map
|
||||
fProbaShellMap[materialName][particleName][shell][T].push_back(diffCrossSectionData[materialName][particleName][shell][T][E]);
|
||||
}
|
||||
else
|
||||
{
|
||||
diffCrossSectionData[materialName][particleName][shell][T][E]*=scaleFactor;
|
||||
|
||||
fEMapWithVector[materialName][particleName][T].push_back(E);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAPTBIonisationModel::RandomizeEjectedElectronEnergy(G4ParticleDefinition* particleDefinition,
|
||||
G4double k, G4int shell, const G4String& materialName)
|
||||
{
|
||||
if (particleDefinition == G4Electron::ElectronDefinition())
|
||||
{
|
||||
//G4double Tcut=25.0E-6;
|
||||
G4double maximumEnergyTransfer=0.;
|
||||
if ((k+ptbStructure.IonisationEnergy(shell, materialName))/2. > k) maximumEnergyTransfer=k;
|
||||
else maximumEnergyTransfer = (k+ptbStructure.IonisationEnergy(shell,materialName))/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
|
||||
|
||||
//if (k > Tcut)
|
||||
//{
|
||||
G4double crossSectionMaximum = 0.;
|
||||
|
||||
G4double minEnergy = ptbStructure.IonisationEnergy(shell, materialName);
|
||||
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, materialName);
|
||||
if(differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
|
||||
value *= stpEnergy;
|
||||
|
||||
}
|
||||
//
|
||||
|
||||
|
||||
G4double secondaryElectronKineticEnergy=0.;
|
||||
|
||||
do
|
||||
{
|
||||
secondaryElectronKineticEnergy = G4UniformRand() * (maximumEnergyTransfer-ptbStructure.IonisationEnergy(shell, materialName));
|
||||
|
||||
} while(G4UniformRand()*crossSectionMaximum >
|
||||
DifferentialCrossSection(particleDefinition, k/eV,(secondaryElectronKineticEnergy+ptbStructure.IonisationEnergy(shell, materialName))/eV,shell, materialName));
|
||||
|
||||
return secondaryElectronKineticEnergy;
|
||||
|
||||
// }
|
||||
|
||||
// else if (k < Tcut)
|
||||
// {
|
||||
|
||||
// G4double bindingEnergy = ptbStructure.IonisationEnergy(shell, materialName);
|
||||
// G4double maxEnergy = ((k-bindingEnergy)/2.);
|
||||
|
||||
// G4double secondaryElectronKineticEnergy = G4UniformRand()*maxEnergy;
|
||||
// return secondaryElectronKineticEnergy;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
else if (particleDefinition == G4Proton::ProtonDefinition())
|
||||
{
|
||||
G4double maximumKineticEnergyTransfer = 4.* (electron_mass_c2 / proton_mass_c2) * k;
|
||||
|
||||
G4double crossSectionMaximum = 0.;
|
||||
for (G4double value = ptbStructure.IonisationEnergy(shell, materialName);
|
||||
value<=4.*ptbStructure.IonisationEnergy(shell, materialName) ;
|
||||
value+=0.1*eV)
|
||||
{
|
||||
G4double differentialCrossSection = DifferentialCrossSection(particleDefinition, k/eV, value/eV, shell, materialName);
|
||||
if (differentialCrossSection >= crossSectionMaximum) crossSectionMaximum = differentialCrossSection;
|
||||
}
|
||||
|
||||
G4double secondaryElectronKineticEnergy = 0.;
|
||||
do
|
||||
{
|
||||
secondaryElectronKineticEnergy = G4UniformRand() * maximumKineticEnergyTransfer;
|
||||
} while(G4UniformRand()*crossSectionMaximum >=
|
||||
DifferentialCrossSection(particleDefinition, k/eV,(secondaryElectronKineticEnergy+ptbStructure.IonisationEnergy(shell, materialName))/eV,shell, materialName));
|
||||
|
||||
return secondaryElectronKineticEnergy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
void G4DNAPTBIonisationModel::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);
|
||||
}
|
||||
}
|
||||
|
||||
else 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 G4DNAPTBIonisationModel::DifferentialCrossSection(G4ParticleDefinition * particleDefinition,
|
||||
G4double k,
|
||||
G4double energyTransfer,
|
||||
G4int ionizationLevelIndex,
|
||||
const G4String& materialName)
|
||||
{
|
||||
G4double sigma = 0.;
|
||||
const G4String& particleName = particleDefinition->GetParticleName();
|
||||
|
||||
G4double shellEnergy (ptbStructure.IonisationEnergy(ionizationLevelIndex, materialName));
|
||||
G4double kSE (energyTransfer-shellEnergy);
|
||||
|
||||
if (energyTransfer >= shellEnergy)
|
||||
{
|
||||
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(fTMapWithVec[materialName][particleName].begin(),fTMapWithVec[materialName][particleName].end(), k);
|
||||
std::vector<double>::iterator t1 = t2-1;
|
||||
|
||||
// SI : the following condition avoids situations where energyTransfer >last vector element
|
||||
if (kSE <= fEMapWithVector[materialName][particleName][(*t1)].back() && kSE <= fEMapWithVector[materialName][particleName][(*t2)].back() )
|
||||
{
|
||||
std::vector<double>::iterator e12 = std::upper_bound(fEMapWithVector[materialName][particleName][(*t1)].begin(),fEMapWithVector[materialName][particleName][(*t1)].end(), kSE);
|
||||
std::vector<double>::iterator e11 = e12-1;
|
||||
|
||||
std::vector<double>::iterator e22 = std::upper_bound(fEMapWithVector[materialName][particleName][(*t2)].begin(),fEMapWithVector[materialName][particleName][(*t2)].end(), kSE);
|
||||
std::vector<double>::iterator e21 = e22-1;
|
||||
|
||||
valueT1 =*t1;
|
||||
valueT2 =*t2;
|
||||
valueE21 =*e21;
|
||||
valueE22 =*e22;
|
||||
valueE12 =*e12;
|
||||
valueE11 =*e11;
|
||||
|
||||
xs11 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT1][valueE11];
|
||||
xs12 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT1][valueE12];
|
||||
xs21 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT2][valueE21];
|
||||
xs22 = diffCrossSectionData[materialName][particleName][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(fTMapWithVec[materialName][particleName].begin(),fTMapWithVec[materialName][particleName].end(), k);
|
||||
std::vector<double>::iterator t1 = t2-1;
|
||||
|
||||
std::vector<double>::iterator e12 = std::upper_bound(fEMapWithVector[materialName][particleName][(*t1)].begin(),fEMapWithVector[materialName][particleName][(*t1)].end(), kSE);
|
||||
std::vector<double>::iterator e11 = e12-1;
|
||||
|
||||
std::vector<double>::iterator e22 = std::upper_bound(fEMapWithVector[materialName][particleName][(*t2)].begin(),fEMapWithVector[materialName][particleName][(*t2)].end(), kSE);
|
||||
std::vector<double>::iterator e21 = e22-1;
|
||||
|
||||
valueT1 =*t1;
|
||||
valueT2 =*t2;
|
||||
valueE21 =*e21;
|
||||
valueE22 =*e22;
|
||||
valueE12 =*e12;
|
||||
valueE11 =*e11;
|
||||
|
||||
xs11 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT1][valueE11];
|
||||
xs12 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT1][valueE12];
|
||||
xs21 = diffCrossSectionData[materialName][particleName][ionizationLevelIndex][valueT2][valueE21];
|
||||
xs22 = diffCrossSectionData[materialName][particleName][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, kSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return sigma;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAPTBIonisationModel::RandomizeEjectedElectronEnergyFromCumulated(G4ParticleDefinition* particleDefinition,G4double k, G4int ionizationLevelIndex, const G4String& materialName)
|
||||
{
|
||||
// k should be in eV
|
||||
|
||||
// Schematic explanation.
|
||||
// We will do an interpolation to get a final E value (ejected electron energy).
|
||||
// 1/ We choose a random number between 0 and 1 (ie we select a cumulated cross section).
|
||||
// 2/ We look for T_lower and T_upper.
|
||||
// 3/ We look for the cumulated corresponding cross sections and their associated E values.
|
||||
//
|
||||
// T_low | CS_low_1 -> E_low_1
|
||||
// | CS_low_2 -> E_low_2
|
||||
// T_up | CS_up_1 -> E_up_1
|
||||
// | CS_up_2 -> E_up_2
|
||||
//
|
||||
// 4/ We interpolate to get our E value.
|
||||
//
|
||||
// T_low | CS_low_1 -> E_low_1 -----
|
||||
// | |----> E_low --
|
||||
// | CS_low_2 -> E_low_2 ----- |
|
||||
// | ---> E_final
|
||||
// T_up | CS_up_1 -> E_up_1 ------- |
|
||||
// | |----> E_up ---
|
||||
// | CS_up_2 -> E_up_2 -------
|
||||
|
||||
// Initialize some values
|
||||
//
|
||||
G4double ejectedElectronEnergy = 0.;
|
||||
G4double valueK1 = 0;
|
||||
G4double valueK2 = 0;
|
||||
G4double valueCumulCS21 = 0;
|
||||
G4double valueCumulCS22 = 0;
|
||||
G4double valueCumulCS12 = 0;
|
||||
G4double valueCumulCS11 = 0;
|
||||
G4double secElecE11 = 0;
|
||||
G4double secElecE12 = 0;
|
||||
G4double secElecE21 = 0;
|
||||
G4double secElecE22 = 0;
|
||||
G4String particleName = particleDefinition->GetParticleName();
|
||||
|
||||
// ***************************************************************************
|
||||
// Get a random number between 0 and 1 to compare with the cumulated CS
|
||||
// ***************************************************************************
|
||||
//
|
||||
// It will allow us to choose an ejected electron energy with respect to the CS.
|
||||
G4double random = G4UniformRand();
|
||||
|
||||
// **********************************************
|
||||
// Take the input from the data tables
|
||||
// **********************************************
|
||||
|
||||
// Cumulated tables are like this: T E cumulatedCS1 cumulatedCS2 cumulatedCS3
|
||||
// We have two sets of loaded data: fTMapWithVec which contains data about T (incident particle energy)
|
||||
// and fProbaShellMap which contains cumulated cross section data.
|
||||
// Since we already have a specific T energy value which could not be explicitly in the table, we must interpolate all the values.
|
||||
|
||||
// First, we select the upper and lower T data values surrounding our T value (ie "k").
|
||||
std::vector<double>::iterator k2 = std::upper_bound(fTMapWithVec[materialName][particleName].begin(),fTMapWithVec[materialName][particleName].end(), k);
|
||||
std::vector<double>::iterator k1 = k2-1;
|
||||
|
||||
// Check if we have found a k2 value (0 if we did not found it).
|
||||
// A missing k2 value can be caused by a energy to high for the data table,
|
||||
// Ex : table done for 12*eV -> 1000*eV and k=2000*eV
|
||||
// then k2 = 0 and k1 = max of the table.
|
||||
// To detect this, we check that k1 is not superior to k2.
|
||||
if(*k1 > *k2)
|
||||
{
|
||||
// Error
|
||||
G4cerr<<"**************** Fatal error ******************"<<G4endl;
|
||||
G4cerr<<"G4DNAPTBIonisationModel::RandomizeEjectedElectronEnergyFromCumulated"<<G4endl;
|
||||
G4cerr<<"You have *k1 > *k2 with k1 "<<*k1<<" and k2 "<<*k2<<G4endl;
|
||||
G4cerr<<"This may be because the energy of the incident particle is to high for the data table."<<G4endl;
|
||||
G4cerr<<"Particle energy (eV): "<<k<<G4endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
// We have a random number and we select the cumulated cross section data values surrounding our random number.
|
||||
// But we need to do that for each T value (ie two T values) previously selected.
|
||||
//
|
||||
// First one.
|
||||
std::vector<double>::iterator cumulCS12 = std::upper_bound(fProbaShellMap[materialName][particleName][ionizationLevelIndex][(*k1)].begin(),
|
||||
fProbaShellMap[materialName][particleName][ionizationLevelIndex][(*k1)].end(), random);
|
||||
std::vector<double>::iterator cumulCS11 = cumulCS12-1;
|
||||
// Second one.
|
||||
std::vector<double>::iterator cumulCS22 = std::upper_bound(fProbaShellMap[materialName][particleName][ionizationLevelIndex][(*k2)].begin(),
|
||||
fProbaShellMap[materialName][particleName][ionizationLevelIndex][(*k2)].end(), random);
|
||||
std::vector<double>::iterator cumulCS21 = cumulCS22-1;
|
||||
|
||||
// Now that we have the "values" through pointers, we access them.
|
||||
valueK1 = *k1;
|
||||
valueK2 = *k2;
|
||||
valueCumulCS11 = *cumulCS11;
|
||||
valueCumulCS12 = *cumulCS12;
|
||||
valueCumulCS21 = *cumulCS21;
|
||||
valueCumulCS22 = *cumulCS22;
|
||||
|
||||
// *************************************************************
|
||||
// Do the interpolation to get the ejected electron energy
|
||||
// *************************************************************
|
||||
|
||||
// Here we will get four E values corresponding to our four cumulated cross section values previously selected.
|
||||
// But we need to take into account a specific case: we have selected a shell by using the ionisation cross section table
|
||||
// and, since we get two T values, we could have differential cross sections (or cumulated) equal to 0 for the lower T
|
||||
// and not for the upper T. When looking for the cumulated cross section values which surround the selected random number (for the lower T),
|
||||
// the upper_bound method will only found 0 values. Thus, the upper_bound method will return the last E value present in the table for the
|
||||
// selected T. The last E value being the highest, we will later perform an interpolation between a high E value (for the lower T) and
|
||||
// a small E value (for the upper T). This is inconsistent because if the cross section are equal to zero for the lower T then it
|
||||
// means it is not possible to ionize and, thus, to have a secondary electron. But, in our situation, it is possible to ionize for the upper T
|
||||
// AND for an interpolate T value between Tupper Tlower. That's why the final E value should be interpolate between 0 and the E value (upper T).
|
||||
//
|
||||
if(cumulCS12==fProbaShellMap[materialName][particleName][ionizationLevelIndex][(*k1)].end())
|
||||
{
|
||||
// Here we are in the special case and we force Elower1 and Elower2 to be equal at 0 for the interpolation.
|
||||
secElecE11 = 0;
|
||||
secElecE12 = 0;
|
||||
secElecE21 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK2][valueCumulCS21];
|
||||
secElecE22 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK2][valueCumulCS22];
|
||||
|
||||
valueCumulCS11 = 0;
|
||||
valueCumulCS12 = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No special case, interpolation will happen as usual.
|
||||
secElecE11 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK1][valueCumulCS11];
|
||||
secElecE12 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK1][valueCumulCS12];
|
||||
secElecE21 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK2][valueCumulCS21];
|
||||
secElecE22 = fEnergySecondaryData[materialName][particleName][ionizationLevelIndex][valueK2][valueCumulCS22];
|
||||
}
|
||||
|
||||
ejectedElectronEnergy = QuadInterpolator(valueCumulCS11, valueCumulCS12,
|
||||
valueCumulCS21, valueCumulCS22,
|
||||
secElecE11, secElecE12,
|
||||
secElecE21, secElecE22,
|
||||
valueK1, valueK2,
|
||||
k, random);
|
||||
|
||||
// **********************************************
|
||||
// Some tests for debugging
|
||||
// **********************************************
|
||||
|
||||
G4double bindingEnergy (ptbStructure.IonisationEnergy(ionizationLevelIndex, materialName)/eV);
|
||||
if(k-ejectedElectronEnergy-bindingEnergy<=0 || ejectedElectronEnergy<=0)
|
||||
{
|
||||
G4cout<<"k "<<k<<G4endl;
|
||||
G4cout<<"material "<<materialName<<G4endl;
|
||||
G4cout<<"secondaryKin "<<ejectedElectronEnergy<<G4endl;
|
||||
G4cout<<"shell "<<ionizationLevelIndex<<G4endl;
|
||||
G4cout<<"bindingEnergy "<<bindingEnergy<<G4endl;
|
||||
G4cout<<"scatteredEnergy "<<k-ejectedElectronEnergy-bindingEnergy<<G4endl;
|
||||
G4cout<<"rand "<<random<<G4endl;
|
||||
G4cout<<"surrounding k values: valueK1 valueK2\n"<<valueK1<<" "<<valueK2<<G4endl;
|
||||
G4cout<<"surrounding E values: secElecE11 secElecE12 secElecE21 secElecE22\n"
|
||||
<<secElecE11<<" "<<secElecE12<<" "<<secElecE21<<" "<<secElecE22<<" "<<G4endl;
|
||||
G4cout<<"surrounding cumulCS values: valueCumulCS11 valueCumulCS12 valueCumulCS21 valueCumulCS22\n"
|
||||
<<valueCumulCS11<<" "<<valueCumulCS12<<" "<<valueCumulCS21<<" "<<valueCumulCS22<<" "<<G4endl;
|
||||
G4cerr<<"*****************************"<<G4endl;
|
||||
G4cerr<<"Fatal error, EXIT."<<G4endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return ejectedElectronEnergy*eV;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAPTBIonisationModel::LogLogInterpolate(G4double e1,
|
||||
G4double e2,
|
||||
G4double e,
|
||||
G4double xs1,
|
||||
G4double xs2)
|
||||
{
|
||||
G4double value (0);
|
||||
|
||||
// Switch to log-lin interpolation for faster code
|
||||
|
||||
if ((e2-e1)!=0 && xs1 !=0 && xs2 !=0)
|
||||
{
|
||||
G4double d1 = std::log10(xs1);
|
||||
G4double d2 = std::log10(xs2);
|
||||
value = std::pow(10.,(d1 + (d2 - d1)*(e - e1)/ (e2 - e1)) );
|
||||
}
|
||||
|
||||
// Switch to lin-lin interpolation for faster code
|
||||
// in case one of xs1 or xs2 (=cum proba) value is zero
|
||||
|
||||
if ((e2-e1)!=0 && (xs1 ==0 || xs2 ==0))
|
||||
{
|
||||
G4double d1 = xs1;
|
||||
G4double d2 = xs2;
|
||||
value = (d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAPTBIonisationModel::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 (-1);
|
||||
if(xs11!=xs12) interpolatedvalue1 = LogLogInterpolate(e11, e12, e, xs11, xs12);
|
||||
else interpolatedvalue1 = xs11;
|
||||
|
||||
G4double interpolatedvalue2 (-1);
|
||||
if(xs21!=xs22) interpolatedvalue2 = LogLogInterpolate(e21, e22, e, xs21, xs22);
|
||||
else interpolatedvalue2 = xs21;
|
||||
|
||||
G4double value (-1);
|
||||
if(interpolatedvalue1!=interpolatedvalue2) value = LogLogInterpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
|
||||
else value = interpolatedvalue1;
|
||||
|
||||
return value;
|
||||
|
||||
// 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;
|
||||
}
|
||||
@@ -23,7 +23,7 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4DNARuddIonisationExtendedModel.cc 96060 2016-03-11 12:58:04Z gcosmo $
|
||||
// $Id: G4DNARuddIonisationExtendedModel.cc 104430 2017-05-31 07:43:44Z gcosmo $
|
||||
// GEANT4 tag $Name: $
|
||||
//
|
||||
// Modified by Z. Francis, S. Incerti to handle HZE
|
||||
@@ -742,7 +742,8 @@ void G4DNARuddIonisationExtendedModel::SampleSecondaries(std::vector<G4DynamicPa
|
||||
|
||||
if (pos2 != highEnergyLimit.end())highLim = pos2->second;
|
||||
|
||||
if (k >= lowLim && k < highLim)
|
||||
if (k >= lowLim && k <= highLim)
|
||||
// SI: no strict limits, like in the non extended version of the model
|
||||
{
|
||||
G4ParticleDefinition* definition = particle->GetDefinition();
|
||||
G4ParticleMomentum primaryDirection = particle->GetMomentumDirection();
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// $Id: G4DNARuddIonisationModel.cc 96060 2016-03-11 12:58:04Z gcosmo $
|
||||
// $Id: G4DNARuddIonisationModel.cc 104430 2017-05-31 07:43:44Z gcosmo $
|
||||
// GEANT4 tag $Name: $
|
||||
//
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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$
|
||||
//
|
||||
|
||||
#include "G4DNAVacuumModel.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
|
||||
G4DNAVacuumModel::G4DNAVacuumModel(const G4String& applyToMaterial, const G4ParticleDefinition*,
|
||||
const G4String& nam)
|
||||
: G4VDNAModel(nam, applyToMaterial)
|
||||
{
|
||||
verboseLevel = 0;
|
||||
|
||||
if( verboseLevel>0 )
|
||||
{
|
||||
G4cout << "G4DNAVacuumModel is constructed " << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNAVacuumModel::~G4DNAVacuumModel()
|
||||
{
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling G4DNAVacuumModel::Initialise()" << G4endl;
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAVacuumModel::Initialise(const G4ParticleDefinition* particle,
|
||||
const G4DataVector& /*cuts*/, G4ParticleChangeForGamma*)
|
||||
{
|
||||
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling G4DNAVacuumModel::Initialise()" << G4endl;
|
||||
|
||||
EnableForMaterialAndParticle("G4_Galactic", particle->GetParticleName() );
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNAVacuumModel::CrossSectionPerVolume(const G4Material* /*material*/,
|
||||
const G4String& /*materialName*/,
|
||||
const G4ParticleDefinition* /*particleDefinition*/,
|
||||
G4double /*ekin*/,
|
||||
G4double /*emin*/,
|
||||
G4double /*emax*/)
|
||||
{
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling CrossSectionPerVolume() of G4DNAVacuumModel" << G4endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNAVacuumModel::SampleSecondaries(std::vector<G4DynamicParticle*>* /*fvect*/,
|
||||
const G4MaterialCutsCouple* /*couple*/,
|
||||
const G4String& /*materialName*/,
|
||||
const G4DynamicParticle* /*aDynamicParticle*/,
|
||||
G4ParticleChangeForGamma* /*particleChangeForGamma*/,
|
||||
G4double /*tmin*/,
|
||||
G4double /*tmax*/)
|
||||
{
|
||||
|
||||
if (verboseLevel > 3)
|
||||
G4cout << "Calling SampleSecondaries() of G4DNAVacuumModel" << G4endl;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,286 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Authors: S. Meylan and C. Villagrasa (IRSN, France)
|
||||
// This class is used to support PTB models that come from
|
||||
// M. Bug et al, Rad. Phys and Chem. 130, 459-479 (2017)
|
||||
//
|
||||
|
||||
#include "G4VDNAModel.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4ParticleTable.hh"
|
||||
|
||||
G4VDNAModel::G4VDNAModel(const G4String &nam, const G4String &applyToMaterial)
|
||||
: fStringOfMaterials(applyToMaterial), fName(nam)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
G4VDNAModel::~G4VDNAModel()
|
||||
{
|
||||
// Clean fTableData
|
||||
std::map<G4String, std::map<G4String,G4DNACrossSectionDataSet*,std::less<G4String> > >::iterator posOuter;
|
||||
std::map<G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator posInner;
|
||||
// iterate on each material
|
||||
for (posOuter = fTableData.begin(); posOuter != fTableData.end(); ++posOuter)
|
||||
{
|
||||
// iterate on each particle
|
||||
for(posInner = posOuter->second.begin(); posInner != posOuter->second.end(); ++posInner)
|
||||
{
|
||||
G4DNACrossSectionDataSet* table = posInner->second;
|
||||
if(table != 0) delete table;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G4VDNAModel::AddCrossSectionData(G4String materialName, G4String particleName, G4String fileCS, G4String fileDiffCS, G4double scaleFactor)
|
||||
{
|
||||
fModelMaterials.push_back(materialName);
|
||||
fModelParticles.push_back(particleName);
|
||||
fModelCSFiles.push_back(fileCS);
|
||||
fModelDiffCSFiles.push_back(fileDiffCS);
|
||||
fModelScaleFactors.push_back(scaleFactor);
|
||||
}
|
||||
|
||||
void G4VDNAModel::AddCrossSectionData(G4String materialName, G4String particleName, G4String fileCS, G4double scaleFactor)
|
||||
{
|
||||
fModelMaterials.push_back(materialName);
|
||||
fModelParticles.push_back(particleName);
|
||||
fModelCSFiles.push_back(fileCS);
|
||||
fModelScaleFactors.push_back(scaleFactor);
|
||||
}
|
||||
|
||||
void G4VDNAModel::LoadCrossSectionData(const G4String& particleName)
|
||||
{
|
||||
G4String fileElectron, fileDiffElectron;
|
||||
G4String materialName, modelParticleName;
|
||||
G4double scaleFactor;
|
||||
|
||||
// construct applyToMatVect with materials specified by the user
|
||||
std::vector<G4String> applyToMatVect = BuildApplyToMatVect(fStringOfMaterials);
|
||||
|
||||
// iterate on each material contained into the fStringOfMaterials variable (through applyToMatVect)
|
||||
for(unsigned int i=0;i<applyToMatVect.size();++i)
|
||||
{
|
||||
// We have selected a material coming from applyToMatVect
|
||||
// We try to find if this material correspond to a model registered material
|
||||
// If it is, then isMatFound becomes true
|
||||
G4bool isMatFound = false;
|
||||
|
||||
// We iterate on each model registered materials to load the CS data
|
||||
// We have to do a for loop because of the "all" option
|
||||
// applyToMatVect[i] == "all" implies applyToMatVect.size()=1 and we want to iterate on all registered materials
|
||||
for(unsigned int j=0;j<fModelMaterials.size();++j)
|
||||
{
|
||||
if(applyToMatVect[i] == fModelMaterials[j] || applyToMatVect[i] == "all")
|
||||
{
|
||||
isMatFound = true;
|
||||
materialName = fModelMaterials[j];
|
||||
modelParticleName = fModelParticles[j];
|
||||
fileElectron = fModelCSFiles[j];
|
||||
if(!fModelDiffCSFiles.empty()) fileDiffElectron = fModelDiffCSFiles[j];
|
||||
scaleFactor = fModelScaleFactors[j];
|
||||
|
||||
ReadAndSaveCSFile(materialName, modelParticleName, fileElectron, scaleFactor);
|
||||
|
||||
if(!fModelDiffCSFiles.empty()) ReadDiffCSFile(materialName, modelParticleName, fileDiffElectron, scaleFactor);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// check if we found a correspondance, if not: fatal error
|
||||
if(!isMatFound)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << applyToMatVect[i] << " material was not found. It means the material specified in the UserPhysicsList is not a model material for ";
|
||||
oss << particleName;
|
||||
G4Exception("G4VDNAModel::LoadCrossSectionData","em0003",
|
||||
FatalException, oss.str().c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G4VDNAModel::ReadDiffCSFile(const G4String&, const G4String&, const G4String&, const G4double)
|
||||
{
|
||||
G4String text("ReadDiffCSFile must be implemented in the model class using a differential cross section data file");
|
||||
|
||||
G4Exception("G4VDNAModel::ReadDiffCSFile","em0003",
|
||||
FatalException, text);
|
||||
}
|
||||
|
||||
void G4VDNAModel::EnableForMaterialAndParticle(const G4String &materialName, const G4String &particleName)
|
||||
{
|
||||
fTableData[materialName][particleName] = 0;
|
||||
}
|
||||
|
||||
std::vector<G4String> G4VDNAModel::BuildApplyToMatVect(const G4String& materials)
|
||||
{
|
||||
// output material vector
|
||||
std::vector<G4String> materialVect;
|
||||
|
||||
// if we don't find any "/" then it means we only have one "material" (could be the "all" option)
|
||||
if(materials.find("/")==std::string::npos)
|
||||
{
|
||||
// we add the material to the output vector
|
||||
materialVect.push_back(materials);
|
||||
}
|
||||
// if we have several materials listed in the string then we must retrieve them
|
||||
else
|
||||
{
|
||||
G4String materialsNonIdentified = materials;
|
||||
|
||||
while(materialsNonIdentified.find_first_of("/") != std::string::npos)
|
||||
{
|
||||
// we select the first material and stop at the "/" caracter
|
||||
G4String mat = materialsNonIdentified.substr(0, materialsNonIdentified.find_first_of("/"));
|
||||
materialVect.push_back(mat);
|
||||
|
||||
// we remove the previous material from the materialsNonIdentified string
|
||||
materialsNonIdentified = materialsNonIdentified.substr(materialsNonIdentified.find_first_of("/")+1,
|
||||
materialsNonIdentified.size()-materialsNonIdentified.find_first_of("/"));
|
||||
}
|
||||
|
||||
// we don't find "/" anymore, it means we only have one material string left
|
||||
// we get it
|
||||
materialVect.push_back(materialsNonIdentified);
|
||||
}
|
||||
|
||||
return materialVect;
|
||||
}
|
||||
|
||||
void G4VDNAModel::ReadAndSaveCSFile(const G4String& materialName,
|
||||
const G4String& particleName,
|
||||
const G4String& file, G4double scaleFactor)
|
||||
{
|
||||
fTableData[materialName][particleName] = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, eV, scaleFactor);
|
||||
fTableData[materialName][particleName]->LoadData(file);
|
||||
}
|
||||
|
||||
G4int G4VDNAModel::RandomSelectShell(G4double k, const G4String& particle, const G4String& materialName)
|
||||
{
|
||||
G4int level = 0;
|
||||
|
||||
TableMapData* tableData = GetTableData();
|
||||
|
||||
std::map< G4String,G4DNACrossSectionDataSet*,std::less<G4String> >::iterator pos;
|
||||
pos = (*tableData)[materialName].find(particle);
|
||||
|
||||
if (pos != (*tableData)[materialName].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("G4VDNAModel::RandomSelectShell","em0002",
|
||||
FatalException,"Model not applicable to particle type.");
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
G4bool G4VDNAModel::IsMaterialDefine(const G4String& materialName)
|
||||
{
|
||||
// Check if the given material is defined in the simulation
|
||||
|
||||
G4bool exist (false);
|
||||
|
||||
double matTableSize = G4Material::GetMaterialTable()->size();
|
||||
|
||||
for(int i=0;i<matTableSize;i++)
|
||||
{
|
||||
if(materialName == G4Material::GetMaterialTable()->at(i)->GetName())
|
||||
{
|
||||
exist = true;
|
||||
return exist;
|
||||
}
|
||||
}
|
||||
|
||||
return exist;
|
||||
}
|
||||
|
||||
G4bool G4VDNAModel::IsMaterialExistingInModel(const G4String& materialName)
|
||||
{
|
||||
// Check if the given material is defined in the current model class
|
||||
|
||||
if (fTableData.find(materialName) == fTableData.end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
G4bool G4VDNAModel::IsParticleExistingInModelForMaterial(const G4String& particleName, const G4String& materialName)
|
||||
{
|
||||
// To check two things:
|
||||
// 1- is the material existing in model ?
|
||||
// 2- if yes, is the particle defined for that material ?
|
||||
|
||||
if(IsMaterialExistingInModel(materialName))
|
||||
{
|
||||
if (fTableData[materialName].find(particleName) == fTableData[materialName].end())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
Reference in New Issue
Block a user