Import Geant4 11.1.0.beta source tree

This commit is contained in:
Gabriele Cosmo
2022-07-01 10:44:02 +02:00
parent b3bf75a2a1
commit c07cea1fe0
2172 changed files with 183300 additions and 123938 deletions
@@ -114,6 +114,13 @@ private:
G4DNADingfelderChargeDecreaseModel & operator=(const G4DNADingfelderChargeDecreaseModel &right);
G4DNADingfelderChargeDecreaseModel(const G4DNADingfelderChargeDecreaseModel&);
// Reusable particle definitions
G4ParticleDefinition* protonDef;
G4ParticleDefinition* alphaPlusPlusDef;
G4ParticleDefinition* alphaPlusDef;
G4ParticleDefinition* hydrogenDef;
G4ParticleDefinition* heliumDef;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -115,6 +115,12 @@ private:
G4DNADingfelderChargeIncreaseModel & operator=(const G4DNADingfelderChargeIncreaseModel &right);
G4DNADingfelderChargeIncreaseModel(const G4DNADingfelderChargeIncreaseModel&);
// Reusable particle definitions
G4ParticleDefinition* hydrogenDef;
G4ParticleDefinition* alphaPlusPlusDef;
G4ParticleDefinition* alphaPlusDef;
G4ParticleDefinition* heliumDef;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -39,6 +39,8 @@
#include "G4ITReaction.hh"
#include "G4DNAEventSet.hh"
#include "G4DNAUpdateSystemModel.hh"
#include "G4H2O2.hh"
#include <CLHEP/Units/SystemOfUnits.h>
class G4VITStepModel;
class G4DNAGillespieDirectMethod;
class G4UserMeshAction;
@@ -66,8 +68,8 @@ class G4DNAEventScheduler : public IEventScheduler
void SetEndTime(const G4double&);
G4double GetStartTime() const;
G4double GetEndTime() const;
[[maybe_unused]] G4double GetTimeStep() const;
[[maybe_unused]] void SetStartTime(G4double time);
G4double GetTimeStep() const;
void SetStartTime(G4double time);
inline void SetVerbose(G4int verbose) { fVerbose = verbose; }
inline G4int GetVerbose() const;
@@ -79,13 +81,13 @@ class G4DNAEventScheduler : public IEventScheduler
void RunInMesh();
void Run();
[[maybe_unused]] void AddTimeToRecord(const G4double& time);
void AddTimeToRecord(const G4double& time);
void RecordTime();
void ClearAndReChargeCounter();
void PrintRecordTime();
void Stop();
[[maybe_unused]] void SetMaxNbSteps(G4int);
void SetMaxNbSteps(G4int);
std::map<G4double /*time*/, MapCounter> GetCounterMap() const;
G4DNAMesh* GetMesh() const;
G4int GetPixels() const;
@@ -93,22 +95,25 @@ class G4DNAEventScheduler : public IEventScheduler
static G4bool CheckingReactionRadius(G4double resolution);
private:
G4int fVerbose;
G4bool fInitialized;
G4double fStartTime;
G4double fEndTime;
G4int fStepNumber;
G4int fMaxStep;
G4bool fRunning;
G4double fTimeStep;
G4double fGlobalTime;
G4double fJumpingNumber;
G4double fReactionNumber;
G4int fVerbose = 0;
G4bool fInitialized = false;
G4double fStartTime = 1 * CLHEP::picosecond;
G4double fEndTime = 10000 * CLHEP::second;
G4int fStepNumber = 0;
G4int fMaxStep = INT_MAX;
G4bool fRunning = true;
G4double fTimeStep = DBL_MAX;
G4double fGlobalTime = 1 * CLHEP::picosecond;
G4double fJumpingNumber = 0;
G4double fReactionNumber = 0;
G4int fPixel;
G4bool fIsChangeMesh;
G4bool fSetChangeMesh;
G4int fStepNumberInMesh;
G4bool fIsChangeMesh = false;
G4bool fSetChangeMesh = true;
G4int fStepNumberInMesh = 0;
G4double fInitialPixels;
G4double fTransferTime = 0.;
const G4double C = 20;
const G4double D = G4H2O2::Definition()->GetDiffusionCoefficient(); // this is the biggest D
std::unique_ptr<G4DNAMesh> fpMesh;
std::unique_ptr<G4DNAGillespieDirectMethod> fpGillespieReaction;
@@ -116,7 +121,6 @@ class G4DNAEventScheduler : public IEventScheduler
std::unique_ptr<G4DNAUpdateSystemModel> fpUpdateSystem;
std::unique_ptr<G4UserMeshAction> fpUserMeshAction;
// an aternative Counter
std::map<G4double /*time*/, MapCounter> fCounterMap;
std::set<G4double> fTimeToRecord;
std::set<G4double>::iterator fLastRecoredTime;
@@ -34,43 +34,42 @@
#include "G4MoleculeTable.hh"
#include "G4ITTrackHolder.hh"
#include "G4DNAEventSet.hh"
class G4DNAMolecularReactionTable;
class G4DNAMolecularReactionData;
class G4DNAScavengerMaterial;
class G4MolecularConfiguration;
class G4DNAGillespieDirectMethod
{
public:
G4DNAGillespieDirectMethod();
~G4DNAGillespieDirectMethod();
using MolType = const G4MolecularConfiguration*;
using Key = unsigned int;
using Index = G4Voxel::Index;
using Index = G4VDNAMesh::Index;
using Voxel = G4DNAMesh::Voxel;
using JumpingData = std::pair<MolType, Index>;
using ReactionData = const G4DNAMolecularReactionData;
using EventIt = G4DNAEventSet::EventSet::iterator;
G4double PropensityFunction(const Index& index, ReactionData* data);
G4double PropensityFunction(const Index& index, MolType moleType);
G4double PropensityFunction(const Voxel& voxel, ReactionData* data);
G4double PropensityFunction(const Voxel& voxel, MolType moleType);
inline void SetVoxelMesh(G4DNAMesh& mesh) { fpMesh = &mesh; }
void SetTimeStep(const G4double& stepTime);
G4double Reaction(const Index& index);
G4double DiffusiveJumping(const Index& index);
G4double ComputeNumberInNode(const Index& index, MolType type);
G4double VolumeOfNode(const Index& index);
void Initialize();
void CreateEvent(unsigned int key);
void CreateEvent(const Index& index);
void SetEventSet(G4DNAEventSet*);
private:
G4double Reaction(const Voxel& voxel);
G4double DiffusiveJumping(const Voxel& voxel);
G4double ComputeNumberInNode(const Voxel& voxel, MolType type);
G4double VolumeOfNode(const Voxel& voxel);
G4DNAMolecularReactionTable* fMolecularReactions;
G4DNAMesh* fpMesh;
G4DNAMesh* fpMesh = nullptr;
G4double fTimeStep;
G4DNAEventSet* fpEventSet;
G4double fVerbose;
G4DNAEventSet* fpEventSet = nullptr;
G4double fVerbose = 0;
std::map<G4double /*Propensity*/, ReactionData*> fReactionDataMap;
std::map<G4double /*Propensity*/, JumpingData> fJumpingDataMap;
G4bool FindScavenging(const Index& index, MolType, G4double&);
G4DNAScavengerMaterial* fpScavengerMaterial;
G4bool FindScavenging(const Voxel& voxel, MolType, G4double&);
G4DNAScavengerMaterial* fpScavengerMaterial = nullptr;
};
#endif
@@ -1,118 +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. *
// ********************************************************************
//
/*
* G4DNAIRT_geometries.hh
*
* Created on: Jul 23, 2019
* Author: W. G. Shin
* J. Ramos-Mendez and B. Faddegon
*/
#ifndef G4DNAIRT_geometries_HH_
#define G4DNAIRT_geometries_HH_
#include "globals.hh"
#include "G4ThreeVector.hh"
#include "G4DNAMolecularReaction.hh"
#include "G4DNAMolecularReactionTable.hh"
#include "G4MoleculeTable.hh"
#include "G4VDNAReactionModel.hh"
#include "G4VITReactionProcess.hh"
#include "G4ITReactionTable.hh"
#include "G4ITTrackHolder.hh"
#include "G4ITReaction.hh"
#include "G4Molecule.hh"
#include "G4VITReactionProcess.hh"
#include "G4ParticleChange.hh"
#include "G4VDNAMolecularGeometry.hh"
#include "AddClone_def.hh"
#include <vector>
#include <map>
class G4DNAMolecularReactionTable;
class G4VDNAReactionModel;
class G4ErrorFunction;
class G4DNAIRT_geometries : public G4VITReactionProcess
{
public:
G4DNAIRT_geometries();
explicit G4DNAIRT_geometries(G4VDNAReactionModel*);
~G4DNAIRT_geometries() override;
G4DNAIRT_geometries(const G4DNAIRT_geometries& other) = delete;
G4DNAIRT_geometries& operator=(const G4DNAIRT_geometries& other) = delete;
G4bool TestReactibility(const G4Track&,
const G4Track&,
G4double ,
G4bool ) override;
std::vector<std::unique_ptr<G4ITReactionChange>> FindReaction(G4ITReactionSet*, const G4double, const G4double, const G4bool) override;
std::unique_ptr<G4ITReactionChange> MakeReaction(const G4Track&, const G4Track&) override;
void SetReactionModel(G4VDNAReactionModel*);
void Initialize() override;
void SpaceBinning();
void IRTSampling();
void Sampling(G4Track*);
G4double GetIndependentReactionTime(const G4MolecularConfiguration*, const G4MolecularConfiguration*, G4double);
G4int FindBin(G4int, G4double, G4double, G4double);
G4double SamplePDC(G4double , G4double );
protected:
const G4DNAMolecularReactionTable*& fMolReactionTable;
G4VDNAReactionModel* fpReactionModel;
private:
G4ITTrackHolder* fTrackHolder;
G4ITReactionSet* fReactionSet;
G4ErrorFunction* erfc;
std::map<G4int,std::map<G4int,std::map<G4int,std::vector<G4Track*>>>> spaceBinned;
std::vector<std::pair<G4ThreeVector,G4Track*>> positionMap;
G4double fRCutOff;
G4double timeMin;
G4double timeMax;
G4double fXMin, fYMin, fZMin;
G4double fXMax, fYMax, fZMax;
G4int fNx, fNy, fNz;
G4int xiniIndex, yiniIndex, ziniIndex;
G4int xendIndex, yendIndex, zendIndex;
G4VDNAMolecularGeometry* fGeometry;
};
#endif /* G4DNAIRT_geometries_HH_ */
@@ -30,34 +30,29 @@
#define G4DNAIndependentReactionTimeModel_hh 1
#include "G4String.hh"
#include "G4VITStepModel.hh"
#include <G4ReferenceCast.hh>
class G4DNAMolecularReactionTable;
class G4VDNAReactionModel;
class G4VReactionTypeManager;
class G4DNAIndependentReactionTimeModel
: public G4VITStepModel
class G4DNAIndependentReactionTimeModel : public G4VITStepModel
{
public:
explicit G4DNAIndependentReactionTimeModel(const G4String& name = "DNAIndependentReactionTimeModel");
G4DNAIndependentReactionTimeModel(const G4String& name,
std::unique_ptr<G4VITTimeStepComputer> pTimeStepper,
std::unique_ptr<G4VITReactionProcess> pReactionProcess);
G4DNAIndependentReactionTimeModel(const G4DNAIndependentReactionTimeModel&) = delete;
~G4DNAIndependentReactionTimeModel() override;
public:
explicit G4DNAIndependentReactionTimeModel(
const G4String& name = "DNAIndependentReactionTimeModel");
G4DNAIndependentReactionTimeModel(
const G4String& name, std::unique_ptr<G4VITTimeStepComputer> pTimeStepper,
std::unique_ptr<G4VITReactionProcess> pReactionProcess);
G4DNAIndependentReactionTimeModel(const G4DNAIndependentReactionTimeModel&) =
delete;
~G4DNAIndependentReactionTimeModel() override;
void PrintInfo() override;
void Initialize() override;
void SetReactionModel(G4VDNAReactionModel*);
G4VDNAReactionModel* GetReactionModel();
void PrintInfo() override;
void Initialize() override;
void SetReactionModel(G4VDNAReactionModel*);
G4VDNAReactionModel* GetReactionModel();
void SetReactionTypeManager(G4VReactionTypeManager* pReactionProcessManager);
protected:
const G4DNAMolecularReactionTable*& fMolecularReactionTable;
std::unique_ptr<G4VDNAReactionModel> fpReactionModel;
std::unique_ptr<G4VReactionTypeManager> fReactionTypeManager;
protected:
const G4DNAMolecularReactionTable*& fMolecularReactionTable =
reference_cast<const G4DNAMolecularReactionTable*>(fpReactionTable);
std::unique_ptr<G4VDNAReactionModel> fpReactionModel;
};
#endif
@@ -33,15 +33,15 @@
#include "G4VITTimeStepComputer.hh"
#include "G4KDTreeResult.hh"
#include "G4IRTUtils.hh"
#include "G4VReactionType.hh"
#include <memory>
#include <set>
#include "G4ITTrackHolder.hh"
#include "G4ITReaction.hh"
#include "G4ReferenceCast.hh"
class G4VReactionTypeManager;
class G4VDNAReactionModel;
class G4DNAMolecularReactionTable;
class G4MolecularConfiguration;
class G4DNAReactionTypeManager;
class G4Molecule;
class G4ITReactionSet;
class G4ITReactionChange;
@@ -50,61 +50,56 @@ class G4ITTrackHolder;
class G4DNAIndependentReactionTimeStepper : public G4VITTimeStepComputer
{
public:
G4DNAIndependentReactionTimeStepper();
~G4DNAIndependentReactionTimeStepper() override = default;
G4DNAIndependentReactionTimeStepper(const G4DNAIndependentReactionTimeStepper&) = delete;
G4DNAIndependentReactionTimeStepper& operator=(const G4DNAIndependentReactionTimeStepper&) = delete;
public:
G4DNAIndependentReactionTimeStepper();
~G4DNAIndependentReactionTimeStepper() override = default;
G4DNAIndependentReactionTimeStepper(
const G4DNAIndependentReactionTimeStepper&) = delete;
G4DNAIndependentReactionTimeStepper& operator =(
const G4DNAIndependentReactionTimeStepper&) = delete;
void Prepare() override;
G4double CalculateStep(const G4Track&, const G4double&) override;
G4double CalculateMinTimeStep(G4double, G4double) override;
void Prepare() override;
G4double CalculateStep(const G4Track&, const G4double&) override;
G4double CalculateMinTimeStep(G4double, G4double) override;
void SetReactionModel(G4VDNAReactionModel*);
G4VDNAReactionModel* GetReactionModel();
void SetReactionModel(G4VDNAReactionModel*);
G4VDNAReactionModel* GetReactionModel();
std::unique_ptr<G4ITReactionChange>
FindReaction(G4ITReactionSet* pReactionSet,
const G4double& currentStepTime = 0,
const G4double& previousStepTime = 0,
const G4bool& reachedUserStepTimeLimit = false);
std::unique_ptr<G4ITReactionChange> FindReaction(
G4ITReactionSet* pReactionSet, const G4double& currentStepTime = 0,
const G4double& previousStepTime = 0,
const G4bool& reachedUserStepTimeLimit = false);
void SetReactionProcess(G4VITReactionProcess* pReactionProcess);
void SetVerbose(G4int);
void SetReactionProcess(G4VITReactionProcess* pReactionProcess);
private:
void InitializeForNewTrack();
class Utils;
void CheckAndRecordResults(const Utils& utils);
void SetReactionTypeManager(G4VReactionTypeManager* typeManager);
void SetVerbose(G4int);
private:
void InitializeForNewTrack();
ReactionType GetReactionType(const G4Track& trackA, const G4Track& trackB);
G4double GetTimeToEncounter(const G4Track& trackA, const G4Track& trackB);
class Utils;
G4bool fHasAlreadyReachedNullTime = false;
const G4DNAMolecularReactionTable*& fMolecularReactionTable =
reference_cast<const G4DNAMolecularReactionTable*>(fpReactionTable);
G4VDNAReactionModel* fReactionModel = nullptr;
G4ITTrackHolder* fpTrackContainer = G4ITTrackHolder::Instance();
G4ITReactionSet* fReactionSet = G4ITReactionSet::Instance();
G4int fVerbose = 0;
G4double fRCutOff = G4IRTUtils::GetRCutOff();
G4VITReactionProcess* fpReactionProcess = nullptr;
std::map<G4int, G4ThreeVector> fSampledPositions;
std::set<G4int> fCheckedTracks;
void CheckAndRecordResults(const Utils& utils);
G4double GetTimeToEncounter(const G4Track& trackA,
const G4Track& trackB);
G4bool fHasAlreadyReachedNullTime;
const G4DNAMolecularReactionTable*& fMolecularReactionTable;
G4VDNAReactionModel* fReactionModel;
G4ITTrackHolder* fpTrackContainer;
G4ITReactionSet* fReactionSet;
G4int fVerbose;
G4double fRCutOff;
G4DNAReactionTypeManager* fReactionTypeManager;
G4VITReactionProcess* fpReactionProcess;
std::map<G4int,G4ThreeVector> fSampledPositions;
class Utils
{
public:
Utils(const G4Track& tA, const G4Track& tB);
~Utils() = default;
const G4Track& fTrackA;
const G4Track& fTrackB;
const G4Molecule* fpMoleculeA;
const G4Molecule* fpMoleculeB;
};
class Utils
{
public:
Utils(const G4Track& tA, const G4Track& tB);
~Utils() = default;
const G4Track& fTrackA;
const G4Track& fTrackB;
const G4Molecule* fpMoleculeA;
const G4Molecule* fpMoleculeB;
};
};
#endif
@@ -131,6 +131,13 @@ private:
G4DNAMillerGreenExcitationModel & operator=(const G4DNAMillerGreenExcitationModel &right);
G4DNAMillerGreenExcitationModel(const G4DNAMillerGreenExcitationModel&);
// Reusable particle definitions
G4ParticleDefinition* protonDef;
G4ParticleDefinition* hydrogenDef;
G4ParticleDefinition* alphaPlusPlusDef;
G4ParticleDefinition* alphaPlusDef;
G4ParticleDefinition* heliumDef;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -0,0 +1,105 @@
//
// ********************************************************************
// * 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 on 2022/03/03
//
// Authors: A.D. Dominguez-Munoz, M.I. Gallardo, M.C. Bordage,
// Z. Francis, S. Incerti, M.A. Cortes-Giraldo
//
// Contact: M.A. Cortes-Giraldo (miancortes -at- us.es)
//
//
#ifndef G4DNARPWBAExcitationModel_h
#define G4DNARPWBAExcitationModel_h 1
#include "G4VEmModel.hh"
#include "G4ParticleChangeForGamma.hh"
#include "G4ProductionCutsTable.hh"
#include "G4DNACrossSectionDataSet.hh"
#include "G4LogLogInterpolation.hh"
#include "G4Electron.hh"
#include "G4Proton.hh"
#include "G4DNAWaterExcitationStructure.hh"
#include "G4NistManager.hh"
class G4DNARPWBAExcitationModel : public G4VEmModel
{
public:
explicit G4DNARPWBAExcitationModel(
const G4ParticleDefinition* p = nullptr,
const G4String& nam = "DNARPWBAExcitationModel");
~G4DNARPWBAExcitationModel() override;
G4DNARPWBAExcitationModel& operator=(const G4DNARPWBAExcitationModel& right) =
delete;
G4DNARPWBAExcitationModel(const G4DNARPWBAExcitationModel&) = delete;
void Initialise(const G4ParticleDefinition*,
const G4DataVector& = *(new G4DataVector())) override;
G4double CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* p, G4double ekin,
G4double emin, G4double emax) override;
G4double GetPartialCrossSection(const G4Material*, G4int level,
const G4ParticleDefinition*,
G4double kineticEnergy) override;
void SampleSecondaries(std::vector<G4DynamicParticle*>*,
const G4MaterialCutsCouple*, const G4DynamicParticle*,
G4double tmin, G4double maxEnergy) override;
inline void SelectStationary(const G4bool& input);
protected:
G4ParticleChangeForGamma* fParticleChangeForGamma = nullptr;
private:
// Partial cross section
G4int RandomSelect(G4double energy);
G4DNAWaterExcitationStructure waterStructure;
G4bool statCode = false;
// Water density table
const std::vector<G4double>* fpMolWaterDensity = nullptr;
G4bool isInitialised = false;
G4int verboseLevel = 0;
const G4ParticleDefinition* fParticleDefinition = G4Proton::ProtonDefinition();
G4double fLowEnergy = 0;
G4double fHighEnergy = 0;
G4String fTableFile;
std::unique_ptr<G4DNACrossSectionDataSet> fTableData;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4DNARPWBAExcitationModel::SelectStationary(const G4bool& input)
{
statCode = input;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#endif
@@ -0,0 +1,151 @@
//
// ********************************************************************
// * 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 on 2022/03/03
//
// Authors: A.D. Dominguez-Munoz, M.I. Gallardo, M.C. Bordage,
// Z. Francis, S. Incerti, M.A. Cortes-Giraldo
//
// Contact: M.A. Cortes-Giraldo (miancortes -at- us.es)
//
//
#ifndef G4DNARPWBAIonisationModel_h
#define G4DNARPWBAIonisationModel_h 1
#include "G4VEmModel.hh"
#include "G4ParticleChangeForGamma.hh"
#include "G4ProductionCutsTable.hh"
#include "G4DNACrossSectionDataSet.hh"
#include "G4Electron.hh"
#include "G4Proton.hh"
#include "G4DNAGenericIonsManager.hh"
#include "G4LogLogInterpolation.hh"
#include "G4DNAWaterIonisationStructure.hh"
#include "G4VAtomDeexcitation.hh"
#include "G4NistManager.hh"
class G4DNARPWBAIonisationModel : public G4VEmModel
{
public:
G4DNARPWBAIonisationModel(const G4ParticleDefinition* p = nullptr,
const G4String& nam = "DNARPWBAIonisationModel");
~G4DNARPWBAIonisationModel() override;
G4DNARPWBAIonisationModel& operator=(const G4DNARPWBAIonisationModel& right) =
delete;
G4DNARPWBAIonisationModel(const G4DNARPWBAIonisationModel&) = delete;
void Initialise(const G4ParticleDefinition*,
const G4DataVector& = *(new G4DataVector())) override;
G4double CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* p, G4double ekin,
G4double emin, G4double emax) override;
void SampleSecondaries(std::vector<G4DynamicParticle*>*,
const G4MaterialCutsCouple*, const G4DynamicParticle*,
G4double tmin, G4double maxEnergy) override;
G4double GetPartialCrossSection(const G4Material*, G4int /*level*/,
const G4ParticleDefinition*,
G4double /*kineticEnergy*/) override;
G4double DifferentialCrossSection(const G4double& k, const G4double& energyTransfer,
const G4int& shell);
G4double TransferedEnergy(G4double incomingParticleEnergy, G4int shell,
const G4double& random);
inline void SelectFasterComputation(const G4bool& input);
inline void SelectStationary(const G4bool& input);
inline void SelectSPScaling(const G4bool& input);
protected:
G4ParticleChangeForGamma* fParticleChangeForGamma = nullptr;
private:
using MapData = std::map<G4String, std::unique_ptr<G4DNACrossSectionDataSet>,
std::less<G4String>>;
using TriDimensionMap = std::map<G4double, std::map<G4double, G4double>>;
using VecMap = std::map<G4double, std::vector<G4double>>;
// methods
G4double RandomizeEjectedElectronEnergy(const G4double&, const G4int& );
G4double RandomizeEjectedElectronEnergyFromCumulatedDcs(const G4double& incomingParticleEnergy,
const G4int& shell);
G4double Interpolate(const G4double& e1, const G4double& e2, const G4double& e, const G4double& xs1,
const G4double& xs2);
G4double QuadInterpolator(const G4double& e11, const G4double& e12, const G4double& e21,
const G4double& e22, const G4double& x11, const G4double& x12,
const G4double& x21, const G4double& x22, const G4double& t1,
const G4double& t2, const G4double& t, const G4double& e);
//shoud change to array ?
G4int RandomSelect(G4double energy);
void InitialiseForProton(const G4ParticleDefinition*);
G4bool InEnergyLimit(const G4double&);
//members
G4bool fasterCode = false;
G4bool statCode = false;
G4bool spScaling = true;
// Water density table
const std::vector<G4double>* fpMolWaterDensity = nullptr;
// Deexcitation manager to produce fluo photons and e-
G4VAtomDeexcitation* fAtomDeexcitation = nullptr;
G4double lowEnergyLimit = 0;
G4double highEnergyLimit = 0;
G4bool isInitialised = false;
G4int verboseLevel = 0;
// Cross section
std::unique_ptr<G4DNACrossSectionDataSet> fpTotalCrossSection;
// Final state
G4DNAWaterIonisationStructure waterStructure;
TriDimensionMap eDiffCrossSectionData[6];
TriDimensionMap eNrjTransfData[6]; // for cumulated dcs
TriDimensionMap pDiffCrossSectionData[6];
TriDimensionMap pNrjTransfData[6]; // for cumulated dcs
std::vector<G4double> eTdummyVec;
std::vector<G4double> pTdummyVec;
VecMap eVecm;
VecMap pVecm;
VecMap eProbaShellMap[6]; // for cumulated dcs
VecMap pProbaShellMap[6]; // for cumulated dcs
const G4ParticleDefinition* fProtonDef = G4Proton::ProtonDefinition();
};
inline void G4DNARPWBAIonisationModel::SelectFasterComputation(
const G4bool& input)
{
fasterCode = input;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4DNARPWBAIonisationModel::SelectStationary(const G4bool& input)
{
statCode = input;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
inline void G4DNARPWBAIonisationModel::SelectSPScaling(const G4bool& input)
{
spScaling = input;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
#endif
@@ -158,12 +158,30 @@ private:
G4double Sum(G4double energy, const G4String& particle);
G4int RandomSelect(G4double energy,const G4String& particle );
G4ParticleDefinition* GetDNAIonParticleDefinition(const G4ParticleDefinition* particleDefinition);
//
G4DNARuddIonisationExtendedModel & operator=(const G4DNARuddIonisationExtendedModel &right);
G4DNARuddIonisationExtendedModel(const G4DNARuddIonisationExtendedModel&);
// Reusable particle definitions
G4ParticleDefinition* protonDef;
G4ParticleDefinition* hydrogenDef;
G4ParticleDefinition* alphaPlusPlusDef;
G4ParticleDefinition* alphaPlusDef;
G4ParticleDefinition* heliumDef;
//G4ParticleDefinition* lithiumDef;
//G4ParticleDefinition* berylliumDef;
//G4ParticleDefinition* boronDef;
G4ParticleDefinition* carbonDef;
G4ParticleDefinition* nitrogenDef;
G4ParticleDefinition* oxygenDef;
G4ParticleDefinition* siliconDef;
G4ParticleDefinition* ironDef;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -155,6 +155,13 @@ private:
G4DNARuddIonisationModel & operator=(const G4DNARuddIonisationModel &right);
G4DNARuddIonisationModel(const G4DNARuddIonisationModel&);
// Reusable particle definitions
G4ParticleDefinition* protonDef;
G4ParticleDefinition* hydrogenDef;
G4ParticleDefinition* alphaPlusPlusDef;
G4ParticleDefinition* alphaPlusDef;
G4ParticleDefinition* heliumDef;
};
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -73,7 +73,7 @@ public :
virtual void InitialiseToPrint(const G4MolecularConfiguration*) ;
virtual G4double GetReactionRadius(const G4MolecularConfiguration*,
const G4MolecularConfiguration*);
virtual G4double GetReactionRadius(const G4int);
virtual G4double GetReactionRadius(const G4int&);
virtual G4bool FindReaction(const G4Track&,
const G4Track&,
@@ -36,7 +36,7 @@ class G4DNAMolecularReactionData;
class G4DNAUpdateSystemModel : public G4VUpdateSystemModel
{
public:
using Index = G4Voxel::Index;
using Index = G4VDNAMesh::Index;
using MolType = const G4MolecularConfiguration*;
using JumpingData = std::pair<MolType, Index>;
using ReactionData = const G4DNAMolecularReactionData;
@@ -45,21 +45,18 @@ class G4DNAUpdateSystemModel : public G4VUpdateSystemModel
~G4DNAUpdateSystemModel() override = default;
void UpdateSystem(const Index& index, const ReactionData& data);
void UpdateSystem(const Index& index, const JumpingData& data);
void KillMolecule(const Index& index, MolType type);
void CreateMolecule(const Index& index, MolType);
void JumpTo(const Index& index, MolType type);
void JumpIn(const Index& index, MolType);
void SetMesh(G4DNAMesh*);
void SetGlobalTime(const G4double& globalTime) { fGlobalTime = globalTime; }
void SetVerbose(G4int verbose) { fVerbose = verbose; }
private:
G4DNAMesh* fpMesh;
G4int fVerbose;
G4double fGlobalTime;
void KillMolecule(const Index& index, MolType type);
void CreateMolecule(const Index& index, MolType);
void JumpTo(const Index& index, MolType type);
void JumpIn(const Index& index, MolType);
G4DNAMesh* fpMesh = nullptr;
G4int fVerbose = 0;
G4double fGlobalTime = DBL_MAX;
};
#endif // G4DNAUPDATESYSTEMMODEL_HH
@@ -32,35 +32,34 @@
#include "G4VDNAReactionModel.hh"
#include <vector>
class G4DNAMolecularReactionData;
class G4VReactionTypeManager;
class G4DNAReactionTypeManager;
class G4DiffusionControlledReactionModel : public G4VDNAReactionModel
{
public :
G4DiffusionControlledReactionModel();
~G4DiffusionControlledReactionModel() override;
public:
G4DiffusionControlledReactionModel();
~G4DiffusionControlledReactionModel() override;
G4DiffusionControlledReactionModel(const G4DiffusionControlledReactionModel&) = delete;
G4DiffusionControlledReactionModel& operator=(const G4DiffusionControlledReactionModel&) = delete;
G4DiffusionControlledReactionModel(
const G4DiffusionControlledReactionModel&) = delete;
G4DiffusionControlledReactionModel& operator =(
const G4DiffusionControlledReactionModel&) = delete;
void Initialise(const G4MolecularConfiguration*, const G4Track&) override;
void InitialiseToPrint(const G4MolecularConfiguration*) override;
G4double GetReactionRadius(const G4MolecularConfiguration*,
const G4MolecularConfiguration*) override;
G4double GetReactionRadius(G4int) override;
void Initialise(const G4MolecularConfiguration*, const G4Track&) override;
void InitialiseToPrint(const G4MolecularConfiguration*) override;
G4double GetReactionRadius(const G4MolecularConfiguration*,
const G4MolecularConfiguration*) override;
G4double GetReactionRadius(const G4int&) override;
G4bool FindReaction(const G4Track&,
const G4Track&,
G4double /*reactionRadius*/,
G4double& /*separationDistance*/,
G4bool /*alongStepInteraction*/) override
{return true;}
void SetReactionTypeManager(G4VReactionTypeManager* typeManager);
private :
const std::vector<const G4DNAMolecularReactionData*>* fpReactionData ;
G4DNAReactionTypeManager* fReactionTypeManager;
G4bool FindReaction(const G4Track&, const G4Track&,
G4double /*reactionRadius*/,
G4double& /*separationDistance*/,
G4bool /*alongStepInteraction*/) override
{
return true;
}
G4double GetTimeToEncounter(const G4Track& trackA, const G4Track& trackB);
private:
const std::vector<const G4DNAMolecularReactionData*>* fpReactionData =
nullptr;
};
#endif
@@ -23,34 +23,32 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// 20/2/2019
// Author : HoangTRAN
#ifndef G4VDNAHitModel_hh
#define G4VDNAHitModel_hh
#include "globals.hh"
#include <vector>
#include <variant>
class G4DNAComponentNode;
class G4VPhysicalVolume;
class G4Track;
#ifndef G4DNAPartiallyDiffusionControlled_h
#define G4DNAPartiallyDiffusionControlled_h 1
#include "G4DNAReactionTypeManager.hh"
#include "G4VReactionType.hh"
class G4MolecularConfiguration;
class G4DNAPartiallyDiffusionControlled
: public G4VReactionType
class G4VDNAHitModel
{
public:
G4DNAPartiallyDiffusionControlled();
~G4DNAPartiallyDiffusionControlled() override;
G4DNAPartiallyDiffusionControlled(const G4DNAPartiallyDiffusionControlled& other) = delete;
G4DNAPartiallyDiffusionControlled& operator=(const G4DNAPartiallyDiffusionControlled& other) = delete;
using DNANode =
std::variant<const G4DNAComponentNode*, /*for dnadamage chain*/
const G4VPhysicalVolume* /*for molecularDNA chain*/>;
G4double GetTimeToEncounter(const G4Track& trackA,
const G4Track& trackB) override;
public:
explicit G4VDNAHitModel(const G4String& name);
virtual ~G4VDNAHitModel() = default;
// delete assignment operator
G4VDNAHitModel& operator=(const G4VDNAHitModel& right) = delete;
G4VDNAHitModel(const G4VDNAHitModel&) = delete;
virtual G4double CalculateReactionTime(const G4Track& trackA, DNANode&) = 0;
virtual G4bool DoReaction(const G4Track& track, const G4double&,
const DNANode&) = 0;
G4bool GeminateRecombinationProbability(const G4MolecularConfiguration*,
const G4MolecularConfiguration*) override;
private:
G4double GetDiffusionCoefficient(const G4MolecularConfiguration*,
const G4MolecularConfiguration*);
private:
const G4String fName;
};
#endif
#endif
@@ -23,7 +23,6 @@ geant4_add_module(G4emdna-models
G4DNAELSEPAElasticModel.hh
G4DNAIonElasticModel.hh
G4DNAIRT.hh
G4DNAIRT_geometries.hh
G4DNAIRTMoleculeEncounterStepper.hh
G4DNAMeltonAttachmentModel.hh
G4DNAMillerGreenExcitationModel.hh
@@ -67,13 +66,14 @@ geant4_add_module(G4emdna-models
G4DNAIndependentReactionTimeModel.hh
G4DNAIndependentReactionTimeStepper.hh
G4DNAMakeReaction.hh
G4DNAPartiallyDiffusionControlled.hh
G4DNATotallyDiffusionControlled.hh
G4DNAUpdateSystemModel.hh
G4DNAGillespieDirectMethod.hh
G4VUpdateSystemModel.hh
G4DNAUpdateSystemModel.hh
G4DNAEventScheduler.hh
G4DNARPWBAExcitationModel.hh
G4DNARPWBAIonisationModel.hh
G4VDNAHitModel.hh
SOURCES
G4DNABornAngle.cc
G4DNABornExcitationModel1.cc
@@ -93,7 +93,6 @@ geant4_add_module(G4emdna-models
G4DNAEmfietzoglouIonisationModel.cc
G4DNAIonElasticModel.cc
G4DNAIRT.cc
G4DNAIRT_geometries.cc
G4DNAIRTMoleculeEncounterStepper.cc
G4DNAMeltonAttachmentModel.cc
G4DNAMillerGreenExcitationModel.cc
@@ -136,12 +135,13 @@ geant4_add_module(G4emdna-models
G4DNAIndependentReactionTimeModel.cc
G4DNAIndependentReactionTimeStepper.cc
G4DNAMakeReaction.cc
G4DNAPartiallyDiffusionControlled.cc
G4DNATotallyDiffusionControlled.cc
G4DNAUpdateSystemModel.cc
G4DNAGillespieDirectMethod.cc
G4DNAUpdateSystemModel.cc
G4DNAEventScheduler.cc)
G4DNAEventScheduler.cc
G4DNARPWBAExcitationModel.cc
G4DNARPWBAIonisationModel.cc
G4VDNAHitModel.cc)
geant4_module_link_libraries(G4emdna-models
PUBLIC
@@ -100,7 +100,7 @@ void G4DNABornExcitationModel2::Initialise(const G4ParticleDefinition* particle,
fParticleDefinition = particle;
std::ostringstream fullFileName;
char *path = std::getenv("G4LEDATA");
const char* path = G4FindDataDir("G4LEDATA");
if(G4String(path) == "")
{
@@ -124,7 +124,7 @@ void G4DNABornIonisationModel1::Initialise(const G4ParticleDefinition* particle,
G4double scaleFactor = (1.e-22 / 3.343) * m*m;
char *path = getenv("G4LEDATA");
const char *path = G4FindDataDir("G4LEDATA");
// *** ELECTRON
@@ -128,7 +128,7 @@ void G4DNABornIonisationModel2::Initialise(const G4ParticleDefinition* particle,
fParticleDef = particle;
// Energy limits
char *path = std::getenv("G4LEDATA");
const char* path = G4FindDataDir("G4LEDATA");
// ***
@@ -173,7 +173,7 @@ void G4DNACPA100ElasticModel::Initialise(const G4ParticleDefinition*
// For final state
char *path = getenv("G4LEDATA");
const char *path = G4FindDataDir("G4LEDATA");
if (!path)
{
@@ -136,7 +136,7 @@ void G4DNACPA100IonisationModel::Initialise(const G4ParticleDefinition* particle
G4double scaleFactor = 1.e-20 * m*m;
char *path = getenv("G4LEDATA");
const char *path = G4FindDataDir("G4LEDATA");
// *** ELECTRON
@@ -952,8 +952,16 @@ G4double G4DNACPA100IonisationModel::RandomTransferedEnergy
<< nrjTransf12 << " " << nrjTransf21 << " " <<nrjTransf22 << G4endl;
*/
}
// Avoids cases where cum xs is 1 in last bin only and zero everywhere else
if (valuePROB11==0. && valuePROB12==1.)
{
G4double interpolatedvalue2 = Interpolate(valuePROB21, valuePROB22, random, nrjTransf21, nrjTransf22);
G4double valueNrjTransf = Interpolate(valueK1, valueK2, k, 0., interpolatedvalue2);
return valueNrjTransf;
}
}
// Avoids cases where cum xs is zero for k1 and is not for k2 (with always k1<k2)
@@ -137,7 +137,7 @@ void G4DNAChampionElasticModel::Initialise(const G4ParticleDefinition* particle,
// For final state
char *path = getenv("G4LEDATA");
const char *path = G4FindDataDir("G4LEDATA");
if (!path)
{
@@ -30,6 +30,12 @@
#include "G4SystemOfUnits.hh"
#include "G4DNAMolecularMaterial.hh"
#include "G4DNAChemistryManager.hh"
#include "G4Log.hh"
#include "G4Pow.hh"
#include "G4Alpha.hh"
static G4Pow * gpow = G4Pow::GetInstance();
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -87,9 +93,11 @@ void G4DNADingfelderChargeDecreaseModel::Initialise(const G4ParticleDefinition*
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
G4ParticleDefinition* alphaPlusPlusDef = instance->GetIon("alpha++");
G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
protonDef = G4Proton::ProtonDefinition();
alphaPlusPlusDef = G4Alpha::Alpha();
alphaPlusDef = instance->GetIon("alpha+");
hydrogenDef = instance->GetIon("hydrogen");
heliumDef = instance->GetIon("helium");
G4String proton;
G4String alphaPlusPlus;
@@ -220,16 +228,12 @@ G4double G4DNADingfelderChargeDecreaseModel::CrossSectionPerVolume(const G4Mater
}
// Calculate total cross section for model
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (
particleDefinition != G4Proton::ProtonDefinition()
particleDefinition != protonDef
&&
particleDefinition != instance->GetIon("alpha++")
particleDefinition != alphaPlusPlusDef
&&
particleDefinition != instance->GetIon("alpha+")
particleDefinition != alphaPlusDef
)
return 0;
@@ -365,17 +369,14 @@ G4int G4DNADingfelderChargeDecreaseModel::NumberOfFinalStates(G4ParticleDefiniti
if (particleDefinition == G4Proton::Proton())
return 1;
G4DNAGenericIonsManager*instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == instance->GetIon("alpha++"))
if (particleDefinition == alphaPlusPlusDef)
{
if (finalStateIndex == 0)
return 1;
return 2;
}
if (particleDefinition == instance->GetIon("alpha+"))
if (particleDefinition == alphaPlusDef)
return 1;
return 0;
@@ -386,20 +387,18 @@ G4int G4DNADingfelderChargeDecreaseModel::NumberOfFinalStates(G4ParticleDefiniti
G4ParticleDefinition* G4DNADingfelderChargeDecreaseModel::OutgoingParticleDefinition(G4ParticleDefinition* particleDefinition,
G4int finalStateIndex)
{
G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
if (particleDefinition == G4Proton::Proton())
return instance->GetIon("hydrogen");
return hydrogenDef;
if (particleDefinition == instance->GetIon("alpha++"))
if (particleDefinition == alphaPlusPlusDef)
{
if (finalStateIndex == 0)
return instance->GetIon("alpha+");
return instance->GetIon("helium");
return alphaPlusDef;
return heliumDef;
}
if (particleDefinition == instance->GetIon("alpha+"))
return instance->GetIon("helium");
if (particleDefinition == alphaPlusDef)
return heliumDef;
return 0;
}
@@ -413,12 +412,10 @@ G4double G4DNADingfelderChargeDecreaseModel::WaterBindingEnergyConstant(G4Partic
// Rad. Phys. Chem. 59 p.267 by Dingf. et al.
// W + 10.79 eV -> W+ + e-
G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
if (particleDefinition == G4Proton::Proton())
return 10.79 * eV;
if (particleDefinition == instance->GetIon("alpha++"))
if (particleDefinition == alphaPlusPlusDef)
{
// Binding energy for W+ -> W++ + e- 10.79 eV
// Binding energy for W -> W+ + e- 10.79 eV
@@ -432,7 +429,7 @@ G4double G4DNADingfelderChargeDecreaseModel::WaterBindingEnergyConstant(G4Partic
return 10.79 * 2 * eV;
}
if (particleDefinition == instance->GetIon("alpha+"))
if (particleDefinition == alphaPlusDef)
{
// Binding energy for W+ -> W++ + e- 10.79 eV
// Binding energy for W -> W+ + e- 10.79 eV
@@ -451,12 +448,10 @@ G4double G4DNADingfelderChargeDecreaseModel::WaterBindingEnergyConstant(G4Partic
G4double G4DNADingfelderChargeDecreaseModel::OutgoingParticleBindingEnergyConstant(G4ParticleDefinition* particleDefinition,
G4int finalStateIndex)
{
G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
if (particleDefinition == G4Proton::Proton())
return 13.6 * eV;
if (particleDefinition == instance->GetIon("alpha++"))
if (particleDefinition == alphaPlusPlusDef)
{
// Binding energy for He+ -> He++ + e- 54.509 eV
// Binding energy for He -> He+ + e- 24.587 eV
@@ -467,7 +462,7 @@ G4double G4DNADingfelderChargeDecreaseModel::OutgoingParticleBindingEnergyConsta
return (54.509 + 24.587) * eV;
}
if (particleDefinition == instance->GetIon("alpha+"))
if (particleDefinition == alphaPlusDef)
{
// Binding energy for He+ -> He++ + e- 54.509 eV
// Binding energy for He -> He+ + e- 24.587 eV
@@ -485,16 +480,14 @@ G4double G4DNADingfelderChargeDecreaseModel::PartialCrossSection(G4double k,
const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == G4Proton::ProtonDefinition())
if (particleDefinition == protonDef)
particleTypeIndex = 0;
if (particleDefinition == instance->GetIon("alpha++"))
if (particleDefinition == alphaPlusPlusDef)
particleTypeIndex = 1;
if (particleDefinition == instance->GetIon("alpha+"))
if (particleDefinition == alphaPlusDef)
particleTypeIndex = 2;
//
@@ -526,7 +519,7 @@ G4double G4DNADingfelderChargeDecreaseModel::PartialCrossSection(G4double k,
//
x1[index][particleTypeIndex] = x0[index][particleTypeIndex]
+ std::pow((a0[index][particleTypeIndex] - a1[index][particleTypeIndex])
+ gpow->powA((a0[index][particleTypeIndex] - a1[index][particleTypeIndex])
/ (c0[index][particleTypeIndex]
* d0[index][particleTypeIndex]),
1. / (d0[index][particleTypeIndex] - 1.));
@@ -534,12 +527,12 @@ G4double G4DNADingfelderChargeDecreaseModel::PartialCrossSection(G4double k,
- a1[index][particleTypeIndex]) * x1[index][particleTypeIndex]
+ b0[index][particleTypeIndex]
- c0[index][particleTypeIndex]
* std::pow(x1[index][particleTypeIndex]
* gpow->powA(x1[index][particleTypeIndex]
- x0[index][particleTypeIndex],
d0[index][particleTypeIndex]);
}
G4double x(std::log10(k / eV));
G4double x(G4Log(k / eV)/gpow->logZ(10));
G4double y;
if (x < x0[index][particleTypeIndex])
@@ -547,12 +540,12 @@ G4double G4DNADingfelderChargeDecreaseModel::PartialCrossSection(G4double k,
else if (x < x1[index][particleTypeIndex])
y = a0[index][particleTypeIndex] * x + b0[index][particleTypeIndex]
- c0[index][particleTypeIndex]
* std::pow(x - x0[index][particleTypeIndex],
* gpow->powA(x - x0[index][particleTypeIndex],
d0[index][particleTypeIndex]);
else
y = a1[index][particleTypeIndex] * x + b1[index][particleTypeIndex];
return f0[index][particleTypeIndex] * std::pow(10., y) * m * m;
return f0[index][particleTypeIndex] * gpow->powA(10., y) * m * m;
}
@@ -560,16 +553,14 @@ G4int G4DNADingfelderChargeDecreaseModel::RandomSelect(G4double k,
const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == G4Proton::ProtonDefinition())
if (particleDefinition == protonDef)
particleTypeIndex = 0;
if (particleDefinition == instance->GetIon("alpha++"))
if (particleDefinition == alphaPlusPlusDef)
particleTypeIndex = 1;
if (particleDefinition == instance->GetIon("alpha+"))
if (particleDefinition == alphaPlusDef)
particleTypeIndex = 2;
const G4int n = numberOfPartialCrossSections[particleTypeIndex];
@@ -608,16 +599,14 @@ G4double G4DNADingfelderChargeDecreaseModel::Sum(G4double k,
const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == G4Proton::ProtonDefinition())
if (particleDefinition == protonDef)
particleTypeIndex = 0;
if (particleDefinition == instance->GetIon("alpha++"))
if (particleDefinition == alphaPlusPlusDef)
particleTypeIndex = 1;
if (particleDefinition == instance->GetIon("alpha+"))
if (particleDefinition == alphaPlusDef)
particleTypeIndex = 2;
G4double totalCrossSection = 0.;
@@ -29,6 +29,11 @@
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4DNAMolecularMaterial.hh"
#include "G4Log.hh"
#include "G4Pow.hh"
#include "G4Alpha.hh"
static G4Pow * gpow = G4Pow::GetInstance();
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -85,9 +90,10 @@ void G4DNADingfelderChargeIncreaseModel::Initialise(const G4ParticleDefinition*
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
G4ParticleDefinition* hydrogenDef = instance->GetIon("hydrogen");
G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
G4ParticleDefinition* heliumDef = instance->GetIon("helium");
hydrogenDef = instance->GetIon("hydrogen");
alphaPlusPlusDef = G4Alpha::Alpha();
alphaPlusDef = instance->GetIon("alpha+");
heliumDef = instance->GetIon("helium");
G4String hydrogen;
G4String alphaPlus;
@@ -208,15 +214,12 @@ G4double G4DNADingfelderChargeIncreaseModel::CrossSectionPerVolume(const G4Mater
// Calculate total cross section for model
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (
particleDefinition != instance->GetIon("hydrogen")
particleDefinition != hydrogenDef
&&
particleDefinition != instance->GetIon("alpha+")
particleDefinition != alphaPlusDef
&&
particleDefinition != instance->GetIon("helium")
particleDefinition != heliumDef
)
return 0;
@@ -248,7 +251,7 @@ G4double G4DNADingfelderChargeIncreaseModel::CrossSectionPerVolume(const G4Mater
if (k >= lowLim && k <= highLim)
{
//HYDROGEN
if (particleDefinition == instance->GetIon("hydrogen"))
if (particleDefinition == hydrogenDef)
{
const G4double aa = 2.835;
const G4double bb = 0.310;
@@ -260,8 +263,8 @@ G4double G4DNADingfelderChargeIncreaseModel::CrossSectionPerVolume(const G4Mater
G4double t = k / (proton_mass_c2/electron_mass_c2);
G4double x = t / rr;
G4double temp = 4.0 * pi * Bohr_radius/nm * Bohr_radius/nm * fac;
G4double sigmal = temp * cc * (std::pow(x,dd));
G4double sigmah = temp * (aa * std::log(1.0 + x) + bb) / x;
G4double sigmal = temp * cc * (gpow->powA(x,dd));
G4double sigmah = temp * (aa * G4Log(1.0 + x) + bb) / x;
totalCrossSection = 1.0/(1.0/sigmal + 1.0/sigmah) *m*m;
}
else
@@ -327,11 +330,8 @@ void G4DNADingfelderChargeIncreaseModel::SampleSecondaries(std::vector<
fParticleChangeForGamma->ProposeTrackStatus(fStopAndKill);
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
G4double electronK;
if (definition == instance->GetIon("hydrogen")) electronK = inK*electron_mass_c2/proton_mass_c2;
if (definition == hydrogenDef) electronK = inK*electron_mass_c2/proton_mass_c2;
else electronK = inK*electron_mass_c2/(particleMass);
if (outK<0)
@@ -362,16 +362,14 @@ G4int G4DNADingfelderChargeIncreaseModel::NumberOfFinalStates(G4ParticleDefiniti
G4int finalStateIndex)
{
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == instance->GetIon("hydrogen"))
if (particleDefinition == hydrogenDef)
return 2;
if (particleDefinition == instance->GetIon("alpha+"))
if (particleDefinition == alphaPlusDef)
return 2;
if (particleDefinition == instance->GetIon("helium"))
if (particleDefinition == heliumDef)
{
if (finalStateIndex == 0)
return 2;
@@ -386,19 +384,18 @@ G4int G4DNADingfelderChargeIncreaseModel::NumberOfFinalStates(G4ParticleDefiniti
G4ParticleDefinition* G4DNADingfelderChargeIncreaseModel::OutgoingParticleDefinition(G4ParticleDefinition* particleDefinition,
G4int finalStateIndex)
{
G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
if (particleDefinition == instance->GetIon("hydrogen"))
if (particleDefinition == hydrogenDef)
return G4Proton::Proton();
if (particleDefinition == instance->GetIon("alpha+"))
return instance->GetIon("alpha++");
if (particleDefinition == alphaPlusDef)
return alphaPlusPlusDef;
if (particleDefinition == instance->GetIon("helium"))
if (particleDefinition == heliumDef)
{
if (finalStateIndex == 0)
return instance->GetIon("alpha+");
return instance->GetIon("alpha++");
return alphaPlusDef;
return alphaPlusPlusDef;
}
return 0;
@@ -409,19 +406,18 @@ G4ParticleDefinition* G4DNADingfelderChargeIncreaseModel::OutgoingParticleDefini
G4double G4DNADingfelderChargeIncreaseModel::IncomingParticleBindingEnergyConstant(G4ParticleDefinition* particleDefinition,
G4int finalStateIndex)
{
G4DNAGenericIonsManager * instance(G4DNAGenericIonsManager::Instance());
if (particleDefinition == instance->GetIon("hydrogen"))
if (particleDefinition == hydrogenDef)
return 13.6 * eV;
if (particleDefinition == instance->GetIon("alpha+"))
if (particleDefinition == alphaPlusDef)
{
// Binding energy for He+ -> He++ + e- 54.509 eV
// Binding energy for He -> He+ + e- 24.587 eV
return 54.509 * eV;
}
if (particleDefinition == instance->GetIon("helium"))
if (particleDefinition == heliumDef)
{
// Binding energy for He+ -> He++ + e- 54.509 eV
// Binding energy for He -> He+ + e- 24.587 eV
@@ -441,13 +437,11 @@ G4double G4DNADingfelderChargeIncreaseModel::PartialCrossSection(G4double k,
const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == instance->GetIon("alpha+"))
if (particleDefinition == alphaPlusDef)
particleTypeIndex = 0;
if (particleDefinition == instance->GetIon("helium"))
if (particleDefinition == heliumDef)
particleTypeIndex = 1;
//
@@ -481,7 +475,7 @@ G4double G4DNADingfelderChargeIncreaseModel::PartialCrossSection(G4double k,
//
x1[index][particleTypeIndex] = x0[index][particleTypeIndex]
+ std::pow((a0[index][particleTypeIndex] - a1[index][particleTypeIndex])
+ gpow->powA((a0[index][particleTypeIndex] - a1[index][particleTypeIndex])
/ (c0[index][particleTypeIndex]
* d0[index][particleTypeIndex]),
1. / (d0[index][particleTypeIndex] - 1.));
@@ -489,12 +483,12 @@ G4double G4DNADingfelderChargeIncreaseModel::PartialCrossSection(G4double k,
- a1[index][particleTypeIndex]) * x1[index][particleTypeIndex]
+ b0[index][particleTypeIndex]
- c0[index][particleTypeIndex]
* std::pow(x1[index][particleTypeIndex]
* gpow->powA(x1[index][particleTypeIndex]
- x0[index][particleTypeIndex],
d0[index][particleTypeIndex]);
}
G4double x(std::log10(k / eV));
G4double x(G4Log(k / eV)/gpow->logZ(10));
G4double y;
if (x < x0[index][particleTypeIndex])
@@ -502,12 +496,12 @@ G4double G4DNADingfelderChargeIncreaseModel::PartialCrossSection(G4double k,
else if (x < x1[index][particleTypeIndex])
y = a0[index][particleTypeIndex] * x + b0[index][particleTypeIndex]
- c0[index][particleTypeIndex]
* std::pow(x - x0[index][particleTypeIndex],
* gpow->powA(x - x0[index][particleTypeIndex],
d0[index][particleTypeIndex]);
else
y = a1[index][particleTypeIndex] * x + b1[index][particleTypeIndex];
return f0[index][particleTypeIndex] * std::pow(10., y) * m * m;
return f0[index][particleTypeIndex] * gpow->powA(10., y) * m * m;
}
@@ -517,16 +511,14 @@ G4int G4DNADingfelderChargeIncreaseModel::RandomSelect(G4double k,
const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == instance->GetIon("hydrogen"))
if (particleDefinition == hydrogenDef)
return 0;
if (particleDefinition == instance->GetIon("alpha+"))
if (particleDefinition == alphaPlusDef)
particleTypeIndex = 0;
if (particleDefinition == instance->GetIon("helium"))
if (particleDefinition == heliumDef)
particleTypeIndex = 1;
const G4int n = numberOfPartialCrossSections[particleTypeIndex];
@@ -565,13 +557,11 @@ G4double G4DNADingfelderChargeIncreaseModel::Sum(G4double k,
const G4ParticleDefinition* particleDefinition)
{
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == instance->GetIon("alpha+"))
if (particleDefinition == alphaPlusDef)
particleTypeIndex = 0;
if (particleDefinition == instance->GetIon("helium"))
if (particleDefinition == heliumDef)
particleTypeIndex = 1;
G4double totalCrossSection = 0.;
@@ -212,7 +212,7 @@ const G4DataVector& )
fpData_Au->LoadData(fileZElectron);
std::ostringstream eFullFileNameZ;
char *path = getenv("G4LEDATA");
const char *path = G4FindDataDir("G4LEDATA");
if (!path)
{
G4Exception("G4DNAELSEPAElasticModel::Initialise","em0002",
@@ -306,7 +306,7 @@ const G4DataVector& )
std::ostringstream eFullFileNameZ;
char *path = getenv("G4LEDATA");
const char *path = G4FindDataDir("G4LEDATA");
if (!path)
{
G4Exception("G4DNAELSEPAElasticModel::Initialise","em0004",
@@ -127,7 +127,7 @@ void G4DNAEmfietzoglouIonisationModel::Initialise(const G4ParticleDefinition* pa
G4double scaleFactor = (1.e-22 / 3.343) * m*m;
char *path = getenv("G4LEDATA");
const char *path = G4FindDataDir("G4LEDATA");
// *** ELECTRON
@@ -36,31 +36,17 @@
#include "G4UserMeshAction.hh"
#include "G4MoleculeCounter.hh"
#include "G4DNAScavengerMaterial.hh"
#include "G4Molecule.hh"
G4DNAEventScheduler::G4DNAEventScheduler(const G4DNABoundingBox& boundingBox,
G4int pixel)
: IEventScheduler()
, fVerbose(0)
, fInitialized(false)
, fStartTime(1 * ps)
, fEndTime(10000 * s)
, fStepNumber(0)
, fMaxStep(INT_MAX)
, fRunning(true)
, fTimeStep(DBL_MAX)
, fGlobalTime(fStartTime)
, fJumpingNumber(0)
, fReactionNumber(0)
, fPixel(pixel)
, fIsChangeMesh(false)
, fSetChangeMesh(true)
, fStepNumberInMesh(0)
, fInitialPixels(fPixel)
, fpMesh(new G4DNAMesh(boundingBox, fPixel))
, fpGillespieReaction(new G4DNAGillespieDirectMethod())
, fpEventSet(new G4DNAEventSet())
, fpUpdateSystem(new G4DNAUpdateSystemModel())
, fpUserMeshAction(nullptr)
{
if(!CheckingReactionRadius(fpMesh->GetResolution()))
{
@@ -76,7 +62,9 @@ void G4DNAEventScheduler::ClearAndReChargeCounter()
fCounterMap.clear();
if(fTimeToRecord.empty())
{
G4cout << "fTimeToRecord is empty " << G4endl;
G4String WarMessage = "fTimeToRecord is empty ";
G4Exception("G4DNAEventScheduler::ClearAndReChargeCounter()",
"TimeToRecord is empty", JustWarning, WarMessage);
}
fLastRecoredTime = fTimeToRecord.begin();
@@ -114,12 +102,18 @@ void G4DNAEventScheduler::ClearAndReChargeCounter()
}
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)
@@ -135,7 +129,7 @@ G4DNAEventScheduler::~G4DNAEventScheduler() = default;
void G4DNAEventScheduler::Voxelizing()
{
auto pMainList = G4ITTrackHolder::Instance()->GetMainList();
std::map<G4DNAMesh::Key, MapList> TrackKeyMap;
std::map<G4VDNAMesh::Index, MapList> TrackKeyMap;
for(auto track : *pMainList)
{
auto molType = GetMolecule(track)->GetMolecularConfiguration();
@@ -148,7 +142,7 @@ void G4DNAEventScheduler::Voxelizing()
continue;
}
auto key = fpMesh->GetKey(track->GetPosition());
auto key = fpMesh->GetIndex(track->GetPosition());
if(TrackKeyMap.find(key) != TrackKeyMap.end())
{
std::map<MolType, size_t>& TrackTypeMap = TrackKeyMap[key];
@@ -169,7 +163,7 @@ void G4DNAEventScheduler::Voxelizing()
for(auto& it : TrackKeyMap)
{
fpMesh->SetVoxelMapList(it.first, std::move(it.second));
fpMesh->InitializeVoxel(it.first, std::move(it.second));
}
}
@@ -180,29 +174,26 @@ void G4DNAEventScheduler::ReVoxelizing(G4int pixel)
auto begin = fpMesh->begin();
auto end = fpMesh->end();
std::map<G4DNAMesh::Key, MapList> TrackKeyMap;
std::map<G4VDNAMesh::Index, MapList> TrackKeyMap;
for(; begin != end; begin++)
{
auto index = fpMesh->GetIndex(begin->first);
auto newKey = newMesh->GetKey(fpMesh->GetIndex(index, fPixel));
auto node = begin->second;
// if (node == nullptr) continue;
if(TrackKeyMap.find(newKey) == TrackKeyMap.end())
auto index = std::get<0>(*begin);
auto newIndex = fpMesh->ConvertIndex(index, fPixel);
if(TrackKeyMap.find(newIndex) == TrackKeyMap.end())
{
TrackKeyMap[newKey] = node->GetMapList();
TrackKeyMap[newIndex] = std::get<2>(*begin);
}
else
{
for(const auto& it : node->GetMapList())
for(const auto& it : std::get<2>(*begin))
{
TrackKeyMap[newKey][it.first] += it.second;
TrackKeyMap[newIndex][it.first] += it.second;
}
if(fVerbose > 1)
{
G4cout << "key : " << begin->first << " index : " << index
<< " new index : " << fpMesh->GetIndex(index, fPixel)
<< " new key : " << newKey
<< " number: " << node->GetMapList().begin()->second << G4endl;
G4cout << " ReVoxelizing:: Old index : " << index
<< " new index : " << fpMesh->ConvertIndex(index, fPixel)
<< " number: " << std::get<2>(*begin).begin()->second << G4endl;
}
}
}
@@ -210,7 +201,7 @@ void G4DNAEventScheduler::ReVoxelizing(G4int pixel)
for(auto& it : TrackKeyMap)
{
fpMesh->SetVoxelMapList(it.first, std::move(it.second));
fpMesh->InitializeVoxel(it.first, std::move(it.second));
}
}
void G4DNAEventScheduler::Reset()
@@ -252,7 +243,7 @@ void G4DNAEventScheduler::Initialize()
G4Scheduler::Instance()->GetScavengerMaterial());
if(pScavengerMaterial == nullptr)
{
G4cout << "pScavengerMaterial == nullptr" << G4endl;
G4cout << "There is no scavenger" << G4endl;
}
else
{
@@ -319,22 +310,29 @@ G4double G4DNAEventScheduler::GetStartTime() const { return fStartTime; }
G4double G4DNAEventScheduler::GetEndTime() const { return fEndTime; }
[[maybe_unused]] G4double G4DNAEventScheduler::GetTimeStep() const { return fTimeStep; }
[[maybe_unused]] G4double G4DNAEventScheduler::GetTimeStep() const
{
return fTimeStep;
}
G4int G4DNAEventScheduler::GetVerbose() const { return fVerbose; }
[[maybe_unused]] void G4DNAEventScheduler::SetMaxNbSteps(G4int max) { fMaxStep = max; }
[[maybe_unused]] void G4DNAEventScheduler::SetMaxNbSteps(G4int max)
{
fMaxStep = max;
}
[[maybe_unused]] void G4DNAEventScheduler::SetStartTime(G4double time)
{
fStartTime = time;
fStartTime = time;
fGlobalTime = fStartTime;
}
void G4DNAEventScheduler::Stop() { fRunning = false; }
void G4DNAEventScheduler::Run()
{
G4Timer localtimer;
if(fVerbose > 0)
if(fVerbose > 2)
{
localtimer.Start();
G4cout << "***G4DNAEventScheduler::Run*** for Pixel : " << fPixel << G4endl;
@@ -343,7 +341,7 @@ void G4DNAEventScheduler::Run()
{
RunInMesh();
}
if(fVerbose > 0)
if(fVerbose > 2)
{
if(!fRunning)
{
@@ -360,7 +358,8 @@ void G4DNAEventScheduler::Run()
G4cout << "***G4DNAEventScheduler::Ending::"
<< G4BestUnit(fGlobalTime, "Time")
<< " Events left : " << fpEventSet->size() << G4endl;
if(fVerbose > 1) {
if(fVerbose > 1)
{
fpMesh->PrintMesh();
}
G4cout << " Computing Time : " << localtimer << G4endl;
@@ -374,18 +373,14 @@ void G4DNAEventScheduler::RunInMesh()
{
InitializeInMesh();
}
G4Timer localtimerInMesh;
// if (fVerbose > 0)
if(fVerbose > 0)
{
localtimerInMesh.Start();
G4double C = 20;
G4double D = G4MoleculeTable::Instance()
->GetConfiguration("H2O2")
->GetDiffusionCoefficient();
G4double transferTime = std::pow(fpMesh->GetResolution(), 2) * C / (6 * D);
G4cout << "***G4DNAEventScheduler::RunInMesh*** for Pixel : " << fPixel
<< " transferTime : " << G4BestUnit(transferTime, "Time") << G4endl;
G4cout << " resolution : " << G4BestUnit(fpMesh->GetResolution(), "Length")
G4double resolution = fpMesh->GetResolution();
G4cout << "At Time : " << std::setw(7) << G4BestUnit(fGlobalTime, "Time")
<< " the Mesh has " << fPixel << " x " << fPixel << " x " << fPixel
<< " voxels with Resolution " << G4BestUnit(resolution, "Length")
<< " during next "
<< G4BestUnit(resolution * resolution * C / (6 * D), "Time")
<< G4endl;
}
@@ -400,6 +395,7 @@ void G4DNAEventScheduler::RunInMesh()
}
// if diffusive jumping is avaiable, EventSet is never empty
while(!fpEventSet->Empty() && !fIsChangeMesh && fEndTime > fGlobalTime)
{
Stepping();
@@ -415,37 +411,31 @@ void G4DNAEventScheduler::RunInMesh()
G4cout << "fGlobalTime : " << G4BestUnit(fGlobalTime, "Time")
<< " fTimeStep : " << G4BestUnit(fTimeStep, "Time") << G4endl;
}
G4double C = 20;
G4double D = G4MoleculeTable::Instance()
->GetConfiguration("H2O2")
->GetDiffusionCoefficient();
if(D == 0)
G4double resolution = fpMesh->GetResolution();
fTransferTime = resolution * resolution * C / (6 * D);
if(fTransferTime == 0)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "D == 0";
exceptionDescription << "fTransferTime == 0";
G4Exception("G4DNAEventScheduler::RunInMesh", "G4DNAEventScheduler001",
FatalErrorInArgument, exceptionDescription);
}
G4double transferTime = std::pow(fpMesh->GetResolution(), 2) * C / (6 * D);
// if(fStepNumberInMesh > 40000 && fPixel != 1)
if(transferTime < fTimeStep &&
fPixel != 1) // dont change Mesj if fPixel == 1
if(fTransferTime < fTimeStep &&
fPixel != 1) // dont change Mesh if fPixel == 1
{
if(fVerbose > 1)
{
G4cout << " Pixels : " << fPixel << " resolution : "
<< G4BestUnit(fpMesh->GetResolution(), "Length")
<< " fStepNumberInMesh : " << fStepNumberInMesh
<< " at fGlobalTime : " << G4BestUnit(fGlobalTime, "Time")
<< " at fTimeStep : " << G4BestUnit(fTimeStep, "Time")
<< " fReactionNumber : " << fReactionNumber
<< " transferTime : " << G4BestUnit(transferTime, "Time")
<< G4endl;
}
if(fSetChangeMesh)
{
if(fVerbose > 1)
{
G4cout << " Pixels : " << fPixel << " resolution : "
<< G4BestUnit(fpMesh->GetResolution(), "Length")
<< " fStepNumberInMesh : " << fStepNumberInMesh
<< " at fGlobalTime : " << G4BestUnit(fGlobalTime, "Time")
<< " at fTimeStep : " << G4BestUnit(fTimeStep, "Time")
<< " fReactionNumber : " << fReactionNumber
<< " transferTime : " << G4BestUnit(fTransferTime, "Time")
<< G4endl;
}
fIsChangeMesh = true;
}
}
@@ -453,11 +443,10 @@ void G4DNAEventScheduler::RunInMesh()
if(fVerbose > 1)
{
localtimerInMesh.Stop();
G4cout << "***G4DNAEventScheduler::Ending::"
<< G4BestUnit(fGlobalTime, "Time")
<< " Event left : " << fpEventSet->size() << G4endl;
G4cout << " Computing Time : " << localtimerInMesh << " Due to : ";
G4cout << " Due to : ";
if(fpEventSet->Empty())
{
G4cout << "EventSet is Empty" << G4endl;
@@ -492,18 +481,17 @@ void G4DNAEventScheduler::RunInMesh()
void G4DNAEventScheduler::Stepping() // this event loop
{
fStepNumber < fMaxStep ? fStepNumber++ : fRunning = false;
if(fpEventSet->size() > fpMesh->size())
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "fpEventSet->size() > fpMesh->size()";
exceptionDescription
<< "impossible that fpEventSet->size() > fpMesh->size()";
G4Exception("G4DNAEventScheduler::Stepping", "G4DNAEventScheduler002",
FatalErrorInArgument, exceptionDescription);
};
}
auto selected = fpEventSet->begin();
const auto& key = (*selected)->GetKey();
auto index = fpMesh->GetIndex(key);
auto selected = fpEventSet->begin();
auto index = (*selected)->GetIndex();
if(fVerbose > 1)
{
@@ -522,8 +510,31 @@ void G4DNAEventScheduler::Stepping() // this event loop
fpUpdateSystem->SetGlobalTime(fTimeStep +
fStartTime); // this is just for printing
if(pJumping == nullptr && pReaction == nullptr)
fpGillespieReaction->SetTimeStep(fTimeStep);
if(pJumping == nullptr && pReaction != nullptr)
{
fpUpdateSystem->UpdateSystem(index, *pReaction);
fpEventSet->RemoveEvent(selected);
// create new event
fpGillespieReaction->CreateEvent(index);
fReactionNumber++;
// recordTime in reaction
RecordTime();
}
else if(pJumping != nullptr && pReaction == nullptr)
{
// dont change this
fpUpdateSystem->UpdateSystem(index, *pJumping);
// save jumping Index before delete selected event
auto jumpingIndex = pJumping->second;
fpEventSet->RemoveEvent(selected);
// create new event
// should create Jumping before key
fpGillespieReaction->CreateEvent(jumpingIndex);
fpGillespieReaction->CreateEvent(index);
fJumpingNumber++;
}
else
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "pJumping == nullptr && pReaction == nullptr";
@@ -531,34 +542,6 @@ void G4DNAEventScheduler::Stepping() // this event loop
FatalErrorInArgument, exceptionDescription);
}
fpGillespieReaction->SetTimeStep(fTimeStep);
if(pJumping == nullptr)
{
fpUpdateSystem->UpdateSystem(index, *pReaction);
fpEventSet->RemoveEvent(selected);
// create new event
fpGillespieReaction->CreateEvent(key);
fReactionNumber++;
// recordTime in reaction
RecordTime();
}
else if(pReaction == nullptr)
{
// dont change this
fpUpdateSystem->UpdateSystem(index, *pJumping);
auto jumpingKey = fpMesh->GetKey(pJumping->second);
fpEventSet->RemoveEvent(selected);
// create new event
// should create Jumping before key
fpGillespieReaction->CreateEvent(jumpingKey);
fpGillespieReaction->CreateEvent(key);
fJumpingNumber++;
}
if(fVerbose > 1)
{
G4cout << "G4DNAEventScheduler::Stepping::end "
@@ -583,45 +566,23 @@ void G4DNAEventScheduler::RecordTime()
auto end = fpMesh->end();
for(; begin != end; begin++)
{
auto node = begin->second;
if(node == nullptr) {
const auto& mapData = std::get<2>(*begin);
if(mapData.empty())
{
continue;
}
for(const auto& it : node->GetMapList())
for(const auto& it : mapData)
{
fCounterMap[recordTime][it.first] += it.second;
}
}
fLastRecoredTime++;
#ifdef DEBUG
PrintRecordTime();
G4MoleculeTable* pMoleculeTable = G4MoleculeTable::Instance();
auto iter = pMoleculeTable->GetConfigurationIterator();
iter.reset();
while(iter())
{
auto conf = iter.value();
G4cout << "GlobalTime : " << G4BestUnit(fGlobalTime, "Time")
<< " recordTime : " << G4BestUnit(recordTime, "Time") << " "
<< conf->GetName()
<< " number : " << fCounterMap[recordTime][conf]
<< " MoleculeCounter : "
<< G4MoleculeCounter::Instance()->GetCurrentNumberOf(conf)
<< G4endl;
assert(G4MoleculeCounter::Instance()->GetCurrentNumberOf(conf) ==
fCounterMap[recordTime][conf]);
}
#endif
}
}
void G4DNAEventScheduler::PrintRecordTime()
{
G4cout << "fCounterMap.size : " << fCounterMap.size() << G4endl;
G4cout << "CounterMap.size : " << fCounterMap.size() << G4endl;
for(const auto& i : fCounterMap)
{
auto map = i.second;
@@ -23,7 +23,6 @@
// ********************************************************************
//
#include "G4DNAMolecularReactionTable.hh"
#include "G4DNAGillespieDirectMethod.hh"
#include "Randomize.hh"
#include "G4PhysicalConstants.hh"
@@ -33,15 +32,10 @@
#include "G4UnitsTable.hh"
#include "G4DNAScavengerMaterial.hh"
#include "G4Scheduler.hh"
#include <cassert>
#include "G4DNAMolecularReactionTable.hh"
G4DNAGillespieDirectMethod::G4DNAGillespieDirectMethod()
: fMolecularReactions(G4DNAMolecularReactionTable::Instance())
, fpMesh(nullptr)
, fTimeStep(0)
, fpEventSet(nullptr)
, fVerbose(0)
, fpScavengerMaterial(nullptr)
{}
G4DNAGillespieDirectMethod::~G4DNAGillespieDirectMethod() = default;
@@ -53,34 +47,40 @@ void G4DNAGillespieDirectMethod::SetEventSet(G4DNAEventSet* pEventSet)
//#define DEBUG 1
G4double G4DNAGillespieDirectMethod::VolumeOfNode(const Index& index)
G4double G4DNAGillespieDirectMethod::VolumeOfNode(const Voxel& voxel)
{
auto LengthY = fpMesh->GetBoundingBox(index).Getyhi() -
fpMesh->GetBoundingBox(index).Getylo();
auto LengthX = fpMesh->GetBoundingBox(index).Getxhi() -
fpMesh->GetBoundingBox(index).Getxlo();
auto LengthZ = fpMesh->GetBoundingBox(index).Getzhi() -
fpMesh->GetBoundingBox(index).Getzlo();
G4double V = LengthY * LengthX * LengthZ;
assert(V > 0);
auto box = std::get<1>(voxel);
auto LengthY = box.Getyhi() - box.Getylo();
auto LengthX = box.Getxhi() - box.Getxlo();
auto LengthZ = box.Getzhi() - box.Getzlo();
G4double V = LengthY * LengthX * LengthZ;
if(V <= 0)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "V > 0 !! ";
G4Exception("G4DNAGillespieDirectMethod::VolumeOfNode",
"G4DNAGillespieDirectMethod03", FatalErrorInArgument,
exceptionDescription);
}
return V;
}
G4double G4DNAGillespieDirectMethod::PropensityFunction(const Index& index,
G4double G4DNAGillespieDirectMethod::PropensityFunction(const Voxel& voxel,
MolType moleType)
{
if(moleType->GetDiffusionCoefficient() == 0)
{
return 0.;
}
const auto& node = fpMesh->GetVoxelMapList(index);
G4double alpha = 0;
auto it = node.find(moleType);
const auto& node = std::get<2>(voxel);
const auto& box = std::get<1>(voxel);
G4double alpha = 0;
auto it = node.find(moleType);
if(it != node.end())
{
auto LengthY = fpMesh->GetBoundingBox(index).Getyhi() -
fpMesh->GetBoundingBox(index).Getylo();
G4double d = it->first->GetDiffusionCoefficient() / std::pow(LengthY, 2);
alpha = d * it->second;
auto LengthY = box.Getyhi() - box.Getylo();
G4double d = it->first->GetDiffusionCoefficient() / std::pow(LengthY, 2);
alpha = d * it->second;
#ifdef DEBUG
G4cout << it->first->GetName() << " " << it->second
@@ -92,20 +92,20 @@ G4double G4DNAGillespieDirectMethod::PropensityFunction(const Index& index,
return alpha;
}
G4double G4DNAGillespieDirectMethod::PropensityFunction(const Index& index,
G4double G4DNAGillespieDirectMethod::PropensityFunction(const Voxel& voxel,
ReactionData* data)
{
G4double value;
auto ConfA = data->GetReactant1();
auto ConfB = data->GetReactant2();
G4double scavengerNumber = 0;
auto typeANumber = FindScavenging(index, ConfA, scavengerNumber)
? scavengerNumber
: ComputeNumberInNode(index, ConfA);
auto typeANumber = FindScavenging(voxel, ConfA, scavengerNumber)
? scavengerNumber
: ComputeNumberInNode(voxel, ConfA);
auto typeBNumber = FindScavenging(index, ConfB, scavengerNumber)
auto typeBNumber = FindScavenging(voxel, ConfB, scavengerNumber)
? scavengerNumber
: ComputeNumberInNode(index, ConfB);
: ComputeNumberInNode(voxel, ConfB);
if(typeANumber == 0 || typeBNumber == 0)
{
@@ -113,7 +113,7 @@ G4double G4DNAGillespieDirectMethod::PropensityFunction(const Index& index,
}
auto k =
data->GetObservedReactionRateConstant() / (Avogadro * VolumeOfNode(index));
data->GetObservedReactionRateConstant() / (Avogadro * VolumeOfNode(voxel));
if(ConfA == ConfB)
{
value = typeANumber * (typeBNumber - 1) * k;
@@ -125,17 +125,19 @@ G4double G4DNAGillespieDirectMethod::PropensityFunction(const Index& index,
if(value < 0)
{
G4cout << "G4DNAGillespieDirectMethod::PropensityFunction for : "
<< ConfA->GetName() << "(" << typeANumber << ") + "
<< ConfB->GetName() << "(" << typeBNumber
<< ") : propensity : " << value
<< " GetObservedReactionRateConstant : "
<< data->GetObservedReactionRateConstant()
<< " GetEffectiveReactionRadius : "
<< G4BestUnit(data->GetEffectiveReactionRadius(), "Length")
<< " k : " << k << " volume : " << VolumeOfNode(index)
<< " Index : " << index << G4endl;
assert(false);
G4ExceptionDescription exceptionDescription;
exceptionDescription
<< "G4DNAGillespieDirectMethod::PropensityFunction for : "
<< ConfA->GetName() << "(" << typeANumber << ") + " << ConfB->GetName()
<< "(" << typeBNumber << ") : propensity : " << value
<< " GetObservedReactionRateConstant : "
<< data->GetObservedReactionRateConstant()
<< " GetEffectiveReactionRadius : "
<< G4BestUnit(data->GetEffectiveReactionRadius(), "Length")
<< " k : " << k << " volume : " << VolumeOfNode(voxel) << G4endl;
G4Exception("G4DNAGillespieDirectMethod::PropensityFunction",
"G4DNAGillespieDirectMethod013", FatalErrorInArgument,
exceptionDescription);
}
#ifdef DEBUG
@@ -161,11 +163,11 @@ void G4DNAGillespieDirectMethod::Initialize()
auto end = fpMesh->end();
for(; begin != end; begin++)
{
auto key = begin->first;
auto index = std::get<0>(*begin);
#ifdef DEBUG
fpMesh->PrintVoxel(fpMesh->GetIndex(key));
fpMesh->PrintVoxel(index);
#endif
CreateEvent(key);
CreateEvent(index);
}
}
@@ -173,13 +175,22 @@ void G4DNAGillespieDirectMethod::SetTimeStep(const G4double& stepTime)
{
fTimeStep = stepTime;
}
void G4DNAGillespieDirectMethod::CreateEvent(unsigned int key)
void G4DNAGillespieDirectMethod::CreateEvent(const Index& index)
{
const auto& voxel = fpMesh->GetVoxel(index);
if(std::get<2>(voxel).empty())
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "This voxel : " << index
<< " is not ready to make event" << G4endl;
G4Exception("G4DNAGillespieDirectMethod::CreateEvent",
"G4DNAGillespieDirectMethod05", FatalErrorInArgument,
exceptionDescription);
}
G4double r1 = G4UniformRand();
G4double r2 = G4UniformRand();
auto index = fpMesh->GetIndex(key);
G4double dAlpha0 = DiffusiveJumping(index);
G4double rAlpha0 = Reaction(index);
G4double dAlpha0 = DiffusiveJumping(voxel);
G4double rAlpha0 = Reaction(voxel);
G4double alphaTotal = dAlpha0 + rAlpha0;
if(alphaTotal == 0)
@@ -202,7 +213,7 @@ void G4DNAGillespieDirectMethod::CreateEvent(unsigned int key)
<< G4endl;
}
auto rSelectedIter = fReactionDataMap.upper_bound(r2 * alphaTotal);
fpEventSet->CreateEvent(timeStep, key, rSelectedIter->second);
fpEventSet->CreateEvent(timeStep, index, rSelectedIter->second);
}
else if(dAlpha0 > 0)
{
@@ -216,26 +227,31 @@ void G4DNAGillespieDirectMethod::CreateEvent(unsigned int key)
auto dSelectedIter = fJumpingDataMap.upper_bound(r2 * alphaTotal - rAlpha0);
auto pDSelected =
std::make_unique<std::pair<MolType, Index>>(dSelectedIter->second);
fpEventSet->CreateEvent(timeStep, key, std::move(pDSelected));
fpEventSet->CreateEvent(timeStep, index, std::move(pDSelected));
}
#ifdef DEBUG
G4cout << G4endl;
#endif
}
G4double G4DNAGillespieDirectMethod::Reaction(const Index& index)
G4double G4DNAGillespieDirectMethod::Reaction(const Voxel& voxel)
{
fReactionDataMap.clear();
G4double alpha0 = 0;
auto dataList = fMolecularReactions->GetVectorOfReactionData();
const auto& dataList =
fMolecularReactions->GetVectorOfReactionData(); // shoud make a member
if(dataList.empty())
{
G4cout << "MolecularReactionTable empty" << G4endl;
assert(false);
G4ExceptionDescription exceptionDescription;
exceptionDescription << "MolecularReactionTable empty" << G4endl;
G4Exception("G4DNAGillespieDirectMethod::Reaction",
"G4DNAGillespieDirectMethod01", FatalErrorInArgument,
exceptionDescription);
}
for(const auto& it : dataList)
{
auto propensity = PropensityFunction(index, it);
auto propensity = PropensityFunction(voxel, it);
if(propensity == 0)
{
continue;
@@ -249,10 +265,11 @@ G4double G4DNAGillespieDirectMethod::Reaction(const Index& index)
return alpha0;
}
G4double G4DNAGillespieDirectMethod::DiffusiveJumping(const Index& index)
G4double G4DNAGillespieDirectMethod::DiffusiveJumping(const Voxel& voxel)
{
fJumpingDataMap.clear();
G4double alpha0 = 0;
auto index = std::get<0>(voxel);
auto NeighboringVoxels = fpMesh->FindNeighboringVoxels(index);
if(NeighboringVoxels.empty())
{
@@ -261,8 +278,8 @@ G4double G4DNAGillespieDirectMethod::DiffusiveJumping(const Index& index)
auto iter = G4MoleculeTable::Instance()->GetConfigurationIterator();
while(iter())
{
const auto conf = iter.value();
auto propensity = PropensityFunction(index, conf);
const auto* conf = iter.value();
auto propensity = PropensityFunction(voxel, conf);
if(propensity == 0)
{
continue;
@@ -286,11 +303,11 @@ G4double G4DNAGillespieDirectMethod::DiffusiveJumping(const Index& index)
}
G4double G4DNAGillespieDirectMethod::ComputeNumberInNode(
const Index& index, MolType type) // depend node ?
const Voxel& voxel, MolType type) // depend node ?
{
if(type->GetDiffusionCoefficient() != 0)
{
const auto& node = fpMesh->GetVoxelMapList(index);
const auto& node = std::get<2>(voxel);
const auto& it = node.find(type);
return (it != node.end()) ? (it->second) : 0;
}
@@ -300,7 +317,7 @@ G4double G4DNAGillespieDirectMethod::ComputeNumberInNode(
}
}
G4bool G4DNAGillespieDirectMethod::FindScavenging(const Index& index,
G4bool G4DNAGillespieDirectMethod::FindScavenging(const Voxel& voxel,
MolType moletype,
G4double& numberOfScavenger)
{
@@ -309,7 +326,7 @@ G4bool G4DNAGillespieDirectMethod::FindScavenging(const Index& index,
{
return false;
}
auto volumeOfNode = VolumeOfNode(index);
auto volumeOfNode = VolumeOfNode(voxel);
if(G4MoleculeTable::Instance()->GetConfiguration("H2O") == moletype)
{
auto factor = Avogadro * volumeOfNode;
@@ -326,19 +343,12 @@ G4bool G4DNAGillespieDirectMethod::FindScavenging(const Index& index,
}
else
{
G4double numberInDouble =
volumeOfNode * std::floor(totalNumber) / fpMesh->GetBoundingBox().Volume();
auto numberInInterg = (int) (std::floor(numberInDouble));
G4double ram = G4UniformRand();
G4double change = numberInDouble - numberInInterg;
if(ram > change)
{
numberOfScavenger = numberInInterg;
}
else
{
numberOfScavenger = numberInInterg + 1;
}
G4double numberInDouble = volumeOfNode * std::floor(totalNumber) /
fpMesh->GetBoundingBox().Volume();
auto numberInInterg = (int64_t) (std::floor(numberInDouble));
G4double change = numberInDouble - numberInInterg;
G4UniformRand() > change ? numberOfScavenger = numberInInterg
: numberOfScavenger = numberInInterg + 1;
return true;
}
}
@@ -243,6 +243,12 @@ void G4DNAIRT::Sampling(G4Track* track){
auto fReactionDatas = fMolReactionTable->GetReactionData(molConfA);
G4double index = -1;
//change the scavenging filter of the IRT beyond 1 us proposed by Naoki and Jose
if(timeMax > 1*us)
{
minTime = timeMax;
}
//
for(size_t u=0; u<fReactionDatas->size();u++){
if((*fReactionDatas)[u]->GetReactant2()->GetDiffusionCoefficient() == 0){
@@ -1,642 +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. *
// ********************************************************************
//
/*
* G4DNAIRT_geometries.cc
*
* Created on: Jul 23, 2019
* Author: W. G. Shin
* J. Ramos-Mendez and B. Faddegon
*/
#include "G4DNAIRT_geometries.hh"
#include "G4ErrorFunction.hh"
#include "G4SystemOfUnits.hh"
#include "G4PhysicalConstants.hh"
#include "Randomize.hh"
#include "G4DNAMolecularReactionTable.hh"
#include "G4MolecularConfiguration.hh"
#include "G4Molecule.hh"
#include "G4ITReactionChange.hh"
#include "G4ITTrackHolder.hh"
#include "G4ITReaction.hh"
#include "G4Scheduler.hh"
#include "G4MoleculeTable.hh"
#include "G4NavigationHistory.hh"
#include "G4DNAMolecularMaterial.hh"
#include "G4VDNAMolecularGeometry.hh"
using namespace std;
G4DNAIRT_geometries::G4DNAIRT_geometries() :
G4VITReactionProcess(),
fMolReactionTable(reference_cast<const G4DNAMolecularReactionTable*>(fpReactionTable)),
fpReactionModel(nullptr),
fTrackHolder(G4ITTrackHolder::Instance()),
fReactionSet(nullptr),
fGeometry(nullptr)
{
timeMin = G4Scheduler::Instance()->GetStartTime();
timeMax = G4Scheduler::Instance()->GetEndTime();
fXMin = 1e9*nm;
fYMin = 1e9*nm;
fZMin = 1e9*nm;
fXMax = 0e0*nm;
fYMax = 0e0*nm;
fZMax = 0e0*nm;
fNx = 0;
fNy = 0;
fNz = 0;
xiniIndex = 0, yiniIndex = 0, ziniIndex = 0;
xendIndex = 0, yendIndex = 0, zendIndex = 0;
fRCutOff =
1.45 * nm + 2 * std::sqrt(8*9.46e9*nm*nm/s * timeMax); // 95% confidence level
erfc = new G4ErrorFunction();
}
G4DNAIRT_geometries::G4DNAIRT_geometries(G4VDNAReactionModel* pReactionModel)
: G4DNAIRT_geometries()
{
fpReactionModel = pReactionModel;
}
G4DNAIRT_geometries::~G4DNAIRT_geometries()
{
delete erfc;
}
void G4DNAIRT_geometries::Initialize(){
timeMin = G4Scheduler::Instance()->GetGlobalTime();
timeMax = std::min(timeMin + G4Scheduler::Instance()->GetLimitingTimeStep(),
G4Scheduler::Instance()->GetEndTime());
if(timeMin == 0) return;
fTrackHolder = G4ITTrackHolder::Instance();
if(fTrackHolder->GetMainList()->size() == 0) return;
fReactionSet = G4ITReactionSet::Instance();
fReactionSet->CleanAllReaction();
fReactionSet->SortByTime();
spaceBinned.clear();
positionMap.clear();
fRCutOff =
1.45 * nm + 2 * std::sqrt(8*9.46e9*nm*nm/s * (timeMax - timeMin));
xiniIndex = 0;
yiniIndex = 0;
ziniIndex = 0;
xendIndex = 0;
yendIndex = 0;
zendIndex = 0;
fXMin = 1e9*nm;
fYMin = 1e9*nm;
fZMin = 1e9*nm;
fXMax = 0e0*nm;
fYMax = 0e0*nm;
fZMax = 0e0*nm;
fNx = 0;
fNy = 0;
fNz = 0;
fGeometry = fMolReactionTable->GetGeometry();
SpaceBinning(); // 1. binning the space
IRTSampling(); // 2. Sampling of the IRT
}
void G4DNAIRT_geometries::SpaceBinning(){
G4double time_step = G4Scheduler::Instance()->GetPreviousTimeStep()*ps;
auto it_begin = fTrackHolder->GetMainList()->begin();
while(it_begin != fTrackHolder->GetMainList()->end()){
// for diffusion
G4double D = GetMolecule(*it_begin)->GetDiffusionCoefficient();
G4double sqrt_2Dt = sqrt(2 * D * time_step);
G4double x = G4RandGauss::shoot(0,sqrt_2Dt);
G4double y = G4RandGauss::shoot(0,sqrt_2Dt);
G4double z = G4RandGauss::shoot(0,sqrt_2Dt);
G4ThreeVector position_ori = it_begin->GetPosition();
G4ThreeVector position = position_ori + G4ThreeVector(x,y,z);
it_begin->SetPosition(position);
it_begin->SetGlobalTime(timeMax);
if ( fXMin > position.x() ) fXMin = position.x();
if ( fYMin > position.y() ) fYMin = position.y();
if ( fZMin > position.z() ) fZMin = position.z();
if ( fXMax < position.x() ) fXMax = position.x();
if ( fYMax < position.y() ) fYMax = position.y();
if ( fZMax < position.z() ) fZMax = position.z();
++it_begin;
}
fNx = G4int((fXMax-fXMin)/fRCutOff) == 0 ? 1 : G4int((fXMax-fXMin)/fRCutOff);
fNy = G4int((fYMax-fYMin)/fRCutOff) == 0 ? 1 : G4int((fYMax-fYMin)/fRCutOff);
fNz = G4int((fZMax-fZMin)/fRCutOff) == 0 ? 1 : G4int((fZMax-fZMin)/fRCutOff);
}
void G4DNAIRT_geometries::IRTSampling(){
auto it_begin = fTrackHolder->GetMainList()->begin();
while(it_begin != fTrackHolder->GetMainList()->end()){
G4int I = FindBin(fNx, fXMin, fXMax, it_begin->GetPosition().x());
G4int J = FindBin(fNy, fYMin, fYMax, it_begin->GetPosition().y());
G4int K = FindBin(fNz, fZMin, fZMax, it_begin->GetPosition().z());
spaceBinned[I][J][K].push_back(*it_begin);
Sampling(*it_begin);
++it_begin;
}
}
void G4DNAIRT_geometries::Sampling(G4Track* track){
G4Molecule* molA = G4Molecule::GetMolecule(track);
const G4MolecularConfiguration* molConfA = molA->GetMolecularConfiguration();
if(molConfA->GetDiffusionCoefficient() == 0) return;
const vector<const G4MolecularConfiguration*>* reactivesVector =
fMolReactionTable->CanReactWith(molConfA);
if(reactivesVector == nullptr) return;
G4double globalTime = G4Scheduler::Instance()->GetGlobalTime();
G4double minTime = timeMax;
xiniIndex = FindBin(fNx, fXMin, fXMax, track->GetPosition().x()-fRCutOff);
xendIndex = FindBin(fNx, fXMin, fXMax, track->GetPosition().x()+fRCutOff);
yiniIndex = FindBin(fNy, fYMin, fYMax, track->GetPosition().y()-fRCutOff);
yendIndex = FindBin(fNy, fYMin, fYMax, track->GetPosition().y()+fRCutOff);
ziniIndex = FindBin(fNz, fZMin, fZMax, track->GetPosition().z()-fRCutOff);
zendIndex = FindBin(fNz, fZMin, fZMax, track->GetPosition().z()+fRCutOff);
for ( G4int ii = xiniIndex; ii <= xendIndex; ++ii ) {
for ( G4int jj = yiniIndex; jj <= yendIndex; ++jj ) {
for ( G4int kk = ziniIndex; kk <= zendIndex; ++kk ) {
std::vector<G4Track*> spaceBin = spaceBinned[ii][jj][kk];
for ( G4int n = 0; n < (G4int)spaceBinned[ii][jj][kk].size(); ++n ) {
if(!spaceBin[n] || track == spaceBin[n]) continue;
if(spaceBin[n]->GetTrackStatus() == fStopButAlive) continue;
G4Molecule* molB = G4Molecule::GetMolecule(spaceBin[n]);
if(!molB) continue;
const G4MolecularConfiguration* molConfB = molB->GetMolecularConfiguration();
if(molConfB->GetDiffusionCoefficient() == 0) continue;
auto it = std::find(reactivesVector->begin(), reactivesVector->end(), molConfB);
if(it == reactivesVector->end()) continue;
G4ThreeVector orgPosB = spaceBin[n]->GetPosition();
G4double dt = track->GetGlobalTime() - spaceBin[n]->GetGlobalTime();
G4ThreeVector newPosB = orgPosB;
if(dt > 0){
G4double sigma, x, y, z;
G4double diffusionCoefficient = G4Molecule::GetMolecule(spaceBin[n])->GetDiffusionCoefficient();
sigma = std::sqrt(2.0 * diffusionCoefficient * dt);
x = G4RandGauss::shoot(0., 1.0)*sigma;
y = G4RandGauss::shoot(0., 1.0)*sigma;
z = G4RandGauss::shoot(0., 1.0)*sigma;
newPosB = orgPosB + G4ThreeVector(x,y,z);
}else if(dt < 0) continue;
G4double r0 = (newPosB - track->GetPosition()).mag();
G4double irt = GetIndependentReactionTime(molConfA,
molConfB,
r0);
if(irt>=0 && irt<timeMax - globalTime)
{
irt += globalTime;
if(irt < minTime) minTime = irt;
#ifdef DEBUG
G4cout<<irt<<'\t'<<molConfA->GetName()<<" "<<track->GetTrackID()<<'\t'<<molConfB->GetName()<<" "<<spaceBin[n]->GetTrackID()<<'\n';
#endif
fReactionSet->AddReaction(irt,track,spaceBin[n]);
}
}
spaceBin.clear();
}
}
}
// Scavenging & first order reactions
auto fReactionDatas = fMolReactionTable->GetReactionData(molConfA);
G4int index = -1;
for(size_t u=0; u<fReactionDatas->size();++u){
auto molB = (*fReactionDatas)[u]->GetReactant2();
if(molB == G4MoleculeTable::Instance()->GetConfiguration("H2O(B)") ||
molB == G4MoleculeTable::Instance()->GetConfiguration("H3Op(B)") ||
molB == G4MoleculeTable::Instance()->GetConfiguration("OHm(B)")){
G4double kObs = (*fReactionDatas)[u]->GetObservedReactionRateConstant();
if(kObs == 0) continue;
G4double time = -(std::log(1.0 - G4UniformRand())/kObs) + globalTime;
if( time < minTime && time >= globalTime && time < timeMax){
minTime = time;
index = (G4int)u;
}
}
}
if(index != -1){
#ifdef DEBUG
G4cout<<"scavenged: "<<minTime<<'\t'<<molConfA->GetName()<<it_begin->GetTrackID()<<'\n';
#endif
G4Molecule* fakeMol = new G4Molecule((*fReactionDatas)[index]->GetReactant2());
G4Track* fakeTrack = fakeMol->BuildTrack(globalTime,track->GetPosition());
fTrackHolder->Push(fakeTrack);
fReactionSet->AddReaction(minTime, track, fakeTrack);
}
// DNA reactions
if(fGeometry == nullptr) return;
const G4VTouchable* touchable = track->GetTouchable();
if(touchable == nullptr) return;
const G4LogicalVolume* logicalVolume = touchable->GetVolume()->GetLogicalVolume();
const G4ThreeVector& globalPos = track->GetPosition();
const G4ThreeVector& localPos = touchable->GetHistory()->GetTopTransform().TransformPoint(globalPos);
G4double D = GetMolecule(track)->GetDiffusionCoefficient();
G4double time_step = abs(timeMax - timeMin);
G4double search_range = 2*sqrt(2*D*time_step);
std::vector<G4VPhysicalVolume*> result_pv;
result_pv.clear();
fGeometry->FindNearbyMolecules(logicalVolume,
localPos,
result_pv,
search_range);
if(result_pv.empty()) return;
for(auto physicalVolume : result_pv){
const G4Material* material = physicalVolume->GetLogicalVolume()->GetMaterial();
G4MolecularConfiguration* dna_molConf =
G4DNAMolecularMaterial::Instance()->GetMolecularConfiguration(material);
auto it = std::find(reactivesVector->begin(), reactivesVector->end(), dna_molConf);
if(it == reactivesVector->end()) continue;
G4ThreeVector pos = physicalVolume->GetTranslation();
G4ThreeVector globalPos_DNA = touchable->GetHistory()->GetTopTransform().Inverse().TransformPoint(pos);
G4double r0 = (pos - localPos).mag();
G4double irt = GetIndependentReactionTime(molConfA,dna_molConf,r0);
if(irt>=0 && irt<timeMax - globalTime)
{
index = -1;
for(size_t i=0;i<positionMap.size();++i){
if(globalPos_DNA == positionMap[i].first){
index = (G4int)i;
break;
}
}
G4Track* DNATrack;
if(index == -1){
auto DNAMol = new G4Molecule(dna_molConf);
DNATrack = DNAMol->BuildTrack(globalTime,globalPos_DNA);
DNATrack->SetTrackStatus(fAlive);
fTrackHolder->Push(DNATrack);
positionMap.push_back(std::make_pair(globalPos_DNA,DNATrack));
}else{
DNATrack = positionMap[index].second;
}
irt += globalTime;
if(irt < minTime) minTime = irt;
#ifdef DEBUG
G4cout<<irt<<'\t'<<globalPos_DNA<<'\t'<<molConfA->GetName()<<" "<<track->GetTrackID()<<'\t'<<dna_molConf->GetName()<<" "<<DNATrack->GetTrackID()<<'\n';
#endif
fReactionSet->AddReaction(irt,track,DNATrack);
}
}
}
G4double G4DNAIRT_geometries::GetIndependentReactionTime(const G4MolecularConfiguration* molA, const G4MolecularConfiguration* molB, G4double distance) {
const auto pMoleculeA = molA;
const auto pMoleculeB = molB;
auto fReactionData = fMolReactionTable->GetReactionData(pMoleculeA, pMoleculeB);
G4int reactionType = fReactionData->GetReactionType();
G4double r0 = distance;
if(r0 == 0) r0 += 1e-3*nm;
G4double irt = -1 * ps;
G4double D = molA->GetDiffusionCoefficient() +
molB->GetDiffusionCoefficient();
if(D == 0) D += 1e-20*(m2/s);
G4double rc = fReactionData->GetOnsagerRadius();
if ( reactionType == 0){
G4double sigma = fReactionData->GetEffectiveReactionRadius();
if(sigma > r0) return 0; // contact reaction
if( rc != 0) r0 = -rc / (1-std::exp(rc/r0));
G4double Winf = sigma/r0;
G4double W = G4UniformRand();
if ( W > 0 && W < Winf ) irt = (0.25/D) * std::pow( (r0-sigma)/erfc->erfcInv(r0*W/sigma), 2 );
return irt;
}
else if ( reactionType == 1 ){
G4double sigma = fReactionData->GetReactionRadius();
G4double kact = fReactionData->GetActivationRateConstant();
G4double kdif = fReactionData->GetDiffusionRateConstant();
G4double kobs = fReactionData->GetObservedReactionRateConstant();
G4double a, b, Winf;
if ( rc == 0 ) {
a = 1/sigma * kact / kobs;
b = (r0 - sigma) / 2;
} else {
G4double v = kact/Avogadro/(4*CLHEP::pi*pow(sigma,2) * exp(-rc / sigma));
G4double alpha = v+rc*D/(pow(sigma,2)*(1-exp(-rc/sigma)));
a = 4*pow(sigma,2)*alpha/(D*pow(rc,2))*pow(sinh(rc/(2*sigma)),2);
b = rc/4*(cosh(rc/(2*r0))/sinh(rc/(2*r0))-cosh(rc/(2*sigma))/sinh(rc/(2*sigma)));
r0 = -rc/(1-std::exp(rc/r0));
sigma = fReactionData->GetEffectiveReactionRadius();
}
if(sigma > r0){
if(fReactionData->GetProbability() > G4UniformRand()) return 0;
else return irt;
}
Winf = sigma / r0 * kobs / kdif;
if(Winf > G4UniformRand()) irt = SamplePDC(a,b)/D;
return irt;
}
return -1 * ps;
}
G4int G4DNAIRT_geometries::FindBin(G4int n, G4double xmin, G4double xmax, G4double value) {
G4int bin = -1;
if ( value <= xmin )
bin = 0; //1;
else if ( value >= xmax) //!(xmax < value) ) //value >= xmax )
bin = n-1; //n;
else
bin = G4int( n * ( value - xmin )/( xmax - xmin ) ); //bin = 1 + G4int( n * ( value - xmin )/( xmax - xmin ) );
if ( bin < 0 ) bin = 0;
if ( bin >= n ) bin = n-1;
return bin;
}
G4double G4DNAIRT_geometries::SamplePDC(G4double a, G4double b) {
G4double p = 2.0 * std::sqrt(2.0*b/a);
G4double q = 2.0 / std::sqrt(2.0*b/a);
G4double M = max(1.0/(a*a),3.0*b/a);
G4double X, U, lambdax;
G4int ntrials = 0;
while(1) {
// Generate X
U = G4UniformRand();
if ( U < p/(p + q * M) ) X = pow(U * (p + q * M) / 2, 2);
else X = pow(2/((1-U)*(p+q*M)/M),2);
U = G4UniformRand();
lambdax = std::exp(-b*b/X) * ( 1.0 - a * std::sqrt(CLHEP::pi * X) * erfc->erfcx(b/std::sqrt(X) + a*std::sqrt(X)));
if ((X <= 2.0*b/a && U <= lambdax) ||
(X >= 2.0*b/a && U*M/X <= lambdax)) break;
ntrials++;
if ( ntrials > 10000 ){
G4cout<<"Totally rejected"<<'\n';
return -1.0;
}
}
return X;
}
std::unique_ptr<G4ITReactionChange> G4DNAIRT_geometries::MakeReaction(const G4Track& trackA,
const G4Track& trackB)
{
std::unique_ptr<G4ITReactionChange> pChanges(new G4ITReactionChange());
pChanges->Initialize(trackA, trackB);
const auto pMoleculeA = GetMolecule(trackA)->GetMolecularConfiguration();
const auto pMoleculeB = GetMolecule(trackB)->GetMolecularConfiguration();
const auto pReactionData = fMolReactionTable->GetReactionData(pMoleculeA, pMoleculeB);
G4double globalTime = G4Scheduler::Instance()->GetGlobalTime();
G4double effectiveReactionRadius = pReactionData->GetEffectiveReactionRadius();
const G4double D1 = pMoleculeA->GetDiffusionCoefficient();
const G4double D2 = pMoleculeB->GetDiffusionCoefficient();
G4ThreeVector r1 = trackA.GetPosition();
G4ThreeVector r2 = trackB.GetPosition();
if(r1 == r2) r2 += G4ThreeVector(0,0,1e-3*nm);
G4ThreeVector S1 = r1 - r2;
G4double r0 = S1.mag();
S1.setMag(effectiveReactionRadius);
G4double dt = globalTime - trackA.GetGlobalTime();
if(dt != 0 && (D1 + D2) != 0 && r0 != 0){
G4double s12 = 2.0 * D1 * dt;
G4double s22 = 2.0 * D2 * dt;
if(s12 == 0) r2 = r1;
else if(s22 == 0) r1 = r2;
else{
G4double alpha = effectiveReactionRadius * r0 / (2*(D1 + D2)*dt);
G4ThreeVector S2 = (r1 + (s12 / s22)*r2) + G4ThreeVector(G4RandGauss::shoot(0, s12 + s22 * s22 / s12),
G4RandGauss::shoot(0, s12 + s22 * s22 / s12),
G4RandGauss::shoot(0, s12 + s22 * s22 / s12));
S1.setPhi(rad * G4UniformRand() * 2.0 * CLHEP::pi);
S1.setTheta(rad * std::acos(1.0 + 1./alpha * std::log(1.0 - G4UniformRand() * (1 - std::exp(-2.0 * alpha)))));
r1 = (D1 * S1 + D2 * S2) / (D1 + D2);
r2 = D2 * (S2 - S1) / (D1 + D2);
}
}
auto pTrackA = const_cast<G4Track*>(pChanges->GetTrackA());
auto pTrackB = const_cast<G4Track*>(pChanges->GetTrackB());
pTrackA->SetPosition(r1);
pTrackB->SetPosition(r2);
pTrackA->SetGlobalTime(globalTime);
pTrackB->SetGlobalTime(globalTime);
pTrackA->SetTrackStatus(fStopButAlive);
pTrackB->SetTrackStatus(fStopButAlive);
const G4int nbProducts = pReactionData->GetNbProducts();
if(nbProducts){
const G4double sqrD1 = D1 == 0. ? 0. : std::sqrt(D1);
const G4double sqrD2 = D2 == 0. ? 0. : std::sqrt(D2);
const G4double inv_numerator = 1./(sqrD1 + sqrD2);
const G4ThreeVector reactionSite = sqrD2 * inv_numerator * trackA.GetPosition()
+ sqrD1 * inv_numerator * trackB.GetPosition();
std::vector<G4ThreeVector> position;
if(nbProducts == 1){
position.push_back(reactionSite);
}else if(nbProducts == 2){
position.push_back(trackA.GetPosition());
position.push_back(trackB.GetPosition());
}else if (nbProducts == 3){
position.push_back(reactionSite);
position.push_back(trackA.GetPosition());
position.push_back(trackB.GetPosition());
}
for(G4int u = 0; u < nbProducts; ++u){
auto product = new G4Molecule(pReactionData->GetProduct(u));
auto productTrack = product->BuildTrack(globalTime,
position[u]);
productTrack->SetTrackStatus(fAlive);
fTrackHolder->Push(productTrack);
pChanges->AddSecondary(productTrack);
G4int I = FindBin(fNx, fXMin, fXMax, position[u].x());
G4int J = FindBin(fNy, fYMin, fYMax, position[u].y());
G4int K = FindBin(fNz, fZMin, fZMax, position[u].z());
spaceBinned[I][J][K].push_back(productTrack);
Sampling(productTrack);
}
}
fTrackHolder->MergeSecondariesWithMainList();
pChanges->KillParents(true);
return pChanges;
}
std::vector<std::unique_ptr<G4ITReactionChange>> G4DNAIRT_geometries::FindReaction(
G4ITReactionSet* pReactionSet,
const G4double /*currentStepTime*/,
const G4double fGlobalTime,
const G4bool /*reachedUserStepTimeLimit*/)
{
std::vector<std::unique_ptr<G4ITReactionChange>> fReactionInfo;
fReactionInfo.clear();
if (pReactionSet == nullptr)
{
return fReactionInfo;
}
auto fReactionsetInTime = pReactionSet->GetReactionsPerTime();
assert(fReactionsetInTime.begin() != fReactionsetInTime.end());
auto it_begin = fReactionsetInTime.begin();
while(it_begin != fReactionsetInTime.end())
{
G4double irt = it_begin->get()->GetTime();
if(fGlobalTime < irt) break;
pReactionSet->SelectThisReaction(*it_begin);
G4Track* pTrackA = it_begin->get()->GetReactants().first;
G4Track* pTrackB = it_begin->get()->GetReactants().second;
auto pReactionChange = MakeReaction(*pTrackA, *pTrackB);
if(pReactionChange){
fReactionInfo.push_back(std::move(pReactionChange));
}
fReactionsetInTime = pReactionSet->GetReactionsPerTime();
it_begin = fReactionsetInTime.begin();
}
return fReactionInfo;
}
G4bool G4DNAIRT_geometries::TestReactibility(const G4Track& /*trackA*/,
const G4Track& /*trackB*/,
G4double /*currentStepTime*/,
G4bool /*userStepTimeLimit*/) /*const*/
{
return true;
}
void G4DNAIRT_geometries::SetReactionModel(G4VDNAReactionModel* model)
{
fpReactionModel = model;
}
@@ -27,108 +27,102 @@
#include "globals.hh"
#include "G4DNAMakeReaction.hh"
#include <G4DNAMolecularReactionTable.hh>
#include <memory>
#include "G4DNAIndependentReactionTimeModel.hh"
#include "G4DNAIndependentReactionTimeStepper.hh"
#include "G4DiffusionControlledReactionModel.hh"
#include "G4Molecule.hh"
#include "G4ReferenceCast.hh"
#include "G4VDNAReactionModel.hh"
#include "G4DNAReactionTypeManager.hh"
#include "G4ChemicalMoleculeFinder.hh"
G4DNAIndependentReactionTimeModel::G4DNAIndependentReactionTimeModel(const G4String& name)
: G4DNAIndependentReactionTimeModel(name,
std::unique_ptr<G4DNAIndependentReactionTimeStepper>
(new G4DNAIndependentReactionTimeStepper()),
std::unique_ptr<G4DNAMakeReaction>
(new G4DNAMakeReaction()))
G4DNAIndependentReactionTimeModel::G4DNAIndependentReactionTimeModel(
const G4String& name)
: G4DNAIndependentReactionTimeModel(
name, std::make_unique<G4DNAIndependentReactionTimeStepper>(),
std::make_unique<G4DNAMakeReaction>())
{}
G4DNAIndependentReactionTimeModel::G4DNAIndependentReactionTimeModel(const G4String& name,
std::unique_ptr<G4VITTimeStepComputer> pTimeStepper,
std::unique_ptr<G4VITReactionProcess> pReactionProcess)
: G4VITStepModel(std::move(pTimeStepper),
std::move(pReactionProcess),
name)
, fMolecularReactionTable(reference_cast<const G4DNAMolecularReactionTable*>(fpReactionTable))
G4DNAIndependentReactionTimeModel::G4DNAIndependentReactionTimeModel(
const G4String& name, std::unique_ptr<G4VITTimeStepComputer> pTimeStepper,
std::unique_ptr<G4VITReactionProcess> pReactionProcess)
: G4VITStepModel(std::move(pTimeStepper), std::move(pReactionProcess), name)
{
fType1 = G4Molecule::ITType();
fType2 = G4Molecule::ITType();
fType1 = G4Molecule::ITType();
fType2 = G4Molecule::ITType();
}
G4DNAIndependentReactionTimeModel::~G4DNAIndependentReactionTimeModel() = default;
G4DNAIndependentReactionTimeModel::~G4DNAIndependentReactionTimeModel() =
default;
void G4DNAIndependentReactionTimeModel::Initialize()
{
if(fpReactionTable == nullptr)
{
SetReactionTable(G4DNAMolecularReactionTable::GetReactionTable());
}
if(fpReactionTable == nullptr)
{
SetReactionTable(G4DNAMolecularReactionTable::GetReactionTable());
}
if(!fpReactionModel)
{
fpReactionModel.reset(new G4DiffusionControlledReactionModel());
}
if(!fpReactionModel)
{
fpReactionModel = std::make_unique<G4DiffusionControlledReactionModel>();
}
fpReactionModel->SetReactionTable((const G4DNAMolecularReactionTable*) fpReactionTable);
fpReactionModel->SetReactionTable(
(const G4DNAMolecularReactionTable*) fpReactionTable);
((G4DiffusionControlledReactionModel*) fpReactionModel.get())->SetReactionTypeManager(fReactionTypeManager.get());
((G4DNAMakeReaction*) fpReactionProcess.get())
->SetReactionModel(fpReactionModel.get());
((G4DNAMakeReaction*) fpReactionProcess.get())->SetReactionModel(fpReactionModel.get());
((G4DNAMakeReaction*) fpReactionProcess.get())
->SetTimeStepComputer(fpTimeStepper.get());
((G4DNAMakeReaction*) fpReactionProcess.get())->SetTimeStepComputer(fpTimeStepper.get());
((G4DNAIndependentReactionTimeStepper*) fpTimeStepper.get())->SetReactionModel(fpReactionModel.get());
((G4DNAIndependentReactionTimeStepper*) fpTimeStepper.get())
->SetReactionModel(fpReactionModel.get());
((G4DNAIndependentReactionTimeStepper*) fpTimeStepper.get())->SetReactionTypeManager(fReactionTypeManager.get());
((G4DNAIndependentReactionTimeStepper*) fpTimeStepper.get())
->SetReactionProcess((fpReactionProcess).get());
((G4DNAIndependentReactionTimeStepper*) fpTimeStepper.get())->SetReactionProcess((fpReactionProcess).get());
G4ChemicalMoleculeFinder::Instance()->Clear();
G4VITStepModel::Initialize();
G4ChemicalMoleculeFinder::Instance()->Clear();
G4ChemicalMoleculeFinder::Instance()->SetOctreeUsed(true);
G4VITStepModel::Initialize();
}
void G4DNAIndependentReactionTimeModel::PrintInfo()
{
#ifdef G4VERBOSE
if(G4Threading::IsMultithreadedApplication())
if(G4Threading::IsMultithreadedApplication())
{
if(G4Threading::G4GetThreadId() == 0)
{
if(G4Threading::G4GetThreadId() == 0)
{
G4VITStepModel::PrintInfo();
G4cout<<G4endl;
G4cout << fName << " will be used ==========================" << G4endl;
G4cout<<G4endl;
G4cout << "==============================="
"========================================"<<G4endl;
G4cout<<G4endl;
}
}
else
{
G4VITStepModel::PrintInfo();
G4cout<<G4endl;
G4cout << fName << " will be used ==========================" << G4endl;
G4cout<<G4endl;
G4cout << "==============================="
"========================================"<<G4endl;
G4cout<<G4endl;
G4VITStepModel::PrintInfo();
G4cout << G4endl;
G4cout << fName << " will be used ==========================" << G4endl;
G4cout << G4endl;
G4cout << "==============================="
"========================================"
<< G4endl;
G4cout << G4endl;
}
}
else
{
G4VITStepModel::PrintInfo();
G4cout << G4endl;
G4cout << fName << " will be used ==========================" << G4endl;
G4cout << G4endl;
G4cout << "==============================="
"========================================"
<< G4endl;
G4cout << G4endl;
}
#endif
}
void G4DNAIndependentReactionTimeModel::SetReactionModel(G4VDNAReactionModel* pReactionModel)
void G4DNAIndependentReactionTimeModel::SetReactionModel(
G4VDNAReactionModel* pReactionModel)
{
fpReactionModel.reset(pReactionModel);
fpReactionModel.reset(pReactionModel);
}
G4VDNAReactionModel* G4DNAIndependentReactionTimeModel::GetReactionModel()
{
return fpReactionModel.get();
}
void G4DNAIndependentReactionTimeModel::SetReactionTypeManager(G4VReactionTypeManager* pReactionProcessManager)
{
fReactionTypeManager.reset(pReactionProcessManager);
}
return fpReactionModel.get();
}
@@ -25,465 +25,452 @@
// 20/2/2019
// Author: HoangTRAN
#include <memory>
#include "G4DNAIndependentReactionTimeStepper.hh"
#include "G4VDNAReactionModel.hh"
#include "G4DNAMolecularReactionTable.hh"
#include "G4memory.hh"
#include "G4UnitsTable.hh"
#include "G4Molecule.hh"
#include "G4ChemicalMoleculeFinder.hh"
#include "G4MolecularConfiguration.hh"
#include "G4DNAChemistryManager.hh"
#include "G4DNAReactionTypeManager.hh"
#include "G4DNAMakeReaction.hh"
#include "G4ITReaction.hh"
#include "G4ITReactionChange.hh"
#include "G4Scheduler.hh"
#include "G4ITTrackHolder.hh"
#include "G4IRTUtils.hh"
#include "Randomize.hh"
#include "G4DiffusionControlledReactionModel.hh"
using namespace std;
using namespace CLHEP;
G4DNAIndependentReactionTimeStepper::Utils::Utils(const G4Track& trackA,
const G4Track& trackB)
: fTrackA(trackA)
, fTrackB(trackB)
: fTrackA(trackA)
, fTrackB(trackB)
{
fpMoleculeA = GetMolecule(trackA);
fpMoleculeB = GetMolecule(trackA);
fpMoleculeA = GetMolecule(trackA);
fpMoleculeB = GetMolecule(trackA);
}
G4DNAIndependentReactionTimeStepper::G4DNAIndependentReactionTimeStepper()
: G4VITTimeStepComputer()
, fHasAlreadyReachedNullTime(false)
, fMolecularReactionTable(reference_cast<const G4DNAMolecularReactionTable*>(fpReactionTable))
, fReactionModel(nullptr)
, fpTrackContainer(G4ITTrackHolder::Instance())
, fReactionSet(G4ITReactionSet::Instance())
, fVerbose(0)
, fRCutOff(G4IRTUtils::GetRCutOff())
, fReactionTypeManager(nullptr)
, fpReactionProcess(nullptr)
: G4VITTimeStepComputer()
{
fReactionSet->SortByTime();
fReactionSet->SortByTime();
}
void G4DNAIndependentReactionTimeStepper::Prepare()
{
G4VITTimeStepComputer::Prepare();
fSampledPositions.clear();
BuildChemicalMoleculeFinder()
G4VITTimeStepComputer::Prepare();
fSampledPositions.clear();
BuildChemicalMoleculeFinder()
}
void G4DNAIndependentReactionTimeStepper::InitializeForNewTrack()
{
if (fReactants != nullptr)
{
fReactants.reset();
}
fSampledMinTimeStep = DBL_MAX;
fHasAlreadyReachedNullTime = false;
if(fReactants != nullptr)
{
fReactants.reset();
}
fSampledMinTimeStep = DBL_MAX;
fHasAlreadyReachedNullTime = false;
}
template<typename T>
inline G4bool IsInf(T value)
G4double G4DNAIndependentReactionTimeStepper::CalculateStep(
const G4Track& trackA, const G4double& userMinTimeStep)
{
return std::numeric_limits<T>::has_infinity
&& value == std::numeric_limits<T>::infinity();
}
G4double
G4DNAIndependentReactionTimeStepper::CalculateStep(const G4Track& trackA,
const G4double& userMinTimeStep)
{
auto pMoleculeA = GetMolecule(trackA);
InitializeForNewTrack();
fUserMinTimeStep = userMinTimeStep;
auto pMoleculeA = GetMolecule(trackA);
InitializeForNewTrack();
fUserMinTimeStep = userMinTimeStep;
fCheckedTracks.insert(trackA.GetTrackID());
#ifdef G4VERBOSE
if (fVerbose)
{
G4cout
<< "_______________________________________________________________________"
<< G4endl;
G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep" << G4endl;
G4cout << "Check done for molecule : " << pMoleculeA->GetName()
<< " (" << trackA.GetTrackID() << ") "
<< G4endl;
}
if(fVerbose != 0)
{
G4cout << "________________________________________________________________"
"_______"
<< G4endl;
G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep" << G4endl;
G4cout << "Check done for molecule : " << pMoleculeA->GetName() << " ("
<< trackA.GetTrackID() << ") " << G4endl;
}
#endif
auto pMolConfA = pMoleculeA->GetMolecularConfiguration();
auto pMolConfA = pMoleculeA->GetMolecularConfiguration();
const auto pReactantList = fMolecularReactionTable->CanReactWith(pMolConfA);
const auto pReactantList = fMolecularReactionTable->CanReactWith(pMolConfA);
if (!pReactantList)
{
if(pReactantList == nullptr)
{
#ifdef G4VERBOSE
if (fVerbose > 1)
{
G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
G4cout << "!!! WARNING" << G4endl;
G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep will return infinity "
if(fVerbose > 1)
{
G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
G4cout << "!!! WARNING" << G4endl;
G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep will "
"return infinity "
"for the reaction because the molecule "
<< pMoleculeA->GetName()
<< " does not have any reactants given in the reaction table."
<< G4endl;
G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
}
#endif
return DBL_MAX;
<< pMoleculeA->GetName()
<< " does not have any reactants given in the reaction table."
<< G4endl;
G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
}
#endif
return DBL_MAX;
}
G4int nbReactives = pReactantList->size();
G4int nbReactives = pReactantList->size();
if (nbReactives == 0)
{
if(nbReactives == 0)
{
#ifdef G4VERBOSE
// DEBUG
if (fVerbose)
{
G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
G4cout << "!!! WARNING" << G4endl;
G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep will return infinity "
// DEBUG
if(fVerbose != 0)
{
G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
G4cout << "!!! WARNING" << G4endl;
G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep will "
"return infinity "
"for the reaction because the molecule "
<< pMoleculeA->GetName()
<< " does not have any reactants given in the reaction table."
<< "This message can also result from a wrong implementation of the reaction table."
<< G4endl;
G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
}
<< pMoleculeA->GetName()
<< " does not have any reactants given in the reaction table."
<< "This message can also result from a wrong implementation of "
"the reaction table."
<< G4endl;
G4cout << "!!!!!!!!!!!!!!!!!!!!" << G4endl;
}
#endif
return DBL_MAX;
}
fReactants.reset(new vector<G4Track*>());
fReactionModel->Initialise(pMolConfA, trackA);
for (G4int i = 0; i < nbReactives; i++)
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
const G4double Reff = fReactionModel->GetReactionRadius(i);
std::vector<std::pair<G4TrackList::iterator, G4double>> resultIndices;
resultIndices.clear();
G4ChemicalMoleculeFinder::Instance()->FindNearestInRange(
trackA, key, fRCutOff, resultIndices);
if(resultIndices.empty())
{
auto pMoleculeB = (*pReactantList)[i];
G4int key = pMoleculeB->GetMoleculeID();
//fRCutOff = G4IRTUtils::GetRCutOff(1 * ps);
fRCutOff = G4IRTUtils::GetRCutOff();
//______________________________________________________________
// Retrieve reaction range
const G4double Reff = fReactionModel->GetReactionRadius(i);
std::vector<std::pair<G4TrackList::iterator,G4double>> resultIndices;
resultIndices.clear();
G4ChemicalMoleculeFinder::Instance()->
FindNearestInRange(trackA,
key,
fRCutOff,
resultIndices);
if(resultIndices.empty())
{
continue;
}
for(auto& it : resultIndices)
{
G4Track* pTrackB = *(std::get<0>(it));
if(pTrackB == &trackA)
{
continue;
}
if(pTrackB == nullptr)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "No trackB no valid";
G4Exception("G4DNAIndependentReactionTimeModel"
"::BuildReactionMap()", "NO_TRACK02",
FatalException, exceptionDescription);
}
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 processTable = *(fReactionTypeManager->GetReactionTypeTable());
auto typeOfReaction = (G4int)GetReactionType(trackA, *pTrackB);
if(processTable[typeOfReaction]->
GeminateRecombinationProbability(pMolConfA, pMolConfB))
{
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);
}
}
continue;
}
for(auto& it : resultIndices)
{
G4Track* pTrackB = *(std::get<0>(it));
if(pTrackB == &trackA)
{
continue;
}
if(pTrackB == nullptr)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "No trackB no valid";
G4Exception("G4DNAIndependentReactionTimeStepper"
"::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(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);
}
}
}
#ifdef G4VERBOSE
if (fVerbose)
if(fVerbose != 0)
{
G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep will finally "
"return :"
<< G4BestUnit(fSampledMinTimeStep, "Time") << G4endl;
if(fVerbose > 1)
{
G4cout << "G4DNAIndependentReactionTimeStepper::CalculateStep will finally return :"
<< G4BestUnit(fSampledMinTimeStep, "Time") << G4endl;
G4cout << "Selected reactants for trackA: " << pMoleculeA->GetName()
<< " (" << trackA.GetTrackID() << ") are: ";
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;
}
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
for (const auto& it : *fReactants)
{
auto pTrackB = it;
fSampledPositions[pTrackB->GetTrackID()] = pTrackB->GetPosition();
}
return fSampledMinTimeStep;
return fSampledMinTimeStep;
}
void G4DNAIndependentReactionTimeStepper::CheckAndRecordResults(const Utils& utils)
void G4DNAIndependentReactionTimeStepper::CheckAndRecordResults(
const Utils& utils)
{
if (utils.fTrackB.GetTrackStatus() != fAlive)
{
return;
}
if(utils.fTrackB.GetTrackStatus() != fAlive)
{
return;
}
if (&utils.fTrackB == &utils.fTrackA)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription<< "A track is reacting with itself"
" (which is impossible) ie fpTrackA == trackB"<< G4endl;
exceptionDescription << "Molecule A is of type : "
<< utils.fpMoleculeA->GetName() << " with trackID : "
<< utils.fTrackA.GetTrackID()<<" and B : "
<< utils.fpMoleculeB->GetName() << " with trackID : "
<< utils.fTrackB.GetTrackID() << G4endl;
G4Exception("G4DNAIndependentReactionTimeStepper::RetrieveResults",
"G4DNAIndependentReactionTimeStepper003", FatalErrorInArgument,
exceptionDescription);
}
if(&utils.fTrackB == &utils.fTrackA)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "A track is reacting with itself"
" (which is impossible) ie fpTrackA == trackB"
<< G4endl;
exceptionDescription << "Molecule A is of type : "
<< utils.fpMoleculeA->GetName()
<< " with trackID : " << utils.fTrackA.GetTrackID()
<< " and B : " << utils.fpMoleculeB->GetName()
<< " with trackID : " << utils.fTrackB.GetTrackID()
<< G4endl;
G4Exception("G4DNAIndependentReactionTimeStepper::RetrieveResults",
"G4DNAIndependentReactionTimeStepper003", FatalErrorInArgument,
exceptionDescription);
}
if (fabs(utils.fTrackB.GetGlobalTime() - utils.fTrackA.GetGlobalTime())
> utils.fTrackA.GetGlobalTime() * (1. - 1. / 100))
{
// DEBUG
G4ExceptionDescription exceptionDescription;
exceptionDescription
<< "The interacting tracks are not synchronized in time" << G4endl;
exceptionDescription
<< "trackB->GetGlobalTime() != fpTrackA.GetGlobalTime()" << G4endl;
if(fabs(utils.fTrackB.GetGlobalTime() - utils.fTrackA.GetGlobalTime()) >
utils.fTrackA.GetGlobalTime() * (1. - 1. / 100))
{
// DEBUG
G4ExceptionDescription exceptionDescription;
exceptionDescription
<< "The interacting tracks are not synchronized in time" << G4endl;
exceptionDescription
<< "trackB->GetGlobalTime() != fpTrackA.GetGlobalTime()" << G4endl;
exceptionDescription << "fpTrackA : trackID : " << utils.fTrackA.GetTrackID()
<< "\t Name :" << utils.fpMoleculeA->GetName()
<< "\t fpTrackA->GetGlobalTime() = "
<< G4BestUnit(utils.fTrackA.GetGlobalTime(), "Time") << G4endl;
exceptionDescription << "fpTrackA : trackID : "
<< utils.fTrackA.GetTrackID()
<< "\t Name :" << utils.fpMoleculeA->GetName()
<< "\t fpTrackA->GetGlobalTime() = "
<< G4BestUnit(utils.fTrackA.GetGlobalTime(), "Time")
<< G4endl;
exceptionDescription << "trackB : trackID : " << utils.fTrackB.GetTrackID()
<< "\t Name :" << utils.fpMoleculeB->GetName()
<< "\t trackB->GetGlobalTime() = "
<< G4BestUnit(utils.fTrackB.GetGlobalTime(), "Time") << G4endl;
exceptionDescription << "trackB : trackID : " << utils.fTrackB.GetTrackID()
<< "\t Name :" << utils.fpMoleculeB->GetName()
<< "\t trackB->GetGlobalTime() = "
<< G4BestUnit(utils.fTrackB.GetGlobalTime(), "Time")
<< G4endl;
G4Exception("G4DNAIndependentReactionTimeStepper::RetrieveResults",
"G4DNAIndependentReactionTimeStepper004", FatalErrorInArgument,
exceptionDescription);
}
fReactants->push_back(const_cast<G4Track*>(&utils.fTrackB));
G4Exception("G4DNAIndependentReactionTimeStepper::RetrieveResults",
"G4DNAIndependentReactionTimeStepper004", FatalErrorInArgument,
exceptionDescription);
}
fReactants->push_back(const_cast<G4Track*>(&utils.fTrackB));
}
std::unique_ptr<G4ITReactionChange>
G4DNAIndependentReactionTimeStepper::FindReaction(G4ITReactionSet* pReactionSet,
const G4double& currentStepTime,
const G4double& /*previousStepTime*/,
const G4bool& /*reachedUserStepTimeLimit*/)
G4DNAIndependentReactionTimeStepper::FindReaction(
G4ITReactionSet* pReactionSet, const G4double& currentStepTime,
const G4double& /*previousStepTime*/,
const G4bool& /*reachedUserStepTimeLimit*/)
{
if (pReactionSet == nullptr)
{
return nullptr;
}
G4ITReactionPerTime& reactionPerTime = pReactionSet->GetReactionsPerTime();
if(reactionPerTime.empty())
{
return nullptr;
}
for (auto reaction_i = reactionPerTime.begin();
reaction_i != reactionPerTime.end();
reaction_i = reactionPerTime.begin())
{
G4Track* pTrackA = (*reaction_i)->GetReactants().first;
if (pTrackA->GetTrackStatus() == fStopAndKill)
{
continue;
}
G4Track* pTrackB = (*reaction_i)->GetReactant(pTrackA);
if (pTrackB->GetTrackStatus() == fStopAndKill)
{
continue;
}
if (pTrackB == pTrackA)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription
<< "The IT reaction process sent back a reaction between trackA and trackB. ";
exceptionDescription << "The problem is trackA == trackB";
G4Exception("G4ITModelProcessor::FindReaction",
"ITModelProcessor005",
FatalErrorInArgument,
exceptionDescription);
}
pReactionSet->SelectThisReaction(*reaction_i);
if(fpReactionProcess != nullptr && fpReactionProcess->TestReactibility(*pTrackA,
*pTrackB,
currentStepTime,
false))
{
pTrackA->SetPosition(fSampledPositions[pTrackA->GetTrackID()]);
pTrackB->SetPosition(fSampledPositions[pTrackB->GetTrackID()]);
auto pReactionChange = fpReactionProcess->MakeReaction(*pTrackA, *pTrackB);
if (pReactionChange == nullptr)
{
return nullptr;
}
return pReactionChange;
}
}
if(pReactionSet == nullptr)
{
return nullptr;
}
G4ITReactionPerTime& reactionPerTime = pReactionSet->GetReactionsPerTime();
if(reactionPerTime.empty())
{
return nullptr;
}
for(auto reaction_i = reactionPerTime.begin();
reaction_i != reactionPerTime.end(); reaction_i = reactionPerTime.begin())
{
G4Track* pTrackA = (*reaction_i)->GetReactants().first;
if(pTrackA->GetTrackStatus() == fStopAndKill)
{
continue;
}
G4Track* pTrackB = (*reaction_i)->GetReactant(pTrackA);
if(pTrackB->GetTrackStatus() == fStopAndKill)
{
continue;
}
if(pTrackB == pTrackA)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "The IT reaction process sent back a reaction "
"between trackA and trackB. ";
exceptionDescription << "The problem is trackA == trackB";
G4Exception("G4DNAIndependentReactionTimeStepper::FindReaction",
"G4DNAIndependentReactionTimeStepper02", FatalErrorInArgument,
exceptionDescription);
}
pReactionSet->SelectThisReaction(*reaction_i);
if(fpReactionProcess != nullptr &&
fpReactionProcess->TestReactibility(*pTrackA, *pTrackB, currentStepTime,
false))
{
if((fSampledPositions.find(pTrackA->GetTrackID()) ==
fSampledPositions.end() &&
(fSampledPositions.find(pTrackB->GetTrackID()) ==
fSampledPositions.end())))
{
G4ExceptionDescription exceptionDescription;
exceptionDescription
<< "The positions of trackA and trackB have no counted ";
G4Exception("G4DNAIndependentReactionTimeStepper::FindReaction",
"G4DNAIndependentReactionTimeStepper0001",
FatalErrorInArgument, exceptionDescription);
}
pTrackA->SetPosition(fSampledPositions[pTrackA->GetTrackID()]);
pTrackB->SetPosition(fSampledPositions[pTrackB->GetTrackID()]);
auto pReactionChange =
fpReactionProcess->MakeReaction(*pTrackA, *pTrackB);
if(pReactionChange == nullptr)
{
return nullptr;
}
return pReactionChange;
}
}
return nullptr;
}
void G4DNAIndependentReactionTimeStepper::SetReactionModel(G4VDNAReactionModel* pReactionModel)
void G4DNAIndependentReactionTimeStepper::SetReactionModel(
G4VDNAReactionModel* pReactionModel)
{
fReactionModel = pReactionModel;
fReactionModel = pReactionModel;
}
G4VDNAReactionModel* G4DNAIndependentReactionTimeStepper::GetReactionModel()
{
return fReactionModel;
return fReactionModel;
}
void G4DNAIndependentReactionTimeStepper::SetVerbose(G4int flag)
{
fVerbose = flag;
fVerbose = flag;
}
ReactionType G4DNAIndependentReactionTimeStepper::GetReactionType(const G4Track& trackA,
const G4Track& trackB)
G4double G4DNAIndependentReactionTimeStepper::GetTimeToEncounter(
const G4Track& trackA, const G4Track& trackB)
{
auto pMoleculeA = GetMolecule(trackA)->GetMolecularConfiguration();
auto pMoleculeB = GetMolecule(trackB)->GetMolecularConfiguration();
auto pData = fMolecularReactionTable->GetReactionData(pMoleculeA,pMoleculeB);
G4int reactionID = pData->GetReactionID();
return fReactionTypeManager->GetReactionTypeByID(reactionID);
G4double timeToReaction =
dynamic_cast<G4DiffusionControlledReactionModel*>(fReactionModel)
->GetTimeToEncounter(trackA, trackB);
return timeToReaction;
}
G4double G4DNAIndependentReactionTimeStepper::GetTimeToEncounter(const G4Track& trackA,
const G4Track& trackB)
void G4DNAIndependentReactionTimeStepper::SetReactionProcess(
G4VITReactionProcess* pReactionProcess)
{
if(fReactionTypeManager == nullptr)
fpReactionProcess = pReactionProcess;
}
G4double G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep(
G4double /*currentGlobalTime*/, G4double definedMinTimeStep)
{
G4double fTSTimeStep = DBL_MAX;
fCheckedTracks.clear();
for(auto pTrack : *fpTrackContainer->GetMainList())
{
if(pTrack == nullptr)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "fpProManager is not "
"initialized ";
G4Exception("G4DNAIndependentReactionTimeModel::"
"GetIndependentReactionTime()",
"G4DNAIndependentReactionTimeModel002",
FatalErrorInArgument,exceptionDescription);
}
auto processTable = *(fReactionTypeManager->GetReactionTypeTable());
ReactionType reactionType = GetReactionType(trackA,trackB);
#ifdef DEBUG
G4cout<<"A: "<<GetMolecule(trackA)->GetName()<<"("<<trackA.GetTrackID()<<")"<<" + B : "
<<GetMolecule(trackB)->GetName()<<"("<<trackB.GetTrackID()<<")"<<G4endl;
#endif
return processTable[(G4int)reactionType]->GetTimeToEncounter(trackA,trackB);
}
void G4DNAIndependentReactionTimeStepper::SetReactionTypeManager(G4VReactionTypeManager* typeManager)
{
fReactionTypeManager = ((G4DNAReactionTypeManager*)typeManager);
}
void G4DNAIndependentReactionTimeStepper::SetReactionProcess(G4VITReactionProcess* pReactionProcess)
{
fpReactionProcess = pReactionProcess;
}
G4double G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep(G4double /*currentGlobalTime*/, G4double definedMinTimeStep)
{
G4double fTSTimeStep = DBL_MAX;
for (auto pTrack : *fpTrackContainer->GetMainList())
{
if (pTrack == nullptr)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "No track found.";
G4Exception("G4Scheduler::CalculateMinStep", "ITScheduler006",
FatalErrorInArgument, exceptionDescription);
continue;
}
G4TrackStatus trackStatus = pTrack->GetTrackStatus();
if (trackStatus == fStopAndKill || trackStatus == fStopButAlive)
{
continue;
}
G4double sampledMinTimeStep = CalculateStep(*pTrack, definedMinTimeStep);
G4TrackVectorHandle reactants = GetReactants();
if (sampledMinTimeStep < fTSTimeStep)
{
fTSTimeStep = sampledMinTimeStep;
fReactionSet->CleanAllReaction();
if (reactants)
{
fReactionSet->AddReactions(fTSTimeStep,
const_cast<G4Track*>(pTrack),
reactants);
ResetReactants();
}
}
else if (fTSTimeStep == sampledMinTimeStep && G4bool(reactants))
{
fReactionSet->AddReactions(fTSTimeStep,
const_cast<G4Track*>(pTrack),
reactants);
ResetReactants();
}
else if (reactants)
{
ResetReactants();
}
G4ExceptionDescription exceptionDescription;
exceptionDescription << "No track found.";
G4Exception("G4DNAIndependentReactionTimeStepper::CalculateMinTimeStep",
"G4DNAIndependentReactionTimeStepper006",
FatalErrorInArgument, exceptionDescription);
continue;
}
return fTSTimeStep;
G4TrackStatus trackStatus = pTrack->GetTrackStatus();
if(trackStatus == fStopAndKill || trackStatus == fStopButAlive)
{
continue;
}
G4double sampledMinTimeStep = CalculateStep(*pTrack, definedMinTimeStep);
G4TrackVectorHandle reactants = GetReactants();
if(sampledMinTimeStep < fTSTimeStep)
{
fTSTimeStep = sampledMinTimeStep;
fReactionSet->CleanAllReaction();
if(reactants)
{
fReactionSet->AddReactions(fTSTimeStep, const_cast<G4Track*>(pTrack),
reactants);
fSampledPositions[pTrack->GetTrackID()] = pTrack->GetPosition();
for(const auto& it : *fReactants)
{
auto pTrackB = it;
// G4cout<<"position : "<<pTrackB->GetTrackID()<<G4endl;
fSampledPositions[pTrackB->GetTrackID()] = pTrackB->GetPosition();
}
ResetReactants();
}
}
else if(fTSTimeStep == sampledMinTimeStep && G4bool(reactants))
{
fReactionSet->AddReactions(fTSTimeStep, const_cast<G4Track*>(pTrack),
reactants);
fSampledPositions[pTrack->GetTrackID()] = pTrack->GetPosition();
for(const auto& it : *fReactants)
{
auto pTrackB = it;
// G4cout<<"position : "<<pTrackB->GetTrackID()<<G4endl;
fSampledPositions[pTrackB->GetTrackID()] = pTrackB->GetPosition();
}
ResetReactants();
}
else if(reactants)
{
ResetReactants();
}
}
return fTSTimeStep;
}
@@ -120,7 +120,7 @@ G4DNAIonElasticModel::Initialise (
G4double scaleFactor = 1e-16*cm*cm;
char *path = getenv("G4LEDATA");
const char *path = G4FindDataDir("G4LEDATA");
if (!path)
{
@@ -30,7 +30,10 @@
#include "G4DNAChemistryManager.hh"
#include "G4DNAMolecularMaterial.hh"
#include "G4Exp.hh"
#include "G4Pow.hh"
#include "G4Alpha.hh"
static G4Pow * gpow = G4Pow::GetInstance();
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
@@ -86,11 +89,11 @@ void G4DNAMillerGreenExcitationModel::Initialise(const G4ParticleDefinition* par
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
G4ParticleDefinition* hydrogenDef = instance->GetIon("hydrogen");
G4ParticleDefinition* alphaPlusPlusDef = instance->GetIon("alpha++");
G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
G4ParticleDefinition* heliumDef = instance->GetIon("helium");
protonDef = G4Proton::ProtonDefinition();
hydrogenDef = instance->GetIon("hydrogen");
alphaPlusPlusDef = G4Alpha::Alpha();
alphaPlusDef = instance->GetIon("alpha+");
heliumDef = instance->GetIon("helium");
G4String proton;
G4String hydrogen;
@@ -232,19 +235,16 @@ G4double G4DNAMillerGreenExcitationModel::CrossSectionPerVolume(const G4Material
// Calculate total cross section for model
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (
particleDefinition != G4Proton::ProtonDefinition()
particleDefinition != protonDef
&&
particleDefinition != instance->GetIon("hydrogen")
particleDefinition != hydrogenDef
&&
particleDefinition != instance->GetIon("alpha++")
particleDefinition != alphaPlusPlusDef
&&
particleDefinition != instance->GetIon("alpha+")
particleDefinition != alphaPlusDef
&&
particleDefinition != instance->GetIon("helium")
particleDefinition != heliumDef
)
return 0;
@@ -279,9 +279,9 @@ G4double G4DNAMillerGreenExcitationModel::CrossSectionPerVolume(const G4Material
// add ONE or TWO electron-water excitation for alpha+ and helium
/*
if ( particleDefinition == instance->GetIon("alpha+")
if ( particleDefinition == alphaPlusDef
||
particleDefinition == instance->GetIon("helium")
particleDefinition == heliumDef
)
{
@@ -295,10 +295,10 @@ G4double G4DNAMillerGreenExcitationModel::CrossSectionPerVolume(const G4Material
excitationXS->CrossSectionPerVolume(material,G4Electron::ElectronDefinition(),k*0.511/3728,tmp,tmp)
/material->GetAtomicNumDensityVector()[1];
if ( particleDefinition == instance->GetIon("alpha+") )
if ( particleDefinition == alphaPlusDef )
crossSection = crossSection + sigmaExcitation ;
if ( particleDefinition == instance->GetIon("helium") )
if ( particleDefinition == heliumDef )
crossSection = crossSection + 2*sigmaExcitation ;
delete excitationXS;
@@ -315,10 +315,10 @@ G4double G4DNAMillerGreenExcitationModel::CrossSectionPerVolume(const G4Material
excitationXS->CrossSectionPerVolume(material,G4Electron::ElectronDefinition(),k*0.511/3728,tmp,tmp)
/material->GetAtomicNumDensityVector()[1];
if ( particleDefinition == instance->GetIon("alpha+") )
if ( particleDefinition == alphaPlusDef )
crossSection = crossSection + sigmaExcitation ;
if ( particleDefinition == instance->GetIon("helium") )
if ( particleDefinition == heliumDef )
crossSection = crossSection + 2*sigmaExcitation ;
delete excitationXS;
@@ -421,14 +421,12 @@ G4double G4DNAMillerGreenExcitationModel::PartialCrossSection(G4double k, G4int
const G4double Eliq[5]={ 8.17*eV, 10.13*eV, 11.31*eV, 12.91*eV, 14.50*eV};
G4int particleTypeIndex = 0;
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == G4Proton::ProtonDefinition()) particleTypeIndex=0;
if (particleDefinition == instance->GetIon("hydrogen")) particleTypeIndex=0;
if (particleDefinition == instance->GetIon("alpha++")) particleTypeIndex=1;
if (particleDefinition == instance->GetIon("alpha+")) particleTypeIndex=2;
if (particleDefinition == instance->GetIon("helium")) particleTypeIndex=3;
if (particleDefinition == protonDef) particleTypeIndex=0;
if (particleDefinition == hydrogenDef) particleTypeIndex=0;
if (particleDefinition == alphaPlusPlusDef) particleTypeIndex=1;
if (particleDefinition == alphaPlusDef) particleTypeIndex=2;
if (particleDefinition == heliumDef) particleTypeIndex=3;
G4double tCorrected;
tCorrected = k * kineticEnergyCorrection[particleTypeIndex];
@@ -440,21 +438,21 @@ G4double G4DNAMillerGreenExcitationModel::PartialCrossSection(G4double k, G4int
G4int z = 10;
G4double numerator;
numerator = std::pow(z * aj[excitationLevel], omegaj[excitationLevel]) *
std::pow(tCorrected - Eliq[excitationLevel], nu);
numerator = gpow->powA(z * aj[excitationLevel], omegaj[excitationLevel]) *
gpow->powA(tCorrected - Eliq[excitationLevel], nu);
// H case : see S. Uehara et al. IJRB 77, 2, 139-154 (2001) - section 3.3
if (particleDefinition == instance->GetIon("hydrogen"))
numerator = std::pow(z * 0.75*aj[excitationLevel], omegaj[excitationLevel]) *
std::pow(tCorrected - Eliq[excitationLevel], nu);
if (particleDefinition == hydrogenDef)
numerator = gpow->powA(z * 0.75*aj[excitationLevel], omegaj[excitationLevel]) *
gpow->powA(tCorrected - Eliq[excitationLevel], nu);
G4double power;
power = omegaj[excitationLevel] + nu;
G4double denominator;
denominator = std::pow(jj[excitationLevel], power) + std::pow(tCorrected, power);
denominator = gpow->powA(jj[excitationLevel], power) + gpow->powA(tCorrected, power);
G4double zEff = particleDefinition->GetPDGCharge() / eplus + particleDefinition->GetLeptonNumber();
@@ -462,7 +460,7 @@ G4double G4DNAMillerGreenExcitationModel::PartialCrossSection(G4double k, G4int
sCoefficient[1][particleTypeIndex] * S_2s(k, Eliq[excitationLevel], slaterEffectiveCharge[1][particleTypeIndex], 2.) +
sCoefficient[2][particleTypeIndex] * S_2p(k, Eliq[excitationLevel], slaterEffectiveCharge[2][particleTypeIndex], 2.) );
if (particleDefinition == instance->GetIon("hydrogen")) zEff = 1.;
if (particleDefinition == hydrogenDef) zEff = 1.;
G4double cross = sigma0 * zEff * zEff * numerator / denominator;
@@ -478,14 +476,11 @@ G4int G4DNAMillerGreenExcitationModel::RandomSelect(G4double k,const G4ParticleD
G4double value = 0.;
std::deque<G4double> values;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if ( particle == instance->GetIon("alpha++") ||
particle == G4Proton::ProtonDefinition()||
particle == instance->GetIon("hydrogen") ||
particle == instance->GetIon("alpha+") ||
particle == instance->GetIon("helium")
if ( particle == alphaPlusPlusDef ||
particle == protonDef||
particle == hydrogenDef ||
particle == alphaPlusDef ||
particle == heliumDef
)
{
while (i > 0)
@@ -511,9 +506,9 @@ G4int G4DNAMillerGreenExcitationModel::RandomSelect(G4double k,const G4ParticleD
/*
// add ONE or TWO electron-water excitation for alpha+ and helium
if ( particle == instance->GetIon("alpha+")
if ( particle == alphaPlusDef
||
particle == instance->GetIon("helium")
particle == heliumDef
)
{
while (i>0)
@@ -529,8 +524,8 @@ G4int G4DNAMillerGreenExcitationModel::RandomSelect(G4double k,const G4ParticleD
G4double partial = PartialCrossSection(k,i,particle);
if (particle == instance->GetIon("alpha+")) partial = PartialCrossSection(k,i,particle) + sigmaExcitation;
if (particle == instance->GetIon("helium")) partial = PartialCrossSection(k,i,particle) + 2*sigmaExcitation;
if (particle == alphaPlusDef) partial = PartialCrossSection(k,i,particle) + sigmaExcitation;
if (particle == heliumDef) partial = PartialCrossSection(k,i,particle) + 2*sigmaExcitation;
values.push_front(partial);
value += partial;
@@ -203,7 +203,7 @@ void G4DNAPTBElasticModel::ReadDiffCSFile(const G4String& materialName,
// This method is not yet standard.
// get the path of the G4LEDATA data folder
char *path = std::getenv("G4LEDATA");
const char* path = G4FindDataDir("G4LEDATA");
// if it is not found then quit and print error message
if(!path)
{
@@ -437,7 +437,7 @@ void G4DNAPTBIonisationModel::ReadDiffCSFile(const G4String& materialName,
// To read and save the informations contained within the differential cross section files
// get the path of the G4LEDATA data folder
char *path = std::getenv("G4LEDATA");
const char* path = G4FindDataDir("G4LEDATA");
// if it is not found then quit and print error message
if(!path)
{
@@ -1,168 +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. *
// ********************************************************************
//
#include "G4DNAPartiallyDiffusionControlled.hh"
#include "G4IRTUtils.hh"
#include "G4DNAMolecularReactionTable.hh"
#include "G4VDNAReactionModel.hh"
#include "G4SystemOfUnits.hh"
#include "G4PhysicalConstants.hh"
#include "G4MolecularConfiguration.hh"
#include "Randomize.hh"
#include "G4Molecule.hh"
#include "G4ITReactionChange.hh"
#include "G4VReactionType.hh"
#include "G4Electron_aq.hh"
#include "G4ErrorFunction.hh"
G4DNAPartiallyDiffusionControlled::G4DNAPartiallyDiffusionControlled()
: G4VReactionType()
{}
G4DNAPartiallyDiffusionControlled::~G4DNAPartiallyDiffusionControlled() = default;
G4bool
G4DNAPartiallyDiffusionControlled::GeminateRecombinationProbability(const G4MolecularConfiguration* mA,
const G4MolecularConfiguration* mB)
{
auto reactionData = G4DNAMolecularReactionTable::Instance()
->GetReactionData(mA, mB);
G4double D = GetDiffusionCoefficient(mA, mB);
G4double R = mA->GetVanDerVaalsRadius() + mB->GetVanDerVaalsRadius();
const G4double Rs = 0.3 * nm;
G4double kobs = reactionData->GetObservedReactionRateConstant() / Avogadro;
if(mA->GetCharge() * mB->GetCharge() == 0)
{
G4double kdif = 4 * CLHEP::pi * D * R * Avogadro;
G4double kact = G4IRTUtils::GetKact(kobs, kdif);
return G4UniformRand() < Rs / ( Rs + ( kdif / kact ) * ( R + Rs ));
}
else
{
G4double rc = 0.71 * nm * mA->GetCharge() *
mB->GetCharge();
G4double sigmaEff = G4IRTUtils::EffectiveDistance(rc, R);
G4double kdif = 4 * CLHEP::pi * D * sigmaEff;
G4double kact = G4IRTUtils::GetKact(kobs, kdif);
G4double a = std::exp( -rc / R );
G4double b = std::exp( -rc / ( R + Rs ) );
G4double Preact = ( a - b ) / ( a - b - ( kdif / kact ) * ( 1 - a ) );
return G4UniformRand() < Preact;
}
}
G4double
G4DNAPartiallyDiffusionControlled::GetDiffusionCoefficient(const G4MolecularConfiguration* mA,
const G4MolecularConfiguration* mB)
{
G4double D;
if(mA == mB)
{
D = (mA->GetDiffusionCoefficient());
}
else
{
D = (mA->GetDiffusionCoefficient() +
mB->GetDiffusionCoefficient());
}
return D;
}
G4double G4DNAPartiallyDiffusionControlled::GetTimeToEncounter(const G4Track& trackA,
const G4Track& trackB)
{
auto pMolConfA = GetMolecule(trackA)->GetMolecularConfiguration();
auto pMolConfB = GetMolecule(trackB)->GetMolecularConfiguration();
G4double D = GetDiffusionCoefficient(pMolConfA, pMolConfB);
auto reactionData = G4DNAMolecularReactionTable::Instance()
->GetReactionData(pMolConfA, pMolConfB);
G4double Reff;
G4double kobs = reactionData->GetObservedReactionRateConstant();
G4double distance = (trackA.GetPosition() - trackB.GetPosition()).mag();
G4double SmoluchowskiRadius;
G4double RVal = pMolConfA->GetVanDerVaalsRadius() + pMolConfB->GetVanDerVaalsRadius();
if((pMolConfA->GetCharge() != 0) &&
(pMolConfB->GetCharge() != 0))
{
G4double rc = 0.71 * nm * pMolConfA->GetCharge() *
pMolConfB->GetCharge();
distance = G4IRTUtils::EffectiveDistance( rc, distance );
Reff = G4IRTUtils::EffectiveDistance( rc, RVal );
SmoluchowskiRadius = Reff;
}
else
{
SmoluchowskiRadius = RVal;
}
G4double Winf = SmoluchowskiRadius / distance;
G4double U1 = G4UniformRand();
G4double U2 = G4UniformRand();
G4double U = G4UniformRand();
G4double X = 0;
G4double irt_1 = -1.0 * ps;
G4double irt_2;
G4double kdif = 4 * CLHEP::pi * D * SmoluchowskiRadius * Avogadro;
G4double kact = G4IRTUtils::GetKact(kobs, kdif);
if ( U < Winf )
{
G4double d = ( distance - SmoluchowskiRadius ) /
G4ErrorFunction::erfcInv( U / Winf );
irt_1 = ( 1.0 / ( 4 * D ) ) * d * d;
}
if( irt_1 < 0)
{
return irt_1;
}
else
{
G4double rateFactor = kact / ( kact + kdif );
if( U1 > rateFactor )
{
return -1.0 * ps;
}
G4double Y = std::abs(G4RandGauss::shoot(0.0,std::sqrt(2)));
if( Y > 0)
{
X = - ( G4Log( U2 ) ) / Y;
}
G4double f = X * SmoluchowskiRadius * kdif / ( kact + kdif );
irt_2 = ( f * f ) / D ;
}
return irt_1 + irt_2;
}
@@ -322,7 +322,7 @@ G4int G4DNAQuinnPlasmonExcitationModel::GetNValenceElectron(G4int z)
if(!datadir)
{
datadir = getenv("G4LEDATA");
datadir = G4FindDataDir("G4LEDATA");
if(!datadir)
{
G4Exception("G4DNAQuinnPlasmonExcitationModel::GetNValenceElectron()"
@@ -0,0 +1,260 @@
//
// ********************************************************************
// * 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 on 2022/03/03
//
// Authors: A.D. Dominguez-Munoz, M.I. Gallardo, M.C. Bordage,
// Z. Francis, S. Incerti, M.A. Cortes-Giraldo
//
// Contact: M.A. Cortes-Giraldo (miancortes -at- us.es)
//
//
#include "G4DNARPWBAExcitationModel.hh"
#include "G4SystemOfUnits.hh"
#include "G4DNAChemistryManager.hh"
#include "G4DNAMolecularMaterial.hh"
#include <map>
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNARPWBAExcitationModel::G4DNARPWBAExcitationModel(
const G4ParticleDefinition*, const G4String& nam)
: G4VEmModel(nam)
{
// 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 << "RPWBA excitation model is constructed " << G4endl;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNARPWBAExcitationModel::~G4DNARPWBAExcitationModel() = default;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNARPWBAExcitationModel::Initialise(const G4ParticleDefinition* particle,
const G4DataVector& /*cuts*/)
{
if(isInitialised)
{
return;
}
if(verboseLevel > 3)
{
G4cout << "Calling G4DNARPWBAExcitationModel::Initialise()" << G4endl;
}
if(fParticleDefinition != nullptr && fParticleDefinition != particle)
{
G4Exception("G4DNARPWBAExcitationModel::Initialise", "em0001",
FatalException,
"Model already initialized for another particle type.");
}
fTableFile = "dna/sigma_excitation_p_RPWBA";
fLowEnergy = 100. * MeV;
fHighEnergy = 300. * MeV;
//SetLowEnergyLimit(fLowEnergy);
//SetHighEnergyLimit(fHighEnergy);
G4double scaleFactor = 1 * cm * cm;
fTableData = make_unique<G4DNACrossSectionDataSet>(new G4LogLogInterpolation,
eV, scaleFactor);
fTableData->LoadData(fTableFile);
if(verboseLevel > 0)
{
G4cout << "RPWBA excitation model is initialized " << G4endl
<< "Energy range: " << LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / keV << " keV for "
<< particle->GetParticleName() << G4endl;
}
// Initialize water density pointer
if(G4Material::GetMaterial("G4_WATER") != nullptr){
fpMolWaterDensity =
G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(
G4Material::GetMaterial("G4_WATER"));
}else{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "G4_WATER does not exist :";
G4Exception("G4DNARPWBAIonisationModel::Initialise", "em00020",
FatalException, exceptionDescription);
}
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNARPWBAExcitationModel::CrossSectionPerVolume(
const G4Material* material, const G4ParticleDefinition* particleDefinition,
G4double ekin, G4double, G4double)
{
if(verboseLevel > 3)
{
G4cout << "Calling CrossSectionPerVolume() of G4DNARPWBAExcitationModel"
<< G4endl;
}
if(fTableData == nullptr)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "No cross section data ";
G4Exception("G4DNARPWBAIonisationModel::CrossSectionPerVolume", "em00120",
FatalException, exceptionDescription);
}
if(particleDefinition != fParticleDefinition)
return 0;
// Calculate total cross section for model
G4double sigma = 0;
G4double waterDensity = (*fpMolWaterDensity)[material->GetIndex()];
if(ekin >= fLowEnergy && ekin <= fHighEnergy)
{
sigma = fTableData->FindValue(ekin);
}
if(verboseLevel > 2)
{
G4cout << "__________________________________" << G4endl;
G4cout << "G4DNARPWBAExcitationModel - XS INFO START" << G4endl;
G4cout << "Kinetic energy(eV)=" << ekin / eV
<< " particle : " << particleDefinition->GetParticleName() << 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 << "G4DNARPWBAExcitationModel - XS INFO END" << G4endl;
}
return sigma * waterDensity;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNARPWBAExcitationModel::SampleSecondaries(
std::vector<G4DynamicParticle*>* /*fvect*/,
const G4MaterialCutsCouple* /*couple*/,
const G4DynamicParticle* aDynamicParticle, G4double, G4double)
{
if(verboseLevel > 3)
{
G4cout << "Calling SampleSecondaries() of G4DNARPWBAExcitationModel"
<< G4endl;
}
G4double k = aDynamicParticle->GetKineticEnergy();
G4int level = RandomSelect(k);
G4double excitationEnergy = waterStructure.ExcitationEnergy(level);
G4double newEnergy = k - excitationEnergy;
if(newEnergy > 0)
{
fParticleChangeForGamma->ProposeMomentumDirection(
aDynamicParticle->GetMomentumDirection());
if(!statCode){
fParticleChangeForGamma->SetProposedKineticEnergy(newEnergy);
}
else{
fParticleChangeForGamma->SetProposedKineticEnergy(k);
}
fParticleChangeForGamma->ProposeLocalEnergyDeposit(excitationEnergy);
}
const G4Track* theIncomingTrack = fParticleChangeForGamma->GetCurrentTrack();
G4DNAChemistryManager::Instance()->CreateWaterMolecule(
eExcitedMolecule, level, theIncomingTrack);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNARPWBAExcitationModel::GetPartialCrossSection(
const G4Material*, G4int level, const G4ParticleDefinition* particle,
G4double kineticEnergy)
{
if(fParticleDefinition != particle)
{
G4Exception("G4DNARPWBAExcitationModel::GetPartialCrossSection",
"RPWBAParticleType", FatalException,
"Model initialized for another particle type.");
}
return fTableData->GetComponent(level)->FindValue(kineticEnergy);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNARPWBAExcitationModel::RandomSelect(G4double k)
{
G4int level = 0;
G4double* valuesBuffer = new G4double[fTableData->NumberOfComponents()];
const size_t n(fTableData->NumberOfComponents());
size_t i(n);
G4double value = 0.;
while(i > 0)
{
i--;
valuesBuffer[i] = fTableData->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];
}
delete[] valuesBuffer;
return level;
}
@@ -0,0 +1,724 @@
//
// ********************************************************************
// * 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 on 2022/03/03
//
// Authors: A.D. Dominguez-Munoz, M.I. Gallardo, M.C. Bordage,
// Z. Francis, S. Incerti, M.A. Cortes-Giraldo
//
// Contact: M.A. Cortes-Giraldo (miancortes -at- us.es)
//
//
#include "G4DNARPWBAIonisationModel.hh"
#include "G4PhysicalConstants.hh"
#include "G4SystemOfUnits.hh"
#include "G4UAtomicDeexcitation.hh"
#include "G4LossTableManager.hh"
#include "G4DNAChemistryManager.hh"
#include "G4DNAMolecularMaterial.hh"
#include "G4DNABornAngle.hh"
#include "G4Exp.hh"
using namespace std;
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNARPWBAIonisationModel::G4DNARPWBAIonisationModel(
const G4ParticleDefinition*, const G4String& nam)
: G4VEmModel(nam)
{
// 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 << "RPWBA ionisation model is constructed " << G4endl;
}
SetDeexcitationFlag(true);
SetAngularDistribution(new G4DNABornAngle());
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4DNARPWBAIonisationModel::~G4DNARPWBAIonisationModel()
{
eVecm.clear();
pVecm.clear();
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4bool G4DNARPWBAIonisationModel::InEnergyLimit(const G4double& k)
{
if(lowEnergyLimit == highEnergyLimit)
{
G4Exception("G4DNARPWBAIonisationModel::InEnergyLimit", "em0102",
FatalException, "lowEnergyLimit == highEnergyLimit");
}
if(k >= lowEnergyLimit && k <= highEnergyLimit)
{
return true;
}
else
{
return false;
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNARPWBAIonisationModel::InitialiseForProton(
const G4ParticleDefinition* part)
{
if(part != fProtonDef)
{
G4Exception("G4DNARPWBAIonisationModel::CrossSectionPerVolume", "em0002",
FatalException, "Model not applicable to particle type.");
}
// Energy limits
G4String fileProton("dna/sigma_ionisation_p_RPWBA");
G4double scaleFactor = 1 * cm * cm;
const char *path = G4FindDataDir("G4LEDATA");
lowEnergyLimit = 100. * MeV;
highEnergyLimit = 300. * MeV;
fpTotalCrossSection = make_unique<G4DNACrossSectionDataSet>(
new G4LogLogInterpolation, eV, scaleFactor);
fpTotalCrossSection->LoadData(fileProton);
// Final state
std::ostringstream pFullFileName;
fasterCode ? pFullFileName
<< path << "/dna/sigmadiff_cumulated_ionisation_p_RPWBA.dat.dat"
: pFullFileName << path << "/dna/sigmadiff_ionisation_p_RPWBA.dat";
std::ifstream pDiffCrossSection(pFullFileName.str().c_str());
if(!pDiffCrossSection)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "Missing data file: " + pFullFileName.str();
G4Exception("G4DNARPWBAIonisationModel::Initialise", "em0003",
FatalException, exceptionDescription);
}
pTdummyVec.push_back(0.);
while(!pDiffCrossSection.eof())
{
G4double tDummy;
G4double eDummy;
pDiffCrossSection >> tDummy >> eDummy;
if(tDummy != pTdummyVec.back())
{
pTdummyVec.push_back(tDummy);
}
for(G4int j = 0; j < 5; j++)
{
pDiffCrossSection >> pDiffCrossSectionData[j][tDummy][eDummy];
if(fasterCode)
{
pNrjTransfData[j][tDummy][pDiffCrossSectionData[j][tDummy][eDummy]] =
eDummy;
pProbaShellMap[j][tDummy].push_back(
pDiffCrossSectionData[j][tDummy][eDummy]);
}
// SI - only if eof is not reached !
if(!pDiffCrossSection.eof() && !fasterCode)
{
pDiffCrossSectionData[j][tDummy][eDummy] *= scaleFactor;
}
if(!fasterCode)
{
pVecm[tDummy].push_back(eDummy);
}
}
}
// be careful about this
// SetLowEnergyLimit(lowEnergyLimit);
// SetHighEnergyLimit(highEnergyLimit);
}
void G4DNARPWBAIonisationModel::Initialise(const G4ParticleDefinition* particle,
const G4DataVector& /*cuts*/)
{
if(isInitialised)
{
return;
}
if(verboseLevel > 3)
{
G4cout << "Calling G4DNARPWBAIonisationModel::Initialise()"
<< particle->GetParticleName() << G4endl;
}
InitialiseForProton(particle);
if(verboseLevel > 0)
{
G4cout << "RPWBA ionisation model is initialized " << G4endl
<< "Energy range: " << LowEnergyLimit() / eV << " eV - "
<< HighEnergyLimit() / keV << " keV for "
<< particle->GetParticleName() << G4endl;
}
// Initialize water density pointer
if(G4Material::GetMaterial("G4_WATER") != nullptr)
{
fpMolWaterDensity =
G4DNAMolecularMaterial::Instance()->GetNumMolPerVolTableFor(
G4Material::GetMaterial("G4_WATER"));
}
else
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "G4_WATER does not exist :";
G4Exception("G4DNARPWBAIonisationModel::Initialise", "em00020",
FatalException, exceptionDescription);
}
fAtomDeexcitation = G4LossTableManager::Instance()->AtomDeexcitation();
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNARPWBAIonisationModel::CrossSectionPerVolume(
const G4Material* material, const G4ParticleDefinition* particleDefinition,
G4double ekin, G4double, G4double)
{
if(particleDefinition != fProtonDef)
{
G4Exception("G4DNARPWBAIonisationModel::CrossSectionPerVolume", "em0402",
FatalException, "Model not applicable to particle type.");
}
if(verboseLevel > 3)
{
G4cout << "Calling CrossSectionPerVolume() of G4DNARPWBAIonisationModel"
<< G4endl;
}
G4double sigma;
G4double waterDensity = (*fpMolWaterDensity)[material->GetIndex()];
if(InEnergyLimit(ekin))
{
sigma = fpTotalCrossSection->FindValue(ekin);
}
else
{
// nput energy is outside this interval the cross section is set to zero
// should add a warning or exception ?
return 0;
}
if(verboseLevel > 2)
{
G4cout << "__________________________________" << G4endl;
G4cout << "G4DNARPWBAIonisationModel - XS INFO START" << G4endl;
G4cout << "Kinetic energy(eV)=" << ekin / eV
<< " particle : " << fProtonDef->GetParticleName() << 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 << "G4DNARPWBAIonisationModel - XS INFO END" << G4endl;
}
return sigma * waterDensity;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
void G4DNARPWBAIonisationModel::SampleSecondaries(
std::vector<G4DynamicParticle*>* fvect, const G4MaterialCutsCouple* couple,
const G4DynamicParticle* particle, G4double, G4double)
{
if(verboseLevel > 3)
{
G4cout << "Calling SampleSecondaries() of G4DNARPWBAIonisationModel"
<< G4endl;
}
G4double k = particle->GetKineticEnergy();
if(InEnergyLimit(k))
{
G4ParticleMomentum primaryDirection = particle->GetMomentumDirection();
G4double particleMass = particle->GetDefinition()->GetPDGMass();
G4double totalEnergy = k + particleMass;
G4double pSquare = k * (totalEnergy + particleMass);
G4double totalMomentum = std::sqrt(pSquare);
G4int ionizationShell;
if(!fasterCode)
{
ionizationShell = RandomSelect(k);
}
else
{
// fasterCode = true
do
{
ionizationShell = RandomSelect(k);
} while(k < 19 * eV && ionizationShell == 2 &&
particle->GetDefinition() == G4Electron::ElectronDefinition());
}
G4double bindingEnergy = 0;
bindingEnergy = waterStructure.IonisationEnergy(ionizationShell);
// SI: additional protection if tcs interpolation method is modified
if(k < bindingEnergy)
{
return;
}
//
G4double secondaryKinetic;
if(!fasterCode)
{
secondaryKinetic = RandomizeEjectedElectronEnergy(k, ionizationShell);
}
else
{
secondaryKinetic =
RandomizeEjectedElectronEnergyFromCumulatedDcs(k, ionizationShell);
}
G4int Z = 8; // water Z (6 Oxygen + 2 hydrogen)
G4ThreeVector deltaDirection =
GetAngularDistribution()->SampleDirectionForShell(
particle, secondaryKinetic, Z, ionizationShell, couple->GetMaterial());
if(secondaryKinetic > 0){
auto dp = new G4DynamicParticle(G4Electron::Electron(), deltaDirection,
secondaryKinetic);
fvect->push_back(dp);
}
if(particle->GetDefinition() == G4Electron::ElectronDefinition()){
G4double deltaTotalMomentum = std::sqrt(
secondaryKinetic * (secondaryKinetic + 2. * electron_mass_c2));
G4double finalPx = totalMomentum * primaryDirection.x() -
deltaTotalMomentum * deltaDirection.x();
G4double finalPy = totalMomentum * primaryDirection.y() -
deltaTotalMomentum * deltaDirection.y();
G4double finalPz = totalMomentum * primaryDirection.z() -
deltaTotalMomentum * deltaDirection.z();
G4double finalMomentum =
std::sqrt(finalPx * finalPx + finalPy * finalPy + finalPz * finalPz);
finalPx /= finalMomentum;
finalPy /= finalMomentum;
finalPz /= finalMomentum;
G4ThreeVector direction;
direction.set(finalPx, finalPy, finalPz);
fParticleChangeForGamma->ProposeMomentumDirection(direction.unit());
}
else
{
fParticleChangeForGamma->ProposeMomentumDirection(primaryDirection);
}
// AM: sample deexcitation
// here we assume that H_{2}O electronic levels are the same as Oxygen.
// this can be considered true with a rough 10% error in energy on K-shell,
size_t secNumberInit; // need to know at a certain point the energy of
// secondaries
size_t
secNumberFinal; // So I'll make the diference and then sum the energies
G4double scatteredEnergy = k - bindingEnergy - secondaryKinetic;
// SI: only atomic deexcitation from K shell is considered
if((fAtomDeexcitation != nullptr) && ionizationShell == 4)
{
const G4AtomicShell* shell =
fAtomDeexcitation->GetAtomicShell(Z, G4AtomicShellEnumerator(0));
secNumberInit = fvect->size();
fAtomDeexcitation->GenerateParticles(fvect, shell, Z, 0, 0);
secNumberFinal = fvect->size();
if(secNumberFinal > secNumberInit){
for(size_t i = secNumberInit; i < secNumberFinal; ++i){
if(bindingEnergy >= ((*fvect)[i])->GetKineticEnergy())
{
bindingEnergy -= ((*fvect)[i])->GetKineticEnergy();
}else{
delete(*fvect)[i];
(*fvect)[i] = nullptr;
}
}
}
}
// This should never happen
if(bindingEnergy < 0.0)
{
G4Exception("G4DNARPWBAIonisatioModel::SampleSecondaries()", "em2050",
FatalException, "Negative local energy deposit");
}
// bindingEnergy has been decreased
// by the amount of energy taken away by deexc. products
if(!statCode){
fParticleChangeForGamma->SetProposedKineticEnergy(scatteredEnergy);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(bindingEnergy);
}else{
fParticleChangeForGamma->SetProposedKineticEnergy(k);
fParticleChangeForGamma->ProposeLocalEnergyDeposit(k - scatteredEnergy);
}
const G4Track* theIncomingTrack =
fParticleChangeForGamma->GetCurrentTrack();
G4DNAChemistryManager::Instance()->CreateWaterMolecule(
eIonizedMolecule, ionizationShell, theIncomingTrack);
}
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNARPWBAIonisationModel::RandomizeEjectedElectronEnergy(
const G4double& k, const G4int& shell)
{
G4double maximumKineticEnergyTransfer =
4. * (electron_mass_c2 / proton_mass_c2) * k;
G4double crossSectionMaximum = 0.;
for(G4double value = waterStructure.IonisationEnergy(shell);
value <= 4. * waterStructure.IonisationEnergy(shell); value += 0.1 * eV)
{
G4double differentialCrossSection =
DifferentialCrossSection(k / eV, value / eV, shell);
if(differentialCrossSection >= crossSectionMaximum)
{
crossSectionMaximum = differentialCrossSection;
}
}
G4double secondaryElectronKineticEnergy = 0.;
do
{
secondaryElectronKineticEnergy =
G4UniformRand() * maximumKineticEnergyTransfer;
} while(G4UniformRand() * crossSectionMaximum >=
DifferentialCrossSection(k / eV,
(secondaryElectronKineticEnergy +
waterStructure.IonisationEnergy(shell)) /
eV,
shell));
return secondaryElectronKineticEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNARPWBAIonisationModel::DifferentialCrossSection(
const G4double& kine, const G4double& energyTransfer,
const G4int& ionizationLevelIndex)
{
G4double k = kine;
G4double sigma = 0.;
if(energyTransfer >=
waterStructure.IonisationEnergy(ionizationLevelIndex) / eV)
{
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;
// Protection against out of boundary access - proton case : 100 MeV
if(k == pTdummyVec.back())
{
k = k * (1. - 1e-12);
}
// k should be in eV and energy transfer eV also
auto t2 = std::upper_bound(pTdummyVec.begin(), pTdummyVec.end(), k);
auto t1 = t2 - 1;
auto e12 = std::upper_bound(pVecm[(*t1)].begin(), pVecm[(*t1)].end(),
energyTransfer);
auto e11 = e12 - 1;
auto e22 = std::upper_bound(pVecm[(*t2)].begin(), pVecm[(*t2)].end(),
energyTransfer);
auto e21 = e22 - 1;
valueT1 = *t1;
valueT2 = *t2;
valueE21 = *e21;
valueE22 = *e22;
valueE12 = *e12;
valueE11 = *e11;
xs11 = pDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE11];
xs12 = pDiffCrossSectionData[ionizationLevelIndex][valueT1][valueE12];
xs21 = pDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE21];
xs22 = pDiffCrossSectionData[ionizationLevelIndex][valueT2][valueE22];
G4double xsProduct = xs11 * xs12 * xs21 * xs22;
if(xsProduct != 0.)
{
sigma =
QuadInterpolator(valueE11, valueE12, valueE21, valueE22, xs11, xs12,
xs21, xs22, valueT1, valueT2, k, energyTransfer);
}
}
return sigma;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNARPWBAIonisationModel::Interpolate(const G4double& e1,
const G4double& e2,
const G4double& e,
const G4double& xs1,
const G4double& xs2)
{
G4double value = 0.;
// Log-log interpolation by default
if(e1 != 0 && e2 != 0 && (std::log10(e2) - std::log10(e1)) != 0 &&
!fasterCode)
{
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;
value = (std::pow(10., sigma));
}
// Switch to lin-lin interpolation
/*
if ((e2-e1)!=0)
{
G4double d1 = xs1;
G4double d2 = xs2;
value = (d1 + (d2 - d1)*(e - e1)/ (e2 - e1));
}
*/
// Switch to log-lin interpolation for faster code
if((e2 - e1) != 0 && xs1 != 0 && xs2 != 0 && fasterCode)
{
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) && fasterCode)
{
G4double d1 = xs1;
G4double d2 = xs2;
value = (d1 + (d2 - d1) * (e - e1) / (e2 - e1));
}
return value;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNARPWBAIonisationModel::QuadInterpolator(
const G4double& e11, const G4double& e12, const G4double& e21,
const G4double& e22, const G4double& xs11, const G4double& xs12,
const G4double& xs21, const G4double& xs22, const G4double& t1,
const G4double& t2, const G4double& t, const G4double& e)
{
G4double interpolatedvalue1 = Interpolate(e11, e12, e, xs11, xs12);
G4double interpolatedvalue2 = Interpolate(e21, e22, e, xs21, xs22);
G4double value =
Interpolate(t1, t2, t, interpolatedvalue1, interpolatedvalue2);
return value;
}
G4double G4DNARPWBAIonisationModel::GetPartialCrossSection(
const G4Material* /*material*/, G4int level,
const G4ParticleDefinition* particle, G4double kineticEnergy)
{
if(fpTotalCrossSection != nullptr && particle != fProtonDef)
{
G4Exception("G4DNARPWBAIonisationModel::GetPartialCrossSection", "em0010",
FatalException, "Model not applicable to particle type.");
}
return fpTotalCrossSection->GetComponent(level)->FindValue(kineticEnergy);
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4int G4DNARPWBAIonisationModel::RandomSelect(G4double k)
{
if(fpTotalCrossSection == nullptr)
{
G4Exception("G4DNARPWBAIonisationModel::RandomSelect", "em0010",
FatalException, "Model not applicable to particle type.");
}
else
{
auto valuesBuffer = new G4double[fpTotalCrossSection->NumberOfComponents()];
const size_t n(fpTotalCrossSection->NumberOfComponents());
size_t i(n);
G4double value = 0.;
while(i > 0)
{
i--;
valuesBuffer[i] = fpTotalCrossSection->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];
}
delete[] valuesBuffer;
}
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double
G4DNARPWBAIonisationModel::RandomizeEjectedElectronEnergyFromCumulatedDcs(
const G4double& k, const G4int& shell)
{
G4double secondaryElectronKineticEnergy = 0.;
G4double random = G4UniformRand();
secondaryElectronKineticEnergy =
TransferedEnergy(k / eV, shell, random) * eV -
waterStructure.IonisationEnergy(shell);
if(secondaryElectronKineticEnergy < 0.)
{
return 0.;
}
return secondaryElectronKineticEnergy;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4double G4DNARPWBAIonisationModel::TransferedEnergy(G4double k,
G4int ionizationLevelIndex,
const G4double& random)
{
G4double nrj = 0.;
G4double valueK1 = 0;
G4double valueK2 = 0;
G4double valuePROB21 = 0;
G4double valuePROB22 = 0;
G4double valuePROB12 = 0;
G4double valuePROB11 = 0;
G4double nrjTransf11 = 0;
G4double nrjTransf12 = 0;
G4double nrjTransf21 = 0;
G4double nrjTransf22 = 0;
// Protection against out of boundary access - proton case : 100 MeV
if(k == pTdummyVec.back())
{
k = k * (1. - 1e-12);
}
// k should be in eV
auto k2 = std::upper_bound(pTdummyVec.begin(), pTdummyVec.end(), k);
auto k1 = k2 - 1;
// SI : the following condition avoids situations where random > last vector
// element,
// for eg. when the last element is zero
if(random <= pProbaShellMap[ionizationLevelIndex][(*k1)].back() &&
random <= pProbaShellMap[ionizationLevelIndex][(*k2)].back())
{
auto prob12 = std::upper_bound(
pProbaShellMap[ionizationLevelIndex][(*k1)].begin(),
pProbaShellMap[ionizationLevelIndex][(*k1)].end(), random);
auto prob11 = prob12 - 1;
auto prob22 = std::upper_bound(
pProbaShellMap[ionizationLevelIndex][(*k2)].begin(),
pProbaShellMap[ionizationLevelIndex][(*k2)].end(), random);
auto prob21 = prob22 - 1;
valueK1 = *k1;
valueK2 = *k2;
valuePROB21 = *prob21;
valuePROB22 = *prob22;
valuePROB12 = *prob12;
valuePROB11 = *prob11;
nrjTransf11 = pNrjTransfData[ionizationLevelIndex][valueK1][valuePROB11];
nrjTransf12 = pNrjTransfData[ionizationLevelIndex][valueK1][valuePROB12];
nrjTransf21 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB21];
nrjTransf22 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB22];
}
// Avoids cases where cum xs is zero for k1 and is not for k2 (with always
// k1<k2)
if(random > pProbaShellMap[ionizationLevelIndex][(*k1)].back())
{
auto prob22 = std::upper_bound(
pProbaShellMap[ionizationLevelIndex][(*k2)].begin(),
pProbaShellMap[ionizationLevelIndex][(*k2)].end(), random);
auto prob21 = prob22 - 1;
valueK1 = *k1;
valueK2 = *k2;
valuePROB21 = *prob21;
valuePROB22 = *prob22;
nrjTransf21 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB21];
nrjTransf22 = pNrjTransfData[ionizationLevelIndex][valueK2][valuePROB22];
G4double interpolatedvalue2 =
Interpolate(valuePROB21, valuePROB22, random, nrjTransf21, nrjTransf22);
G4double value = Interpolate(valueK1, valueK2, k, 0., interpolatedvalue2);
return value;
}
G4double nrjTransfProduct =
nrjTransf11 * nrjTransf12 * nrjTransf21 * nrjTransf22;
if(nrjTransfProduct != 0.)
{
nrj = QuadInterpolator(valuePROB11, valuePROB12, valuePROB21, valuePROB22,
nrjTransf11, nrjTransf12, nrjTransf21, nrjTransf22,
valueK1, valueK2, k, random);
}
return nrj;
}
@@ -116,7 +116,7 @@ void G4DNARelativisticIonisationModel::Initialise(const G4ParticleDefinition* pa
std::ostringstream eFullFileNameZ;
char *path = getenv("G4LEDATA");
const char *path = G4FindDataDir("G4LEDATA");
if (!path)
{
G4Exception("G4DNARelativisticIonisationModel::Initialise","em0006",
@@ -404,7 +404,7 @@ void G4DNARelativisticIonisationModel::LoadAtomicStates(
const char *datadir = path;
if(!datadir)
{
datadir = getenv("G4LEDATA");
datadir = G4FindDataDir("G4LEDATA");
if(!datadir)
{
G4Exception("G4DNARelativisticIonisationModel::LoadAtomicStates()",
@@ -39,6 +39,12 @@
#include "G4DNARuddAngle.hh"
#include "G4DeltaAngle.hh"
#include "G4Exp.hh"
#include "G4Log.hh"
#include "G4Pow.hh"
#include "G4Alpha.hh"
static G4Pow * gpow = G4Pow::GetInstance();
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
@@ -130,9 +136,9 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* pa
G4String fileAlphaPlusPlus("dna/sigma_ionisation_alphaplusplus_rudd");
G4String fileAlphaPlus("dna/sigma_ionisation_alphaplus_rudd");
G4String fileHelium("dna/sigma_ionisation_he_rudd");
G4String fileLithium("dna/sigma_ionisation_li_rudd");
G4String fileBeryllium("dna/sigma_ionisation_be_rudd");
G4String fileBoron("dna/sigma_ionisation_b_rudd");
//G4String fileLithium("dna/sigma_ionisation_li_rudd");
//G4String fileBeryllium("dna/sigma_ionisation_be_rudd");
//G4String fileBoron("dna/sigma_ionisation_b_rudd");
G4String fileCarbon("dna/sigma_ionisation_c_rudd");
G4String fileNitrogen("dna/sigma_ionisation_n_rudd");
G4String fileOxygen("dna/sigma_ionisation_o_rudd");
@@ -141,35 +147,29 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* pa
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
G4ParticleDefinition* hydrogenDef = instance->GetIon("hydrogen");
G4ParticleDefinition* alphaPlusPlusDef = instance->GetIon("alpha++");
G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
G4ParticleDefinition* heliumDef = instance->GetIon("helium");
protonDef = G4Proton::ProtonDefinition();
hydrogenDef = instance->GetIon("hydrogen");
alphaPlusPlusDef = G4Alpha::Alpha();
alphaPlusDef = instance->GetIon("alpha+");
heliumDef = instance->GetIon("helium");
//G4ParticleDefinition* carbonDef = instance->GetIon("carbon");
//G4ParticleDefinition* nitrogenDef = instance->GetIon("nitrogen");
//G4ParticleDefinition* oxygenDef = instance->GetIon("oxygen");
//G4ParticleDefinition* siliconDef = instance->GetIon("silicon");
//G4ParticleDefinition* ironDef = instance->GetIon("iron");
G4ParticleDefinition* lithiumDef = G4IonTable::GetIonTable()->GetIon(3,7);
G4ParticleDefinition* berylliumDef = G4IonTable::GetIonTable()->GetIon(4,9);
G4ParticleDefinition* boronDef = G4IonTable::GetIonTable()->GetIon(5,11);
G4ParticleDefinition* carbonDef = G4IonTable::GetIonTable()->GetIon(6,12);
G4ParticleDefinition* nitrogenDef = G4IonTable::GetIonTable()->GetIon(7,14);
G4ParticleDefinition* oxygenDef = G4IonTable::GetIonTable()->GetIon(8,16);
G4ParticleDefinition* siliconDef = G4IonTable::GetIonTable()->GetIon(14,28);
G4ParticleDefinition* ironDef = G4IonTable::GetIonTable()->GetIon(26,56);
//
carbonDef = instance->GetIon("carbon");
nitrogenDef = instance->GetIon("nitrogen");
oxygenDef = instance->GetIon("oxygen");
siliconDef = instance->GetIon("silicon");
ironDef = instance->GetIon("iron");
//lithiumDef = G4IonTable::GetIonTable()->GetIon(3,7);
//berylliumDef = G4IonTable::GetIonTable()->GetIon(4,9);
//boronDef = G4IonTable::GetIonTable()->GetIon(5,11);
G4String proton;
G4String hydrogen;
G4String alphaPlusPlus;
G4String alphaPlus;
G4String helium;
G4String lithium;
G4String beryllium;
G4String boron;
//G4String lithium;
//G4String beryllium;
//G4String boron;
G4String carbon;
G4String nitrogen;
G4String oxygen;
@@ -262,7 +262,7 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* pa
tableData[helium] = tableHelium;
// **********************************************************************************************
/*
lithium = lithiumDef->GetParticleName();
tableFile[lithium] = fileLithium;
@@ -272,7 +272,7 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* pa
lowEnergyLimit[lithium] = 0.5*7*MeV;
highEnergyLimit[lithium] = 1e6*7*MeV;
//
// Cross section
G4DNACrossSectionDataSet* tableLithium = new G4DNACrossSectionDataSet(new G4LogLogInterpolation,
@@ -280,7 +280,7 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* pa
scaleFactor );
tableLithium->LoadData(fileLithium);
tableData[lithium] = tableLithium;
// **********************************************************************************************
beryllium = berylliumDef->GetParticleName();
@@ -320,7 +320,7 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* pa
scaleFactor );
tableBoron->LoadData(fileBoron);
tableData[boron] = tableBoron;
*/
// **********************************************************************************************
carbon = carbonDef->GetParticleName();
@@ -457,7 +457,7 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* pa
SetLowEnergyLimit(lowEnergyLimit[alphaPlusPlus]);
SetHighEnergyLimit(highEnergyLimit[alphaPlusPlus]);
}
/*
if (particle==lithiumDef)
{
SetLowEnergyLimit(lowEnergyLimit[lithium]);
@@ -475,7 +475,7 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* pa
SetLowEnergyLimit(lowEnergyLimit[boron]);
SetHighEnergyLimit(highEnergyLimit[boron]);
}
*/
if (particle==carbonDef)
{
SetLowEnergyLimit(lowEnergyLimit[carbon]);
@@ -533,7 +533,7 @@ void G4DNARuddIonisationExtendedModel::Initialise(const G4ParticleDefinition* pa
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
G4double G4DNARuddIonisationExtendedModel::CrossSectionPerVolume(const G4Material* material,
const G4ParticleDefinition* particleDefinition,
const G4ParticleDefinition* partDef,
G4double k,
G4double,
G4double)
@@ -545,21 +545,20 @@ G4double G4DNARuddIonisationExtendedModel::CrossSectionPerVolume(const G4Materia
if (verboseLevel > 3)
G4cout << "Calling CrossSectionPerVolume() of G4DNARuddIonisationExtendedModel" << G4endl;
auto particleDefinition = GetDNAIonParticleDefinition(partDef);
// Calculate total cross section for model
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (
particleDefinition != G4Proton::ProtonDefinition()
particleDefinition != protonDef
&&
particleDefinition != instance->GetIon("hydrogen")
particleDefinition != hydrogenDef
&&
particleDefinition != instance->GetIon("alpha++")
particleDefinition != alphaPlusPlusDef
&&
particleDefinition != instance->GetIon("alpha+")
particleDefinition != alphaPlusDef
&&
particleDefinition != instance->GetIon("helium")
particleDefinition != heliumDef
&&
// SI
//particleDefinition != instance->GetIon("carbon")
@@ -569,21 +568,23 @@ G4double G4DNARuddIonisationExtendedModel::CrossSectionPerVolume(const G4Materia
//particleDefinition != instance->GetIon("oxygen")
//&&
//particleDefinition != instance->GetIon("iron")
particleDefinition != G4IonTable::GetIonTable()->GetIon(3,7)
/*
particleDefinition != lithiumDef
&&
particleDefinition != G4IonTable::GetIonTable()->GetIon(4,9)
particleDefinition != berylliumDef
&&
particleDefinition != G4IonTable::GetIonTable()->GetIon(5,11)
particleDefinition != boronDef
&&
particleDefinition != G4IonTable::GetIonTable()->GetIon(6,12)
*/
particleDefinition != carbonDef
&&
particleDefinition != G4IonTable::GetIonTable()->GetIon(7,14)
particleDefinition != nitrogenDef
&&
particleDefinition != G4IonTable::GetIonTable()->GetIon(8,16)
particleDefinition != oxygenDef
&&
particleDefinition != G4IonTable::GetIonTable()->GetIon(14,28)
particleDefinition != siliconDef
&&
particleDefinition != G4IonTable::GetIonTable()->GetIon(26,56)
particleDefinition != ironDef
//
)
@@ -591,15 +592,15 @@ G4double G4DNARuddIonisationExtendedModel::CrossSectionPerVolume(const G4Materia
G4double lowLim = 0;
if ( particleDefinition == G4Proton::ProtonDefinition()
|| particleDefinition == instance->GetIon("hydrogen")
if ( particleDefinition == protonDef
|| particleDefinition == hydrogenDef
)
lowLim = lowEnergyLimitOfModelForA[1];
else if ( particleDefinition == instance->GetIon("alpha++")
|| particleDefinition == instance->GetIon("alpha+")
|| particleDefinition == instance->GetIon("helium")
else if ( particleDefinition == alphaPlusPlusDef
|| particleDefinition == alphaPlusDef
|| particleDefinition == heliumDef
)
lowLim = lowEnergyLimitOfModelForA[4];
@@ -682,29 +683,30 @@ void G4DNARuddIonisationExtendedModel::SampleSecondaries(std::vector<G4DynamicPa
if (verboseLevel > 3)
G4cout << "Calling SampleSecondaries() of G4DNARuddIonisationExtendedModel" << G4endl;
auto particleDefinition = GetDNAIonParticleDefinition(particle->GetDefinition());
G4double lowLim = 0;
G4double highLim = 0;
// ZF: the following line summarizes the commented part
if(particle->GetDefinition()->GetAtomicMass() <= 4) lowLim = killBelowEnergyForA[particle->GetDefinition()->GetAtomicMass()];
if(particle->GetDefinition()->GetAtomicMass() <= 4) lowLim = killBelowEnergyForA[particleDefinition->GetAtomicMass()];
else lowLim = killBelowEnergyForA[5]*particle->GetDefinition()->GetAtomicMass();
else lowLim = killBelowEnergyForA[5]*particleDefinition->GetAtomicMass();
/*
if(particle->GetDefinition()->GetAtomicMass() >= 5) lowLim = killBelowEnergyForA[5]*particle->GetDefinition()->GetAtomicMass();
if ( particle->GetDefinition() == G4Proton::ProtonDefinition()
|| particle->GetDefinition() == instance->GetIon("hydrogen")
if ( particle->GetDefinition() == protonDef
|| particle->GetDefinition() == hydrogenDef
)
lowLim = killBelowEnergyForA[1];
if ( particle->GetDefinition() == instance->GetIon("alpha++")
|| particle->GetDefinition() == instance->GetIon("alpha+")
|| particle->GetDefinition() == instance->GetIon("helium")
if ( particle->GetDefinition() == alphaPlusPlusDef
|| particle->GetDefinition() == alphaPlusDef
|| particle->GetDefinition() == heliumDef
)
lowLim = killBelowEnergyForA[4];
@@ -714,7 +716,7 @@ void G4DNARuddIonisationExtendedModel::SampleSecondaries(std::vector<G4DynamicPa
G4double k = particle->GetKineticEnergy();
const G4String& particleName = particle->GetDefinition()->GetParticleName();
const G4String& particleName = particleDefinition->GetParticleName();
// SI - the following is useless since lowLim is already defined
/*
@@ -736,7 +738,7 @@ void G4DNARuddIonisationExtendedModel::SampleSecondaries(std::vector<G4DynamicPa
// SI: no strict limits, like in the non extended version of the model
{
G4ParticleDefinition* definition = particle->GetDefinition();
G4ParticleDefinition* definition = particleDefinition;
G4ParticleMomentum primaryDirection = particle->GetMomentumDirection();
/*
G4double particleMass = definition->GetPDGMass();
@@ -987,8 +989,7 @@ G4double G4DNARuddIonisationExtendedModel::RejectionFunction(G4ParticleDefinitio
G4double energyTransfer = proposed_ws + Bj_energy;
proposed_ws/=Bj_energy;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
G4double tau = 0.;
G4double A_ion = 0.;
tau = (electron_mass_c2 / particleDefinition->GetPDGMass()) * k;
@@ -1017,8 +1018,8 @@ G4double G4DNARuddIonisationExtendedModel::RejectionFunction(G4ParticleDefinitio
G4bool isHelium = false;
if ( particleDefinition == G4Proton::ProtonDefinition()
|| particleDefinition == instance->GetIon("hydrogen")
if ( particleDefinition == protonDef
|| particleDefinition == hydrogenDef
)
{
return(rejection_term);
@@ -1028,12 +1029,12 @@ G4double G4DNARuddIonisationExtendedModel::RejectionFunction(G4ParticleDefinitio
{
G4double Z = particleDefinition->GetAtomicNumber();
G4double x = 100.*std::sqrt(beta2)/std::pow(Z,(2./3.));
G4double x = 100.*std::sqrt(beta2)/gpow->powA(Z,(2./3.));
G4double Zeffion = Z*(1.-G4Exp(-1.316*x+0.112*x*x-0.0650*x*x*x));
rejection_term*=Zeffion*Zeffion;
}
else if (particleDefinition == instance->GetIon("alpha++") )
else if (particleDefinition == alphaPlusPlusDef )
{
isHelium = true;
slaterEffectiveCharge[0]=0.;
@@ -1044,7 +1045,7 @@ G4double G4DNARuddIonisationExtendedModel::RejectionFunction(G4ParticleDefinitio
sCoefficient[2]=0.;
}
else if (particleDefinition == instance->GetIon("alpha+") )
else if (particleDefinition == alphaPlusDef )
{
isHelium = true;
slaterEffectiveCharge[0]=2.0;
@@ -1057,7 +1058,7 @@ G4double G4DNARuddIonisationExtendedModel::RejectionFunction(G4ParticleDefinitio
sCoefficient[2]=0.15;
}
else if (particleDefinition == instance->GetIon("helium") )
else if (particleDefinition == heliumDef )
{
isHelium = true;
slaterEffectiveCharge[0]=1.7;
@@ -1068,9 +1069,9 @@ G4double G4DNARuddIonisationExtendedModel::RejectionFunction(G4ParticleDefinitio
sCoefficient[2]=0.25;
}
// if ( particleDefinition == instance->GetIon("helium")
// || particleDefinition == instance->GetIon("alpha+")
// || particleDefinition == instance->GetIon("alpha++")
// if ( particleDefinition == heliumDef
// || particleDefinition == alphaPlusDef
// || particleDefinition == alphaPlusPlusDef
// )
if (isHelium)
@@ -1167,9 +1168,9 @@ G4double G4DNARuddIonisationExtendedModel::ProposedSampledEnergy(G4ParticleDefin
G4double v = std::sqrt(v2);
//G4double wc = 4.*v2 - 2.*v - (Ry/(4.*Bj_energy));
G4double L1 = (C1* std::pow(v,(D1))) / (1.+ E1*std::pow(v, (D1+4.)));
G4double L2 = C2*std::pow(v,(D2));
G4double H1 = (A1*std::log(1.+v2)) / (v2+(B1/v2));
G4double L1 = (C1* gpow->powA(v,(D1))) / (1.+ E1*gpow->powA(v, (D1+4.)));
G4double L2 = C2*gpow->powA(v,(D2));
G4double H1 = (A1*G4Log(1.+v2)) / (v2+(B1/v2));
G4double H2 = (A2/v2) + (B2/(v2*v2));
G4double F1 = L1+H1;
G4double F2 = (L2*H2)/(L2+H2);
@@ -1280,12 +1281,10 @@ G4double G4DNARuddIonisationExtendedModel::R(G4double t,
G4double G4DNARuddIonisationExtendedModel::CorrectionFactor(G4ParticleDefinition* particleDefinition, G4double k, G4int shell)
{
// ZF Shortened
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == instance->GetIon("hydrogen") && shell < 4)
if (particleDefinition == hydrogenDef && shell < 4)
{
G4double value = (std::log10(k/eV)-4.2)/0.5;
G4double value = ((G4Log(k/eV)/gpow->logZ(10))-4.2)/0.5;
// The following values are provided by M. Dingfelder (priv. comm)
return((0.6/(1+G4Exp(value))) + 0.9);
}
@@ -1416,3 +1415,34 @@ G4double G4DNARuddIonisationExtendedModel::Sum(G4double /* energy */, const G4St
return 0;
}
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
G4ParticleDefinition* G4DNARuddIonisationExtendedModel::GetDNAIonParticleDefinition(const G4ParticleDefinition* particleDefinition)
{
//for proton, hydrogen, alphas
if(particleDefinition->GetAtomicMass() <= 4)
{
return const_cast<G4ParticleDefinition*>(particleDefinition);
}
else{
auto instance = G4DNAGenericIonsManager::Instance();
auto PDGEncoding = particleDefinition->GetPDGEncoding();
if(PDGEncoding == 1000140280){
return instance->GetIon("silicon");
}else if(PDGEncoding == 1000260560){
return instance->GetIon("iron");
}else if(PDGEncoding == 1000080160){
return instance->GetIon("oxygen");
}else if(PDGEncoding == 1000070140){
return instance->GetIon("nitrogen");
}else if(PDGEncoding == 1000060120){
return instance->GetIon("carbon");
}
G4ExceptionDescription description;
description << "DNA physics does not support this ion : "<<particleDefinition->GetParticleName()<< G4endl;
G4Exception("G4DNARuddIonisationExtendedModel::GetDNAIonParticleDefinition()",
"em2051",FatalException,description);
return nullptr;
}
}
@@ -35,7 +35,11 @@
#include "G4DNARuddAngle.hh"
#include "G4DeltaAngle.hh"
#include "G4Exp.hh"
#include "G4Pow.hh"
#include "G4Log.hh"
#include "G4Alpha.hh"
static G4Pow * gpow = G4Pow::GetInstance();
//....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo....
using namespace std;
@@ -128,11 +132,11 @@ void G4DNARuddIonisationModel::Initialise(const G4ParticleDefinition* particle,
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
G4ParticleDefinition* protonDef = G4Proton::ProtonDefinition();
G4ParticleDefinition* hydrogenDef = instance->GetIon("hydrogen");
G4ParticleDefinition* alphaPlusPlusDef = instance->GetIon("alpha++");
G4ParticleDefinition* alphaPlusDef = instance->GetIon("alpha+");
G4ParticleDefinition* heliumDef = instance->GetIon("helium");
protonDef = G4Proton::ProtonDefinition();
hydrogenDef = instance->GetIon("hydrogen");
alphaPlusPlusDef = G4Alpha::Alpha();
alphaPlusDef = instance->GetIon("alpha+");
heliumDef = instance->GetIon("helium");
G4String proton;
G4String hydrogen;
@@ -298,34 +302,31 @@ G4double G4DNARuddIonisationModel::CrossSectionPerVolume(const G4Material* mater
// Calculate total cross section for model
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (
particleDefinition != G4Proton::ProtonDefinition()
particleDefinition != protonDef
&&
particleDefinition != instance->GetIon("hydrogen")
particleDefinition != hydrogenDef
&&
particleDefinition != instance->GetIon("alpha++")
particleDefinition != alphaPlusPlusDef
&&
particleDefinition != instance->GetIon("alpha+")
particleDefinition != alphaPlusDef
&&
particleDefinition != instance->GetIon("helium")
particleDefinition != heliumDef
)
return 0;
G4double lowLim = 0;
if ( particleDefinition == G4Proton::ProtonDefinition()
|| particleDefinition == instance->GetIon("hydrogen")
if ( particleDefinition == protonDef
|| particleDefinition == hydrogenDef
)
lowLim = lowEnergyLimitOfModelForZ1;
if ( particleDefinition == instance->GetIon("alpha++")
|| particleDefinition == instance->GetIon("alpha+")
|| particleDefinition == instance->GetIon("helium")
if ( particleDefinition == alphaPlusPlusDef
|| particleDefinition == alphaPlusDef
|| particleDefinition == heliumDef
)
lowLim = lowEnergyLimitOfModelForZ2;
@@ -416,18 +417,15 @@ void G4DNARuddIonisationModel::SampleSecondaries(std::vector<G4DynamicParticle*>
G4double lowLim = 0;
G4double highLim = 0;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if ( particle->GetDefinition() == G4Proton::ProtonDefinition()
|| particle->GetDefinition() == instance->GetIon("hydrogen")
if ( particle->GetDefinition() == protonDef
|| particle->GetDefinition() == hydrogenDef
)
lowLim = killBelowEnergyForZ1;
if ( particle->GetDefinition() == instance->GetIon("alpha++")
|| particle->GetDefinition() == instance->GetIon("alpha+")
|| particle->GetDefinition() == instance->GetIon("helium")
if ( particle->GetDefinition() == alphaPlusPlusDef
|| particle->GetDefinition() == alphaPlusDef
|| particle->GetDefinition() == heliumDef
)
lowLim = killBelowEnergyForZ2;
@@ -605,18 +603,15 @@ G4double G4DNARuddIonisationModel::RandomizeEjectedElectronEnergy(G4ParticleDefi
{
G4double maximumKineticEnergyTransfer = 0.;
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == G4Proton::ProtonDefinition()
|| particleDefinition == instance->GetIon("hydrogen"))
if (particleDefinition == protonDef
|| particleDefinition == hydrogenDef)
{
maximumKineticEnergyTransfer = 4. * (electron_mass_c2 / proton_mass_c2) * k;
}
else if (particleDefinition == instance->GetIon("helium")
|| particleDefinition == instance->GetIon("alpha+")
|| particleDefinition == instance->GetIon("alpha++"))
else if (particleDefinition == heliumDef
|| particleDefinition == alphaPlusDef
|| particleDefinition == alphaPlusPlusDef)
{
maximumKineticEnergyTransfer = 4. * (0.511 / 3728) * k;
}
@@ -663,15 +658,15 @@ G4double G4DNARuddIonisationModel::RandomizeEjectedElectronEnergy(G4ParticleDefi
G4double maxSecKinetic = 0.;
if (particleDefinition == G4Proton::ProtonDefinition()
|| particleDefinition == instance->GetIon("hydrogen"))
if (particleDefinition == protonDef
|| particleDefinition == hydrogenDef)
{
maxSecKinetic = 4.* (electron_mass_c2 / proton_mass_c2) * k;
}
else if (particleDefinition == instance->GetIon("helium")
|| particleDefinition == instance->GetIon("alpha+")
|| particleDefinition == instance->GetIon("alpha++"))
else if (particleDefinition == heliumDef
|| particleDefinition == alphaPlusDef
|| particleDefinition == alphaPlusPlusDef)
{
maxSecKinetic = 4.* (0.511 / 3728) * k;
}
@@ -760,9 +755,6 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
const G4double n = 2.;
const G4double Gj[5] = { 0.99, 1.11, 1.11, 0.52, 1. };
G4DNAGenericIonsManager* instance;
instance = G4DNAGenericIonsManager::Instance();
G4double wBig = (energyTransfer
- waterStructure.IonisationEnergy(ionizationLevelIndex));
if (wBig < 0)
@@ -780,26 +772,26 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
G4bool isProtonOrHydrogen = false;
G4bool isHelium = false;
if (particleDefinition == G4Proton::ProtonDefinition()
|| particleDefinition == instance->GetIon("hydrogen"))
if (particleDefinition == protonDef
|| particleDefinition == hydrogenDef)
{
isProtonOrHydrogen = true;
tau = (electron_mass_c2 / proton_mass_c2) * k;
}
else if (particleDefinition == instance->GetIon("helium")
|| particleDefinition == instance->GetIon("alpha+")
|| particleDefinition == instance->GetIon("alpha++"))
else if (particleDefinition == heliumDef
|| particleDefinition == alphaPlusDef
|| particleDefinition == alphaPlusPlusDef)
{
isHelium = true;
tau = (0.511 / 3728.) * k;
}
G4double S = 4. * pi * Bohr_radius * Bohr_radius * n
* std::pow((Ry / Bj[ionizationLevelIndex]), 2);
* gpow->powN((Ry / Bj[ionizationLevelIndex]), 2);
if (j == 4)
S = 4. * pi * Bohr_radius * Bohr_radius * n
* std::pow((Ry / waterStructure.IonisationEnergy(ionizationLevelIndex)),
* gpow->powN((Ry / waterStructure.IonisationEnergy(ionizationLevelIndex)),
2);
G4double v2 = tau / Bj[ionizationLevelIndex];
@@ -812,9 +804,9 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
wc = 4. * v2 - 2. * v
- (Ry / (4. * waterStructure.IonisationEnergy(ionizationLevelIndex)));
G4double L1 = (C1 * std::pow(v, (D1))) / (1. + E1 * std::pow(v, (D1 + 4.)));
G4double L2 = C2 * std::pow(v, (D2));
G4double H1 = (A1 * std::log(1. + v2)) / (v2 + (B1 / v2));
G4double L1 = (C1 * gpow->powA(v, (D1))) / (1. + E1 * gpow->powA(v, (D1 + 4.)));
G4double L2 = C2 * gpow->powA(v, (D2));
G4double H1 = (A1 * G4Log(1. + v2)) / (v2 + (B1 / v2));
G4double H2 = (A2 / v2) + (B2 / (v2 * v2));
G4double F1 = L1 + H1;
@@ -824,28 +816,28 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
CorrectionFactor(particleDefinition, k) * Gj[j]
* (S / Bj[ionizationLevelIndex])
* ((F1 + w * F2)
/ (std::pow((1. + w), 3)
/ (gpow->powN((1. + w), 3)
* (1. + G4Exp(alphaConst * (w - wc) / v))));
if (j == 4)
sigma = CorrectionFactor(particleDefinition, k) * Gj[j]
* (S / waterStructure.IonisationEnergy(ionizationLevelIndex))
* ((F1 + w * F2)
/ (std::pow((1. + w), 3)
/ (gpow->powN((1. + w), 3)
* (1. + G4Exp(alphaConst * (w - wc) / v))));
if ((particleDefinition == instance->GetIon("hydrogen"))
if ((particleDefinition == hydrogenDef)
&& (ionizationLevelIndex == 4))
{
// sigma = Gj[j] * (S/Bj[ionizationLevelIndex])
sigma = Gj[j] * (S / waterStructure.IonisationEnergy(ionizationLevelIndex))
* ((F1 + w * F2)
/ (std::pow((1. + w), 3)
/ (gpow->powN((1. + w), 3)
* (1. + G4Exp(alphaConst * (w - wc) / v))));
}
// if ( particleDefinition == G4Proton::ProtonDefinition()
// || particleDefinition == instance->GetIon("hydrogen")
// if ( particleDefinition == protonDef
// || particleDefinition == hydrogenDef
// )
if (isProtonOrHydrogen)
@@ -853,7 +845,7 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
return (sigma);
}
if (particleDefinition == instance->GetIon("alpha++"))
if (particleDefinition == alphaPlusPlusDef)
{
slaterEffectiveCharge[0] = 0.;
slaterEffectiveCharge[1] = 0.;
@@ -863,7 +855,7 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
sCoefficient[2] = 0.;
}
else if (particleDefinition == instance->GetIon("alpha+"))
else if (particleDefinition == alphaPlusDef)
{
slaterEffectiveCharge[0] = 2.0;
// The following values are provided by M. Dingfelder (priv. comm)
@@ -875,7 +867,7 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
sCoefficient[2] = 0.15;
}
else if (particleDefinition == instance->GetIon("helium"))
else if (particleDefinition == heliumDef)
{
slaterEffectiveCharge[0] = 1.7;
slaterEffectiveCharge[1] = 1.15;
@@ -885,22 +877,22 @@ G4double G4DNARuddIonisationModel::DifferentialCrossSection(G4ParticleDefinition
sCoefficient[2] = 0.25;
}
// if ( particleDefinition == instance->GetIon("helium")
// || particleDefinition == instance->GetIon("alpha+")
// || particleDefinition == instance->GetIon("alpha++")
// if ( particleDefinition == heliumDef
// || particleDefinition == alphaPlusDef
// || particleDefinition == alphaPlusPlusDef
// )
if (isHelium)
{
sigma = Gj[j] * (S / Bj[ionizationLevelIndex])
* ((F1 + w * F2)
/ (std::pow((1. + w), 3)
/ (gpow->powN((1. + w), 3)
* (1. + G4Exp(alphaConst * (w - wc) / v))));
if (j == 4)
sigma = Gj[j]
* (S / waterStructure.IonisationEnergy(ionizationLevelIndex))
* ((F1 + w * F2)
/ (std::pow((1. + w), 3)
/ (gpow->powN((1. + w), 3)
* (1. + G4Exp(alphaConst * (w - wc) / v))));
G4double zEff = particleDefinition->GetPDGCharge() / eplus
@@ -995,15 +987,13 @@ G4double G4DNARuddIonisationModel::R(G4double t,
G4double G4DNARuddIonisationModel::CorrectionFactor(G4ParticleDefinition* particleDefinition,
G4double k)
{
G4DNAGenericIonsManager *instance;
instance = G4DNAGenericIonsManager::Instance();
if (particleDefinition == G4Proton::Proton())
{
return (1.);
} else if (particleDefinition == instance->GetIon("hydrogen"))
} else if (particleDefinition == hydrogenDef)
{
G4double value = (std::log10(k / eV) - 4.2) / 0.5;
G4double value = (G4Log(k / eV)/gpow->logZ(10) - 4.2) / 0.5;
// The following values are provided by M. Dingfelder (priv. comm)
return ((0.6 / (1 + G4Exp(value))) + 0.9);
} else
@@ -136,7 +136,7 @@ Initialise(const G4ParticleDefinition* /*particle*/,
fParticleChangeForGamma = GetParticleChangeForGamma();
isInitialised = true;
char *path = getenv("G4LEDATA");
const char *path = G4FindDataDir("G4LEDATA");
std::ostringstream eFullFileName;
eFullFileName << path << "/dna/sigma_excitationvib_e_sanche.dat";
std::ifstream input(eFullFileName.str().c_str());
@@ -58,7 +58,7 @@ G4double G4DNASmoluchowskiReactionModel::GetReactionRadius(const G4MolecularConf
return __output;
}
G4double G4DNASmoluchowskiReactionModel::GetReactionRadius(const G4int __i)
G4double G4DNASmoluchowskiReactionModel::GetReactionRadius(const G4int& __i)
{
G4double __output = (*fpReactionData)[__i]->GetEffectiveReactionRadius();
return __output;
@@ -1,129 +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. *
// ********************************************************************
//
// 20/2/2019
// Author : HoangTRAN
#include "G4DNATotallyDiffusionControlled.hh"
#include "G4IRTUtils.hh"
#include "G4DNAMolecularReactionTable.hh"
#include "G4VDNAReactionModel.hh"
#include "G4OctreeFinder.hh"
#include "G4SystemOfUnits.hh"
#include "G4PhysicalConstants.hh"
#include "G4MolecularConfiguration.hh"
#include "Randomize.hh"
#include "G4Molecule.hh"
#include "G4Electron_aq.hh"
#include "G4Hydrogen.hh"
#include "G4ErrorFunction.hh"
G4DNATotallyDiffusionControlled::G4DNATotallyDiffusionControlled()
: G4VReactionType()
{}
G4DNATotallyDiffusionControlled::~G4DNATotallyDiffusionControlled() = default;
G4double G4DNATotallyDiffusionControlled::GetTimeToEncounter(const G4Track& trackA,
const G4Track& trackB)
{
auto pMolConfA = GetMolecule(trackA)->GetMolecularConfiguration();
auto pMolConfB = GetMolecule(trackB)->GetMolecularConfiguration();
G4double D = GetDiffusionCoefficient(pMolConfA, pMolConfB);
auto reactionData = G4DNAMolecularReactionTable::Instance()
->GetReactionData(pMolConfA, pMolConfB);
G4double kobs = reactionData->GetObservedReactionRateConstant();
G4double distance = (trackA.GetPosition() - trackB.GetPosition()).mag();
G4double Reff = kobs / ( 4 * CLHEP::pi * D * Avogadro );
if( distance < Reff )
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "distance = "<< distance
<< " is uncorrected with "
<<" Reff = "<<Reff
<<" for : "<<pMolConfA->GetName()
<<" and "<<pMolConfB->GetName();
G4Exception("G4DNATotallyDiffusionControlled"
"::GetTimeToEncounter()", "G4DNATotallyDiffusionControlled02",
FatalException, exceptionDescription);
}
G4double Winf = Reff / distance;
G4double U = G4UniformRand();
G4double irt = -1.0 * ps;
if ( U < Winf )
{
G4double d = ( distance - Reff ) /
G4ErrorFunction::erfcInv( U / Winf );
irt = ( 1.0 / ( 4 * D ) ) * d * d;
}
return irt;
}
G4bool G4DNATotallyDiffusionControlled::
GeminateRecombinationProbability(const G4MolecularConfiguration* pMolA,
const G4MolecularConfiguration* pMolB)
{
if(pMolA->GetDefinition() == G4Electron_aq::Definition() ||
pMolA->GetDefinition() == G4Hydrogen::Definition())
{
G4bool spinA;
G4bool spinB;
spinA = G4UniformRand() < 0.5;
if(spinA &&
(pMolB->GetDefinition() == G4Electron_aq::Definition() ||
pMolB->GetDefinition() == G4Hydrogen::Definition()))
{
spinB = G4UniformRand() < 0.5;
if( !spinB )
{
return true;
}
}
return false;
}
return true;
}
G4double
G4DNATotallyDiffusionControlled::GetDiffusionCoefficient(const G4MolecularConfiguration* mA,
const G4MolecularConfiguration* mB)
{
G4double D;
if(mA == mB)
{
D = (mA->GetDiffusionCoefficient());
}
else
{
D = (mA->GetDiffusionCoefficient() +
mB->GetDiffusionCoefficient());//
}
return D;
}
@@ -33,9 +33,6 @@
#include "G4Scheduler.hh"
G4DNAUpdateSystemModel::G4DNAUpdateSystemModel()
: G4VUpdateSystemModel()
, fpMesh(nullptr)
, fVerbose(0)
, fGlobalTime(DBL_MAX)
{}
void G4DNAUpdateSystemModel::SetMesh(G4DNAMesh* pMesh) { fpMesh = pMesh; }
@@ -48,10 +45,13 @@ void G4DNAUpdateSystemModel::KillMolecule(const Index& index, MolType type)
{
if(iter->second <= 0)
{
G4cout << "G4DNAUpdateSystemModel::KillMolecule::molecule : "
<< type->GetName() << " index : " << index
<< " number : " << iter->second << G4endl;
assert(false);
G4ExceptionDescription exceptionDescription;
exceptionDescription
<< "G4DNAUpdateSystemModel::KillMolecule::molecule : "
<< type->GetName() << " index : " << index
<< " number : " << iter->second << G4endl;
G4Exception("G4DNAEventScheduler::Stepping", "G4DNAEventScheduler002",
FatalErrorInArgument, exceptionDescription);
}
iter->second--;
if(G4VMoleculeCounter::Instance()->InUse())
@@ -70,10 +70,13 @@ void G4DNAUpdateSystemModel::KillMolecule(const Index& index, MolType type)
}
else
{
G4cout << "index : " << index << " " << type->GetName() << G4endl;
G4cout << "This molecule is not belong scavengers or particle-base"
<< G4endl;
assert(false);
G4ExceptionDescription exceptionDescription;
exceptionDescription
<< "index : " << index << " " << type->GetName()
<< " This molecule is not belong scavengers or particle-base"
<< G4endl;
G4Exception("G4DNAEventScheduler::Stepping", "G4DNAEventScheduler002",
FatalErrorInArgument, exceptionDescription);
}
}
}
@@ -81,24 +84,28 @@ void G4DNAUpdateSystemModel::KillMolecule(const Index& index, MolType type)
void G4DNAUpdateSystemModel::JumpTo(const Index& index, MolType type)
{
auto& node = fpMesh->GetVoxelMapList(index);
auto iter = node.find(type);
auto iter = node.find(type);
if(iter != node.end())
{
if(iter->second <= 0)
{
G4cout << "G4DNAUpdateSystemModel::KillMolecule::molecule : "
<< type->GetName() << " index : " << index
<< " number : " << iter->second << G4endl;
assert(false);
G4ExceptionDescription exceptionDescription;
exceptionDescription << "G4DNAUpdateSystemModel::JumpTo::molecule : "
<< type->GetName() << " index : " << index
<< " number : " << iter->second;
G4Exception("G4DNAUpdateSystemModel::JumpTo", "G4DNAUpdateSystemModel001",
FatalErrorInArgument, exceptionDescription);
}
iter->second--;
}
else
{
G4cout << "index : " << index << " " << type->GetName() << G4endl;
G4cout << "This molecule is not belong particle-base" << G4endl;
assert(false);
fpMesh->PrintVoxel(index);
G4ExceptionDescription exceptionDescription;
exceptionDescription << "index : " << index << " " << type->GetName()
<< " There is no this type";
G4Exception("G4DNAUpdateSystemModel::JumpTo", "G4DNAUpdateSystemModel002",
FatalErrorInArgument, exceptionDescription);
}
}
@@ -172,34 +179,9 @@ void G4DNAUpdateSystemModel::UpdateSystem(const Index& index,
if(fVerbose != 0)
{
G4cout << data.GetProduct(j)->GetName();
// for test
// G4cout<<" fGlobalTime : "<<fGlobalTime;
// end fortest
}
#endif
CreateMolecule(index, data.GetProduct(j));
//#define DEBUG 1
#ifdef DEBUG
if(G4MoleculeCounter::Instance()->InUse())
if(fpMesh->GetNumberOfType(data.GetProduct(j)) !=
G4MoleculeCounter::Instance()->GetCurrentNumberOf(
data.GetProduct(j)))
{
G4cout << "*********G4DNAUpdateSystemModel::DEBUG::GetNumberOfType("
<< data.GetProduct(j)->GetName()
<< ") : " << fpMesh->GetNumberOfType(data.GetProduct(j))
<< G4endl;
G4cout << "G4MoleculeCounter::GetCurrentNumberOf ("
<< data.GetProduct(j)->GetName() << ") : "
<< G4MoleculeCounter::Instance()->GetCurrentNumberOf(
data.GetProduct(j))
<< G4endl;
G4MoleculeCounter::Instance()->Dump();
throw;
}
#endif
}
}
else
@@ -208,9 +190,6 @@ void G4DNAUpdateSystemModel::UpdateSystem(const Index& index,
if(fVerbose != 0)
{
G4cout << "No product";
// for test
// G4cout<<" fGlobalTime : "<<fGlobalTime;
// end fortest
}
#endif
}
@@ -221,40 +200,7 @@ void G4DNAUpdateSystemModel::UpdateSystem(const Index& index,
}
#endif
KillMolecule(index, reactant1);
#ifdef DEBUG
if(G4MoleculeCounter::Instance()->InUse())
if(fpMesh->GetNumberOfType(reactant1) !=
G4MoleculeCounter::Instance()->GetCurrentNumberOf(reactant1))
{
G4cout << "*********G4DNAUpdateSystemModel::DEBUG::GetNumberOfType("
<< reactant1->GetName()
<< ") : " << fpMesh->GetNumberOfType(reactant1) << G4endl;
G4cout << "G4MoleculeCounter::GetCurrentNumberOf ("
<< reactant1->GetName() << ") : "
<< G4MoleculeCounter::Instance()->GetCurrentNumberOf(reactant1)
<< G4endl;
G4MoleculeCounter::Instance()->Dump();
throw;
}
#endif
KillMolecule(index, reactant2);
#ifdef DEBUG
if(G4MoleculeCounter::Instance()->InUse())
if(fpMesh->GetNumberOfType(reactant2) !=
G4MoleculeCounter::Instance()->GetCurrentNumberOf(reactant2))
{
G4cout << "*********G4DNAUpdateSystemModel::DEBUG::GetNumberOfType("
<< reactant2->GetName()
<< ") : " << fpMesh->GetNumberOfType(reactant2) << G4endl;
G4cout << "G4MoleculeCounter::GetCurrentNumberOf ("
<< reactant2->GetName() << ") : "
<< G4MoleculeCounter::Instance()->GetCurrentNumberOf(reactant2)
<< G4endl;
G4MoleculeCounter::Instance()->Dump();
throw;
}
#endif
}
void G4DNAUpdateSystemModel::UpdateSystem(const Index& index,
@@ -32,78 +32,148 @@
#include "G4Exp.hh"
#include "G4IRTUtils.hh"
#include "G4SystemOfUnits.hh"
#include "G4DNAReactionTypeManager.hh"
#include "G4Electron_aq.hh"
#include "Randomize.hh"
#include "G4Molecule.hh"
#include "G4ErrorFunction.hh"
G4DiffusionControlledReactionModel::G4DiffusionControlledReactionModel()
: G4VDNAReactionModel()
, fpReactionData(nullptr)
, fReactionTypeManager(nullptr)
: G4VDNAReactionModel()
{}
G4DiffusionControlledReactionModel::~G4DiffusionControlledReactionModel() =
default;
void G4DiffusionControlledReactionModel::Initialise(
const G4MolecularConfiguration* pMolecule, const G4Track&)
{
fpReactionData = fpReactionTable->GetReactionData(pMolecule);
}
G4DiffusionControlledReactionModel::~G4DiffusionControlledReactionModel() = default;
void G4DiffusionControlledReactionModel::Initialise(const G4MolecularConfiguration* pMolecule,
const G4Track&)
void G4DiffusionControlledReactionModel::InitialiseToPrint(
const G4MolecularConfiguration* pMolecule)
{
fpReactionData = fpReactionTable->GetReactionData(pMolecule);
fpReactionData = fpReactionTable->GetReactionData(pMolecule);
}
void G4DiffusionControlledReactionModel::InitialiseToPrint(const G4MolecularConfiguration* pMolecule)
G4double G4DiffusionControlledReactionModel::GetReactionRadius(
const G4MolecularConfiguration* pMol1, const G4MolecularConfiguration* pMol2)
{
fpReactionData = fpReactionTable->GetReactionData(pMolecule);
auto reactionData = fpReactionTable->GetReactionData(pMol1, pMol2);
if(reactionData == nullptr)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "No reactionData"
<< " for : " << pMol1->GetName() << " and "
<< pMol2->GetName();
G4Exception("G4DiffusionControlledReactionModel"
"::GetReactionRadius()",
"G4DiffusionControlledReactionModel00", FatalException,
exceptionDescription);
}
return reactionData->GetEffectiveReactionRadius();
}
G4double G4DiffusionControlledReactionModel::GetReactionRadius(const G4MolecularConfiguration* pMol1,
const G4MolecularConfiguration* pMol2)
G4double G4DiffusionControlledReactionModel::GetReactionRadius(const G4int& i)
{
auto reactionData = fpReactionTable->GetReactionData(pMol1, pMol2);
if(reactionData == nullptr)
auto pMol1 = (*fpReactionData)[i]->GetReactant1();
auto pMol2 = (*fpReactionData)[i]->GetReactant2();
return GetReactionRadius(pMol1, pMol2);
}
G4double G4DiffusionControlledReactionModel::GetTimeToEncounter(
const G4Track& trackA, const G4Track& trackB)
{
auto pMolConfA = GetMolecule(trackA)->GetMolecularConfiguration();
auto pMolConfB = GetMolecule(trackB)->GetMolecularConfiguration();
G4double D =
pMolConfA->GetDiffusionCoefficient() + pMolConfB->GetDiffusionCoefficient();
if(D == 0)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "The total diffusion coefficient for : "
<< pMolConfA->GetName() << " and "
<< pMolConfB->GetName() << " is null ";
G4Exception("G4DiffusionControlledReactionModel"
"::GetTimeToEncounter()",
"G4DiffusionControlledReactionModel03", FatalException,
exceptionDescription);
}
auto reactionData = G4DNAMolecularReactionTable::Instance()->GetReactionData(
pMolConfA, pMolConfB);
G4double kobs = reactionData->GetObservedReactionRateConstant();
G4double distance = (trackA.GetPosition() - trackB.GetPosition()).mag();
G4double SmoluchowskiRadius = reactionData->GetEffectiveReactionRadius();
if(distance == 0 || distance < SmoluchowskiRadius)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "distance = " << distance << " is uncorrected with "
<< " Reff = " << SmoluchowskiRadius
<< " for : " << pMolConfA->GetName() << " and "
<< pMolConfB->GetName();
G4Exception("G4DiffusionControlledReactionModel"
"::GetTimeToEncounter()",
"G4DiffusionControlledReactionModel02", FatalException,
exceptionDescription);
}
else
{
G4double Winf = SmoluchowskiRadius / distance;
G4double U = G4UniformRand();
G4double X = 0;
G4double irt_1 = -1.0 * ps;
if(Winf > 0 && U < Winf)
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "No reactionData"
<<" for : "<<pMol1->GetName()
<<" and "<<pMol2->GetName();
G4Exception("G4DiffusionControlledReactionModel"
"::GetReactionRadius()", "G4DiffusionControlledReactionModel00",
FatalException, exceptionDescription);
G4double erfcIn = G4ErrorFunction::erfcInv(U / Winf);
if(erfcIn != 0)
{
G4double d =
(distance - SmoluchowskiRadius) / erfcIn;
irt_1 = (1.0 / (4 * D)) * d * d;
}
}
G4double kobs = reactionData->GetObservedReactionRateConstant();
G4double D;
if(pMol1 == pMol2)
{
D = (pMol1->GetDiffusionCoefficient());
if(reactionData->GetReactionType() == 0) // Totally diffused contr
{
return irt_1;
}
if(irt_1 < 0)
{
return irt_1;
}
else
{
D = (pMol1->GetDiffusionCoefficient() +
pMol2->GetDiffusionCoefficient());//
G4double kdif = 4 * CLHEP::pi * D * SmoluchowskiRadius * Avogadro;
if(pMolConfA == pMolConfB)
{
kdif /= 2;
}
G4double kact = G4IRTUtils::GetKact(kobs, kdif);
G4double sumOfk = kact + kdif;
if(sumOfk != 0)
{
G4double rateFactor = kact / sumOfk;
if(G4UniformRand() > rateFactor)
{
return -1.0 * ps;
}
G4double Y = std::abs(G4RandGauss::shoot(0.0, std::sqrt(2)));
if(Y > 0)
{
X = -(G4Log(G4UniformRand())) / Y;
}
G4double f = X * SmoluchowskiRadius * kdif / sumOfk;
G4double irt_2 = (f * f) / D;
return irt_1 + irt_2;
}
}
if ( D == 0 )
{
G4ExceptionDescription exceptionDescription;
exceptionDescription << "D = "<< D
<< " is uncorrected"
<<" for : "<<pMol1->GetName()
<<" and "<<pMol2->GetName();
G4Exception("G4DiffusionControlledReactionModel"
"::GetReactionRadius()", "G4DiffusionControlledReactionModel01",
FatalException, exceptionDescription);
}
G4double Reff = kobs / ( 4 * CLHEP::pi * D * Avogadro );
return Reff;
}
G4double G4DiffusionControlledReactionModel::GetReactionRadius(G4int i)
{
auto pMol1 = (*fpReactionData)[i]->GetReactant1();
auto pMol2 = (*fpReactionData)[i]->GetReactant2();
return GetReactionRadius(pMol1,pMol2);
}
void G4DiffusionControlledReactionModel::SetReactionTypeManager(G4VReactionTypeManager* typeManager)
{
fReactionTypeManager = ((G4DNAReactionTypeManager*)typeManager);
}
return -1.0 * ps;
}
@@ -23,36 +23,7 @@
// * acceptance of all terms of the Geant4 Software license. *
// ********************************************************************
//
// 20/2/2019
// Author : HoangTRAN
#ifndef G4DNATotallyDiffusionControlled_h
#define G4DNATotallyDiffusionControlled_h 1
#include "G4DNAReactionTypeManager.hh"
#include "G4VReactionType.hh"
class G4MolecularConfiguration;
class G4DNAMolecularReactionTable;
class G4VDNAReactionModel;
class G4DNATotallyDiffusionControlled
: public G4VReactionType
{
public:
G4DNATotallyDiffusionControlled();
~G4DNATotallyDiffusionControlled() override;
G4DNATotallyDiffusionControlled(const G4DNATotallyDiffusionControlled& other) = delete;
G4DNATotallyDiffusionControlled& operator=(const G4DNATotallyDiffusionControlled& other) = delete;
G4double GetTimeToEncounter(const G4Track& trackA,
const G4Track& trackB) override;
G4bool GeminateRecombinationProbability(const G4MolecularConfiguration* pConfMolA,
const G4MolecularConfiguration* pConfMolB) override;
private:
G4double GetDiffusionCoefficient(const G4MolecularConfiguration* pMA,
const G4MolecularConfiguration* pMB);
};
#endif
#include "G4VDNAHitModel.hh"
G4VDNAHitModel::G4VDNAHitModel(const G4String& name)
: fName(name)
{}
@@ -84,7 +84,7 @@ G4double G4VLEPTSModel::GetMeanFreePath(const G4Material* aMaterial,
void G4VLEPTSModel::BuildPhysicsTable(const G4ParticleDefinition& aParticleType)
{
//CHECK IF PATH VARIABLE IS DEFINED
char* path = std::getenv("G4LEDATA");
const char* path = G4FindDataDir("G4LEDATA");
if( !path ) {
G4Exception("G4VLEPTSModel",
"",