Import Geant4 11.4.0.beta source tree
This commit is contained in:
@@ -1,127 +0,0 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
//
|
||||
// Created by ngoc hoang tran on 03/08/2023.
|
||||
//
|
||||
|
||||
#include "G4ChemEquilibrium.hh"
|
||||
#include "G4DNAMolecularReactionTable.hh"
|
||||
|
||||
G4ChemEquilibrium::G4ChemEquilibrium(const G4int& type, const G4double& time)
|
||||
: fEquilibriumDuration(time), fRectionType(type)
|
||||
{}
|
||||
|
||||
void G4ChemEquilibrium::Initialize()
|
||||
{
|
||||
MolType H2O =
|
||||
G4MoleculeTable::Instance()->GetConfiguration("H2O");
|
||||
MolType H3OpB =
|
||||
G4MoleculeTable::Instance()->GetConfiguration("H3Op(B)");
|
||||
MolType OHmB =
|
||||
G4MoleculeTable::Instance()->GetConfiguration("OHm(B)");
|
||||
const auto& reactionList = G4DNAMolecularReactionTable::Instance()->
|
||||
GetVectorOfReactionData();
|
||||
for(const auto& it : reactionList)
|
||||
{
|
||||
if(it->GetReactionType()==fRectionType)
|
||||
{
|
||||
if(it->GetReactant1() != H2O
|
||||
&& it->GetReactant1() != H3OpB
|
||||
&& it->GetReactant1() != OHmB)
|
||||
{
|
||||
fReactant1 = it->GetReactant1();
|
||||
fReactantB1 = it->GetReactant2();
|
||||
}else
|
||||
{
|
||||
fReactant1 = it->GetReactant2();
|
||||
fReactantB1 = it->GetReactant1();
|
||||
}
|
||||
for(const auto& itt : *(it->GetProducts()))
|
||||
{
|
||||
if(itt != H3OpB
|
||||
&& itt != OHmB)
|
||||
{
|
||||
fReactant2 = itt;
|
||||
}else
|
||||
{
|
||||
fReactantB2 = itt;
|
||||
}
|
||||
}
|
||||
if(fVerbose > 1) {
|
||||
G4cout << "Equilibrium processes(ID) " << fRectionType << " : " << fReactant1->GetName()
|
||||
<< " <=> " << fReactant2->GetName()
|
||||
<< " Time to Equilibrium : " << fEquilibriumDuration / CLHEP::us
|
||||
<< " Initial status : " << fAddEquilibrium << G4endl;
|
||||
}
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void G4ChemEquilibrium::PrintInfo() const
|
||||
{
|
||||
G4cout<<"Equilibrium reactions : "<<fReactant1->GetName()
|
||||
<<" + "<<fReactantB1->GetName()
|
||||
<<" <=> "<<fReactant2->GetName()
|
||||
<<" + "<<fReactantB2->GetName()
|
||||
<<" Status : "<<fAddEquilibrium
|
||||
<<" from "<<G4BestUnit(fEquilibriumTime,"Time")<<" to "
|
||||
<<G4BestUnit(fEquilibriumTime + fEquilibriumDuration,"Time")<<G4endl;
|
||||
}
|
||||
|
||||
|
||||
void G4ChemEquilibrium::SetEquilibrium(Reaction pReaction)
|
||||
{
|
||||
if(pReaction->GetReactionType() != fRectionType)
|
||||
{
|
||||
std::vector<MolType> molVector;
|
||||
molVector.push_back(pReaction->GetReactant1());
|
||||
molVector.push_back(pReaction->GetReactant2());
|
||||
const G4int nbProducts = pReaction->GetNbProducts();
|
||||
if (nbProducts) {
|
||||
for (G4int j = 0; j < nbProducts; ++j) {
|
||||
auto product = pReaction->GetProduct(j);
|
||||
molVector.push_back(product);
|
||||
}
|
||||
}
|
||||
for(const auto& it : molVector)
|
||||
{
|
||||
if(it == fReactant1 || it == fReactant2 )
|
||||
{
|
||||
fAddEquilibrium = true;
|
||||
fEquilibriumTime = fGlobalTime;
|
||||
if(fVerbose >1) {
|
||||
G4cout << "Reaction type : " << pReaction->GetReactionType() << " : "
|
||||
<< pReaction->GetReactant1()->GetName() << " + "
|
||||
<< pReaction->GetReactant2()->GetName() << G4endl;
|
||||
G4cout << "SetEquilibrium : on " << fRectionType << " fEquilibriumTime : "
|
||||
<< G4BestUnit(fEquilibriumTime, "Time")<<G4endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,386 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * License and Disclaimer *
|
||||
// * *
|
||||
// * The Geant4 software is copyright of the Copyright Holders of *
|
||||
// * the Geant4 Collaboration. It is provided under the terms and *
|
||||
// * conditions of the Geant4 Software License, included in the file *
|
||||
// * LICENSE and available at http://cern.ch/geant4/license . These *
|
||||
// * include a list of copyright holders. *
|
||||
// * *
|
||||
// * Neither the authors of this software system, nor their employing *
|
||||
// * institutes,nor the agencies providing financial support for this *
|
||||
// * work make any representation or warranty, express or implied, *
|
||||
// * regarding this software system or assume any liability for its *
|
||||
// * use. Please see the license in the file LICENSE and URL above *
|
||||
// * for the full disclaimer and the limitation of liability. *
|
||||
// * *
|
||||
// * This code implementation is the result of the scientific and *
|
||||
// * technical work of the GEANT4 collaboration. *
|
||||
// * By using, copying, modifying or distributing the software (or *
|
||||
// * any work based on the software) you agree to acknowledge its *
|
||||
// * use in resulting scientific publications, and indicate your *
|
||||
// * acceptance of all terms of the Geant4 Software license. *
|
||||
// ********************************************************************
|
||||
//
|
||||
|
||||
#include "G4DNABornIonisationModel.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4VAtomDeexcitation.hh"
|
||||
#include "G4UAtomicDeexcitation.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4NistManager.hh"
|
||||
#include "G4DNACrossSectionDataSet.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
#include "G4DNABornAngle.hh"
|
||||
#include "G4DNASamplingTable.hh"
|
||||
#include "G4LogLogInterpolation.hh"
|
||||
#include "G4DeltaAngle.hh"
|
||||
#include "G4Log.hh"
|
||||
#include "G4Exp.hh"
|
||||
#include "G4Electron.hh"
|
||||
#include "G4Proton.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNACrossSectionDataSet* G4DNABornIonisationModel::xsdata_e = nullptr;
|
||||
G4DNACrossSectionDataSet* G4DNABornIonisationModel::xsdata_p = nullptr;
|
||||
G4DNASamplingTable* G4DNABornIonisationModel::sampling_e = nullptr;
|
||||
G4DNASamplingTable* G4DNABornIonisationModel::sampling_p = nullptr;
|
||||
const std::vector<G4double>* G4DNABornIonisationModel::fpWaterDensity = nullptr;
|
||||
|
||||
namespace
|
||||
{
|
||||
G4double scaleFactor = (1.e-22 / 3.343) * CLHEP::m*CLHEP::m;
|
||||
G4double tolerance = 10*CLHEP::eV;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNABornIonisationModel::G4DNABornIonisationModel(const G4ParticleDefinition*,
|
||||
const G4String& nam) :
|
||||
G4VEmModel(nam)
|
||||
{
|
||||
SetDeexcitationFlag(true);
|
||||
|
||||
// Define default angular generator
|
||||
SetAngularDistribution(new G4DNABornAngle());
|
||||
|
||||
fasterCode = G4EmParameters::Instance()->DNAFast();
|
||||
|
||||
if (nullptr == xsdata_p) {
|
||||
isFirst = true;
|
||||
LoadData();
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNABornIonisationModel::~G4DNABornIonisationModel()
|
||||
{
|
||||
if (isFirst) {
|
||||
delete xsdata_e;
|
||||
xsdata_e = nullptr;
|
||||
delete xsdata_p;
|
||||
xsdata_p = nullptr;
|
||||
delete sampling_e;
|
||||
sampling_e = nullptr;
|
||||
delete sampling_p;
|
||||
sampling_p = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNABornIonisationModel::LoadData()
|
||||
{
|
||||
// initialisation of static data once
|
||||
G4String fileElectron("dna/sigma_ionisation_e_born");
|
||||
xsdata_e = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_e->LoadData(fileElectron);
|
||||
|
||||
G4String fileProton("dna/sigma_ionisation_p_born");
|
||||
xsdata_p = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_p->LoadData(fileProton);
|
||||
|
||||
// to avoid possible threading problem fill this vector only once
|
||||
auto water = G4NistManager::Instance()->FindMaterial("G4_WATER");
|
||||
fpWaterDensity =
|
||||
G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(water);
|
||||
|
||||
G4bool verb = true;
|
||||
sampling_e = new G4DNASamplingTable(100);
|
||||
sampling_p = new G4DNASamplingTable(100);
|
||||
|
||||
if (fasterCode) {
|
||||
G4String eb = "/dna/sigmadiff_cumulated_ionisation_e_born.dat";
|
||||
sampling_e->LoadData(eb, CLHEP::eV, 1.0, verb);
|
||||
G4String pb = "/dna/sigmadiff_cumulated_ionisation_p_born.dat";
|
||||
sampling_p->LoadData(pb, CLHEP::eV, 1.0, verb);
|
||||
} else {
|
||||
G4String eb = "/dna/sigmadiff_ionisation_e_born.dat";
|
||||
sampling_e->LoadData(eb, CLHEP::eV, scaleFactor, verb);
|
||||
G4String pb = "/dna/sigmadiff_ionisation_p_born.dat";
|
||||
sampling_p->LoadData(pb, CLHEP::eV, scaleFactor, verb);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNABornIonisationModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector&)
|
||||
{
|
||||
if (isInitialised) { return; }
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
isInitialised = true;
|
||||
|
||||
if (p == G4Electron::Electron()) {
|
||||
fParticle = p;
|
||||
xsdata = xsdata_e;
|
||||
sampling = sampling_e;
|
||||
fLowEnergy = 8*CLHEP::eV;
|
||||
fHighEnergy = 1*CLHEP::MeV;
|
||||
feLimitEnergy = 19*CLHEP::eV;
|
||||
fAbsorptionEnergy = 6*CLHEP::eV;
|
||||
fMass = CLHEP::electron_mass_c2;
|
||||
isElectron = true;
|
||||
} else if (p == G4Proton::Proton()) {
|
||||
fParticle = p;
|
||||
xsdata = xsdata_p;
|
||||
sampling = sampling_p;
|
||||
fLowEnergy = 100*CLHEP::keV;
|
||||
fHighEnergy = 100*CLHEP::MeV;
|
||||
fpLimitEnergy = 70*CLHEP::MeV;
|
||||
fAbsorptionEnergy = 50*CLHEP::eV;
|
||||
fMass = CLHEP::proton_mass_c2;
|
||||
isElectron = false;
|
||||
} else {
|
||||
G4ExceptionDescription ed;
|
||||
ed << "Born ionisation model is used for " << p->GetParticleName();
|
||||
G4Exception("G4DNABornIonisationModel::Initialise","em0003",
|
||||
FatalException, ed, " it is not available.");
|
||||
}
|
||||
verbose = G4EmParameters::Instance()->WorkerVerbose();
|
||||
|
||||
// defined stationary mode
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
// initialise atomic de-excitation
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
// chemistry
|
||||
auto chem = G4DNAChemistryManager::Instance();
|
||||
if (chem->IsChemistryActivated()) {
|
||||
fChemistry = chem;
|
||||
}
|
||||
|
||||
InitialiseIntegrator(0.1, 0.25, 1.05, 1*CLHEP::eV, 0.2*CLHEP::eV, 10*CLHEP::keV);
|
||||
if (verbose > 1) {
|
||||
G4cout << "Born ionisation model is initialized for "
|
||||
<< fParticle->GetParticleName() << G4endl;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNABornIonisationModel::StartTracking(G4Track* track)
|
||||
{
|
||||
fTrack = track;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNABornIonisationModel::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition*,
|
||||
G4double ekin, G4double, G4double)
|
||||
{
|
||||
// check if model is applicable for given material
|
||||
G4double density = (material->GetIndex() < fpWaterDensity->size())
|
||||
? (*fpWaterDensity)[material->GetIndex()] : 0.0;
|
||||
if (0.0 == density) { return 0.0; }
|
||||
|
||||
// check on kinetic energy (not scaled energy) to stop low-energy ion
|
||||
const G4double xSecMax = 1.e+10*CLHEP::barn;
|
||||
if (ekin < fAbsorptionEnergy) { return xSecMax; }
|
||||
|
||||
G4double e = std::min(ekin, fHighEnergy);
|
||||
G4double sigma = (e > fLowEnergy) ? xsdata->FindValue(e)
|
||||
: xsdata->FindValue(fLowEnergy) * e / fLowEnergy;
|
||||
|
||||
sigma *= density;
|
||||
|
||||
// ICRU49 electronic SP scaling - ZF, SI
|
||||
if (!isElectron && spScaling && e < fpLimitEnergy) {
|
||||
const G4double A = 1.39241700556072800000e-9;
|
||||
const G4double B = -8.52610412942622630000e-2;
|
||||
sigma *= G4Exp(A*(ekin/CLHEP::eV) + B);
|
||||
}
|
||||
if (verbose > 1) {
|
||||
G4cout << "G4DNABornIonisationModel for " << fParticle->GetParticleName()
|
||||
<< " Ekin(keV)=" << ekin/CLHEP::keV
|
||||
<< " sigma(cm^2)=" << sigma/CLHEP::cm2 << G4endl;
|
||||
}
|
||||
return sigma;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNABornIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dynParticle,
|
||||
G4double, G4double)
|
||||
{
|
||||
fPrimaryEnergy = dynParticle->GetKineticEnergy();
|
||||
// proton shoud be stopped - check on kinetic energy
|
||||
// electrons never have such low energy
|
||||
if (fPrimaryEnergy <= fAbsorptionEnergy) {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(0.);
|
||||
fParticleChangeForGamma->ProposeTrackStatus(fStopButAlive);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(fPrimaryEnergy);
|
||||
return;
|
||||
}
|
||||
|
||||
fSelectedShell = SelectShell();
|
||||
G4double bindingEnergy = waterStructure.IonisationEnergy(fSelectedShell);
|
||||
|
||||
//SI: additional protection if tcs interpolation method is modified
|
||||
if (fPrimaryEnergy < bindingEnergy) { return; }
|
||||
|
||||
// compute max energy
|
||||
if (isElectron) {
|
||||
fMaxEnergy = 0.5*(fPrimaryEnergy - bindingEnergy);
|
||||
} else {
|
||||
G4double tau = fPrimaryEnergy/fMass;
|
||||
fMaxEnergy = 2.0*CLHEP::electron_mass_c2*tau*(tau + 2.0);
|
||||
}
|
||||
// SI: The following protection is necessary to avoid infinite loops :
|
||||
// e- ionisation cross section has non zero partial xs at 18 eV for shell 2.
|
||||
// e- has zero cumulated partial xs at 18 eV for shell 2.
|
||||
// This is due to the fact that the max allowed transfered energy is
|
||||
// (18+10.79)/2=17.025 eV and only transfered energies strictly above this
|
||||
// value have non zero partial cross section starting at transition energy 17.12 eV.
|
||||
if (fasterCode && isElectron && 2 == fSelectedShell && fPrimaryEnergy < feLimitEnergy) {
|
||||
do {
|
||||
fSelectedShell = SelectShell();
|
||||
} while (2 == fSelectedShell);
|
||||
}
|
||||
|
||||
G4double esec = fasterCode ? SampleCumulative() : SampleDifferential();
|
||||
G4double esum = 0.0;
|
||||
|
||||
// sample deexcitation
|
||||
// here we assume that H2O electronic levels are the same as Oxygen.
|
||||
// this can be considered true with a rough 10% error in energy on K-shell,
|
||||
G4int Z = 8;
|
||||
G4ThreeVector deltaDir =
|
||||
GetAngularDistribution()->SampleDirectionForShell(dynParticle, esec, Z,
|
||||
fSelectedShell,
|
||||
couple->GetMaterial());
|
||||
|
||||
// SI: only atomic deexcitation from K shell is considered
|
||||
if (fAtomDeexcitation != nullptr && fSelectedShell == 4) {
|
||||
auto as = G4AtomicShellEnumerator(0);
|
||||
auto ashell = fAtomDeexcitation->GetAtomicShell(Z, as);
|
||||
fAtomDeexcitation->GenerateParticles(fvect, ashell, Z, 0, 0);
|
||||
|
||||
// compute energy sum from de-excitation
|
||||
for (auto const & ptr : *fvect) {
|
||||
esum += ptr->GetKineticEnergy();
|
||||
}
|
||||
}
|
||||
// check energy balance
|
||||
// remaining excitation energy of water molecule
|
||||
G4double exc = std::max(bindingEnergy - esum, 0.0);
|
||||
|
||||
// remaining projectile energy
|
||||
G4double scatteredEnergy = fPrimaryEnergy - bindingEnergy - esec;
|
||||
if (scatteredEnergy < -tolerance || exc < -tolerance) {
|
||||
G4cout << "G4DNABornIonisationModel::SampleSecondaries: "
|
||||
<< "final E(keV)=" << scatteredEnergy/CLHEP::keV << " Ein(keV)="
|
||||
<< fPrimaryEnergy/CLHEP::keV << " " << fParticle->GetParticleName()
|
||||
<< " Edelta(keV)=" << esec/CLHEP::keV << " MeV, Exc(keV)=" << exc/CLHEP::keV
|
||||
<< G4endl;
|
||||
}
|
||||
scatteredEnergy = std::max(scatteredEnergy, 0.0);
|
||||
|
||||
// projectile
|
||||
if (!statCode) {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(exc);
|
||||
} else {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(fPrimaryEnergy);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(fPrimaryEnergy - scatteredEnergy);
|
||||
}
|
||||
|
||||
// delta-electron
|
||||
auto dp = new G4DynamicParticle(G4Electron::Electron(), deltaDir, esec);
|
||||
fvect->push_back(dp);
|
||||
|
||||
// create radical
|
||||
if (nullptr != fChemistry) {
|
||||
fChemistry->CreateWaterMolecule(eIonizedMolecule, fSelectedShell, fTrack);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4int G4DNABornIonisationModel::SelectShell()
|
||||
{
|
||||
G4double sum = 0.0;
|
||||
G4double xs;
|
||||
G4double e = std::min(fPrimaryEnergy, fHighEnergy);
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
auto ptr = xsdata->GetComponent(i);
|
||||
xs = (e > fLowEnergy) ? ptr->FindValue(e)
|
||||
: ptr->FindValue(fLowEnergy) * e/fLowEnergy;
|
||||
sum += xs;
|
||||
fTemp[i] = sum;
|
||||
}
|
||||
sum *= G4UniformRand();
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
if (sum <= fTemp[i]) { return i; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNABornIonisationModel::SampleCumulative()
|
||||
{
|
||||
G4double e = sampling->SampleCumulative(fPrimaryEnergy, fSelectedShell);
|
||||
if (verbose > 1) {
|
||||
G4cout << "G4DNABornIonisationModel::SampleCumulative: "
|
||||
<< fParticle->GetParticleName()
|
||||
<< " Ekin(keV)=" << fPrimaryEnergy/CLHEP::keV
|
||||
<< " Ee(keV)=" << e/CLHEP::keV << G4endl;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNABornIonisationModel::SampleDifferential()
|
||||
{
|
||||
G4double xs = ComputeIntegral(0.0, fMaxEnergy);
|
||||
G4double e = (xs > 0.0) ? SampleValue() : G4UniformRand()*fMaxEnergy;
|
||||
if (verbose > 1) {
|
||||
G4cout << "G4DNABornIonisationModel::SampleDifferential: "
|
||||
<< fParticle->GetParticleName()
|
||||
<< " Ekin(keV)=" << fPrimaryEnergy/CLHEP::keV
|
||||
<< " Ee(keV)=" << e/CLHEP::keV << G4endl;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNABornIonisationModel::ProbabilityDensityFunction(G4double ekin)
|
||||
{
|
||||
return sampling->GetValue(fPrimaryEnergy, ekin, fSelectedShell);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4UAtomicDeexcitation.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
@@ -68,17 +69,7 @@ G4VEmModel(nam)
|
||||
// Define default angular generator
|
||||
SetAngularDistribution(new G4DNABornAngle());
|
||||
|
||||
// Selection of computation method
|
||||
|
||||
fasterCode = false;
|
||||
|
||||
// Selection of stationary mode
|
||||
|
||||
statCode = false;
|
||||
|
||||
// Selection of SP scaling
|
||||
|
||||
spScaling = true;
|
||||
fasterCode = G4EmParameters::Instance()->DNAFast();
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
@@ -123,7 +114,7 @@ void G4DNABornIonisationModel1::Initialise(const G4ParticleDefinition* particle,
|
||||
G4String proton;
|
||||
|
||||
G4double scaleFactor = (1.e-22 / 3.343) * m*m;
|
||||
|
||||
|
||||
const char *path = G4FindDataDir("G4LEDATA");
|
||||
|
||||
// *** ELECTRON
|
||||
@@ -295,25 +286,36 @@ void G4DNABornIonisationModel1::Initialise(const G4ParticleDefinition* particle,
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
// Initialize water density pointer
|
||||
|
||||
if (isInitialised) { return; }
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
|
||||
// Initialize water density pointer
|
||||
fpMolWaterDensity = G4DNAMolecularMaterial::Instance()->
|
||||
GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
|
||||
|
||||
// AD
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
// AD
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
//
|
||||
|
||||
if (isInitialised)
|
||||
{ return;}
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
// chemistry
|
||||
auto chem = G4DNAChemistryManager::Instance();
|
||||
if (chem->IsChemistryActivated()) {
|
||||
fChemistry = chem;
|
||||
}
|
||||
isInitialised = true;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNABornIonisationModel1::StartTracking(G4Track* track)
|
||||
{
|
||||
fTrack = track;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double G4DNABornIonisationModel1::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* particleDefinition,
|
||||
G4double ekin,
|
||||
@@ -450,20 +452,19 @@ void G4DNABornIonisationModel1::SampleSecondaries(std::vector<G4DynamicParticle*
|
||||
|
||||
G4int ionizationShell = 0;
|
||||
|
||||
if (!fasterCode) ionizationShell = RandomSelect(k,particleName);
|
||||
|
||||
// SI: The following protection is necessary to avoid infinite loops :
|
||||
// sigmadiff_ionisation_e_born.dat has non zero partial xs at 18 eV for shell 3 (ionizationShell ==2)
|
||||
// sigmadiff_cumulated_ionisation_e_born.dat has zero cumulated partial xs at 18 eV for shell 3 (ionizationShell ==2)
|
||||
// this is due to the fact that the max allowed transfered energy is (18+10.79)/2=17.025 eV and only transfered energies
|
||||
// strictly above this value have non zero partial xs in sigmadiff_ionisation_e_born.dat (starting at trans = 17.12 eV)
|
||||
|
||||
if (fasterCode)
|
||||
do
|
||||
{
|
||||
if (!fasterCode) {
|
||||
ionizationShell = RandomSelect(k,particleName);
|
||||
} while (k<19*eV && ionizationShell==2 && particle->GetDefinition()==G4Electron::ElectronDefinition());
|
||||
|
||||
} else {
|
||||
do {
|
||||
ionizationShell = RandomSelect(k,particleName);
|
||||
} while (k<19*eV && ionizationShell==2 && particle->GetDefinition()==G4Electron::ElectronDefinition());
|
||||
}
|
||||
G4double bindingEnergy = 0;
|
||||
bindingEnergy = waterStructure.IonisationEnergy(ionizationShell);
|
||||
|
||||
@@ -481,8 +482,6 @@ void G4DNABornIonisationModel1::SampleSecondaries(std::vector<G4DynamicParticle*
|
||||
{
|
||||
secondaryKinetic = RandomizeEjectedElectronEnergyFromCumulatedDcs(particle->GetDefinition(),k,ionizationShell);
|
||||
}
|
||||
//
|
||||
|
||||
G4int Z = 8;
|
||||
|
||||
G4ThreeVector deltaDirection =
|
||||
@@ -587,17 +586,10 @@ void G4DNABornIonisationModel1::SampleSecondaries(std::vector<G4DynamicParticle*
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(k-scatteredEnergy);
|
||||
}
|
||||
|
||||
// TEST //////////////////////////
|
||||
// if (secondaryKinetic<0) abort();
|
||||
// if (scatteredEnergy<0) abort();
|
||||
// if (k-scatteredEnergy-secondaryKinetic-deexSecEnergy<0) abort();
|
||||
// if (k-scatteredEnergy<0) abort();
|
||||
/////////////////////////////////
|
||||
|
||||
const G4Track * theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack();
|
||||
G4DNAChemistryManager::Instance()->CreateWaterMolecule(eIonizedMolecule,
|
||||
ionizationShell,
|
||||
theIncomingTrack);
|
||||
// create radical
|
||||
if (nullptr != fChemistry) {
|
||||
fChemistry->CreateWaterMolecule(eIonizedMolecule, ionizationShell, fTrack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,50 +688,6 @@ G4double G4DNABornIonisationModel1::RandomizeEjectedElectronEnergy(G4ParticleDef
|
||||
return 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
// The following section is not used anymore but is kept for memory
|
||||
// GetAngularDistribution()->SampleDirectionForShell is used instead
|
||||
|
||||
/*
|
||||
void G4DNABornIonisationModel1::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......
|
||||
G4double G4DNABornIonisationModel1::DifferentialCrossSection(G4ParticleDefinition * particleDefinition,
|
||||
G4double k,
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
#include "G4EmParameters.hh"
|
||||
#include "G4DNABornAngle.hh"
|
||||
#include "G4DeltaAngle.hh"
|
||||
#include "G4Exp.hh"
|
||||
@@ -91,13 +92,7 @@ G4VEmModel(nam)
|
||||
|
||||
G4DNABornIonisationModel2::~G4DNABornIonisationModel2()
|
||||
{
|
||||
// Cross section
|
||||
|
||||
|
||||
delete fTableData;
|
||||
|
||||
// Final state
|
||||
|
||||
delete fTableData;
|
||||
fVecm.clear();
|
||||
}
|
||||
|
||||
@@ -248,13 +243,14 @@ void G4DNABornIonisationModel2::Initialise(const G4ParticleDefinition* particle,
|
||||
fpMolWaterDensity = G4DNAMolecularMaterial::Instance()->
|
||||
GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
|
||||
|
||||
// AD
|
||||
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
if (isInitialised)
|
||||
{ return;}
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
isInitialised = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,79 +44,58 @@ G4DNAEventScheduler::G4DNAEventScheduler()
|
||||
, fpUpdateSystem(new G4DNAUpdateSystemModel())
|
||||
{}
|
||||
|
||||
void G4DNAEventScheduler::ClearAndReChargeCounter()
|
||||
{
|
||||
fCounterMap.clear();
|
||||
if(fTimeToRecord.empty())
|
||||
{
|
||||
G4String WarMessage = "fTimeToRecord is empty ";
|
||||
G4Exception("G4DNAEventScheduler::ClearAndReChargeCounter()",
|
||||
"TimeToRecord is empty", JustWarning, WarMessage);
|
||||
}
|
||||
fLastRecoredTime = fTimeToRecord.begin();
|
||||
|
||||
if(G4VMoleculeCounter::Instance()->InUse()) // copy from MoleculeCounter
|
||||
{
|
||||
G4MoleculeCounter::RecordedMolecules species;
|
||||
species = G4MoleculeCounter::Instance()->GetRecordedMolecules();
|
||||
if(species.get() == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if(species->empty())
|
||||
{
|
||||
G4MoleculeCounter::Instance()->ResetCounter();
|
||||
return;
|
||||
}
|
||||
for(auto time_mol : fTimeToRecord)
|
||||
{
|
||||
if(time_mol > fStartTime)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for(auto molecule : *species)
|
||||
{
|
||||
G4int n_mol = G4MoleculeCounter::Instance()->GetNMoleculesAtTime(
|
||||
molecule, time_mol);
|
||||
|
||||
if(n_mol < 0)
|
||||
{
|
||||
G4cerr << "G4DNAEventScheduler::ClearAndReChargeCounter() ::N "
|
||||
"molecules not valid < 0 "
|
||||
<< G4endl;
|
||||
G4Exception("", "N<0", FatalException, "");
|
||||
}
|
||||
fCounterMap[time_mol][molecule] = n_mol;
|
||||
}
|
||||
fLastRecoredTime++;
|
||||
}
|
||||
G4MoleculeCounter::Instance()->ResetCounter(); // reset
|
||||
G4MoleculeCounter::Instance()->Use(false); // no more used
|
||||
}
|
||||
else
|
||||
{
|
||||
G4ExceptionDescription exceptionDescription;
|
||||
exceptionDescription << "G4VMoleculeCounter is not used";
|
||||
G4Exception("G4DNAEventScheduler::ClearAndReChargeCounter()",
|
||||
"G4DNAEventScheduler010", JustWarning, exceptionDescription);
|
||||
}
|
||||
}
|
||||
|
||||
[[maybe_unused]] void G4DNAEventScheduler::AddTimeToRecord(const G4double& time)
|
||||
{
|
||||
if(fTimeToRecord.find(time) == fTimeToRecord.end())
|
||||
{
|
||||
fTimeToRecord.insert(time);
|
||||
}
|
||||
fLastRecoredTime = fTimeToRecord.begin();
|
||||
}
|
||||
|
||||
G4DNAEventScheduler::~G4DNAEventScheduler() = default;
|
||||
|
||||
void G4DNAEventScheduler::Voxelizing()
|
||||
void G4DNAEventScheduler::Voxelizing(const G4DNABoundingBox& boundingBox)
|
||||
{
|
||||
auto pMainList = G4ITTrackHolder::Instance()->GetMainList();
|
||||
std::map<G4VDNAMesh::Index, MapList> TrackKeyMap;
|
||||
if(fpMesh == nullptr){
|
||||
fpMesh = std::make_unique<G4DNAMesh>(boundingBox, fPixel);
|
||||
}else
|
||||
{
|
||||
auto newMesh = new G4DNAMesh(fpMesh->GetBoundingBox(), fPixel);
|
||||
|
||||
auto begin = fpMesh->begin();//old mesh, should be homogeneous
|
||||
auto end = fpMesh->end();
|
||||
for(; begin != end; begin++)
|
||||
{
|
||||
auto numberOfBoxes = fPixel*fPixel*fPixel;
|
||||
const auto& mapData = std::get<2>(*begin);
|
||||
for(auto it : mapData)
|
||||
{
|
||||
if(it.second == 0) continue;
|
||||
|
||||
G4int base_mol = std::floor((G4double)it.second / numberOfBoxes);
|
||||
G4int remainder = (G4int)it.second % numberOfBoxes;
|
||||
for(G4int i = 0; i < remainder; i++)
|
||||
{
|
||||
auto oldIndex = std::get<0>(*begin);
|
||||
auto idx = newMesh->GetRandomIndex(oldIndex, fpMesh->GetResolution());
|
||||
TrackKeyMap[idx][it.first] += base_mol + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
fpMesh.reset(newMesh);
|
||||
}
|
||||
|
||||
if(!CheckingReactionRadius(fpMesh->GetResolution()))
|
||||
{
|
||||
G4String WarMessage = "resolution is not good : " +
|
||||
std::to_string(fpMesh->GetResolution() / nm);
|
||||
G4Exception("G4DNAEventScheduler::InitializeInMesh()", "WrongResolution",
|
||||
JustWarning, WarMessage);
|
||||
}
|
||||
|
||||
auto pMainList = G4ITTrackHolder::Instance()->GetMainList();
|
||||
for(auto track : *pMainList)
|
||||
{
|
||||
auto molType = GetMolecule(track)->GetMolecularConfiguration();
|
||||
@@ -146,7 +125,9 @@ void G4DNAEventScheduler::Voxelizing()
|
||||
{
|
||||
TrackKeyMap[key][molType] = 1;
|
||||
}
|
||||
track->SetTrackStatus(fStopAndKill);//kill the track
|
||||
}
|
||||
G4ITReactionSet::Instance()->CleanAllReaction();
|
||||
|
||||
for(auto& it : TrackKeyMap)
|
||||
{
|
||||
@@ -212,9 +193,12 @@ void G4DNAEventScheduler::Reset()
|
||||
fRunning = true;
|
||||
fReactionNumber = 0;
|
||||
fJumpingNumber = 0;
|
||||
|
||||
fpEventSet->RemoveEventSet();
|
||||
fpMesh->Reset();
|
||||
if(fpMesh != nullptr) {
|
||||
fpMesh->Reset();
|
||||
fpMesh.reset();
|
||||
//reset for each event
|
||||
}
|
||||
fpGillespieReaction->ResetEquilibrium();
|
||||
}
|
||||
|
||||
@@ -224,16 +208,6 @@ void G4DNAEventScheduler::Initialize(const G4DNABoundingBox& boundingBox,
|
||||
if(!fInitialized)
|
||||
{
|
||||
fPixel = pixel;
|
||||
fpMesh = std::make_unique<G4DNAMesh>(boundingBox, pixel);
|
||||
|
||||
if(!CheckingReactionRadius(fpMesh->GetResolution()))
|
||||
{
|
||||
G4String WarMessage = "resolution is not good : " +
|
||||
std::to_string(fpMesh->GetResolution() / nm);
|
||||
G4Exception("G4DNAEventScheduler::InitializeInMesh()", "WrongResolution",
|
||||
JustWarning, WarMessage);
|
||||
}
|
||||
|
||||
// Scavenger();
|
||||
|
||||
auto pScavengerMaterial = dynamic_cast<G4DNAScavengerMaterial*>(
|
||||
@@ -250,14 +224,17 @@ void G4DNAEventScheduler::Initialize(const G4DNABoundingBox& boundingBox,
|
||||
}
|
||||
}
|
||||
|
||||
Voxelizing();
|
||||
Voxelizing(boundingBox);
|
||||
fEndTime = std::min(G4ITTrackHolder::Instance()->GetNextTime(), G4Scheduler::Instance()->GetEndTime()-1*ps);
|
||||
|
||||
//G4cout<<"fEndTime" <<fEndTime<<" G4ITTrackHolder::Instance()->GetNextTime() : "<<G4ITTrackHolder::Instance()->GetNextTime()<<G4endl;
|
||||
|
||||
fpGillespieReaction->SetVoxelMesh(*fpMesh);
|
||||
fpGillespieReaction->SetEventSet(fpEventSet.get());
|
||||
fpGillespieReaction->SetTimeStep(0);// reset fTimeStep = 0 in fpGillespieReaction
|
||||
fpGillespieReaction->Initialize();
|
||||
fpGillespieReaction->CreateEvents();
|
||||
fpUpdateSystem->SetMesh(fpMesh.get());
|
||||
ClearAndReChargeCounter();
|
||||
fInitialized = true;
|
||||
}
|
||||
|
||||
@@ -305,6 +282,8 @@ void G4DNAEventScheduler::ResetInMesh()
|
||||
|
||||
G4double G4DNAEventScheduler::GetStartTime() const { return fStartTime; }
|
||||
|
||||
G4double G4DNAEventScheduler::GetGlobalTime() const { return fGlobalTime; }
|
||||
|
||||
G4double G4DNAEventScheduler::GetEndTime() const { return fEndTime; }
|
||||
|
||||
[[maybe_unused]] G4double G4DNAEventScheduler::GetTimeStep() const
|
||||
@@ -338,6 +317,7 @@ void G4DNAEventScheduler::Run()
|
||||
{
|
||||
RunInMesh();
|
||||
}
|
||||
fInitialized = false;
|
||||
if(fVerbose > 2)
|
||||
{
|
||||
if(!fRunning)
|
||||
@@ -361,7 +341,6 @@ void G4DNAEventScheduler::Run()
|
||||
}
|
||||
G4cout << " Computing Time : " << localtimer << G4endl;
|
||||
}
|
||||
Reset();
|
||||
}
|
||||
|
||||
void G4DNAEventScheduler::RunInMesh()
|
||||
@@ -377,7 +356,7 @@ void G4DNAEventScheduler::RunInMesh()
|
||||
<< " the Mesh has " << fPixel << " x " << fPixel << " x " << fPixel
|
||||
<< " voxels with Resolution " << G4BestUnit(resolution, "Length")
|
||||
<< " during next "
|
||||
<< G4BestUnit(resolution * resolution * C / (6 * D), "Time")
|
||||
<< G4BestUnit(fGlobalTime + resolution * resolution * C / (6 * D), "Time")
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
@@ -501,6 +480,8 @@ void G4DNAEventScheduler::Stepping() // this event loop
|
||||
// get selected time step
|
||||
fTimeStep = (*selected)->GetTime();
|
||||
|
||||
if(fTimeStep + fStartTime >fEndTime){ return;}
|
||||
|
||||
// selected data
|
||||
auto pJumping = (*selected)->GetJumpingData();
|
||||
auto pReaction = (*selected)->GetReactionData();
|
||||
@@ -564,9 +545,15 @@ void G4DNAEventScheduler::SetEndTime(const G4double& endTime)
|
||||
|
||||
void G4DNAEventScheduler::RecordTime()
|
||||
{
|
||||
if(fLastRecoredTime == fTimeToRecord.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto recordTime = *fLastRecoredTime;
|
||||
if(fGlobalTime >= recordTime && fCounterMap[recordTime].empty())
|
||||
{
|
||||
if(fpMesh == nullptr) return;
|
||||
//G4cout<<"recordTime for meso: "<<recordTime<<" fGlobalTime : "<<fGlobalTime<<G4endl;
|
||||
auto begin = fpMesh->begin();
|
||||
auto end = fpMesh->end();
|
||||
for(; begin != end; begin++)
|
||||
@@ -671,4 +658,63 @@ void G4DNAEventScheduler::LastRegisterForCounter()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void G4DNAEventScheduler::ParticleBasedCounter() {
|
||||
if(fLastRecoredTime == fTimeToRecord.end())
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto recordTime = *fLastRecoredTime;
|
||||
if (recordTime < G4Scheduler::Instance()->GetGlobalTime()) {
|
||||
|
||||
//check meso if exist
|
||||
|
||||
if(fpMesh != nullptr){
|
||||
//G4cout<<"there is a mesh"<<G4endl;
|
||||
auto begin = fpMesh->begin();
|
||||
auto end = fpMesh->end();
|
||||
for(; begin != end; begin++)
|
||||
{
|
||||
const auto& mapData = std::get<2>(*begin);
|
||||
if(mapData.empty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for(const auto& it : mapData)
|
||||
{
|
||||
fCounterMap[recordTime][it.first] += it.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//then particle based
|
||||
auto pMainList = G4ITTrackHolder::Instance()->GetMainList();
|
||||
for (auto track: *pMainList) {
|
||||
auto molType = GetMolecule(track)->GetMolecularConfiguration();
|
||||
|
||||
auto pScavengerMaterial =
|
||||
dynamic_cast<G4DNAScavengerMaterial *>(G4Scheduler::Instance()->GetScavengerMaterial());
|
||||
if (pScavengerMaterial != nullptr
|
||||
&& pScavengerMaterial->find(molType)) // avoid voxelize the scavenger
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fCounterMap[recordTime][molType]++;
|
||||
}
|
||||
fLastRecoredTime++;
|
||||
//PrintRecordTime();
|
||||
}
|
||||
}
|
||||
|
||||
void G4DNAEventScheduler::ResetCounter()
|
||||
{
|
||||
fCounterMap.clear();
|
||||
if(fTimeToRecord.empty())
|
||||
{
|
||||
G4String WarMessage = "fTimeToRecord is empty ";
|
||||
G4Exception("G4DNAEventScheduler::ClearAndReChargeCounter()",
|
||||
"TimeToRecord is empty", JustWarning, WarMessage);
|
||||
}
|
||||
fLastRecoredTime = fTimeToRecord.begin();
|
||||
}
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "G4ITTrackHolder.hh"
|
||||
#include "G4ITReaction.hh"
|
||||
#include "G4Scheduler.hh"
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -399,7 +400,10 @@ std::unique_ptr<G4ITReactionChange> G4DNAIRT::MakeReaction(const G4Track& trackA
|
||||
const auto pMoleculeA = GetMolecule(trackA)->GetMolecularConfiguration();
|
||||
const auto pMoleculeB = GetMolecule(trackB)->GetMolecularConfiguration();
|
||||
const auto pReactionData = fMolReactionTable->GetReactionData(pMoleculeA, pMoleculeB);
|
||||
|
||||
// Notify molecule (reaction) counter
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive()) {
|
||||
G4MoleculeCounterManager::Instance()->RecordReaction(pReactionData, trackA.GetGlobalTime());
|
||||
}
|
||||
G4double globalTime = G4Scheduler::Instance()->GetGlobalTime();
|
||||
G4double effectiveReactionRadius = pReactionData->GetEffectiveReactionRadius();
|
||||
|
||||
|
||||
+164
-145
@@ -45,10 +45,11 @@ using namespace std;
|
||||
using namespace CLHEP;
|
||||
|
||||
G4DNAIndependentReactionTimeStepper::Utils::Utils(const G4Track& trackA, const G4Track& trackB)
|
||||
: fTrackA(trackA), fTrackB(trackB)
|
||||
: fpTrackA(const_cast<G4Track*>(&trackA)), fpTrackB(const_cast<G4Track*>(&trackB))
|
||||
{
|
||||
fpMoleculeA = GetMolecule(trackA);
|
||||
fpMoleculeB = GetMolecule(trackA);
|
||||
fpMoleculeB = GetMolecule(trackB);
|
||||
fUserMinTimeStep = 1 * CLHEP::ps;
|
||||
}
|
||||
|
||||
G4DNAIndependentReactionTimeStepper::G4DNAIndependentReactionTimeStepper()
|
||||
@@ -58,30 +59,31 @@ G4DNAIndependentReactionTimeStepper::G4DNAIndependentReactionTimeStepper()
|
||||
|
||||
void G4DNAIndependentReactionTimeStepper::Prepare()
|
||||
{
|
||||
G4VITTimeStepComputer::Prepare();
|
||||
fSampledPositions.clear();
|
||||
BuildChemicalMoleculeFinder()
|
||||
//fVerbose = G4Scheduler::Instance()->GetVerbose();
|
||||
if (G4Scheduler::Instance()->IsInteractionStep()) {
|
||||
fReactionSet->CleanAllReaction();
|
||||
fIsInitialized = false;
|
||||
fSampledPositions.clear();
|
||||
fSecondaries.clear();
|
||||
InitializeForNewTrack();
|
||||
}
|
||||
}
|
||||
|
||||
void G4DNAIndependentReactionTimeStepper::InitializeForNewTrack()
|
||||
{
|
||||
if (fReactants != nullptr) {
|
||||
fReactants.reset();
|
||||
}
|
||||
fSampledMinTimeStep = DBL_MAX;
|
||||
fHasAlreadyReachedNullTime = false;
|
||||
fCheckedTracks.clear();
|
||||
BuildChemicalMoleculeFinder()
|
||||
}
|
||||
|
||||
G4double G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& trackA,
|
||||
const G4double& userMinTimeStep)
|
||||
const G4double& /*userMinTimeStep*/)
|
||||
{
|
||||
auto pMoleculeA = GetMolecule(trackA);
|
||||
InitializeForNewTrack();
|
||||
fUserMinTimeStep = userMinTimeStep;
|
||||
fSampledMinTimeStep = DBL_MAX;
|
||||
fCheckedTracks.insert(trackA.GetTrackID());
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if (fVerbose != 0) {
|
||||
if (fVerbose > 1) {
|
||||
G4cout << "________________________________________________________________"
|
||||
"_______"
|
||||
<< G4endl;
|
||||
@@ -96,7 +98,7 @@ G4double G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& track
|
||||
const auto pReactantList = fMolecularReactionTable->CanReactWith(pMolConfA);
|
||||
|
||||
if (pReactantList == nullptr) {
|
||||
if(fVerbose > 1) {
|
||||
if (fVerbose > 1) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "G4DNAIndependentReactionTimeStepper::CalculateStep will return infinity "
|
||||
"for the reaction because the molecule "
|
||||
@@ -111,7 +113,7 @@ G4double G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& track
|
||||
auto nbReactives = (G4int)pReactantList->size();
|
||||
|
||||
if (nbReactives == 0) {
|
||||
if(fVerbose != 0){
|
||||
if (fVerbose > 1) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "G4DNAIndependentReactionTimeStepper::CalculateStep will "
|
||||
"return infinity "
|
||||
@@ -125,13 +127,10 @@ G4double G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& track
|
||||
}
|
||||
return DBL_MAX;
|
||||
}
|
||||
fReactants = std::make_shared<vector<G4Track*>>();
|
||||
fReactionModel->Initialise(pMolConfA, trackA);
|
||||
for (G4int i = 0; i < nbReactives; ++i) {
|
||||
auto pMoleculeB = (*pReactantList)[i];
|
||||
G4int key = pMoleculeB->GetMoleculeID();
|
||||
|
||||
// fRCutOff = G4IRTUtils::GetRCutOff(1 * ps);
|
||||
fRCutOff = G4IRTUtils::GetRCutOff();
|
||||
//______________________________________________________________
|
||||
// Retrieve reaction range
|
||||
@@ -157,115 +156,107 @@ G4double G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& track
|
||||
"::CalculateStep()",
|
||||
"G4DNAIndependentReactionTimeStepper007", FatalException, exceptionDescription);
|
||||
}
|
||||
if (fCheckedTracks.find(pTrackB->GetTrackID()) != fCheckedTracks.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Utils utils(trackA, *pTrackB);
|
||||
auto pMolB = GetMolecule(pTrackB);
|
||||
auto pMolConfB = pMolB->GetMolecularConfiguration();
|
||||
G4double distance = (trackA.GetPosition() - pTrackB->GetPosition()).mag();
|
||||
if (distance * distance < Reff * Reff) {
|
||||
auto reactionData = fMolecularReactionTable->GetReactionData(pMolConfA, pMolConfB);
|
||||
if (G4Scheduler::Instance()->GetGlobalTime() == G4Scheduler::Instance()->GetStartTime()) {
|
||||
if (reactionData->GetProbability() > G4UniformRand()) {
|
||||
fSampledMinTimeStep = 0.;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fCheckedTracks.find(pTrackB->GetTrackID()) != fCheckedTracks.end()) {
|
||||
G4double tempMinET = GetTimeToEncounter(trackA, *pTrackB);
|
||||
if (tempMinET < 0 || tempMinET > G4Scheduler::Instance()->GetEndTime()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Utils utils(trackA, *pTrackB);
|
||||
|
||||
auto pMolB = GetMolecule(pTrackB);
|
||||
auto pMolConfB = pMolB->GetMolecularConfiguration();
|
||||
G4double distance = (trackA.GetPosition() - pTrackB->GetPosition()).mag();
|
||||
if (distance * distance < Reff * Reff) {
|
||||
auto reactionData = fMolecularReactionTable->GetReactionData(pMolConfA, pMolConfB);
|
||||
if (G4Scheduler::Instance()->GetGlobalTime() == G4Scheduler::Instance()->GetStartTime()) {
|
||||
if (reactionData->GetProbability() > G4UniformRand()) {
|
||||
if (!fHasAlreadyReachedNullTime) {
|
||||
fReactants->clear();
|
||||
fHasAlreadyReachedNullTime = true;
|
||||
}
|
||||
fSampledMinTimeStep = 0.;
|
||||
CheckAndRecordResults(utils);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
G4double tempMinET = GetTimeToEncounter(trackA, *pTrackB);
|
||||
if (tempMinET < 0 || tempMinET > G4Scheduler::Instance()->GetEndTime()) {
|
||||
continue;
|
||||
}
|
||||
if (tempMinET >= fSampledMinTimeStep) {
|
||||
continue;
|
||||
}
|
||||
fSampledMinTimeStep = tempMinET;
|
||||
fReactants->clear();
|
||||
CheckAndRecordResults(utils);
|
||||
fSampledMinTimeStep = tempMinET;
|
||||
if (tempMinET < fUserMinTimeStep) {
|
||||
fSampledMinTimeStep = fUserMinTimeStep;
|
||||
}
|
||||
}
|
||||
CheckAndRecordResults(fSampledMinTimeStep, utils);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef G4VERBOSE
|
||||
if (fVerbose != 0) {
|
||||
G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep will finally "
|
||||
"return :"
|
||||
<< G4BestUnit(fSampledMinTimeStep, "Time") << G4endl;
|
||||
|
||||
if (fVerbose > 1) {
|
||||
G4cout << "Selected reactants for trackA: " << pMoleculeA->GetName() << " ("
|
||||
<< trackA.GetTrackID() << ") are: ";
|
||||
|
||||
vector<G4Track*>::iterator it;
|
||||
for (it = fReactants->begin(); it != fReactants->end(); it++) {
|
||||
G4Track* trackB = *it;
|
||||
G4cout << GetMolecule(trackB)->GetName() << " (" << trackB->GetTrackID() << ") \t ";
|
||||
}
|
||||
G4cout << G4endl;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return fSampledMinTimeStep;
|
||||
}
|
||||
|
||||
void G4DNAIndependentReactionTimeStepper::CheckAndRecordResults(const Utils& utils)
|
||||
void G4DNAIndependentReactionTimeStepper::CheckAndRecordResults(G4double reactionTime,
|
||||
const Utils& utils)
|
||||
{
|
||||
if (utils.fTrackB.GetTrackStatus() != fAlive) {
|
||||
if (utils.fpTrackB->GetTrackStatus() != fAlive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (&utils.fTrackB == &utils.fTrackA) {
|
||||
if (&utils.fpTrackB == &utils.fpTrackA) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "A track is reacting with itself"
|
||||
" (which is impossible) ie fpTrackA == trackB"
|
||||
<< G4endl;
|
||||
" (which is impossible) ie fpTrackA == trackB"
|
||||
<< G4endl;
|
||||
msg << "Molecule A is of type : " << utils.fpMoleculeA->GetName()
|
||||
<< " with trackID : " << utils.fTrackA.GetTrackID()
|
||||
<< " and B : " << utils.fpMoleculeB->GetName()
|
||||
<< " with trackID : " << utils.fTrackB.GetTrackID() << G4endl;
|
||||
<< " with trackID : " << utils.fpTrackA->GetTrackID()
|
||||
<< " and B : " << utils.fpMoleculeB->GetName()
|
||||
<< " with trackID : " << utils.fpTrackB->GetTrackID() << G4endl;
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::RetrieveResults",
|
||||
"G4DNAIndependentReactionTimeStepper003", FatalErrorInArgument,
|
||||
msg);
|
||||
"G4DNAIndependentReactionTimeStepper003", FatalErrorInArgument, msg);
|
||||
}
|
||||
|
||||
if (fabs(utils.fTrackB.GetGlobalTime() - utils.fTrackA.GetGlobalTime())
|
||||
> utils.fTrackA.GetGlobalTime() * (1. - 1. / 100))
|
||||
if (fabs(utils.fpTrackB->GetGlobalTime() - utils.fpTrackA->GetGlobalTime())
|
||||
> utils.fpTrackA->GetGlobalTime() * (1. - 1. / 100))
|
||||
{
|
||||
// DEBUG
|
||||
G4ExceptionDescription msg;
|
||||
msg << "The interacting tracks are not synchronized in time" << G4endl;
|
||||
msg << "trackB->GetGlobalTime() != fpTrackA.GetGlobalTime()" << G4endl;
|
||||
|
||||
msg << "fpTrackA : trackID : " << utils.fTrackA.GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeA->GetName()
|
||||
<< "\t fpTrackA->GetGlobalTime() = "
|
||||
<< G4BestUnit(utils.fTrackA.GetGlobalTime(), "Time") << G4endl;
|
||||
msg << "fpTrackA : trackID : " << utils.fpTrackA->GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeA->GetName()
|
||||
<< "\t fpTrackA->GetGlobalTime() = " << G4BestUnit(utils.fpTrackA->GetGlobalTime(), "Time")
|
||||
<< G4endl;
|
||||
|
||||
msg << "trackB : trackID : " << utils.fTrackB.GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeB->GetName()
|
||||
<< "\t trackB->GetGlobalTime() = "
|
||||
<< G4BestUnit(utils.fTrackB.GetGlobalTime(), "Time") << G4endl;
|
||||
msg << "trackB : trackID : " << utils.fpTrackB->GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeB->GetName()
|
||||
<< "\t trackB->GetGlobalTime() = " << G4BestUnit(utils.fpTrackB->GetGlobalTime(), "Time")
|
||||
<< G4endl;
|
||||
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::RetrieveResults",
|
||||
"G4DNAIndependentReactionTimeStepper004", FatalErrorInArgument,
|
||||
msg);
|
||||
"G4DNAIndependentReactionTimeStepper004", FatalErrorInArgument, msg);
|
||||
}
|
||||
fReactants->push_back(const_cast<G4Track*>(&utils.fTrackB));
|
||||
if (reactionTime < 0) {
|
||||
// DEBUG
|
||||
G4ExceptionDescription msg;
|
||||
msg << "The interacting tracks are not in good time" << G4endl;
|
||||
|
||||
msg << "fpTrackA : trackID : " << utils.fpTrackA->GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeA->GetName()
|
||||
<< "\t fpTrackA->GetGlobalTime() = " << G4BestUnit(utils.fpTrackA->GetGlobalTime(), "Time")
|
||||
<< G4endl;
|
||||
|
||||
msg << "trackB : trackID : " << utils.fpTrackB->GetTrackID()
|
||||
<< "\t Name :" << utils.fpMoleculeB->GetName()
|
||||
<< "\t trackB->GetGlobalTime() = " << G4BestUnit(utils.fpTrackB->GetGlobalTime(), "Time")
|
||||
<< G4endl;
|
||||
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::CheckAndRecordResults",
|
||||
"G4DNAIndependentReactionTimeStepper1", FatalErrorInArgument, msg);
|
||||
}
|
||||
|
||||
G4double globalTime = G4Scheduler::Instance()->GetGlobalTime();
|
||||
|
||||
fReactionSet->AddReaction(reactionTime + globalTime, utils.fpTrackA, utils.fpTrackB);
|
||||
fSampledPositions[utils.fpTrackA->GetTrackID()] = utils.fpTrackA->GetPosition();
|
||||
fSampledPositions[utils.fpTrackB->GetTrackID()] = utils.fpTrackB->GetPosition();
|
||||
}
|
||||
|
||||
std::unique_ptr<G4ITReactionChange> G4DNAIndependentReactionTimeStepper::FindReaction(
|
||||
G4ITReactionSet* pReactionSet, const G4double& currentStepTime,
|
||||
const G4double& /*previousStepTime*/, const G4bool& /*reachedUserStepTimeLimit*/)
|
||||
G4ITReactionSet* pReactionSet, G4double& currentStepTime, const G4double globalTime)
|
||||
{
|
||||
if (pReactionSet == nullptr) {
|
||||
return nullptr;
|
||||
@@ -278,16 +269,13 @@ std::unique_ptr<G4ITReactionChange> G4DNAIndependentReactionTimeStepper::FindRea
|
||||
for (auto reaction_i = reactionPerTime.begin(); reaction_i != reactionPerTime.end();
|
||||
reaction_i = reactionPerTime.begin())
|
||||
{
|
||||
if ((*reaction_i)->GetTime() > currentStepTime) {
|
||||
fReactionSet->CleanAllReaction();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
G4Track* pTrackA = (*reaction_i)->GetReactants().first;
|
||||
currentStepTime = DBL_MAX;
|
||||
if (pTrackA->GetTrackStatus() == fStopAndKill) {
|
||||
continue;
|
||||
}
|
||||
G4Track* pTrackB = (*reaction_i)->GetReactant(pTrackA);
|
||||
currentStepTime = DBL_MAX;
|
||||
if (pTrackB->GetTrackStatus() == fStopAndKill) {
|
||||
continue;
|
||||
}
|
||||
@@ -295,24 +283,27 @@ std::unique_ptr<G4ITReactionChange> G4DNAIndependentReactionTimeStepper::FindRea
|
||||
if (pTrackB == pTrackA) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "The IT reaction process sent back a reaction "
|
||||
"between trackA and trackB. ";
|
||||
"between trackA and trackB. ";
|
||||
msg << "The problem is trackA == trackB";
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::FindReaction",
|
||||
"G4DNAIndependentReactionTimeStepper02", FatalErrorInArgument,
|
||||
msg);
|
||||
"G4DNAIndependentReactionTimeStepper02", FatalErrorInArgument, msg);
|
||||
}
|
||||
G4double reactionTime = (*reaction_i)->GetTime();
|
||||
currentStepTime = reactionTime - globalTime;
|
||||
if(fVerbose > 1)
|
||||
G4cout << " reaction Time : " << reactionTime << " currentStepTime : " << currentStepTime
|
||||
<< " globalTime : " << globalTime << " " << pTrackA->GetTrackID() << " + "
|
||||
<< pTrackB->GetTrackID() << G4endl;
|
||||
|
||||
pReactionSet->SelectThisReaction(*reaction_i);
|
||||
if (fpReactionProcess != nullptr
|
||||
&& fpReactionProcess->TestReactibility(*pTrackA, *pTrackB, currentStepTime, false))
|
||||
{
|
||||
if (fpReactionProcess != nullptr) {
|
||||
if ((fSampledPositions.find(pTrackA->GetTrackID()) == fSampledPositions.end()
|
||||
&& (fSampledPositions.find(pTrackB->GetTrackID()) == fSampledPositions.end())))
|
||||
{
|
||||
G4ExceptionDescription msg;
|
||||
msg << "The positions of trackA and trackB have no counted ";
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::FindReaction",
|
||||
"G4DNAIndependentReactionTimeStepper0001", FatalErrorInArgument,
|
||||
msg);
|
||||
"G4DNAIndependentReactionTimeStepper0001", FatalErrorInArgument, msg);
|
||||
}
|
||||
|
||||
pTrackA->SetPosition(fSampledPositions[pTrackA->GetTrackID()]);
|
||||
@@ -321,6 +312,13 @@ std::unique_ptr<G4ITReactionChange> G4DNAIndependentReactionTimeStepper::FindRea
|
||||
if (pReactionChange == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
G4int nbSecondaries = pReactionChange->GetNumberOfSecondaries();
|
||||
if (nbSecondaries > 0) {
|
||||
const std::vector<G4Track*>* productsVector = pReactionChange->GetfSecondary();
|
||||
for (const auto& it : *productsVector) {
|
||||
fSecondaries.push_back(it);
|
||||
}
|
||||
}
|
||||
return pReactionChange;
|
||||
}
|
||||
}
|
||||
@@ -354,19 +352,44 @@ void G4DNAIndependentReactionTimeStepper::SetReactionProcess(G4VITReactionProces
|
||||
{
|
||||
fpReactionProcess = pReactionProcess;
|
||||
}
|
||||
G4double G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep(G4double /*currentGlobalTime*/,
|
||||
G4double definedMinTimeStep)
|
||||
G4double G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep(G4double currentGlobalTime,
|
||||
G4double /*definedMinTimeStep*/)
|
||||
{
|
||||
G4double fTSTimeStep = DBL_MAX;
|
||||
fCheckedTracks.clear();
|
||||
// fUserMinTimeStep = definedMinTimeStep;
|
||||
if (!fIsInitialized) {
|
||||
InitializeReactions(currentGlobalTime);
|
||||
}
|
||||
|
||||
G4int nbPreviousSecondaries = (G4int)fSecondaries.size();
|
||||
if (nbPreviousSecondaries > 0) {
|
||||
InitializeForNewTrack();
|
||||
for (const auto& it : fSecondaries) {
|
||||
CalculateStep(*it, fUserMinTimeStep);
|
||||
}
|
||||
fSecondaries.clear();
|
||||
}
|
||||
fTSTimeStep = GetNextReactionTime() - currentGlobalTime;
|
||||
if (fTSTimeStep < 0) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "fTSTimeStep < 0" << ": fTSTimeStep : " << fTSTimeStep
|
||||
<< " GetNextReactionTime() : " << GetNextReactionTime()
|
||||
<< " currentGlobalTime : " << currentGlobalTime << G4endl;
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep",
|
||||
"G4DNAIndependentReactionTimeStepper002", FatalErrorInArgument, msg);
|
||||
}
|
||||
return fTSTimeStep;
|
||||
}
|
||||
|
||||
void G4DNAIndependentReactionTimeStepper::InitializeReactions(G4double /*currentGlobalTime*/)
|
||||
{
|
||||
fCheckedTracks.clear();
|
||||
for (auto pTrack : *fpTrackContainer->GetMainList()) {
|
||||
if (pTrack == nullptr) {
|
||||
G4ExceptionDescription msg;
|
||||
msg << "No track found.";
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep",
|
||||
"G4DNAIndependentReactionTimeStepper006", FatalErrorInArgument,
|
||||
msg);
|
||||
G4Exception("G4DNAIndependentReactionTimeStepper::InitializeReactions",
|
||||
"G4DNAIndependentReactionTimeStepper030", FatalErrorInArgument, msg);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -374,36 +397,32 @@ G4double G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep(G4double /*cu
|
||||
if (trackStatus == fStopAndKill || trackStatus == fStopButAlive) {
|
||||
continue;
|
||||
}
|
||||
|
||||
G4double sampledMinTimeStep = CalculateStep(*pTrack, definedMinTimeStep);
|
||||
G4TrackVectorHandle reactants = GetReactants();
|
||||
|
||||
if (sampledMinTimeStep < fTSTimeStep) {
|
||||
fTSTimeStep = sampledMinTimeStep;
|
||||
if (reactants) {
|
||||
fReactionSet->AddReactions(fTSTimeStep, const_cast<G4Track*>(pTrack), std::move(reactants));
|
||||
|
||||
fSampledPositions[pTrack->GetTrackID()] = pTrack->GetPosition();
|
||||
for (const auto& it : *fReactants) {
|
||||
auto pTrackB = it;
|
||||
fSampledPositions[pTrackB->GetTrackID()] = pTrackB->GetPosition();
|
||||
}
|
||||
ResetReactants();
|
||||
}
|
||||
}
|
||||
else if (fTSTimeStep == sampledMinTimeStep && G4bool(reactants)) {
|
||||
fReactionSet->AddReactions(fTSTimeStep, const_cast<G4Track*>(pTrack), std::move(reactants));
|
||||
|
||||
fSampledPositions[pTrack->GetTrackID()] = pTrack->GetPosition();
|
||||
for (const auto& it : *fReactants) {
|
||||
auto pTrackB = it;
|
||||
fSampledPositions[pTrackB->GetTrackID()] = pTrackB->GetPosition();
|
||||
}
|
||||
ResetReactants();
|
||||
}
|
||||
else if (reactants) {
|
||||
ResetReactants();
|
||||
}
|
||||
CalculateStep(*pTrack, fUserMinTimeStep);
|
||||
}
|
||||
return fTSTimeStep;
|
||||
if (fVerbose > 0)
|
||||
G4cout << "InitializeReactions : reaction events : "
|
||||
<< fReactionSet->GetReactionsPerTime().size() << ". The previous time step : "
|
||||
<< G4BestUnit(G4Scheduler::Instance()->GetPreviousTimeStep(), "Time") << G4endl;
|
||||
fIsInitialized = true;
|
||||
}
|
||||
|
||||
G4double G4DNAIndependentReactionTimeStepper::GetNextReactionTime()
|
||||
{
|
||||
G4double output = DBL_MAX;
|
||||
auto nextReaction = GetNextReaction();
|
||||
if (nextReaction != nullptr) {
|
||||
output = GetNextReaction()->GetTime();
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
const G4ITReaction* G4DNAIndependentReactionTimeStepper::GetNextReaction()
|
||||
{
|
||||
G4ITReaction* output = nullptr;
|
||||
G4ITReactionPerTime& reactionPerTime = fReactionSet->GetReactionsPerTime();
|
||||
auto reaction_i = reactionPerTime.begin();
|
||||
if (reaction_i != reactionPerTime.end()) {
|
||||
output = (reaction_i->get());
|
||||
}
|
||||
return output;
|
||||
}
|
||||
@@ -37,6 +37,8 @@
|
||||
#include "G4DNAIndependentReactionTimeStepper.hh"
|
||||
#include "G4Scheduler.hh"
|
||||
#include "G4UnitsTable.hh"
|
||||
#include "G4DNAScavengerMaterial.hh"
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
G4DNAMakeReaction::G4DNAMakeReaction()
|
||||
:
|
||||
@@ -45,6 +47,8 @@ G4DNAMakeReaction::G4DNAMakeReaction()
|
||||
, fpTimeStepper(nullptr)
|
||||
, fTimeStep(0)
|
||||
{
|
||||
fpScavengerMaterial = dynamic_cast<G4DNAScavengerMaterial*>(
|
||||
G4Scheduler::Instance()->GetScavengerMaterial());
|
||||
}
|
||||
|
||||
G4DNAMakeReaction::G4DNAMakeReaction(G4VDNAReactionModel* pReactionModel)
|
||||
@@ -83,6 +87,10 @@ G4DNAMakeReaction::MakeReaction(const G4Track &trackA,
|
||||
|
||||
const auto pReactionData = fMolReactionTable->GetReactionData(pMoleculeA, pMoleculeB);
|
||||
const G4int nbProducts = pReactionData->GetNbProducts();
|
||||
// Notify molecule (reaction) counter
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive()) {
|
||||
G4MoleculeCounterManager::Instance()->RecordReaction(pReactionData, trackA.GetGlobalTime());
|
||||
}
|
||||
if (nbProducts != 0)
|
||||
{
|
||||
const G4double D1 = pMoleculeA->GetDiffusionCoefficient();
|
||||
@@ -98,7 +106,18 @@ G4DNAMakeReaction::MakeReaction(const G4Track &trackA,
|
||||
|
||||
for (G4int j = 0; j < nbProducts; ++j)
|
||||
{
|
||||
auto pProduct = new G4Molecule(pReactionData->GetProduct(j));
|
||||
auto product = pReactionData->GetProduct(j);
|
||||
|
||||
if(fpScavengerMaterial != nullptr) {
|
||||
auto isScavenger = fpScavengerMaterial->find(product);
|
||||
if (isScavenger) {
|
||||
fpScavengerMaterial->AddNumberMoleculePerVolumeUnitForMaterialConf(
|
||||
product, trackA.GetGlobalTime());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
auto pProduct = new G4Molecule(product);
|
||||
auto pProductTrack = pProduct->BuildTrack(trackA.GetGlobalTime(), (reactionSite + randP)/2);
|
||||
pProductTrack->SetTrackStatus(fAlive);
|
||||
G4ITTrackHolder::Instance()->Push(pProductTrack);
|
||||
@@ -181,27 +200,30 @@ void G4DNAMakeReaction::UpdatePositionForReaction(G4Track& trackA,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::unique_ptr<G4ITReactionChange>>
|
||||
G4DNAMakeReaction::FindReaction(G4ITReactionSet* pReactionSet,
|
||||
const G4double currentStepTime,
|
||||
const G4double /*globalTime*/,
|
||||
const G4double globalTime,
|
||||
const G4bool /*reachedUserStepTimeLimit*/)
|
||||
{
|
||||
std::vector<std::unique_ptr<G4ITReactionChange>> ReactionInfo;
|
||||
ReactionInfo.clear();
|
||||
auto stepper = dynamic_cast<G4DNAIndependentReactionTimeStepper*>(fpTimeStepper);
|
||||
if(stepper == nullptr){
|
||||
return ReactionInfo;
|
||||
}else
|
||||
{
|
||||
do{
|
||||
auto pReactionChange = stepper->
|
||||
FindReaction(pReactionSet,currentStepTime);
|
||||
if (pReactionChange != nullptr)
|
||||
{
|
||||
ReactionInfo.push_back(std::move(pReactionChange));
|
||||
}
|
||||
}while (!pReactionSet->GetReactionsPerTime().empty());
|
||||
}
|
||||
std::vector<std::unique_ptr<G4ITReactionChange>> ReactionInfo;
|
||||
auto stepper = dynamic_cast<G4DNAIndependentReactionTimeStepper*>(fpTimeStepper);
|
||||
if (stepper == nullptr) {
|
||||
return ReactionInfo;
|
||||
}else {
|
||||
G4double StepTime = 0;
|
||||
do {
|
||||
auto pReactionChange = stepper->FindReaction(pReactionSet, StepTime, globalTime);
|
||||
if (pReactionChange != nullptr) {
|
||||
// G4cout<<" time : "<<globalTime<<" "<<pReactionChange->GetTrackA()->GetTrackID()
|
||||
// <<" + "<<pReactionChange->GetTrackB()->GetTrackID()<<G4endl;
|
||||
ReactionInfo.push_back(std::move(pReactionChange));
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
}while(StepTime == currentStepTime);
|
||||
}
|
||||
return ReactionInfo;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "G4ITReaction.hh"
|
||||
|
||||
#include "G4ITTrackHolder.hh"
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
G4DNAMolecularReaction::G4DNAMolecularReaction()
|
||||
:
|
||||
@@ -91,7 +92,10 @@ std::unique_ptr<G4ITReactionChange> G4DNAMolecularReaction::MakeReaction(const G
|
||||
const auto pMoleculeB = GetMolecule(trackB)->GetMolecularConfiguration();
|
||||
|
||||
const auto pReactionData = fMolReactionTable->GetReactionData(pMoleculeA, pMoleculeB);
|
||||
|
||||
// Notify molecule (reaction) counter
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive()) {
|
||||
G4MoleculeCounterManager::Instance()->RecordReaction(pReactionData, trackA.GetGlobalTime());
|
||||
}
|
||||
const G4int nbProducts = pReactionData->GetNbProducts();
|
||||
|
||||
if (nbProducts != 0)
|
||||
|
||||
@@ -0,0 +1,556 @@
|
||||
//
|
||||
// ********************************************************************
|
||||
// * 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. *
|
||||
// ********************************************************************
|
||||
//
|
||||
// Created 11.02.2025 V.Ivanchenko & M. Vologzhin
|
||||
// on base of previous Rudd models
|
||||
//
|
||||
// Russian Goverment grant No 075-15-2024-667 23.08.2024
|
||||
//
|
||||
|
||||
#include "G4DNARuddIonisationDynamicModel.hh"
|
||||
#include "G4PhysicalConstants.hh"
|
||||
#include "G4SystemOfUnits.hh"
|
||||
#include "G4VAtomDeexcitation.hh"
|
||||
#include "G4UAtomicDeexcitation.hh"
|
||||
#include "G4LossTableManager.hh"
|
||||
#include "G4NistManager.hh"
|
||||
#include "G4DNAChemistryManager.hh"
|
||||
#include "G4DNAMolecularMaterial.hh"
|
||||
#include "G4LogLogInterpolation.hh"
|
||||
#include "G4ProductionCutsTable.hh"
|
||||
|
||||
#include "G4DNAGenericIonsManager.hh"
|
||||
#include "G4DNACrossSectionDataSet.hh"
|
||||
#include "G4NistManager.hh"
|
||||
|
||||
#include "G4IonTable.hh"
|
||||
#include "G4DNARuddAngle.hh"
|
||||
#include "G4DeltaAngle.hh"
|
||||
#include "G4Exp.hh"
|
||||
#include "G4Log.hh"
|
||||
#include "G4Pow.hh"
|
||||
#include "G4Alpha.hh"
|
||||
#include "G4Proton.hh"
|
||||
#include "G4Electron.hh"
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNACrossSectionDataSet* G4DNARuddIonisationDynamicModel::xsdata_hydrogen = nullptr;
|
||||
G4DNACrossSectionDataSet* G4DNARuddIonisationDynamicModel::xsdata_helium = nullptr;
|
||||
G4DNACrossSectionDataSet* G4DNARuddIonisationDynamicModel::xsdata_p = nullptr;
|
||||
const std::vector<G4double>* G4DNARuddIonisationDynamicModel::fpWaterDensity = nullptr;
|
||||
|
||||
namespace
|
||||
{
|
||||
const G4double scaleFactor = CLHEP::m*CLHEP::m;
|
||||
const G4double tolerance = 1*CLHEP::eV;
|
||||
const G4double Ry = 13.6*CLHEP::eV;
|
||||
|
||||
// Following values provided by M. Dingfelder (priv. comm)
|
||||
const G4double Bj[5] = {12.60*CLHEP::eV, 14.70*CLHEP::eV, 18.40*CLHEP::eV,
|
||||
32.20*CLHEP::eV, 539*CLHEP::eV};
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNARuddIonisationDynamicModel::G4DNARuddIonisationDynamicModel(const G4ParticleDefinition*,
|
||||
const G4String& nam)
|
||||
: G4VEmModel(nam)
|
||||
{
|
||||
fGpow = G4Pow::GetInstance();
|
||||
fLowestEnergy = 100*CLHEP::eV;
|
||||
fAbsorptionEnergy = 50*CLHEP::eV;
|
||||
|
||||
// Mark this model as "applicable" for atomic deexcitation
|
||||
SetDeexcitationFlag(true);
|
||||
|
||||
// Define default angular generator
|
||||
SetAngularDistribution(new G4DNARuddAngle());
|
||||
|
||||
if (nullptr == xsdata_p) {
|
||||
isFirst = true;
|
||||
LoadData();
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4DNARuddIonisationDynamicModel::~G4DNARuddIonisationDynamicModel()
|
||||
{
|
||||
if (isFirst) {
|
||||
delete xsdata_p;
|
||||
delete xsdata_hydrogen;
|
||||
delete xsdata_helium;
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNARuddIonisationDynamicModel::LoadData()
|
||||
{
|
||||
// initialisation of static data once
|
||||
G4String filename = "dna/sigma_ionisation_p_rudd";
|
||||
xsdata_p = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_p->LoadData(filename);
|
||||
|
||||
filename = "dna/sigma_ionisation_h_rudd";
|
||||
xsdata_hydrogen = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_hydrogen->LoadData(filename);
|
||||
|
||||
filename = "dna/sigma_ionisation_he_rudd";
|
||||
xsdata_helium = new G4DNACrossSectionDataSet(new G4LogLogInterpolation, CLHEP::eV, scaleFactor);
|
||||
xsdata_helium->LoadData(filename);
|
||||
|
||||
// to avoid possible threading problem fill this vector only once
|
||||
auto water = G4NistManager::Instance()->FindMaterial("G4_WATER");
|
||||
fpWaterDensity =
|
||||
G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(water);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNARuddIonisationDynamicModel::Initialise(const G4ParticleDefinition* p,
|
||||
const G4DataVector&)
|
||||
{
|
||||
if (p != fParticle) { SetParticle(p); }
|
||||
|
||||
// particle change object may be externally set
|
||||
if (nullptr == fParticleChangeForGamma) {
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
}
|
||||
const G4String& pname = p->GetParticleName();
|
||||
|
||||
// the same definition of generic ion as in G4VEmProcess class
|
||||
if (p->GetParticleType() == "nucleus" && p->GetParticleSubType() == "generic") {
|
||||
if (pname != "deuteron" && pname != "triton" &&
|
||||
pname != "He3" && pname != "alpha" && pname != "alpha+" &&
|
||||
pname != "helium" && pname != "hydrogen") {
|
||||
isIon = true;
|
||||
}
|
||||
}
|
||||
|
||||
// initialisation once in each thread
|
||||
if (!isInitialised) {
|
||||
isInitialised = true;
|
||||
xsdata = xsdata_p;
|
||||
|
||||
if (pname == "helium") {
|
||||
isHelium = true;
|
||||
xsdata = xsdata_helium;
|
||||
slaterEffectiveCharge[0]=1.7;
|
||||
slaterEffectiveCharge[1]=1.15;
|
||||
slaterEffectiveCharge[2]=1.15;
|
||||
sCoefficient[0]=0.5;
|
||||
sCoefficient[1]=0.25;
|
||||
sCoefficient[2]=0.25;
|
||||
fLowestEnergy = 1*CLHEP::keV;
|
||||
} else if (pname == "alpha+") {
|
||||
isHelium = true;
|
||||
// The following values are provided by M. Dingfelder (priv. comm)
|
||||
slaterEffectiveCharge[0]=2.0;
|
||||
slaterEffectiveCharge[1]=2.0;
|
||||
slaterEffectiveCharge[2]=2.0;
|
||||
sCoefficient[0]=0.7;
|
||||
sCoefficient[1]=0.15;
|
||||
sCoefficient[2]=0.15;
|
||||
} else if (pname == "hydrogen") {
|
||||
xsdata = xsdata_hydrogen;
|
||||
}
|
||||
|
||||
// defined stationary mode
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
// initialise atomic de-excitation
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
// chemistry
|
||||
auto chem = G4DNAChemistryManager::Instance();
|
||||
if (chem->IsChemistryActivated()) {
|
||||
fChemistry = chem;
|
||||
}
|
||||
|
||||
InitialiseIntegrator(0.1, 0.25, 1.05, 1*CLHEP::eV, 0.2*CLHEP::eV, 10*CLHEP::keV);
|
||||
|
||||
if (verbose > 0) {
|
||||
G4cout << "### G4DNARuddIonisationDynamicModel::Initialise(..) "
|
||||
<< fParticle->GetParticleName() << G4endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNARuddIonisationDynamicModel::SetParticle(const G4ParticleDefinition* p)
|
||||
{
|
||||
fParticle = p;
|
||||
fMass = p->GetPDGMass();
|
||||
fMassRate = CLHEP::proton_mass_c2/fMass;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void G4DNARuddIonisationDynamicModel::StartTracking(G4Track* track)
|
||||
{
|
||||
fTrack = track;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
G4double
|
||||
G4DNARuddIonisationDynamicModel::CrossSectionPerVolume(const G4Material* material,
|
||||
const G4ParticleDefinition* part,
|
||||
G4double kinE,
|
||||
G4double, G4double)
|
||||
{
|
||||
// check if model is applicable for given material
|
||||
G4double density = (material->GetIndex() < fpWaterDensity->size())
|
||||
? (*fpWaterDensity)[material->GetIndex()] : 0.0;
|
||||
if (0.0 == density) { return 0.0; }
|
||||
|
||||
// check on kinetic energy (not scaled energy) to stop low-energy ion
|
||||
if (kinE < fAbsorptionEnergy) { return DBL_MAX; }
|
||||
|
||||
// ion may be different
|
||||
if (fParticle != part) { SetParticle(part); }
|
||||
G4double q = fTrack->GetDynamicParticle()->GetCharge()*inveplus;
|
||||
|
||||
// cross section for scaled energy
|
||||
G4double e = kinE*fMassRate;
|
||||
|
||||
auto xs = xsdata;
|
||||
if (0.0 == q) { xs = isHelium ? xsdata_helium : xsdata_hydrogen; }
|
||||
|
||||
G4double sigma = (e > fLowestEnergy) ? xs->FindValue(e)
|
||||
: xs->FindValue(fLowestEnergy) * e / fLowestEnergy;
|
||||
|
||||
sigma *= density;
|
||||
if (q > 1.5) { sigma *= q * q; }
|
||||
|
||||
if (verbose > 1) {
|
||||
G4cout << "G4DNARuddIonisationDynamicModel for " << part->GetParticleName()
|
||||
<< " Ekin(keV)=" << kinE/CLHEP::keV
|
||||
<< " sigma(cm^2)=" << sigma/CLHEP::cm2 << G4endl;
|
||||
}
|
||||
return sigma;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
void
|
||||
G4DNARuddIonisationDynamicModel::SampleSecondaries(std::vector<G4DynamicParticle*>* fvect,
|
||||
const G4MaterialCutsCouple* couple,
|
||||
const G4DynamicParticle* dpart,
|
||||
G4double, G4double)
|
||||
{
|
||||
const G4ParticleDefinition* pd = dpart->GetDefinition();
|
||||
if (fParticle != pd) { SetParticle(pd); }
|
||||
|
||||
// stop ion with energy below low energy limit
|
||||
G4double kinE = dpart->GetKineticEnergy();
|
||||
// ion shoud be stopped - check on kinetic energy and not scaled energy
|
||||
if (kinE <= fAbsorptionEnergy) {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(0.);
|
||||
fParticleChangeForGamma->ProposeTrackStatus(fStopButAlive);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(kinE);
|
||||
return;
|
||||
}
|
||||
|
||||
fScaledEnergy = kinE*fMassRate;
|
||||
fSelectedShell = SelectShell();
|
||||
G4double bindingEnergy = (useDNAWaterStructure)
|
||||
? waterStructure.IonisationEnergy(fSelectedShell) : Bj[fSelectedShell];
|
||||
|
||||
//Si: additional protection if tcs interpolation method is modified
|
||||
if (kinE < bindingEnergy) { return; }
|
||||
|
||||
G4double esec = SampleElectronEnergy();
|
||||
G4double esum = 0.0;
|
||||
|
||||
// sample deexcitation
|
||||
// here we assume that H2O electronic levels are the same as Oxygen.
|
||||
// this can be considered true with a rough 10% error in energy on K-shell,
|
||||
G4int Z = 8;
|
||||
G4ThreeVector deltaDir =
|
||||
GetAngularDistribution()->SampleDirectionForShell(dpart, esec, Z,
|
||||
fSelectedShell,
|
||||
couple->GetMaterial());
|
||||
|
||||
// SI: only atomic deexcitation from K shell is considered
|
||||
if (fAtomDeexcitation != nullptr && fSelectedShell == 4) {
|
||||
auto as = G4AtomicShellEnumerator(0);
|
||||
auto ashell = fAtomDeexcitation->GetAtomicShell(Z, as);
|
||||
fAtomDeexcitation->GenerateParticles(fvect, ashell, Z, 0, 0);
|
||||
|
||||
// compute energy sum from de-excitation
|
||||
for (auto const & ptr : *fvect) {
|
||||
esum += ptr->GetKineticEnergy();
|
||||
}
|
||||
}
|
||||
// check energy balance
|
||||
// remaining excitation energy of water molecule
|
||||
G4double exc = std::max(bindingEnergy - esum, 0.0);
|
||||
|
||||
// remaining projectile energy
|
||||
G4double scatteredEnergy = kinE - bindingEnergy - esec;
|
||||
if(scatteredEnergy < -tolerance || exc < -tolerance) {
|
||||
G4cout << "G4DNARuddIonisationDynamicModel::SampleSecondaries: "
|
||||
<< "negative final E(keV)=" << scatteredEnergy/CLHEP::keV << " Ein(keV)="
|
||||
<< kinE/CLHEP::keV << " " << pd->GetParticleName()
|
||||
<< " Edelta(keV)=" << esec/CLHEP::keV << " MeV, Exc(keV)=" << exc/CLHEP::keV
|
||||
<< G4endl;
|
||||
}
|
||||
scatteredEnergy = std::max(scatteredEnergy, 0.0);
|
||||
|
||||
// projectile
|
||||
if (!statCode) {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(exc);
|
||||
} else {
|
||||
fParticleChangeForGamma->SetProposedKineticEnergy(kinE);
|
||||
fParticleChangeForGamma->ProposeLocalEnergyDeposit(kinE - scatteredEnergy);
|
||||
}
|
||||
|
||||
// delta-electron
|
||||
auto dp = new G4DynamicParticle(G4Electron::Electron(), deltaDir, esec);
|
||||
fvect->push_back(dp);
|
||||
|
||||
// create radical
|
||||
if (nullptr != fChemistry) {
|
||||
fChemistry->CreateWaterMolecule(eIonizedMolecule, fSelectedShell, fTrack);
|
||||
}
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4int G4DNARuddIonisationDynamicModel::SelectShell()
|
||||
{
|
||||
G4double sum = 0.0;
|
||||
G4double xs;
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
auto ptr = xsdata->GetComponent(i);
|
||||
xs = (fScaledEnergy > fLowestEnergy) ? ptr->FindValue(fScaledEnergy)
|
||||
: ptr->FindValue(fLowestEnergy)*fScaledEnergy/fLowestEnergy;
|
||||
sum += xs;
|
||||
fTemp[i] = sum;
|
||||
}
|
||||
sum *= G4UniformRand();
|
||||
for (G4int i=0; i<5; ++i) {
|
||||
if (sum <= fTemp[i]) { return i; }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double
|
||||
G4DNARuddIonisationDynamicModel::MaxEnergy()
|
||||
{
|
||||
// kinematic limit
|
||||
G4double tau = fScaledEnergy/CLHEP::proton_mass_c2;
|
||||
G4double gam = 1.0 + tau;
|
||||
G4double emax = 2.0*CLHEP::electron_mass_c2*tau*(tau + 2.0);
|
||||
|
||||
// Initialisation of sampling
|
||||
G4double A1, B1, C1, D1, E1, A2, B2, C2, D2;
|
||||
if (fSelectedShell == 4) {
|
||||
//Data For Liquid Water K SHELL from Dingfelder (Protons in Water)
|
||||
A1 = 1.25;
|
||||
B1 = 0.5;
|
||||
C1 = 1.00;
|
||||
D1 = 1.00;
|
||||
E1 = 3.00;
|
||||
A2 = 1.10;
|
||||
B2 = 1.30;
|
||||
C2 = 1.00;
|
||||
D2 = 0.00;
|
||||
alphaConst = 0.66;
|
||||
} else {
|
||||
//Data For Liquid Water from Dingfelder (Protons in Water)
|
||||
A1 = 1.02;
|
||||
B1 = 82.0;
|
||||
C1 = 0.45;
|
||||
D1 = -0.80;
|
||||
E1 = 0.38;
|
||||
A2 = 1.07;
|
||||
// Value provided by M. Dingfelder (priv. comm)
|
||||
B2 = 11.6;
|
||||
C2 = 0.60;
|
||||
D2 = 0.04;
|
||||
alphaConst = 0.64;
|
||||
}
|
||||
bEnergy = Bj[fSelectedShell];
|
||||
G4double v2 = 0.25*emax/(bEnergy*gam*gam);
|
||||
v = std::sqrt(v2);
|
||||
u = Ry/bEnergy;
|
||||
wc = 4.*v2 - 2.*v - 0.25*u;
|
||||
|
||||
G4double L1 = (C1 * fGpow->powA(v, D1)) / (1. + E1 * fGpow->powA(v, (D1 + 4.)));
|
||||
G4double L2 = C2 * fGpow->powA(v, D2);
|
||||
G4double H1 = (A1 * G4Log(1. + v2)) / (v2 + (B1 / v2));
|
||||
G4double H2 = (A2 / v2) + (B2 / (v2 * v2));
|
||||
|
||||
F1 = L1 + H1;
|
||||
F2 = (L2 * H2) / (L2 + H2);
|
||||
return emax;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double
|
||||
G4DNARuddIonisationDynamicModel::SampleElectronEnergy()
|
||||
{
|
||||
// sampling is performed for proton projectile
|
||||
G4double emax = MaxEnergy();
|
||||
|
||||
ComputeIntegral(0.0, emax);
|
||||
G4double e = SampleValue();
|
||||
if (verbose > 1) {
|
||||
G4cout << "G4DNARuddIonisationDynamicModel::SampleElectronEnergy: "
|
||||
<< fParticle->GetParticleName()
|
||||
<< " Escaled(keV)=" << fScaledEnergy/CLHEP::keV << " Ee(keV)=" << e/CLHEP::keV
|
||||
<< G4endl;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::ProbabilityDensityFunction(G4double e)
|
||||
{
|
||||
// Shells ids are 0 1 2 3 4 (4 is k shell)
|
||||
// !!Attention, "energyTransfer" here is the energy transfered to the electron which means
|
||||
// that the secondary kinetic energy is w = energyTransfer - bindingEnergy
|
||||
//
|
||||
// ds S F1(nu) + w * F2(nu)
|
||||
// ---- = G(k) * ---- -------------------------------------------
|
||||
// dw Bj (1+w)^3 * [1 + exp{alpha * (w - wc) / nu}]
|
||||
//
|
||||
// w is the secondary electron kinetic Energy in eV
|
||||
//
|
||||
// All the other parameters can be found in Rudd's Papers
|
||||
//
|
||||
// M.Eugene Rudd, 1988, User-Friendly model for the energy distribution of
|
||||
// electrons from protons or electron collisions. Nucl. Tracks Rad. Meas.Vol 16 N0 2/3 pp 219-218
|
||||
//
|
||||
G4double w = e/bEnergy;
|
||||
G4double x = alphaConst*(w - wc)/v;
|
||||
G4double y = (x > -15.) ? 1.0 + G4Exp(x) : 1.0;
|
||||
|
||||
G4double res = CorrectionFactor() * (F1 + w*F2) /
|
||||
(fGpow->powN((1. + w)/u, 3) * y);
|
||||
|
||||
if (isHelium) {
|
||||
G4double energyTransfer = e + bEnergy;
|
||||
G4double Zeff = 2.0 -
|
||||
(sCoefficient[0] * S_1s(fScaledEnergy, energyTransfer, slaterEffectiveCharge[0], 1.) +
|
||||
sCoefficient[1] * S_2s(fScaledEnergy, energyTransfer, slaterEffectiveCharge[1], 2.) +
|
||||
sCoefficient[2] * S_2p(fScaledEnergy, energyTransfer, slaterEffectiveCharge[2], 2.) );
|
||||
|
||||
res *= Zeff * Zeff;
|
||||
}
|
||||
return std::max(res, 0.0);
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::S_1s(G4double kine,
|
||||
G4double energyTransfer,
|
||||
G4double slaterEffCharge,
|
||||
G4double shellNumber)
|
||||
{
|
||||
// 1 - e^(-2r) * ( 1 + 2 r + 2 r^2)
|
||||
// Dingfelder, in Chattanooga 2005 proceedings, formula (7)
|
||||
|
||||
G4double r = Rh(kine, energyTransfer, slaterEffCharge, shellNumber);
|
||||
G4double value = 1. - G4Exp(-2 * r) * ( ( 2. * r + 2. ) * r + 1. );
|
||||
return value;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::S_2s(G4double kine,
|
||||
G4double energyTransfer,
|
||||
G4double slaterEffCharge,
|
||||
G4double shellNumber)
|
||||
{
|
||||
// 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 2 r^4)
|
||||
// Dingfelder, in Chattanooga 2005 proceedings, formula (8)
|
||||
|
||||
G4double r = Rh(kine, energyTransfer, slaterEffCharge, shellNumber);
|
||||
G4double value =
|
||||
1. - G4Exp(-2 * r) * (((2. * r * r + 2.) * r + 2.) * r + 1.);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::S_2p(G4double kine,
|
||||
G4double energyTransfer,
|
||||
G4double slaterEffCharge,
|
||||
G4double shellNumber)
|
||||
{
|
||||
// 1 - e^(-2 r) * ( 1 + 2 r + 2 r^2 + 4/3 r^3 + 2/3 r^4)
|
||||
// Dingfelder, in Chattanooga 2005 proceedings, formula (9)
|
||||
|
||||
G4double r = Rh(kine, energyTransfer, slaterEffCharge, shellNumber);
|
||||
G4double value =
|
||||
1. - G4Exp(-2 * r) * (((( 2./3. * r + 4./3.) * r + 2.) * r + 2.) * r + 1.);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::Rh(G4double ekin, G4double etrans,
|
||||
G4double q, G4double shell)
|
||||
{
|
||||
// The following values are provided by M. Dingfelder (priv. comm)
|
||||
// Dingfelder, in Chattanooga 2005 proceedings, p 4
|
||||
|
||||
G4double escaled = CLHEP::electron_mass_c2/fMass * ekin;
|
||||
const G4double H = 13.60569172 * CLHEP::eV;
|
||||
G4double value = 2.0*std::sqrt(escaled / H)*q*H /(etrans*shell);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
|
||||
G4double G4DNARuddIonisationDynamicModel::CorrectionFactor()
|
||||
{
|
||||
// ZF Shortened
|
||||
G4double res = 1.0;
|
||||
if (fSelectedShell < 4) {
|
||||
const G4double ln10 = fGpow->logZ(10);
|
||||
G4double x = 2.0*((G4Log(fScaledEnergy/CLHEP::eV)/ln10) - 4.2);
|
||||
// The following values are provided by M. Dingfelder (priv. comm)
|
||||
res = 0.6/(1.0 + G4Exp(x)) + 0.9;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
|
||||
@@ -91,7 +91,7 @@ G4DNARuddIonisationExtendedModel::G4DNARuddIonisationExtendedModel(const G4Parti
|
||||
|
||||
G4DNARuddIonisationExtendedModel::~G4DNARuddIonisationExtendedModel()
|
||||
{
|
||||
if(isFirst) {
|
||||
if (isFirst) {
|
||||
for(auto & i : xsdata) { delete i; }
|
||||
}
|
||||
}
|
||||
@@ -222,7 +222,8 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* p,
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
// initialise atomic de-excitation
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
if (verbose > 0) {
|
||||
G4cout << "### G4DNARuddIonisationExtendedModel::Initialise(..) " << pname
|
||||
@@ -330,17 +331,18 @@ G4DNARuddIonisationExtendedModel::SampleSecondaries(std::vector<G4DynamicParticl
|
||||
}
|
||||
// check energy balance
|
||||
// remaining excitation energy of water molecule
|
||||
G4double exc = bindingEnergy - esum;
|
||||
G4double exc = std::max(bindingEnergy - esum, 0.0);
|
||||
|
||||
// remaining projectile energy
|
||||
G4double scatteredEnergy = kinE - bindingEnergy - esec;
|
||||
if(scatteredEnergy < -tolerance || exc < -tolerance) {
|
||||
if (scatteredEnergy < -tolerance || exc < -tolerance) {
|
||||
G4cout << "G4DNARuddIonisationExtendedModel::SampleSecondaries: "
|
||||
<< "negative final E(keV)=" << scatteredEnergy/CLHEP::keV << " Ein(keV)="
|
||||
<< kinE/CLHEP::keV << " " << pd->GetParticleName()
|
||||
<< " Edelta(keV)=" << esec/CLHEP::keV << " MeV, Exc(keV)=" << exc/CLHEP::keV
|
||||
<< G4endl;
|
||||
}
|
||||
scatteredEnergy = std::max(scatteredEnergy, 0.0);
|
||||
|
||||
// projectile
|
||||
if (!statCode) {
|
||||
|
||||
@@ -258,7 +258,22 @@ void G4DNARuddIonisationModel::Initialise(const G4ParticleDefinition* particle,
|
||||
SetHighEnergyLimit(highEnergyLimit[alphaPlusPlus]);
|
||||
}
|
||||
|
||||
if( verboseLevel>0 )
|
||||
if (isInitialised) { return; }
|
||||
|
||||
// defined stationary mode
|
||||
statCode = G4EmParameters::Instance()->DNAStationary();
|
||||
|
||||
// Initialize water density pointer
|
||||
fpWaterDensity = G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
|
||||
|
||||
// atomic de-excitation
|
||||
if (!statCode)
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
isInitialised = true;
|
||||
|
||||
if (verboseLevel > 0)
|
||||
{
|
||||
G4cout << "Rudd ionisation model is initialized " << G4endl
|
||||
<< "Energy range: "
|
||||
@@ -267,19 +282,6 @@ void G4DNARuddIonisationModel::Initialise(const G4ParticleDefinition* particle,
|
||||
<< particle->GetParticleName()
|
||||
<< G4endl;
|
||||
}
|
||||
|
||||
// Initialize water density pointer
|
||||
fpWaterDensity = G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(G4Material::GetMaterial("G4_WATER"));
|
||||
|
||||
//
|
||||
|
||||
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
|
||||
|
||||
if (isInitialised)
|
||||
{ return;}
|
||||
fParticleChangeForGamma = GetParticleChangeForGamma();
|
||||
isInitialised = true;
|
||||
|
||||
}
|
||||
|
||||
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "G4DNAScavengerMaterial.hh"
|
||||
#include "G4Scheduler.hh"
|
||||
|
||||
#include "G4MoleculeCounterManager.hh"
|
||||
|
||||
G4DNAUpdateSystemModel::G4DNAUpdateSystemModel() = default;
|
||||
|
||||
void G4DNAUpdateSystemModel::SetMesh(G4DNAMesh* pMesh) { fpMesh = pMesh; }
|
||||
@@ -53,9 +55,9 @@ void G4DNAUpdateSystemModel::KillMolecule(const Index& index, MolType type)
|
||||
FatalErrorInArgument, exceptionDescription);
|
||||
}
|
||||
iter->second--;
|
||||
if(G4VMoleculeCounter::Instance()->InUse())
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive())
|
||||
{
|
||||
G4VMoleculeCounter::Instance()->RemoveAMoleculeAtTime(type, fGlobalTime);
|
||||
G4MoleculeCounterManager::Instance()->RemoveMoleculeWithoutTrack(type, fGlobalTime);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -131,9 +133,9 @@ void G4DNAUpdateSystemModel::CreateMolecule(const Index& index, MolType type)
|
||||
node[type] = 1;
|
||||
}
|
||||
|
||||
if(G4VMoleculeCounter::Instance()->InUse())
|
||||
if (G4MoleculeCounterManager::Instance()->GetIsActive())
|
||||
{
|
||||
G4VMoleculeCounter::Instance()->AddAMoleculeAtTime(type, fGlobalTime);
|
||||
G4MoleculeCounterManager::Instance()->AddMoleculeWithoutTrack(type, fGlobalTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user